From d38f722e15b79862321b54251d67fd95dd61e8e6 Mon Sep 17 00:00:00 2001 From: yue Date: Thu, 2 Sep 2021 18:07:21 +0800 Subject: [PATCH 1/2] add hdi-gen Signed-off-by: yue --- tools/hdi-gen/LICENSE | 51 + tools/hdi-gen/Makefile | 46 + tools/hdi-gen/README.md | 48 + tools/hdi-gen/README_zh.md | 46 + tools/hdi-gen/ast/Makefile | 12 + tools/hdi-gen/ast/ast.cpp | 236 +++ tools/hdi-gen/ast/ast.h | 174 ++ tools/hdi-gen/ast/ast_array_type.cpp | 389 +++++ tools/hdi-gen/ast/ast_array_type.h | 74 + tools/hdi-gen/ast/ast_boolean_type.cpp | 177 ++ tools/hdi-gen/ast/ast_boolean_type.h | 62 + tools/hdi-gen/ast/ast_byte_type.cpp | 174 ++ tools/hdi-gen/ast/ast_byte_type.h | 62 + tools/hdi-gen/ast/ast_double_type.cpp | 173 ++ tools/hdi-gen/ast/ast_double_type.h | 62 + tools/hdi-gen/ast/ast_enum_type.cpp | 277 ++++ tools/hdi-gen/ast/ast_enum_type.h | 188 +++ tools/hdi-gen/ast/ast_fd_type.cpp | 183 +++ tools/hdi-gen/ast/ast_fd_type.h | 62 + tools/hdi-gen/ast/ast_float_type.cpp | 173 ++ tools/hdi-gen/ast/ast_float_type.h | 62 + tools/hdi-gen/ast/ast_integer_type.cpp | 173 ++ tools/hdi-gen/ast/ast_integer_type.h | 62 + tools/hdi-gen/ast/ast_interface_type.cpp | 184 +++ tools/hdi-gen/ast/ast_interface_type.h | 120 ++ tools/hdi-gen/ast/ast_list_type.cpp | 390 +++++ tools/hdi-gen/ast/ast_list_type.h | 75 + tools/hdi-gen/ast/ast_long_type.cpp | 173 ++ tools/hdi-gen/ast/ast_long_type.h | 62 + tools/hdi-gen/ast/ast_map_type.cpp | 133 ++ tools/hdi-gen/ast/ast_map_type.h | 69 + tools/hdi-gen/ast/ast_method.cpp | 68 + tools/hdi-gen/ast/ast_method.h | 85 + tools/hdi-gen/ast/ast_module.cpp | 27 + tools/hdi-gen/ast/ast_module.h | 36 + tools/hdi-gen/ast/ast_namespace.cpp | 100 ++ tools/hdi-gen/ast/ast_namespace.h | 78 + tools/hdi-gen/ast/ast_node.cpp | 26 + tools/hdi-gen/ast/ast_node.h | 28 + tools/hdi-gen/ast/ast_parameter.cpp | 209 +++ tools/hdi-gen/ast/ast_parameter.h | 78 + tools/hdi-gen/ast/ast_sequenceable_type.cpp | 129 ++ tools/hdi-gen/ast/ast_sequenceable_type.h | 51 + tools/hdi-gen/ast/ast_short_type.cpp | 174 ++ tools/hdi-gen/ast/ast_short_type.h | 62 + tools/hdi-gen/ast/ast_string_type.cpp | 179 ++ tools/hdi-gen/ast/ast_string_type.h | 62 + tools/hdi-gen/ast/ast_struct_type.cpp | 265 +++ tools/hdi-gen/ast/ast_struct_type.h | 131 ++ tools/hdi-gen/ast/ast_type.cpp | 242 +++ tools/hdi-gen/ast/ast_type.h | 164 ++ tools/hdi-gen/ast/ast_uchar_type.cpp | 174 ++ tools/hdi-gen/ast/ast_uchar_type.h | 62 + tools/hdi-gen/ast/ast_uint_type.cpp | 174 ++ tools/hdi-gen/ast/ast_uint_type.h | 62 + tools/hdi-gen/ast/ast_ulong_type.cpp | 174 ++ tools/hdi-gen/ast/ast_ulong_type.h | 62 + tools/hdi-gen/ast/ast_union_type.cpp | 276 ++++ tools/hdi-gen/ast/ast_union_type.h | 131 ++ tools/hdi-gen/ast/ast_ushort_type.cpp | 174 ++ tools/hdi-gen/ast/ast_ushort_type.h | 62 + tools/hdi-gen/ast/ast_void_type.cpp | 43 + tools/hdi-gen/ast/ast_void_type.h | 33 + tools/hdi-gen/codegen/Makefile | 12 + .../c_client_interface_code_emitter.cpp | 141 ++ .../codegen/c_client_interface_code_emitter.h | 42 + .../codegen/c_client_proxy_code_emitter.cpp | 524 ++++++ .../codegen/c_client_proxy_code_emitter.h | 69 + tools/hdi-gen/codegen/c_code_emitter.cpp | 175 ++ tools/hdi-gen/codegen/c_code_emitter.h | 93 ++ tools/hdi-gen/codegen/c_code_generator.cpp | 84 + tools/hdi-gen/codegen/c_code_generator.h | 35 + .../codegen/c_custom_types_code_emitter.cpp | 446 +++++ .../codegen/c_custom_types_code_emitter.h | 65 + .../codegen/c_service_driver_code_emitter.cpp | 166 ++ .../codegen/c_service_driver_code_emitter.h | 44 + .../codegen/c_service_impl_code_emitter.cpp | 194 +++ .../codegen/c_service_impl_code_emitter.h | 45 + .../c_service_interface_code_emitter.cpp | 149 ++ .../c_service_interface_code_emitter.h | 46 + .../codegen/c_service_stub_code_emitter.cpp | 449 +++++ .../codegen/c_service_stub_code_emitter.h | 68 + tools/hdi-gen/codegen/code_generator.h | 39 + .../cpp_client_interface_code_emitter.cpp | 219 +++ .../cpp_client_interface_code_emitter.h | 56 + .../codegen/cpp_client_proxy_code_emitter.cpp | 305 ++++ .../codegen/cpp_client_proxy_code_emitter.h | 57 + tools/hdi-gen/codegen/cpp_code_emitter.cpp | 253 +++ tools/hdi-gen/codegen/cpp_code_emitter.h | 107 ++ tools/hdi-gen/codegen/cpp_code_generator.cpp | 84 + tools/hdi-gen/codegen/cpp_code_generator.h | 35 + .../codegen/cpp_custom_types_code_emitter.cpp | 311 ++++ .../codegen/cpp_custom_types_code_emitter.h | 62 + .../cpp_service_driver_code_emitter.cpp | 172 ++ .../codegen/cpp_service_driver_code_emitter.h | 45 + .../codegen/cpp_service_impl_code_emitter.cpp | 206 +++ .../codegen/cpp_service_impl_code_emitter.h | 47 + .../cpp_service_interface_code_emitter.cpp | 207 +++ .../cpp_service_interface_code_emitter.h | 56 + .../codegen/cpp_service_stub_code_emitter.cpp | 449 +++++ .../codegen/cpp_service_stub_code_emitter.h | 82 + tools/hdi-gen/codegen/generator_factory.cpp | 29 + tools/hdi-gen/codegen/generator_factory.h | 23 + .../java_client_interface_code_emitter.cpp | 142 ++ .../java_client_interface_code_emitter.h | 47 + .../java_client_proxy_code_emitter.cpp | 668 ++++++++ .../codegen/java_client_proxy_code_emitter.h | 84 + tools/hdi-gen/codegen/java_code_emitter.cpp | 121 ++ tools/hdi-gen/codegen/java_code_emitter.h | 72 + tools/hdi-gen/codegen/java_code_generator.cpp | 68 + tools/hdi-gen/codegen/java_code_generator.h | 35 + tools/hdi-gen/main.cpp | 90 + tools/hdi-gen/parser/Makefile | 12 + tools/hdi-gen/parser/file_detail.cpp | 48 + tools/hdi-gen/parser/file_detail.h | 82 + tools/hdi-gen/parser/lexer.cpp | 337 ++++ tools/hdi-gen/parser/lexer.h | 124 ++ tools/hdi-gen/parser/module_parser.cpp | 128 ++ tools/hdi-gen/parser/module_parser.h | 67 + tools/hdi-gen/parser/parser.cpp | 1443 +++++++++++++++++ tools/hdi-gen/parser/parser.h | 142 ++ tools/hdi-gen/parser/token.h | 71 + .../c_test/array_test/v1_0/IArrayTest.idl | 46 + .../c_test/array_test/v1_0/c_array_test.cpp | 676 ++++++++ .../test/c_test/cb_test/v1_0/ICallback.idl | 16 + .../test/c_test/cb_test/v1_0/ICbTest.idl | 15 + .../test/c_test/cb_test/v1_0/c_cb_test.cpp | 61 + .../test/c_test/data_test/v1_0/IDataTest.idl | 46 + .../c_test/data_test/v1_0/c_data_test.cpp | 275 ++++ .../test/c_test/list_test/v1_0/IListTest.idl | 46 + .../c_test/list_test/v1_0/c_list_test.cpp | 676 ++++++++ .../c_test/struct_test/v1_0/IStructTest.idl | 20 + .../c_test/struct_test/v1_0/c_struct_test.cpp | 823 ++++++++++ .../hdi-gen/test/c_test/types/v1_0/Types.idl | 95 ++ .../cpp_test/array_test/v1_0/IArrayTest.idl | 50 + .../array_test/v1_0/cpp_array_test.cpp | 416 +++++ .../test/cpp_test/cb_test/v1_0/ICallback.idl | 14 + .../test/cpp_test/cb_test/v1_0/ICbTest.idl | 15 + .../cpp_test/cb_test/v1_0/cpp_cb_test.cpp | 63 + .../cpp_test/data_test/v1_0/IDataTest.idl | 50 + .../cpp_test/data_test/v1_0/cpp_data_test.cpp | 265 +++ .../cpp_test/list_test/v1_0/IListTest.idl | 50 + .../cpp_test/list_test/v1_0/cpp_list_test.cpp | 416 +++++ .../test/cpp_test/map_test/v1_0/IMapTest.idl | 39 + .../cpp_test/map_test/v1_0/cpp_map_test.cpp | 350 ++++ .../cpp_test/struct_test/v1_0/IStructTest.idl | 20 + .../struct_test/v1_0/cpp_struct_test.cpp | 719 ++++++++ .../test/cpp_test/types/v1_0/Types.idl | 99 ++ .../java_test/array_test/v1_0/IArrayTest.idl | 34 + .../test/java_test/cb_test/v1_0/ICallback.idl | 14 + .../test/java_test/cb_test/v1_0/ICbTest.idl | 15 + .../java_test/data_test/v1_0/IDataTest.idl | 34 + .../java_test/list_test/v1_0/IListTest.idl | 34 + .../test/java_test/map_test/v1_0/IMapTest.idl | 49 + tools/hdi-gen/util/Makefile | 14 + tools/hdi-gen/util/autoptr.h | 261 +++ tools/hdi-gen/util/file.cpp | 233 +++ tools/hdi-gen/util/file.h | 92 ++ tools/hdi-gen/util/light_refcount_base.cpp | 28 + tools/hdi-gen/util/light_refcount_base.h | 41 + tools/hdi-gen/util/logger.cpp | 60 + tools/hdi-gen/util/logger.h | 49 + tools/hdi-gen/util/options.cpp | 148 ++ tools/hdi-gen/util/options.h | 125 ++ tools/hdi-gen/util/string.cpp | 748 +++++++++ tools/hdi-gen/util/string.h | 147 ++ tools/hdi-gen/util/string_builder.cpp | 150 ++ tools/hdi-gen/util/string_builder.h | 41 + 168 files changed, 24943 insertions(+) create mode 100755 tools/hdi-gen/LICENSE create mode 100755 tools/hdi-gen/Makefile create mode 100755 tools/hdi-gen/README.md create mode 100755 tools/hdi-gen/README_zh.md create mode 100755 tools/hdi-gen/ast/Makefile create mode 100755 tools/hdi-gen/ast/ast.cpp create mode 100755 tools/hdi-gen/ast/ast.h create mode 100755 tools/hdi-gen/ast/ast_array_type.cpp create mode 100755 tools/hdi-gen/ast/ast_array_type.h create mode 100755 tools/hdi-gen/ast/ast_boolean_type.cpp create mode 100755 tools/hdi-gen/ast/ast_boolean_type.h create mode 100755 tools/hdi-gen/ast/ast_byte_type.cpp create mode 100755 tools/hdi-gen/ast/ast_byte_type.h create mode 100755 tools/hdi-gen/ast/ast_double_type.cpp create mode 100755 tools/hdi-gen/ast/ast_double_type.h create mode 100755 tools/hdi-gen/ast/ast_enum_type.cpp create mode 100755 tools/hdi-gen/ast/ast_enum_type.h create mode 100755 tools/hdi-gen/ast/ast_fd_type.cpp create mode 100755 tools/hdi-gen/ast/ast_fd_type.h create mode 100755 tools/hdi-gen/ast/ast_float_type.cpp create mode 100755 tools/hdi-gen/ast/ast_float_type.h create mode 100755 tools/hdi-gen/ast/ast_integer_type.cpp create mode 100755 tools/hdi-gen/ast/ast_integer_type.h create mode 100755 tools/hdi-gen/ast/ast_interface_type.cpp create mode 100755 tools/hdi-gen/ast/ast_interface_type.h create mode 100755 tools/hdi-gen/ast/ast_list_type.cpp create mode 100755 tools/hdi-gen/ast/ast_list_type.h create mode 100755 tools/hdi-gen/ast/ast_long_type.cpp create mode 100755 tools/hdi-gen/ast/ast_long_type.h create mode 100755 tools/hdi-gen/ast/ast_map_type.cpp create mode 100755 tools/hdi-gen/ast/ast_map_type.h create mode 100755 tools/hdi-gen/ast/ast_method.cpp create mode 100755 tools/hdi-gen/ast/ast_method.h create mode 100755 tools/hdi-gen/ast/ast_module.cpp create mode 100755 tools/hdi-gen/ast/ast_module.h create mode 100755 tools/hdi-gen/ast/ast_namespace.cpp create mode 100755 tools/hdi-gen/ast/ast_namespace.h create mode 100755 tools/hdi-gen/ast/ast_node.cpp create mode 100755 tools/hdi-gen/ast/ast_node.h create mode 100755 tools/hdi-gen/ast/ast_parameter.cpp create mode 100755 tools/hdi-gen/ast/ast_parameter.h create mode 100755 tools/hdi-gen/ast/ast_sequenceable_type.cpp create mode 100755 tools/hdi-gen/ast/ast_sequenceable_type.h create mode 100755 tools/hdi-gen/ast/ast_short_type.cpp create mode 100755 tools/hdi-gen/ast/ast_short_type.h create mode 100755 tools/hdi-gen/ast/ast_string_type.cpp create mode 100755 tools/hdi-gen/ast/ast_string_type.h create mode 100755 tools/hdi-gen/ast/ast_struct_type.cpp create mode 100755 tools/hdi-gen/ast/ast_struct_type.h create mode 100755 tools/hdi-gen/ast/ast_type.cpp create mode 100755 tools/hdi-gen/ast/ast_type.h create mode 100755 tools/hdi-gen/ast/ast_uchar_type.cpp create mode 100755 tools/hdi-gen/ast/ast_uchar_type.h create mode 100755 tools/hdi-gen/ast/ast_uint_type.cpp create mode 100755 tools/hdi-gen/ast/ast_uint_type.h create mode 100755 tools/hdi-gen/ast/ast_ulong_type.cpp create mode 100755 tools/hdi-gen/ast/ast_ulong_type.h create mode 100755 tools/hdi-gen/ast/ast_union_type.cpp create mode 100755 tools/hdi-gen/ast/ast_union_type.h create mode 100755 tools/hdi-gen/ast/ast_ushort_type.cpp create mode 100755 tools/hdi-gen/ast/ast_ushort_type.h create mode 100755 tools/hdi-gen/ast/ast_void_type.cpp create mode 100755 tools/hdi-gen/ast/ast_void_type.h create mode 100755 tools/hdi-gen/codegen/Makefile create mode 100755 tools/hdi-gen/codegen/c_client_interface_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_client_interface_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_client_proxy_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_client_proxy_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_code_generator.cpp create mode 100755 tools/hdi-gen/codegen/c_code_generator.h create mode 100755 tools/hdi-gen/codegen/c_custom_types_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_custom_types_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_service_driver_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_service_driver_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_service_impl_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_service_impl_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_service_interface_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_service_interface_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_service_stub_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_service_stub_code_emitter.h create mode 100755 tools/hdi-gen/codegen/code_generator.h create mode 100755 tools/hdi-gen/codegen/cpp_client_interface_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_client_interface_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_code_generator.cpp create mode 100755 tools/hdi-gen/codegen/cpp_code_generator.h create mode 100755 tools/hdi-gen/codegen/cpp_custom_types_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_custom_types_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_service_driver_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_service_driver_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_service_impl_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_service_impl_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_service_interface_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_service_interface_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_service_stub_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_service_stub_code_emitter.h create mode 100755 tools/hdi-gen/codegen/generator_factory.cpp create mode 100755 tools/hdi-gen/codegen/generator_factory.h create mode 100755 tools/hdi-gen/codegen/java_client_interface_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/java_client_interface_code_emitter.h create mode 100755 tools/hdi-gen/codegen/java_client_proxy_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/java_client_proxy_code_emitter.h create mode 100755 tools/hdi-gen/codegen/java_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/java_code_emitter.h create mode 100755 tools/hdi-gen/codegen/java_code_generator.cpp create mode 100755 tools/hdi-gen/codegen/java_code_generator.h create mode 100755 tools/hdi-gen/main.cpp create mode 100755 tools/hdi-gen/parser/Makefile create mode 100755 tools/hdi-gen/parser/file_detail.cpp create mode 100755 tools/hdi-gen/parser/file_detail.h create mode 100755 tools/hdi-gen/parser/lexer.cpp create mode 100755 tools/hdi-gen/parser/lexer.h create mode 100755 tools/hdi-gen/parser/module_parser.cpp create mode 100755 tools/hdi-gen/parser/module_parser.h create mode 100755 tools/hdi-gen/parser/parser.cpp create mode 100755 tools/hdi-gen/parser/parser.h create mode 100755 tools/hdi-gen/parser/token.h create mode 100755 tools/hdi-gen/test/c_test/array_test/v1_0/IArrayTest.idl create mode 100755 tools/hdi-gen/test/c_test/array_test/v1_0/c_array_test.cpp create mode 100755 tools/hdi-gen/test/c_test/cb_test/v1_0/ICallback.idl create mode 100755 tools/hdi-gen/test/c_test/cb_test/v1_0/ICbTest.idl create mode 100755 tools/hdi-gen/test/c_test/cb_test/v1_0/c_cb_test.cpp create mode 100755 tools/hdi-gen/test/c_test/data_test/v1_0/IDataTest.idl create mode 100755 tools/hdi-gen/test/c_test/data_test/v1_0/c_data_test.cpp create mode 100755 tools/hdi-gen/test/c_test/list_test/v1_0/IListTest.idl create mode 100755 tools/hdi-gen/test/c_test/list_test/v1_0/c_list_test.cpp create mode 100755 tools/hdi-gen/test/c_test/struct_test/v1_0/IStructTest.idl create mode 100755 tools/hdi-gen/test/c_test/struct_test/v1_0/c_struct_test.cpp create mode 100755 tools/hdi-gen/test/c_test/types/v1_0/Types.idl create mode 100755 tools/hdi-gen/test/cpp_test/array_test/v1_0/IArrayTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/array_test/v1_0/cpp_array_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICallback.idl create mode 100755 tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICbTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/cb_test/v1_0/cpp_cb_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/data_test/v1_0/IDataTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/data_test/v1_0/cpp_data_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/list_test/v1_0/IListTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/list_test/v1_0/cpp_list_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/map_test/v1_0/IMapTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/map_test/v1_0/cpp_map_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/struct_test/v1_0/IStructTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/struct_test/v1_0/cpp_struct_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/types/v1_0/Types.idl create mode 100755 tools/hdi-gen/test/java_test/array_test/v1_0/IArrayTest.idl create mode 100755 tools/hdi-gen/test/java_test/cb_test/v1_0/ICallback.idl create mode 100755 tools/hdi-gen/test/java_test/cb_test/v1_0/ICbTest.idl create mode 100755 tools/hdi-gen/test/java_test/data_test/v1_0/IDataTest.idl create mode 100755 tools/hdi-gen/test/java_test/list_test/v1_0/IListTest.idl create mode 100755 tools/hdi-gen/test/java_test/map_test/v1_0/IMapTest.idl create mode 100755 tools/hdi-gen/util/Makefile create mode 100755 tools/hdi-gen/util/autoptr.h create mode 100755 tools/hdi-gen/util/file.cpp create mode 100755 tools/hdi-gen/util/file.h create mode 100755 tools/hdi-gen/util/light_refcount_base.cpp create mode 100755 tools/hdi-gen/util/light_refcount_base.h create mode 100755 tools/hdi-gen/util/logger.cpp create mode 100755 tools/hdi-gen/util/logger.h create mode 100755 tools/hdi-gen/util/options.cpp create mode 100755 tools/hdi-gen/util/options.h create mode 100755 tools/hdi-gen/util/string.cpp create mode 100755 tools/hdi-gen/util/string.h create mode 100755 tools/hdi-gen/util/string_builder.cpp create mode 100755 tools/hdi-gen/util/string_builder.h diff --git a/tools/hdi-gen/LICENSE b/tools/hdi-gen/LICENSE new file mode 100755 index 000000000..b76f76aa7 --- /dev/null +++ b/tools/hdi-gen/LICENSE @@ -0,0 +1,51 @@ +HDF - Hardware Driver Foundation +Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. + +HDF is dual licensed: you can use it either under the terms of +the GPL V2, or the BSD3 license, at your option. +a) GNU General Public License version 2, (https://opensource.org/licenses/GPL-2.0) +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public +License along with this library; if not, write to the Free +Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301 USA + +Alternatively, +b) The BSD3 License, (https://opensource.org/licenses/BSD-3-Clause) +Redistribution and use in source and binary forms, with or +without modification, are permitted provided that the following +conditions are met: + +1. Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. +2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/tools/hdi-gen/Makefile b/tools/hdi-gen/Makefile new file mode 100755 index 000000000..223697901 --- /dev/null +++ b/tools/hdi-gen/Makefile @@ -0,0 +1,46 @@ +TARGET = hdi-gen + +PWD:=$(shell pwd) +export BUILD_DIR = $(PWD)/build +export BOUNDS_CHECK_LIB := $(abspath ../../../../third_party/bounds_checking_function) +export INCLUDES = -I$(PWD) -I$(BOUNDS_CHECK_LIB)/include +export CXXFLAGS = -std=c++14 -O2 +export Q := @ +export MAKEFLAGS += --no-print-directory + +BOUNDS_CHECK_SOURCE := $(wildcard $(BOUNDS_CHECK_LIB)/src/*.c) +BOUNDS_CHECK_BUILD := $(BUILD_DIR)/bounds_checking_function +BOUNDS_CHECK_OBJS := $(addprefix $(BOUNDS_CHECK_BUILD)/, $(patsubst %.c, %.o, $(notdir $(BOUNDS_CHECK_SOURCE)))) +BOUNDS_CHECK_TARGET := $(BOUNDS_CHECK_BUILD)/bounds_checking_function.a + +SOURCE := $(wildcard *.cpp) +OBJS := $(addprefix $(BUILD_DIR)/, $(patsubst %.cpp, %.o, $(SOURCE))) + +SUBDIRS = util ast parser codegen +LIBS = $(BUILD_DIR)/codegen/codegen.a $(BUILD_DIR)/parser/parser.a $(BUILD_DIR)/ast/ast.a $(BUILD_DIR)/util/util.a + +all:$(TARGET) + +$(TARGET): $(OBJS) | $(BOUNDS_CHECK_TARGET) + $(Q) for subdir in $(SUBDIRS); do \ + $(MAKE) -C $$subdir || exit 1; \ + done + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $@ $(LIBS) $(BOUNDS_CHECK_TARGET) + $(Q) echo $(TARGET):build successful. + +$(OBJS):$(SOURCE) + $(Q) mkdir -p $(BUILD_DIR) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ + +$(BOUNDS_CHECK_TARGET):$(BOUNDS_CHECK_OBJS) + $(Q) echo $(BOUNDS_CHECK_TARGET) + $(Q) ar -rc $@ $^ + +$(BOUNDS_CHECK_BUILD)/%.o : $(BOUNDS_CHECK_LIB)/src/%.c + $(Q) mkdir -p $(BOUNDS_CHECK_BUILD) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ + +clean: + $(Q) rm -rf $(BUILD_DIR) $(TARGET) + +.PHONY:all clean \ No newline at end of file diff --git a/tools/hdi-gen/README.md b/tools/hdi-gen/README.md new file mode 100755 index 000000000..cc6b7f1e9 --- /dev/null +++ b/tools/hdi-gen/README.md @@ -0,0 +1,48 @@ +# HDI-GEN + - [Introduction](#introduction) + - [Usage](#Usage) + +## Introduction +HDI-GEN is a part of the HDF development suite and is used to convert the HDI interface description language into target source code (C/CPP and Java) that can be compiled and executed during compilation. + + +## Usage +**Show help** +```shell +$./hdi-gen --help +Compile a .idl file and generate C/C++ and Java codes. +Usage: idl [options] file +Options: + --help Display command line options + --version Display toolchain version information + --hash Display hash key of the idl file + --dump-ast Display the AST of the compiled file + -c Compile the .idl file + --gen-c Generate C codes + --gen-cpp Generate C++ codes + --gen-java Generate Java codes + -d Place generated codes into + +``` + +**Show version** +```shell +$hdi-gen --version +``` + +**Generates hash-key of the .idl file** +```shell +$hdi-gen -c ./test/ISample.idl --hash +``` + +**Show ast dump of th idl file** +```shell +$hdi-gen -c ./test/ISample.idl --dump-ast +``` + +**Generates c code** +```shell +$hdi-gen -c ./test/ISample.idl --gen-c -d ./out +``` + +Node: It's supported to generates C/C++ and Java code now. \ No newline at end of file diff --git a/tools/hdi-gen/README_zh.md b/tools/hdi-gen/README_zh.md new file mode 100755 index 000000000..b9109261e --- /dev/null +++ b/tools/hdi-gen/README_zh.md @@ -0,0 +1,46 @@ +# HDI-GEN + - [简介](#简介) + - [使用说明](#使用说明) + +## 简介 +HDI-GEN工具属于HDF开发套件的一部分,用于在编译阶段将HDI接口描述语言转换为可以编制执行的目标源码(C/CPP、Java). + +## 使用说明 +查看帮助 +```shell +$./hdi-gen --help +Compile a .idl file and generate C/C++ and Java codes. +Usage: idl [options] file +Options: + --help Display command line options + --version Display toolchain version information + --hash Display hash key of the idl file + --dump-ast Display the AST of the compiled file + -c Compile the .idl file + --gen-c Generate C codes + --gen-cpp Generate C++ codes + --gen-java Generate Java codes + -d Place generated codes into + +``` + +查看版本 +```shell +$hdi-gen --version +``` + +生成.idl文件hash值 +```shell +$hdi-gen -c ./test/ISample.idl --hash +``` + +查看.idl文件dump +```shell +$hdi-gen -c ./test/ISample.idl --dump-ast +``` + +生成C代码 +```shell +$hdi-gen -c ./test/ISample.idl --gen-c -d ./out +``` +注:现支持C、C++、Java代码生成 \ No newline at end of file diff --git a/tools/hdi-gen/ast/Makefile b/tools/hdi-gen/ast/Makefile new file mode 100755 index 000000000..04f71251b --- /dev/null +++ b/tools/hdi-gen/ast/Makefile @@ -0,0 +1,12 @@ +OBJS_DIR:=$(BUILD_DIR)/ast +TARGET = $(OBJS_DIR)/ast.a +SOURCE:=$(wildcard *.cpp) +OBJS:=$(patsubst %.cpp, $(OBJS_DIR)/%.o, $(SOURCE)) + +$(TARGET):$(OBJS) + $(Q) echo $(TARGET) + $(Q) ar -rc $@ $^ + +$(OBJS_DIR)/%.o:%.cpp + $(Q) mkdir -p $(dir $@) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast.cpp b/tools/hdi-gen/ast/ast.cpp new file mode 100755 index 000000000..251e659d8 --- /dev/null +++ b/tools/hdi-gen/ast/ast.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +AST::AST() +{ + types_["boolean"] = new ASTBooleanType(); + types_["byte"] = new ASTByteType(); + types_["short"] = new ASTShortType(); + types_["int"] = new ASTIntegerType(); + types_["long"] = new ASTLongType(); + types_["float"] = new ASTFloatType(); + types_["double"] = new ASTDoubleType(); + types_["String"] = new ASTStringType(); + types_["unsigned char"] = new ASTUcharType(); + types_["unsigned short"] = new ASTUshortType(); + types_["unsigned int"] = new ASTUintType(); + types_["unsigned long"] = new ASTUlongType(); + types_["void"] = new ASTVoidType(); + types_["FileDescriptor"] = new ASTFdType(); +} + +void AST::SetIdlFile(const String& idlFile) +{ + idlFilePath_ = idlFile; +#ifdef __MINGW32__ + int index = idlFilePath_.LastIndexOf('\\'); +#else + int index = idlFilePath_.LastIndexOf('/'); +#endif + int end = (idlFilePath_.LastIndexOf(".idl") == -1) ? + (idlFilePath_.LastIndexOf(".idl")) : (idlFilePath_.LastIndexOf(".idl")); + name_ = idlFilePath_.Substring((index == -1) ? 0 : (index + 1), end); +} + +void AST::SetFullName(const String& fullName) +{ + int index = fullName.LastIndexOf('.'); + if (index != -1) { + packageName_ = fullName.Substring(0, index); + name_ = fullName.Substring(index + 1); + } else { + packageName_ = ""; + name_ = fullName; + } +} + +void AST::SetPackageName(const String& packageName) +{ + packageName_ = packageName; +} + +String AST::GetPackageName() +{ + return packageName_; +} + +AutoPtr AST::ParseNamespace(const String& nspaceStr) +{ + AutoPtr currNspace; + int begin = 0; + int index = 0; + while ((index = nspaceStr.IndexOf('.', begin)) != -1) { + String ns = nspaceStr.Substring(begin, index); + AutoPtr nspace; + if (currNspace == nullptr) { + nspace = FindNamespace(ns); + } else { + nspace = currNspace->FindNamespace(ns); + } + if (nspace == nullptr) { + nspace = new ASTNamespace(ns); + if (currNspace == nullptr) { + AddNamespace(nspace); + } else { + currNspace->AddNamespace(nspace); + } + } + currNspace = nspace; + begin = index + 1; + } + return currNspace; +} + +void AST::AddNamespace(const AutoPtr& nspace) +{ + if (nspace == nullptr) { + return; + } + namespaces_.push_back(nspace); +} + +AutoPtr AST::FindNamespace(const String& nspaceStr) +{ + for (auto nspace : namespaces_) { + if (nspace->ToShortString().Equals(nspaceStr)) { + return nspace; + } + } + return nullptr; +} + +AutoPtr AST::GetNamespace(size_t index) +{ + if (index >= namespaces_.size()) { + return nullptr; + } + + return namespaces_[index]; +} + +void AST::AddInterfaceDef(const AutoPtr& interface) +{ + if (interface == nullptr) { + return; + } + + interfaceDef_ = interface; + AddType(interface.Get()); +} + +void AST::AddSequenceableDef(const AutoPtr& sequenceable) +{ + if (sequenceable == nullptr) { + return; + } + + sequenceableDef_ = sequenceable; + AddType(sequenceable.Get()); +} + +void AST::AddType(const AutoPtr& type) +{ + if (type == nullptr) { + return; + } + + types_[type->ToString()] = type; +} + +AutoPtr AST::FindType(const String& typeName) +{ + if (typeName.IsEmpty()) { + return nullptr; + } + + auto it = types_.find(typeName); + if (it != types_.end()) { + return it->second; + } + + AutoPtr type = nullptr; + for (const auto& importPair : imports_) { + type = importPair.second->FindType(typeName); + if (type != nullptr) { + break; + } + } + return type; +} + +void AST::AddTypeDefinition(const AutoPtr& type) +{ + if (type == nullptr) { + return; + } + + AddType(type); + typeDefinitions_.push_back(type); +} + +AutoPtr AST::GetTypeDefintion(size_t index) +{ + if (index >= typeDefinitions_.size()) { + return nullptr; + } + return typeDefinitions_[index]; +} + +String AST::Dump(const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + sb.Append("AST["); + sb.Append("name: ").Append(name_).Append(" "); + sb.Append("file: ").Append(idlFilePath_); + sb.Append("]\n"); + + sb.Append("pakage ").Append(packageName_).Append(";"); + sb.Append('\n'); + sb.Append('\n'); + + if (imports_.size() > 0) { + for (const auto& import : imports_) { + sb.AppendFormat("import %s;\n", import.first.string()); + } + sb.Append("\n"); + } + + if (typeDefinitions_.size() > 0) { + for (auto type : typeDefinitions_) { + String info = type->Dump(""); + sb.Append(info).Append("\n"); + } + } + + if (interfaceDef_ != nullptr) { + String info = interfaceDef_->Dump(""); + sb.Append(info).Append("\n"); + } + + return sb.ToString(); +} + +bool AST::AddImport(const AutoPtr& importAst) +{ + if (imports_.find(importAst->GetFullName()) != imports_.end()) { + return false; + } + + imports_[importAst->GetFullName()] = importAst; + + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast.h b/tools/hdi-gen/ast/ast.h new file mode 100755 index 000000000..5804b77e8 --- /dev/null +++ b/tools/hdi-gen/ast/ast.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_AST_H +#define OHOS_HDI_AST_H + +#include +#include +#include "ast/ast_boolean_type.h" +#include "ast/ast_byte_type.h" +#include "ast/ast_double_type.h" +#include "ast/ast_fd_type.h" +#include "ast/ast_float_type.h" +#include "ast/ast_integer_type.h" +#include "ast/ast_interface_type.h" +#include "ast/ast_long_type.h" +#include "ast/ast_namespace.h" +#include "ast/ast_node.h" +#include "ast/ast_sequenceable_type.h" +#include "ast/ast_short_type.h" +#include "ast/ast_string_type.h" +#include "ast/ast_uchar_type.h" +#include "ast/ast_ushort_type.h" +#include "ast/ast_uint_type.h" +#include "ast/ast_ulong_type.h" +#include "ast/ast_void_type.h" +#include "ast/ast_enum_type.h" +#include "ast/ast_struct_type.h" +#include "ast/ast_union_type.h" +#include "ast/ast_array_type.h" +#include "ast/ast_list_type.h" +#include "ast/ast_map_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace HDI { +enum class ASTFileType { + AST_IFACE, // this idl file contains class of normal interface + AST_ICALLBACK, // this idl file contains class of callback interface + AST_TYPES, // this idl file contains custom types + AST_SEQUENCEABLE, // this is not an idl file, but a c++/java file +}; + +class AST : public ASTNode { +public: + using StrASTMap = std::unordered_map, StringHashFunc, StringEqualFunc>; + + AST(); + + virtual ~AST() = default; + + void SetAStFileType(ASTFileType fileType) + { + astFileType_ = fileType; + } + + ASTFileType GetASTFileType() + { + return astFileType_; + } + + void SetIdlFile(const String& idlFile); + + inline String GetName() + { + return name_; + } + + void SetFullName(const String& fullName); + + inline String GetFullName() + { + return packageName_ + "." + name_; + } + + inline void SetLicense(const String& license) + { + license_ = license; + } + + inline String GetLicense() + { + return license_; + } + + void SetPackageName(const String& packageName); + + String GetPackageName(); + + AutoPtr ParseNamespace(const String& nspaceStr); + + void AddNamespace(const AutoPtr& nspace); + + AutoPtr FindNamespace(const String& nspaceStr); + + AutoPtr GetNamespace(size_t index); + + inline size_t GetNamespaceNumber() + { + return namespaces_.size(); + } + + void AddInterfaceDef(const AutoPtr& interface); + + inline AutoPtr GetInterfaceDef() + { + return interfaceDef_; + } + + void AddSequenceableDef(const AutoPtr& sequenceable); + + inline AutoPtr GetSequenceableDef() + { + return sequenceableDef_; + } + + void AddType(const AutoPtr& type); + + AutoPtr FindType(const String& typeName); + + using TypeStringMap = std::unordered_map, StringHashFunc, StringEqualFunc>; + + inline const TypeStringMap& GetTypes() const + { + return types_; + } + + inline size_t GetTypeNumber() const + { + return types_.size(); + } + + void AddTypeDefinition(const AutoPtr& type); + + inline size_t GetTypeDefinitionNumber() const + { + return typeDefinitions_.size(); + } + + AutoPtr GetTypeDefintion(size_t index); + + String Dump(const String& prefix) override; + + bool AddImport(const AutoPtr& importAst); + + inline const StrASTMap& GetImports() const + { + return imports_; + } + +private: + ASTFileType astFileType_ = ASTFileType::AST_IFACE; + String name_; + String license_; + String packageName_; + std::vector> namespaces_; + std::vector> typeDefinitions_; + AutoPtr sequenceableDef_ = nullptr; + AutoPtr interfaceDef_ = nullptr; + + StrASTMap imports_; + TypeStringMap types_; + + String idlFilePath_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_AST_H diff --git a/tools/hdi-gen/ast/ast_array_type.cpp b/tools/hdi-gen/ast/ast_array_type.cpp new file mode 100755 index 000000000..62e239d39 --- /dev/null +++ b/tools/hdi-gen/ast/ast_array_type.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_array_type.h" + +namespace OHOS { +namespace HDI { +bool ASTArrayType::IsArrayType() +{ + return true; +} + +String ASTArrayType::ToString() +{ + return String::Format("%s[]", elementType_->ToString().string()); +} + +TypeKind ASTArrayType::GetTypeKind() +{ + return TypeKind::TYPE_ARRAY; +} + +String ASTArrayType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s*", elementType_->EmitCType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_IN: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + return String::Format("%s*", elementType_->EmitCType(TypeMode::NO_MODE).string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return String::Format("%s", elementType_->EmitCType(TypeMode::PARAM_IN).string()); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::PARAM_IN).string()); + } + } + case TypeMode::PARAM_OUT: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return elementType_->EmitCType(TypeMode::PARAM_OUT); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::PARAM_OUT).string()); + } + } + case TypeMode::LOCAL_VAR: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return String::Format("%s", elementType_->EmitCType(TypeMode::LOCAL_VAR).string()); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::LOCAL_VAR).string()); + } + } + default: + return "unknow type"; + } +} + +String ASTArrayType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("std::vector<%s>", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_IN: + return String::Format("const std::vector<%s>&", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_OUT: + return String::Format("std::vector<%s>&", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::LOCAL_VAR: + return String::Format("std::vector<%s>", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + default: + return "unknow type"; + } +} + +String ASTArrayType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return String::Format("%s[]", elementType_->EmitJavaType(TypeMode::NO_MODE, false).string()); +} + +void ASTArrayType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + + String elementName; + String elementReadName; + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + elementName = String::Format("%s[i]", name.string()); + elementReadName = "&" + elementName; + } else { + elementName = String::Format("%s[i]", name.string()); + elementReadName = elementName; + } + + elementType_->EmitCProxyWriteVar(parcelName, elementReadName, gotoLabel, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %sLen)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string(), name.string()); + + String element; + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + element = String::Format("&%s[i]", name.string()); + } else { + element = String::Format("%s[i]", name.string()); + } + + elementType_->EmitCStubWriteVar(parcelName, element, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, %s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix).AppendFormat("*%s = (%s*)OsalMemAlloc(sizeof(%s) * (*%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).AppendFormat("}\n"); + } else { + sb.Append(prefix).AppendFormat("*%s = (%s*)OsalMemCalloc(sizeof(%s) * (*%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).AppendFormat("}\n"); + } + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < *%s; i++) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String cpName = String::Format("%sCp", name.string()); + elementType_->EmitCProxyReadVar(parcelName, cpName, true, gotoLabel, sb, prefix + TAB); + sb.Append(prefix).Append(TAB).AppendFormat("(*%s)[i] = strdup(%sCp);\n", + name.string(), name.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("&(*%s)[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCProxyReadVar(parcelName, elementCp, true, gotoLabel, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("(void)memcpy_s(%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR) { + String element = String::Format("(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } else { + String element = String::Format("&(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, &%s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + + sb.Append(prefix).AppendFormat("if (%s > 0) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB).AppendFormat("%s = (%s*)OsalMemAlloc(sizeof(%s) * (%s));\n", name.string(), + elementType_->EmitCType().string(), elementType_->EmitCType().string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("goto errors;\n"); + sb.Append(prefix + TAB).AppendFormat("}\n"); + } else { + sb.Append(prefix + TAB).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s) * (%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("goto errors;\n"); + sb.Append(prefix + TAB).AppendFormat("}\n"); + } + + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String element = String::Format("%sCp", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + sb.Append(prefix + TAB + TAB).AppendFormat("%s[i] = strdup(%sCp);\n", name.string(), name.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("%s[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCStubReadVar(parcelName, elementCp, sb, prefix + TAB + TAB); + sb.Append(prefix + TAB + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR) { + String element = String::Format("%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } else { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s.size() failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + elementType_->EmitCppWriteVar(parcelName, elementName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i%d = 0; i%d < %sSize; ++i%d) {\n", + innerLevel, innerLevel, name.string(), innerLevel); + + String valueName = String::Format("value%d", innerLevel++); + elementType_->EmitCppReadVar(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(data, %sLen)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %sLen failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + + String elementName = String::Format("(%s)[i]", name.string()); + elementType_->EmitCMarshalling(elementName, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(data, &%s)) {\n", lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", lenName.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("if (%s > 0) {\n", lenName.string()); + String newPrefix = prefix + TAB; + + sb.Append(newPrefix).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s) * %s);\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), lenName.string()); + sb.Append(newPrefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(newPrefix + TAB).AppendFormat("goto errors;\n"); + sb.Append(newPrefix).Append("}\n"); + freeObjStatements.push_back(String::Format("OsalMemFree(%s);\n", name.string())); + sb.Append(newPrefix).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String element = String::Format("%sElement", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + sb.Append(newPrefix).Append(TAB).AppendFormat("%s[i] = strdup(%s);\n", + name.string(), element.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("%s[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCUnMarshalling(elementCp, sb, newPrefix + TAB, freeObjStatements); + sb.Append(newPrefix + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else { + String element = String::Format("%s[i]", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + } + sb.Append(newPrefix).Append("}\n"); + sb.Append(prefix).Append("}\n"); + freeObjStatements.pop_back(); +} + +void ASTArrayType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s.size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + elementType_->EmitCppMarshalling(parcelName, elementName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + int index = name.IndexOf('.', 0); + String memberName = name.Substring(index + 1); + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), memberName.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", + memberName.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i%d = 0; i%d < %sSize; ++i%d) {\n", + innerLevel, innerLevel, memberName.string(), innerLevel); + + String valueName = String::Format("value%d", innerLevel++); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("%s %s;\n", + elementType_->EmitCppType().string(), valueName.string()); + elementType_->EmitCppUnMarshalling(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append(prefix + TAB).AppendFormat("%s %s;\n", + elementType_->EmitCppType().string(), valueName.string()); + String cpName = String::Format("%sCp", valueName.string()); + elementType_->EmitCppUnMarshalling(parcelName, cpName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + valueName.string(), elementType_->EmitCppType().string(), cpName.string(), + elementType_->EmitCppType().string()); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } else { + elementType_->EmitCppUnMarshalling(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_array_type.h b/tools/hdi-gen/ast/ast_array_type.h new file mode 100755 index 000000000..bd1c50f1d --- /dev/null +++ b/tools/hdi-gen/ast/ast_array_type.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTARRAYTYPE_H +#define OHOS_HDI_ASTARRAYTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTArrayType : public ASTType { +public: + inline void SetElementType(const AutoPtr& elementType) + { + elementType_ = elementType; + } + + inline AutoPtr GetElementType() + { + return elementType_; + } + + bool IsArrayType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + AutoPtr elementType_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTARRAYTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_boolean_type.cpp b/tools/hdi-gen/ast/ast_boolean_type.cpp new file mode 100755 index 000000000..924944852 --- /dev/null +++ b/tools/hdi-gen/ast/ast_boolean_type.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_boolean_type.h" + +namespace OHOS { +namespace HDI { +bool ASTBooleanType::IsBooleanType() +{ + return true; +} + +String ASTBooleanType::ToString() +{ + return "boolean"; +} + +TypeKind ASTBooleanType::GetTypeKind() +{ + return TypeKind::TYPE_BOOLEAN; +} + +String ASTBooleanType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "bool"; + case TypeMode::PARAM_IN: + return "bool"; + case TypeMode::PARAM_OUT: + return "bool*"; + case TypeMode::LOCAL_VAR: + return "bool"; + default: + return "unknow type"; + } +} + +String ASTBooleanType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "bool"; + case TypeMode::PARAM_IN: + return "bool"; + case TypeMode::PARAM_OUT: + return "bool&"; + case TypeMode::LOCAL_VAR: + return "bool"; + default: + return "unknow type"; + } +} + +String ASTBooleanType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Boolean" : "boolean"; +} + +void ASTBooleanType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(%s, %s ? 1 : 0)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(%s, %s ? 1 : 0)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(%s, (int8_t *)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(%s, (int8_t *)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteBool(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadBool();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadBool();\n", + name.string(), parcelName.string()); + } +} + +void ASTBooleanType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(data, %s ? 1 : 0)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(data, (int8_t *)&%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteBool(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadBool();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadBool();\n", + name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_boolean_type.h b/tools/hdi-gen/ast/ast_boolean_type.h new file mode 100755 index 000000000..1b42378fb --- /dev/null +++ b/tools/hdi-gen/ast/ast_boolean_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTBOOLEANTYPE_H +#define OHOS_HDI_ASTBOOLEANTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTBooleanType : public ASTType { +public: + bool IsBooleanType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTBOOLEANTYPE_H diff --git a/tools/hdi-gen/ast/ast_byte_type.cpp b/tools/hdi-gen/ast/ast_byte_type.cpp new file mode 100755 index 000000000..a5e59a65a --- /dev/null +++ b/tools/hdi-gen/ast/ast_byte_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_byte_type.h" + +namespace OHOS { +namespace HDI { +bool ASTByteType::IsByteType() +{ + return true; +} + +String ASTByteType::ToString() +{ + return "byte"; +} + +TypeKind ASTByteType::GetTypeKind() +{ + return TypeKind::TYPE_BYTE; +} + +String ASTByteType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int8_t"; + case TypeMode::PARAM_IN: + return "int8_t"; + case TypeMode::PARAM_OUT: + return "int8_t*"; + case TypeMode::LOCAL_VAR: + return "int8_t"; + default: + return "unknow type"; + } +} + +String ASTByteType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int8_t"; + case TypeMode::PARAM_IN: + return "int8_t"; + case TypeMode::PARAM_OUT: + return "int8_t&"; + case TypeMode::LOCAL_VAR: + return "int8_t"; + default: + return "unknow type"; + } +} + +String ASTByteType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Byte" : "byte"; +} + +void ASTByteType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt8(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadInt8();\n", EmitCppType().string(), + name.string(), EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = (%s)%s.ReadInt8();\n", name.string(), + EmitCppType().string(), parcelName.string()); + } +} + +void ASTByteType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt8(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadInt8();\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt8();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_byte_type.h b/tools/hdi-gen/ast/ast_byte_type.h new file mode 100755 index 000000000..7b93a6b46 --- /dev/null +++ b/tools/hdi-gen/ast/ast_byte_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTBYTETYPE_H +#define OHOS_HDI_ASTBYTETYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTByteType : public ASTType { +public: + bool IsByteType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTBYTETYPE_H diff --git a/tools/hdi-gen/ast/ast_double_type.cpp b/tools/hdi-gen/ast/ast_double_type.cpp new file mode 100755 index 000000000..2812b655a --- /dev/null +++ b/tools/hdi-gen/ast/ast_double_type.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_double_type.h" + +namespace OHOS { +namespace HDI { +bool ASTDoubleType::IsDoubleType() +{ + return true; +} + +String ASTDoubleType::ToString() +{ + return "double"; +} + +TypeKind ASTDoubleType::GetTypeKind() +{ + return TypeKind::TYPE_DOUBLE; +} + +String ASTDoubleType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "double"; + case TypeMode::PARAM_IN: + return "double"; + case TypeMode::PARAM_OUT: + return "double*"; + case TypeMode::LOCAL_VAR: + return "double"; + default: + return "unknow type"; + } +} + +String ASTDoubleType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "double"; + case TypeMode::PARAM_IN: + return "double"; + case TypeMode::PARAM_OUT: + return "double&"; + case TypeMode::LOCAL_VAR: + return "double"; + default: + return "unknow type"; + } +} + +String ASTDoubleType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Double" : "double"; +} + +void ASTDoubleType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteDouble(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteDouble(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadDouble(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadDouble(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteDouble(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadDouble();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadDouble();\n", name.string(), parcelName.string()); + } +} + +void ASTDoubleType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteDouble(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadDouble(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteDouble(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadDouble();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadDouble();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_double_type.h b/tools/hdi-gen/ast/ast_double_type.h new file mode 100755 index 000000000..266082c17 --- /dev/null +++ b/tools/hdi-gen/ast/ast_double_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTDOUBLETYPE_H +#define OHOS_HDI_ASTDOUBLETYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTDoubleType : public ASTType { +public: + bool IsDoubleType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + virtual void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTDOUBLETYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_enum_type.cpp b/tools/hdi-gen/ast/ast_enum_type.cpp new file mode 100755 index 000000000..829437078 --- /dev/null +++ b/tools/hdi-gen/ast/ast_enum_type.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_enum_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTEnumType::SetBaseType(const AutoPtr& baseType) +{ + if (baseType == nullptr) { + return; + } + baseType_ = baseType; +} + +void ASTEnumType::AddMember(const AutoPtr& member) +{ + members_.push_back(member); +} + +bool ASTEnumType::IsEnumType() +{ + return true; +} + +String ASTEnumType::ToString() +{ + return "enum " + name_; +} + +String ASTEnumType::Dump(const String& prefix) +{ + StringBuilder sb; + + std::vector attributes; + if (isFull_) attributes.push_back("full"); + if (isLite_) attributes.push_back("lite"); + if (attributes.size() > 0) { + sb.Append("["); + for (size_t i = 0; i < attributes.size(); i++) { + sb.Append(attributes[i]); + if (i < attributes.size() - 1) { + sb.Append(','); + } + } + sb.Append("] "); + } + + if (isDisplayBase_ && baseType_ != nullptr) { + sb.AppendFormat("enum %s : %s {\n", name_.string(), baseType_->ToString().string()); + } else { + sb.AppendFormat("enum %s {\n", name_.string()); + } + + if (members_.size() > 0) { + for (auto it : members_) { + if (it->isDefaultValue()) { + sb.Append(" ").AppendFormat("%s,\n", it->GetName().string()); + } else { + sb.Append(" ").AppendFormat("%s = %lu,\n", it->GetName().string(), it->GetValue()); + } + } + } + + sb.Append(prefix).Append("};\n"); + + return sb.ToString(); +} + +TypeKind ASTEnumType::GetTypeKind() +{ + return TypeKind::TYPE_ENUM; +} + +String ASTEnumType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("enum %s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("enum %s", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("enum %s*", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("enum %s", name_.string()); + default: + return "unknow type"; + } +} + +String ASTEnumType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("%s", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("%s&", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("%s", name_.string()); + default: + return "unknow type"; + } +} + +String ASTEnumType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // currently, Java does not support the enum type. + return "/"; +} + +String ASTEnumType::EmitCTypeDecl() const +{ + StringBuilder sb; + sb.AppendFormat("enum %s {\n", name_.string()); + + for (auto it : members_) { + if (it->isDefaultValue()) { + sb.Append(" ").AppendFormat("%s,\n", it->GetName().string()); + } else { + sb.Append(" ").AppendFormat("%s = %lu,\n", it->GetName().string(), it->GetValue()); + } + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTEnumType::EmitCppTypeDecl() const +{ + StringBuilder sb; + if (isDisplayBase_ && baseType_ != nullptr) { + sb.AppendFormat("enum %s : %s {\n", name_.string(), baseType_->EmitCppType().string()); + } else { + sb.AppendFormat("enum %s {\n", name_.string()); + } + + for (auto it : members_) { + if (it->isDefaultValue()) { + sb.Append(" ").AppendFormat("%s,\n", it->GetName().string()); + } else { + sb.Append(" ").AppendFormat("%s = %lu,\n", it->GetName().string(), it->GetValue()); + } + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTEnumType::EmitJavaTypeDecl() const +{ + StringBuilder sb; + + return sb.ToString(); +} + +void ASTEnumType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, (uint32_t)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, (uint32_t)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, (uint32_t*)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, (uint32_t*)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32((uint32_t)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadUint32();\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = (%s)%s.ReadUint32();\n", + name.string(), EmitCppType().string(), parcelName.string()); + } +} + +void ASTEnumType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt32(data, (int32_t)%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt32(data, (int32_t*)&%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32((uint32_t)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadUint32();\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = (%s)%s.ReadUint32();\n", + name.string(), EmitCppType().string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_enum_type.h b/tools/hdi-gen/ast/ast_enum_type.h new file mode 100755 index 000000000..9d1c3dd75 --- /dev/null +++ b/tools/hdi-gen/ast/ast_enum_type.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTENUMTYPE_H +#define OHOS_HDI_ASTENUMTYPE_H + +#include +#include "ast/ast_type.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class ASTEnumValue : public LightRefCountBase { +public: + ASTEnumValue(const String& name) + :mName_(name), isDefault_(true), mValue_(0) + {} + + inline virtual ~ASTEnumValue() {} + + inline String GetName() + { + return mName_; + } + + inline void SetType(const AutoPtr& type) + { + mType_ = type; + } + + inline AutoPtr GetType() + { + return mType_; + } + + inline void SetValue(unsigned long value) + { + isDefault_ = false; + mValue_ = value; + } + + inline unsigned long GetValue() + { + return mValue_; + } + + inline bool isDefaultValue() + { + return isDefault_; + } + +private: + String mName_; + AutoPtr mType_; + bool isDefault_; + unsigned long mValue_; +}; + +class ASTEnumType : public ASTType { +public: + inline void SetName(const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetFull(bool full) + { + isFull_ = full; + } + + inline bool IsFull() + { + return isFull_; + } + + inline void SetLite(bool lite) + { + isLite_ = lite; + } + + inline bool IsLite() + { + return isLite_; + } + + inline void SetDisplayBase(bool display) + { + isDisplayBase_ = display; + } + + inline bool IsDisplayBase() + { + return isDisplayBase_; + } + + void SetBaseType(const AutoPtr& baseType); + + inline AutoPtr GetBaseType() + { + return baseType_; + } + + void AddMember(const AutoPtr& member); + + inline size_t GetMemberNumber() + { + return members_.size(); + } + + inline AutoPtr GetMember(size_t index) + { + if (index >= members_.size()) { + return nullptr; + } + return members_[index]; + } + + bool IsEnumType() override; + + String ToString() override; + + String Dump(const String& prefix) override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + String EmitCTypeDecl() const; + + String EmitCppTypeDecl() const; + + String EmitJavaTypeDecl() const; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + bool isFull_ = false; + bool isLite_ = false; + bool isDisplayBase_ = false; + AutoPtr baseType_ = nullptr; + + std::vector> members_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTENUMTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_fd_type.cpp b/tools/hdi-gen/ast/ast_fd_type.cpp new file mode 100755 index 000000000..7e36c9d11 --- /dev/null +++ b/tools/hdi-gen/ast/ast_fd_type.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_fd_type.h" + +namespace OHOS { +namespace HDI { +bool ASTFdType::IsFdType() +{ + return true; +} + +String ASTFdType::ToString() +{ + return "FileDescriptor"; +} + +TypeKind ASTFdType::GetTypeKind() +{ + return TypeKind::TYPE_FILEDESCRIPTOR; +} + +String ASTFdType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int"; + case TypeMode::PARAM_IN: + return "int"; + case TypeMode::PARAM_OUT: + return "int*"; + case TypeMode::LOCAL_VAR: + return "int"; + default: + return "unknow type"; + } +} + +String ASTFdType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int"; + case TypeMode::PARAM_IN: + return "int"; + case TypeMode::PARAM_OUT: + return "int&"; + case TypeMode::LOCAL_VAR: + return "int"; + default: + return "unknow type"; + } +} + +String ASTFdType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Integer" : "int"; +} + +void ASTFdType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFileDescriptor(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFileDescriptor(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + if (isInnerType) { + sb.Append(prefix).AppendFormat("%s = HdfSbufReadFileDescriptor(%s);\n", + name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("if (%s < 0) {\n", name.string()); + } else { + sb.Append(prefix).AppendFormat("*%s = HdfSbufReadFileDescriptor(%s);\n", + name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("if (*%s < 0) {\n", name.string()); + } + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("%s = HdfSbufReadFileDescriptor(%s);\n", + name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("if (%s < 0) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteFileDescriptor(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadFileDescriptor();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadFileDescriptor();\n", name.string(), parcelName.string()); + } +} + +void ASTFdType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFileDescriptor(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("%s = HdfSbufReadFileDescriptor(data);\n", name.string()); + sb.Append(prefix).AppendFormat("if (%s < 0) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteFileDescriptor(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadFileDescriptor();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadFileDescriptor();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_fd_type.h b/tools/hdi-gen/ast/ast_fd_type.h new file mode 100755 index 000000000..c73d8911a --- /dev/null +++ b/tools/hdi-gen/ast/ast_fd_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_FDTYPE_H +#define OHOS_HDI_FDTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTFdType : public ASTType { +public: + bool IsFdType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_FDTYPE_H diff --git a/tools/hdi-gen/ast/ast_float_type.cpp b/tools/hdi-gen/ast/ast_float_type.cpp new file mode 100755 index 000000000..701c794a9 --- /dev/null +++ b/tools/hdi-gen/ast/ast_float_type.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_float_type.h" + +namespace OHOS { +namespace HDI { +bool ASTFloatType::IsFloatType() +{ + return true; +} + +String ASTFloatType::ToString() +{ + return "float"; +} + +TypeKind ASTFloatType::GetTypeKind() +{ + return TypeKind::TYPE_FLOAT; +} + +String ASTFloatType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "float"; + case TypeMode::PARAM_IN: + return "float"; + case TypeMode::PARAM_OUT: + return "float*"; + case TypeMode::LOCAL_VAR: + return "float"; + default: + return "unknow type"; + } +} + +String ASTFloatType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "float"; + case TypeMode::PARAM_IN: + return "float"; + case TypeMode::PARAM_OUT: + return "float&"; + case TypeMode::LOCAL_VAR: + return "float"; + default: + return "unknow type"; + } +} + +String ASTFloatType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Float" : "float"; +} + +void ASTFloatType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFloat(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFloat(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadFloat(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadFloat(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteFloat(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadFloat();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadFloat();\n", name.string(), parcelName.string()); + } +} + +void ASTFloatType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFloat(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadFloat(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteFloat(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadFloat();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadFloat();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_float_type.h b/tools/hdi-gen/ast/ast_float_type.h new file mode 100755 index 000000000..f48e5a92e --- /dev/null +++ b/tools/hdi-gen/ast/ast_float_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTFLOATTYPE_H +#define OHOS_HDI_ASTFLOATTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTFloatType : public ASTType { +public: + bool IsFloatType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTFLOATTYPE_H diff --git a/tools/hdi-gen/ast/ast_integer_type.cpp b/tools/hdi-gen/ast/ast_integer_type.cpp new file mode 100755 index 000000000..6bf7e14a5 --- /dev/null +++ b/tools/hdi-gen/ast/ast_integer_type.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_integer_type.h" + +namespace OHOS { +namespace HDI { +bool ASTIntegerType::IsIntegerType() +{ + return true; +} + +String ASTIntegerType::ToString() +{ + return "int"; +} + +TypeKind ASTIntegerType::GetTypeKind() +{ + return TypeKind::TYPE_INT; +} + +String ASTIntegerType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int32_t"; + case TypeMode::PARAM_IN: + return "int32_t"; + case TypeMode::PARAM_OUT: + return "int32_t*"; + case TypeMode::LOCAL_VAR: + return "int32_t"; + default: + return "unknow type"; + } +} + +String ASTIntegerType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int32_t"; + case TypeMode::PARAM_IN: + return "int32_t"; + case TypeMode::PARAM_OUT: + return "int32_t&"; + case TypeMode::LOCAL_VAR: + return "int32_t"; + default: + return "unknow type"; + } +} + +String ASTIntegerType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Integer" : "int"; +} + +void ASTIntegerType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt32(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt32(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt32(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt32(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt32(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadInt32();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt32();\n", name.string(), parcelName.string()); + } +} + +void ASTIntegerType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt32(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt32(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt32(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadInt32();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt32();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_integer_type.h b/tools/hdi-gen/ast/ast_integer_type.h new file mode 100755 index 000000000..fb7724a0d --- /dev/null +++ b/tools/hdi-gen/ast/ast_integer_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTINTEGERTYPE_H +#define OHOS_HDI_ASTINTEGERTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTIntegerType : public ASTType { +public: + bool IsIntegerType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTINTEGERTYPE_H diff --git a/tools/hdi-gen/ast/ast_interface_type.cpp b/tools/hdi-gen/ast/ast_interface_type.cpp new file mode 100755 index 000000000..1a7c64f6e --- /dev/null +++ b/tools/hdi-gen/ast/ast_interface_type.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_interface_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTInterfaceType::SetNamespace(const AutoPtr& nspace) +{ + ASTType::SetNamespace(nspace); + if (namespace_ != nullptr) { + namespace_->AddInterface(this); + } +} + +void ASTInterfaceType::AddMethod(const AutoPtr& method) +{ + if (method == nullptr) { + return; + } + methods_.push_back(method); +} + +AutoPtr ASTInterfaceType::GetMethod(size_t index) +{ + if (index >= methods_.size()) { + return nullptr; + } + + return methods_[index]; +} + +bool ASTInterfaceType::IsInterfaceType() +{ + return true; +} + +String ASTInterfaceType::ToString() +{ + return name_; +} + +String ASTInterfaceType::Dump(const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + + std::vector attributes; + if (isOneWay_) attributes.push_back("oneway"); + if (isCallback_) attributes.push_back("callback"); + if (isFull_) attributes.push_back("full"); + if (isLite_) attributes.push_back("lite"); + if (attributes.size() > 0) { + sb.Append("["); + for (size_t i = 0; i < attributes.size(); i++) { + sb.Append(attributes[i]); + if (i < attributes.size() - 1) { + sb.Append(','); + } + } + sb.Append("] "); + } + + sb.AppendFormat("interface %s {\n", name_.string()); + + for (auto method : methods_) { + String info = method->Dump(prefix + " "); + sb.Append(info); + if (method != methods_[methods_.size() - 1]) { + sb.Append('\n'); + } + } + sb.Append(prefix).Append("}\n"); + + return sb.ToString(); +} + +TypeKind ASTInterfaceType::GetTypeKind() +{ + return TypeKind::TYPE_INTERFACE; +} + +String ASTInterfaceType::GetFullName() const +{ + return namespace_->ToString() + name_; +} + +String ASTInterfaceType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("struct %s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("struct %s*", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("struct %s**", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("struct %s*", name_.string()); + default: + return "unknow type"; + } +} + +String ASTInterfaceType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const sptr<%s>&", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("sptr<%s>&", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("sptr<%s>", name_.string()); + default: + return "unknow type"; + } +} + +String ASTInterfaceType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return name_; +} + +void ASTInterfaceType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (HdfSBufWriteRemoteService(data, %s->remote) != 0) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTInterfaceType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + String remoteName = String::Format("%sRemote", name.string()); + String miName = name_.StartsWith("I") ? name_.Substring(1) : name_; + + sb.Append(prefix).AppendFormat("struct HdfRemoteService *%s = HdfSBufReadRemoteService(data);\n", + remoteName.string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", remoteName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", remoteName.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("%s = %sProxyObtain(%s);\n", + name.string(), miName.string(), remoteName.string()); +} + +void ASTInterfaceType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteRemoteObject(%s->AsObject())) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTInterfaceType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("sptr<%s> %s = iface_cast<%s>(%s.ReadRemoteObject());\n", + name_.string(), name.string(), name_.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = iface_cast<%s>(%s.ReadRemoteObject());\n", + name.string(), name_.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_interface_type.h b/tools/hdi-gen/ast/ast_interface_type.h new file mode 100755 index 000000000..9c38d69a6 --- /dev/null +++ b/tools/hdi-gen/ast/ast_interface_type.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTINTERFACETYPE_H +#define OHOS_HDI_ASTINTERFACETYPE_H + +#include +#include "ast/ast_method.h" +#include "ast/ast_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace HDI { +class ASTInterfaceType : public ASTType { +public: + void SetNamespace(const AutoPtr& nspace) override; + + inline void SetLicense(const String& license) + { + license_ = license; + } + + inline String GetLicense() const + { + return license_; + } + + inline void SetOneWay(bool oneway) + { + isOneWay_ = oneway; + } + + inline bool IsOneWay() + { + return isOneWay_; + } + + inline void SetCallback(bool callback) + { + isCallback_ = callback; + } + + inline bool IsCallback() + { + return isCallback_; + } + + inline void SetFull(bool full) + { + isFull_ = full; + } + + inline bool IsFull() + { + return isFull_; + } + + inline void SetLite(bool lite) + { + isLite_ = lite; + } + + inline bool IsLite() + { + return isLite_; + } + + void AddMethod(const AutoPtr& method); + + AutoPtr GetMethod(size_t index); + + inline size_t GetMethodNumber() + { + return methods_.size(); + } + + bool IsInterfaceType() override; + + String ToString() override; + + String Dump(const String& prefix) override; + + TypeKind GetTypeKind() override; + + String GetFullName() const; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; +private: + String license_; + bool isOneWay_ = false; + bool isCallback_ = false; + bool isFull_ = false; + bool isLite_ = false; + std::vector> methods_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTINTERFACETYPE_H diff --git a/tools/hdi-gen/ast/ast_list_type.cpp b/tools/hdi-gen/ast/ast_list_type.cpp new file mode 100755 index 000000000..8b62d1509 --- /dev/null +++ b/tools/hdi-gen/ast/ast_list_type.cpp @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_list_type.h" + +namespace OHOS { +namespace HDI { +bool ASTListType::IsListType() +{ + return true; +} + +String ASTListType::ToString() +{ + return String::Format("List<%s>", elementType_->ToString().string()); +} + +TypeKind ASTListType::GetTypeKind() +{ + return TypeKind::TYPE_LIST; +} + +String ASTListType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s*", elementType_->EmitCType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_IN: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + return String::Format("%s*", elementType_->EmitCType(TypeMode::NO_MODE).string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return String::Format("%s", elementType_->EmitCType(TypeMode::PARAM_IN).string()); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::PARAM_IN).string()); + } + } + case TypeMode::PARAM_OUT: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return elementType_->EmitCType(TypeMode::PARAM_OUT); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::PARAM_OUT).string()); + } + } + case TypeMode::LOCAL_VAR: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return String::Format("%s", elementType_->EmitCType(TypeMode::LOCAL_VAR).string()); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::LOCAL_VAR).string()); + } + } + default: + return "unknow type"; + } +} + +String ASTListType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("std::vector<%s>", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_IN: + return String::Format("const std::vector<%s>&", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_OUT: + return String::Format("std::vector<%s>&", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::LOCAL_VAR: + return String::Format("std::vector<%s>", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + default: + return "unknow type"; + } +} + +String ASTListType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return String::Format("List<%s>", elementType_->EmitJavaType(mode, true).string()); +} + +void ASTListType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + + String elementName; + String elementReadName; + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + elementName = String::Format("%s[i]", name.string()); + elementReadName = "&" + elementName; + } else { + elementName = String::Format("%s[i]", name.string()); + elementReadName = elementName; + } + + elementType_->EmitCProxyWriteVar(parcelName, elementReadName, gotoLabel, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %sLen)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string(), name.string()); + + String element; + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + element = String::Format("&%s[i]", name.string()); + } else { + element = String::Format("%s[i]", name.string()); + } + elementType_->EmitCStubWriteVar(parcelName, element, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ +String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, %s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix).AppendFormat("*%s = (%s*)OsalMemAlloc(sizeof(%s) * (*%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).AppendFormat("}\n"); + } else { + sb.Append(prefix).AppendFormat("*%s = (%s*)OsalMemCalloc(sizeof(%s) * (*%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).AppendFormat("}\n"); + } + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < *%s; i++) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String cpName = String::Format("%sCp", name.string()); + elementType_->EmitCProxyReadVar(parcelName, cpName, true, gotoLabel, sb, prefix + TAB); + sb.Append(prefix).Append(TAB).AppendFormat("(*%s)[i] = strdup(%sCp);\n", + name.string(), name.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("&(*%s)[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCProxyReadVar(parcelName, elementCp, true, gotoLabel, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("(void)memcpy_s(%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR) { + String element = String::Format("(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } else { + String element = String::Format("&(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, &%s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + + sb.Append(prefix).AppendFormat("if (%s > 0) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB).AppendFormat("%s = (%s*)OsalMemAlloc(sizeof(%s) * (%s));\n", name.string(), + elementType_->EmitCType().string(), elementType_->EmitCType().string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("goto errors;\n"); + sb.Append(prefix + TAB).AppendFormat("}\n"); + } else { + sb.Append(prefix + TAB).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s) * (%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("goto errors;\n"); + sb.Append(prefix + TAB).AppendFormat("}\n"); + } + + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String element = String::Format("%sCp", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + sb.Append(prefix + TAB + TAB).AppendFormat("%s[i] = strdup(%sCp);\n", name.string(), name.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("%s[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCStubReadVar(parcelName, elementCp, sb, prefix + TAB + TAB); + sb.Append(prefix + TAB + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR) { + String element = String::Format("%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } else { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s.size() failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + elementType_->EmitCppWriteVar(parcelName, elementName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i%d = 0; i%d < %sSize; ++i%d) {\n", + innerLevel, innerLevel, name.string(), innerLevel); + + String valueName = String::Format("value%d", innerLevel++); + elementType_->EmitCppReadVar(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(data, %sLen)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %sLen failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + + String elementName = String::Format("(%s)[i]", name.string()); + elementType_->EmitCMarshalling(elementName, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(data, &%s)) {\n", lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", lenName.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + + sb.Append(prefix).AppendFormat("if (%s > 0) {\n", lenName.string()); + String newPrefix = prefix + TAB; + + sb.Append(newPrefix).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s) * %s);\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), lenName.string()); + sb.Append(newPrefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(newPrefix + TAB).AppendFormat("goto errors;\n"); + sb.Append(newPrefix).Append("}\n"); + + freeObjStatements.push_back(String::Format("OsalMemFree(%s);\n", name.string())); + sb.Append(newPrefix).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String element = String::Format("%sElement", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + sb.Append(newPrefix).Append(TAB).AppendFormat("%s[i] = strdup(%s);\n", + name.string(), element.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("%s[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCUnMarshalling(elementCp, sb, newPrefix + TAB, freeObjStatements); + sb.Append(newPrefix + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else { + String element = String::Format("%s[i]", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + } + sb.Append(newPrefix).Append("}\n"); + sb.Append(prefix).Append("}\n"); + freeObjStatements.pop_back(); +} + +void ASTListType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s.size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + elementType_->EmitCppMarshalling(parcelName, elementName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + int index = name.IndexOf('.', 0); + String memberName = name.Substring(index + 1); + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), memberName.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", + memberName.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i%d = 0; i%d < %sSize; ++i%d) {\n", + innerLevel, innerLevel, memberName.string(), innerLevel); + + String valueName = String::Format("value%d", innerLevel++); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("%s %s;\n", + elementType_->EmitCppType().string(), valueName.string()); + elementType_->EmitCppUnMarshalling(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append(prefix + TAB).AppendFormat("%s %s;\n", + elementType_->EmitCppType().string(), valueName.string()); + String cpName = String::Format("%sCp", valueName.string()); + elementType_->EmitCppUnMarshalling(parcelName, cpName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + valueName.string(), elementType_->EmitCppType().string(), cpName.string(), + elementType_->EmitCppType().string()); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } else { + elementType_->EmitCppUnMarshalling(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_list_type.h b/tools/hdi-gen/ast/ast_list_type.h new file mode 100755 index 000000000..c58233d51 --- /dev/null +++ b/tools/hdi-gen/ast/ast_list_type.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTLISTTYPE_H +#define OHOS_HDI_ASTLISTTYPE_H + +#include "ast/ast_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace HDI { +class ASTListType : public ASTType { +public: + inline void SetElementType(const AutoPtr& elementType) + { + elementType_ = elementType; + } + + inline AutoPtr GetElementType() + { + return elementType_; + } + + bool IsListType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + AutoPtr elementType_ = nullptr; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTLISTTYPE_H diff --git a/tools/hdi-gen/ast/ast_long_type.cpp b/tools/hdi-gen/ast/ast_long_type.cpp new file mode 100755 index 000000000..55264732b --- /dev/null +++ b/tools/hdi-gen/ast/ast_long_type.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_long_type.h" + +namespace OHOS { +namespace HDI { +bool ASTLongType::IsLongType() +{ + return true; +} + +String ASTLongType::ToString() +{ + return "long"; +} + +TypeKind ASTLongType::GetTypeKind() +{ + return TypeKind::TYPE_LONG; +} + +String ASTLongType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int64_t"; + case TypeMode::PARAM_IN: + return "int64_t"; + case TypeMode::PARAM_OUT: + return "int64_t*"; + case TypeMode::LOCAL_VAR: + return "int64_t"; + default: + return "unknow type"; + } +} + +String ASTLongType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int64_t"; + case TypeMode::PARAM_IN: + return "int64_t"; + case TypeMode::PARAM_OUT: + return "int64_t&"; + case TypeMode::LOCAL_VAR: + return "int64_t"; + default: + return "unknow type"; + } +} + +String ASTLongType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Long" : "long"; +} + +void ASTLongType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt64(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt64(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt64(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt64(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt64(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadInt64();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt64();\n", name.string(), parcelName.string()); + } +} + +void ASTLongType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt64(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt64(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt64(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadInt64();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt64();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_long_type.h b/tools/hdi-gen/ast/ast_long_type.h new file mode 100755 index 000000000..dde4c8d01 --- /dev/null +++ b/tools/hdi-gen/ast/ast_long_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTLONGTYPE_H +#define OHOS_HDI_ASTLONGTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTLongType : public ASTType { +public: + bool IsLongType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTLONGTYPE_H diff --git a/tools/hdi-gen/ast/ast_map_type.cpp b/tools/hdi-gen/ast/ast_map_type.cpp new file mode 100755 index 000000000..f51f0eba4 --- /dev/null +++ b/tools/hdi-gen/ast/ast_map_type.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_map_type.h" + +namespace OHOS { +namespace HDI { +bool ASTMapType::IsMapType() +{ + return true; +} + +String ASTMapType::ToString() +{ + return String::Format("Map<%s, %s>", keyType_->ToString().string(), valueType_->ToString().string()); +} + +TypeKind ASTMapType::GetTypeKind() +{ + return TypeKind::TYPE_MAP; +} + +String ASTMapType::EmitCType(TypeMode mode) const +{ + // c language has no map type + return "/"; +} + +String ASTMapType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("std::map<%s, %s>", + keyType_->EmitCppType().string(), valueType_->EmitCppType().string()); + case TypeMode::PARAM_IN: + return String::Format("const std::map<%s, %s>&", + keyType_->EmitCppType().string(), valueType_->EmitCppType().string()); + case TypeMode::PARAM_OUT: + return String::Format("std::map<%s, %s>&", + keyType_->EmitCppType().string(), valueType_->EmitCppType().string()); + case TypeMode::LOCAL_VAR: + return String::Format("std::map<%s, %s>", + keyType_->EmitCppType().string(), valueType_->EmitCppType().string()); + default: + return "unknow type"; + } +} + +String ASTMapType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return String::Format("HashMap<%s, %s>", keyType_->EmitJavaType(mode, true).string(), + valueType_->EmitJavaType(mode, true).string()); +} + +void ASTMapType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + String keyName = String::Format("(%s.first)", elementName.string()); + String valueName = String::Format("(%s.second)", elementName.string()); + keyType_->EmitCppWriteVar(parcelName, keyName, sb, prefix + TAB, innerLevel); + valueType_->EmitCppWriteVar(parcelName, valueName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTMapType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sSize; ++i) {\n", name.string()); + + String KeyName = String::Format("key%d", innerLevel); + String valueName = String::Format("value%d", innerLevel); + innerLevel++; + keyType_->EmitCppReadVar(parcelName, KeyName, sb, prefix + TAB, true, innerLevel); + valueType_->EmitCppReadVar(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s[%s] = %s;\n", name.string(), KeyName.string(), valueName.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTMapType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s.size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + String keyName = String::Format("(%s.first)", elementName.string()); + String valName = String::Format("(%s.second)", elementName.string()); + keyType_->EmitCppMarshalling(parcelName, keyName, sb, prefix + TAB, innerLevel); + valueType_->EmitCppMarshalling(parcelName, valName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTMapType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sSize; ++i) {\n", name.string()); + + String KeyName = String::Format("key%d", innerLevel); + String valueName = String::Format("value%d", innerLevel); + innerLevel++; + keyType_->EmitCppUnMarshalling(parcelName, KeyName, sb, prefix + TAB, true, innerLevel); + valueType_->EmitCppUnMarshalling(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s[%s] = %s;\n", + name.string(), KeyName.string(), valueName.string()); + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_map_type.h b/tools/hdi-gen/ast/ast_map_type.h new file mode 100755 index 000000000..44c011a1e --- /dev/null +++ b/tools/hdi-gen/ast/ast_map_type.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTMAPTYPE_H +#define OHOS_HDI_ASTMAPTYPE_H + +#include "ast/ast_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace HDI { +class ASTMapType : public ASTType { +public: + inline void SetKeyType(const AutoPtr& keyType) + { + keyType_ = keyType; + } + + inline AutoPtr GetKeyType() + { + return keyType_; + } + + inline void SetValueType(const AutoPtr& valueType) + { + valueType_ = valueType; + } + + inline AutoPtr GetValueType() + { + return valueType_; + } + + bool IsMapType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + AutoPtr keyType_; + AutoPtr valueType_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTMAPTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_method.cpp b/tools/hdi-gen/ast/ast_method.cpp new file mode 100755 index 000000000..05db4aad1 --- /dev/null +++ b/tools/hdi-gen/ast/ast_method.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_method.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTMethod::AddParameter(const AutoPtr& parameter) +{ + if (parameter == nullptr) { + return; + } + parameters_.push_back(parameter); +} + +AutoPtr ASTMethod::GetParameter(size_t index) +{ + if (index >= parameters_.size()) { + return nullptr; + } + + return parameters_[index]; +} + +String ASTMethod::Dump(const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + + std::vector attributes; + if (isOneWay_) attributes.push_back("oneway"); + if (isFull_) attributes.push_back("full"); + if (isLite_) attributes.push_back("lite"); + if (attributes.size() > 0) { + sb.Append("["); + for (size_t i = 0; i < attributes.size(); i++) { + sb.Append(attributes[i]); + if (i < attributes.size() - 1) { + sb.Append(','); + } + } + sb.Append("] "); + } + + sb.Append(name_).Append('('); + if (parameters_.size() != 0) { + sb.Append('\n'); + for (auto parameter : parameters_) { + String info = parameter->Dump(prefix + " "); + sb.Append(info); + if (parameter != parameters_[parameters_.size() - 1]) { + sb.Append(",\n"); + } + } + } + sb.Append(");\n"); + + return sb.ToString(); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_method.h b/tools/hdi-gen/ast/ast_method.h new file mode 100755 index 000000000..fd157b22d --- /dev/null +++ b/tools/hdi-gen/ast/ast_method.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTMETHOD_H +#define OHOS_HDI_ASTMETHOD_H + +#include +#include "ast/ast_node.h" +#include "ast/ast_parameter.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class ASTMethod : public ASTNode { +public: + + inline void SetName(const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetOneWay(bool oneway) + { + isOneWay_ = oneway; + } + + inline bool IsOneWay() + { + return isOneWay_; + } + + inline void SetFull(bool full) + { + isFull_ = full; + } + + inline bool IsFull() + { + return isFull_; + } + + inline void SetLite(bool lite) + { + isLite_ = lite; + } + + inline bool IsLite() + { + return isLite_; + } + + void AddParameter(const AutoPtr& parameter); + + AutoPtr GetParameter(size_t index); + + inline size_t GetParameterNumber() + { + return parameters_.size(); + } + + String Dump(const String& prefix) override; + +private: + String name_; + bool isOneWay_ = false; + bool isFull_ = false; + bool isLite_ = false; + + std::vector> parameters_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTMETHOD_H diff --git a/tools/hdi-gen/ast/ast_module.cpp b/tools/hdi-gen/ast/ast_module.cpp new file mode 100755 index 000000000..f07c1c57b --- /dev/null +++ b/tools/hdi-gen/ast/ast_module.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_module.h" + +namespace OHOS { +namespace HDI { +void ASTModule::AddAST(const String& astName, const AutoPtr ast) +{ + asts_[astName] = ast; +} + +AutoPtr ASTModule::GetAst(const String& astName) +{ + auto astIter = asts_.find(astName); + if (astIter == asts_.end()) { + return nullptr; + } + return astIter->second; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_module.h b/tools/hdi-gen/ast/ast_module.h new file mode 100755 index 000000000..328f6cd10 --- /dev/null +++ b/tools/hdi-gen/ast/ast_module.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_AST_MODULE_H +#define OHOS_HDI_AST_MODULE_H + +#include +#include "ast/ast.h" + +namespace OHOS { +namespace HDI { +class ASTModule : public LightRefCountBase { +public: + using ASTMap = std::unordered_map, StringHashFunc, StringEqualFunc>; + + void AddAST(const String& astName, const AutoPtr ast); + + AutoPtr GetAst(const String& astName); + + inline const ASTMap& GetAllAsts() const + { + return asts_; + } +private: + // all ast data + ASTMap asts_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_AST_MODULE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_namespace.cpp b/tools/hdi-gen/ast/ast_namespace.cpp new file mode 100755 index 000000000..02355c377 --- /dev/null +++ b/tools/hdi-gen/ast/ast_namespace.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_namespace.h" +#include "ast/ast_interface_type.h" +#include "ast/ast_sequenceable_type.h" + +namespace OHOS { +namespace HDI { +ASTNamespace::ASTNamespace(const String& nspaceStr) + : name_(nspaceStr), + outerNamespace_(nullptr) +{} + +void ASTNamespace::AddNamespace(const AutoPtr& innerNspace) +{ + if (innerNspace == nullptr) { + return; + } + + innerNamespaces_.push_back(innerNspace); + innerNspace->outerNamespace_ = this; +} + +AutoPtr ASTNamespace::FindNamespace(const String& nspaceStr) +{ + if (nspaceStr.IsEmpty()) { + return nullptr; + } + + for (auto nspace : innerNamespaces_) { + if (nspace->name_.Equals(nspaceStr)) { + return nspace; + } + } + return nullptr; +} + +AutoPtr ASTNamespace::GetNamespace(size_t index) +{ + if (index >= innerNamespaces_.size()) { + return nullptr; + } + + return innerNamespaces_[index]; +} + +void ASTNamespace::AddInterface(const AutoPtr& interface) +{ + if (interface == nullptr) { + return; + } + + interfaces_.push_back(interface); +} + +AutoPtr ASTNamespace::GetInterface(size_t index) +{ + if (index >= interfaces_.size()) { + return nullptr; + } + + return interfaces_[index]; +} + +void ASTNamespace::AddSequenceable(const AutoPtr& sequenceable) +{ + if (sequenceable == nullptr) { + return; + } + + sequenceables_.push_back(sequenceable); +} + +AutoPtr ASTNamespace::GetSequenceable(size_t index) +{ + if (index >= sequenceables_.size()) { + return nullptr; + } + + return sequenceables_[index]; +} + +String ASTNamespace::ToString() +{ + String nspaceStr; + ASTNamespace* nspace = this; + while (nspace != nullptr) { + nspaceStr = nspace->name_ + "." + nspaceStr; + nspace = nspace->outerNamespace_; + } + return nspaceStr; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_namespace.h b/tools/hdi-gen/ast/ast_namespace.h new file mode 100755 index 000000000..26944c594 --- /dev/null +++ b/tools/hdi-gen/ast/ast_namespace.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTNAMESPACE_H +#define OHOS_HDI_ASTNAMESPACE_H + +#include +#include "ast/ast_node.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace HDI { +class ASTInterfaceType; +class ASTSequenceableType; + +class ASTNamespace : public ASTNode { +public: + ASTNamespace(const String& nspaceStr); + + virtual ~ASTNamespace() = default; + + inline String GetName() + { + return name_; + } + + void AddNamespace(const AutoPtr& innerNspace); + + AutoPtr FindNamespace(const String& nspaceStr); + + AutoPtr GetNamespace(size_t index); + + inline size_t GetNamespaceNumber() + { + return innerNamespaces_.size(); + } + + void AddInterface(const AutoPtr& interface); + + AutoPtr GetInterface(size_t index); + + inline size_t GetInterfaceNumber() + { + return interfaces_.size(); + } + + void AddSequenceable(const AutoPtr& sequenceable); + + AutoPtr GetSequenceable(size_t index); + + inline size_t GetSequenceableNumber() + { + return sequenceables_.size(); + } + + inline String ToShortString() + { + return name_; + } + + String ToString() override; + +private: + String name_; + ASTNamespace* outerNamespace_; + std::vector> innerNamespaces_; + std::vector> sequenceables_; + std::vector> interfaces_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTNAMESPACE_H diff --git a/tools/hdi-gen/ast/ast_node.cpp b/tools/hdi-gen/ast/ast_node.cpp new file mode 100755 index 000000000..b1cb909d8 --- /dev/null +++ b/tools/hdi-gen/ast/ast_node.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_node.h" + +namespace OHOS { +namespace HDI { +ASTNode::~ASTNode() +{} + +String ASTNode::ToString() +{ + return "ASTNode"; +} + +String ASTNode::Dump(const String& prefix) +{ + return prefix + "ASTNode"; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_node.h b/tools/hdi-gen/ast/ast_node.h new file mode 100755 index 000000000..0aebbaafb --- /dev/null +++ b/tools/hdi-gen/ast/ast_node.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTNODE_H +#define OHOS_HDI_ASTNODE_H + +#include "util/light_refcount_base.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class ASTNode : public LightRefCountBase { +public: + virtual ~ASTNode(); + + virtual String ToString(); + + virtual String Dump(const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTNODE_H diff --git a/tools/hdi-gen/ast/ast_parameter.cpp b/tools/hdi-gen/ast/ast_parameter.cpp new file mode 100755 index 000000000..6247f981d --- /dev/null +++ b/tools/hdi-gen/ast/ast_parameter.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_parameter.h" +#include "ast/ast_array_type.h" +#include "ast/ast_list_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +String ASTParameter::Dump(const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + sb.Append('['); + + if (attribute_ == ParamAttr::PARAM_IN) { + sb.Append("in"); + } else { + sb.Append("out"); + } + + sb.Append("] "); + sb.Append(type_->ToString()).Append(' '); + sb.Append(name_); + + return sb.ToString(); +} + +String ASTParameter::EmitCParameter() +{ + StringBuilder sb; + + switch (type_->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + case TypeKind::TYPE_BYTE: + case TypeKind::TYPE_SHORT: + case TypeKind::TYPE_INT: + case TypeKind::TYPE_LONG: + case TypeKind::TYPE_UCHAR: + case TypeKind::TYPE_USHORT: + case TypeKind::TYPE_UINT: + case TypeKind::TYPE_ULONG: + case TypeKind::TYPE_FLOAT: + case TypeKind::TYPE_DOUBLE: + case TypeKind::TYPE_ENUM: + case TypeKind::TYPE_FILEDESCRIPTOR: + case TypeKind::TYPE_STRING: + case TypeKind::TYPE_INTERFACE: + case TypeKind::TYPE_STRUCT: + case TypeKind::TYPE_UNION: + case TypeKind::TYPE_VOID: { + if (attribute_ == ParamAttr::PARAM_IN) { + return String::Format("%s %s", type_->EmitCType(TypeMode::PARAM_IN).string(), name_.string()); + } else { + return String::Format("%s %s", type_->EmitCType(TypeMode::PARAM_OUT).string(), name_.string()); + } + } + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: { + StringBuilder paramStr; + if (attribute_ == ParamAttr::PARAM_IN) { + paramStr.AppendFormat("%s %s", type_->EmitCType(TypeMode::PARAM_IN).string(), name_.string()); + } else { + paramStr.AppendFormat("%s %s", type_->EmitCType(TypeMode::PARAM_OUT).string(), name_.string()); + } + + if (attribute_ == ParamAttr::PARAM_IN) { + paramStr.AppendFormat(", uint32_t %sLen", name_.string()); + } else { + paramStr.AppendFormat(", uint32_t* %sLen", name_.string()); + } + + return paramStr.ToString(); + } + default: + return String::Format("unknow type %s", name_.string()); + } + + return sb.ToString(); +} + +String ASTParameter::EmitCppParameter() +{ + if (attribute_ == ParamAttr::PARAM_IN) { + return String::Format("%s %s", type_->EmitCppType(TypeMode::PARAM_IN).string(), name_.string()); + } else { + return String::Format("%s %s", type_->EmitCppType(TypeMode::PARAM_OUT).string(), name_.string()); + } +} + +String ASTParameter::EmitJavaParameter() +{ + StringBuilder sb; + switch (type_->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + case TypeKind::TYPE_BYTE: + case TypeKind::TYPE_SHORT: + case TypeKind::TYPE_INT: + case TypeKind::TYPE_LONG: + case TypeKind::TYPE_UCHAR: + case TypeKind::TYPE_USHORT: + case TypeKind::TYPE_UINT: + case TypeKind::TYPE_ULONG: + case TypeKind::TYPE_FLOAT: + case TypeKind::TYPE_DOUBLE: + case TypeKind::TYPE_ENUM: + case TypeKind::TYPE_FILEDESCRIPTOR: + case TypeKind::TYPE_STRING: + case TypeKind::TYPE_SEQUENCEABLE: + case TypeKind::TYPE_INTERFACE: + case TypeKind::TYPE_STRUCT: + case TypeKind::TYPE_UNION: + case TypeKind::TYPE_VOID: + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: + case TypeKind::TYPE_MAP: { + return String::Format("%s %s", type_->EmitJavaType(TypeMode::NO_MODE, false).string(), name_.string()); + } + default: + return String::Format("unknow type %s", name_.string()); + } + + return sb.ToString(); +} + +String ASTParameter::EmitCLocalVar() +{ + StringBuilder sb; + sb.AppendFormat("%s %s", type_->EmitCType(TypeMode::LOCAL_VAR).string(), name_.string()); + switch (type_->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(" = false"); + break; + case TypeKind::TYPE_BYTE: + case TypeKind::TYPE_SHORT: + case TypeKind::TYPE_INT: + case TypeKind::TYPE_LONG: + case TypeKind::TYPE_UCHAR: + case TypeKind::TYPE_USHORT: + case TypeKind::TYPE_UINT: + case TypeKind::TYPE_ULONG: + case TypeKind::TYPE_FLOAT: + case TypeKind::TYPE_DOUBLE: + sb.Append(" = 0"); + break; + case TypeKind::TYPE_STRING: + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: + case TypeKind::TYPE_STRUCT: + case TypeKind::TYPE_UNION: + case TypeKind::TYPE_INTERFACE: + sb.Append(" = NULL"); + break; + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(" = -1"); + break; + default: + break; + } + sb.Append(";"); + return sb.ToString(); +} + +String ASTParameter::EmitCppLocalVar() +{ + StringBuilder sb; + sb.AppendFormat("%s %s", type_->EmitCppType(TypeMode::LOCAL_VAR).string(), name_.string()); + switch (type_->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(" = false"); + break; + case TypeKind::TYPE_BYTE: + case TypeKind::TYPE_SHORT: + case TypeKind::TYPE_INT: + case TypeKind::TYPE_LONG: + case TypeKind::TYPE_UCHAR: + case TypeKind::TYPE_USHORT: + case TypeKind::TYPE_UINT: + case TypeKind::TYPE_ULONG: + case TypeKind::TYPE_FLOAT: + case TypeKind::TYPE_DOUBLE: + sb.Append(" = 0"); + break; + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(" = -1"); + break; + case TypeKind::TYPE_SEQUENCEABLE: + sb.Append(" = nullptr"); + break; + default: + break; + } + sb.Append(";"); + return sb.ToString(); +} + +String ASTParameter::EmitJavaLocalVar() +{ + return ""; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_parameter.h b/tools/hdi-gen/ast/ast_parameter.h new file mode 100755 index 000000000..d2c905198 --- /dev/null +++ b/tools/hdi-gen/ast/ast_parameter.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTPARAMETER_H +#define OHOS_HDI_ASTPARAMETER_H + +#include "ast/ast_node.h" +#include "ast/ast_type.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +// parameter attribute +enum class ParamAttr { + PARAM_IN, + PARAM_OUT, +}; + +class ASTParameter : public ASTNode { +public: + inline void SetName(const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetType(const AutoPtr& type) + { + type_ = type; + } + + inline AutoPtr GetType() + { + return type_; + } + + inline void SetAttribute(ParamAttr attribute) + { + attribute_ = attribute; + } + + inline ParamAttr GetAttribute() + { + return attribute_; + } + + String Dump(const String& prefix) override; + + String EmitCParameter(); + + String EmitCppParameter(); + + String EmitJavaParameter(); + + String EmitCLocalVar(); + + String EmitCppLocalVar(); + + String EmitJavaLocalVar(); +private: + String name_; + AutoPtr type_ = nullptr; + ParamAttr attribute_ = ParamAttr::PARAM_IN; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTPARAMETER_H diff --git a/tools/hdi-gen/ast/ast_sequenceable_type.cpp b/tools/hdi-gen/ast/ast_sequenceable_type.cpp new file mode 100755 index 000000000..da20f21ab --- /dev/null +++ b/tools/hdi-gen/ast/ast_sequenceable_type.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_sequenceable_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTSequenceableType::SetNamespace(const AutoPtr& nspace) +{ + ASTType::SetNamespace(nspace); + if (namespace_ != nullptr) { + namespace_->AddSequenceable(this); + } +} + +bool ASTSequenceableType::IsSequenceableType() +{ + return true; +} + +String ASTSequenceableType::ToString() +{ + return name_; +} + +TypeKind ASTSequenceableType::GetTypeKind() +{ + return TypeKind::TYPE_SEQUENCEABLE; +} + +String ASTSequenceableType::Dump(const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix).Append("sequenceable "); + if (namespace_ != nullptr) { + sb.Append(namespace_->ToString()); + } + sb.Append(name_); + sb.Append(";\n"); + + return sb.ToString(); +} + +String ASTSequenceableType::GetFullName() const +{ + return namespace_->ToString() + name_; +} + +String ASTSequenceableType::EmitCType(TypeMode mode) const +{ + // c language has no Sequenceable type + return "/"; +} + +String ASTSequenceableType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("sptr<%s>", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const sptr<%s>&", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("sptr<%s>&", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("sptr<%s>", name_.string()); + default: + return "unknow type"; + } +} + +String ASTSequenceableType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return name_; +} + +void ASTSequenceableType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteStrongParcelable(%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTSequenceableType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("sptr<%s> %s = %s.ReadStrongParcelable<%s>();\n", + name_.string(), name.string(), parcelName.string(), name_.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadStrongParcelable<%s>();\n", + name.string(), parcelName.string(), name_.string()); + } +} + +void ASTSequenceableType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteStrongParcelable(%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTSequenceableType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadStrongParcelable<%s>();\n", + EmitCppType().string(), name.string(), parcelName.string(), name_.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadStrongParcelable<%s>();\n", + name.string(), parcelName.string(), name_.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_sequenceable_type.h b/tools/hdi-gen/ast/ast_sequenceable_type.h new file mode 100755 index 000000000..92539424b --- /dev/null +++ b/tools/hdi-gen/ast/ast_sequenceable_type.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTSEQUENCEABLETYPE_H +#define OHOS_HDI_ASTSEQUENCEABLETYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTSequenceableType : public ASTType { +public: + void SetNamespace(const AutoPtr& nspace) override; + + bool IsSequenceableType() override; + + String ToString() override; + + String Dump(const String& prefix) override; + + TypeKind GetTypeKind() override; + + String GetFullName() const; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTSEQUENCEABLETYPE_H diff --git a/tools/hdi-gen/ast/ast_short_type.cpp b/tools/hdi-gen/ast/ast_short_type.cpp new file mode 100755 index 000000000..a30e7a101 --- /dev/null +++ b/tools/hdi-gen/ast/ast_short_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_short_type.h" + +namespace OHOS { +namespace HDI { +bool ASTShortType::IsShortType() +{ + return true; +} + +String ASTShortType::ToString() +{ + return "short"; +} + +TypeKind ASTShortType::GetTypeKind() +{ + return TypeKind::TYPE_SHORT; +} + +String ASTShortType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int16_t"; + case TypeMode::PARAM_IN: + return "int16_t"; + case TypeMode::PARAM_OUT: + return "int16_t*"; + case TypeMode::LOCAL_VAR: + return "int16_t"; + default: + return "unknow type"; + } +} + +String ASTShortType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int16_t"; + case TypeMode::PARAM_IN: + return "int16_t"; + case TypeMode::PARAM_OUT: + return "int16_t&"; + case TypeMode::LOCAL_VAR: + return "int16_t"; + default: + return "unknow type"; + } +} + +String ASTShortType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Short" : "short"; +} + +void ASTShortType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt16(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt16(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt16(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt16(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt16(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadInt16();\n", EmitCppType().string(), name.string(), + EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = (%s)%s.ReadInt16();\n", name.string(), EmitCppType().string(), + parcelName.string()); + } +} + +void ASTShortType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt16(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt16(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt16(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadInt16();\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt16();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_short_type.h b/tools/hdi-gen/ast/ast_short_type.h new file mode 100755 index 000000000..b85ff3715 --- /dev/null +++ b/tools/hdi-gen/ast/ast_short_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTSHORTTYPE_H +#define OHOS_HDI_ASTSHORTTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTShortType : public ASTType { +public: + bool IsShortType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTSHORTTYPE_H diff --git a/tools/hdi-gen/ast/ast_string_type.cpp b/tools/hdi-gen/ast/ast_string_type.cpp new file mode 100755 index 000000000..d658766fd --- /dev/null +++ b/tools/hdi-gen/ast/ast_string_type.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_string_type.h" + +namespace OHOS { +namespace HDI { +bool ASTStringType::IsStringType() +{ + return true; +} + +String ASTStringType::ToString() +{ + return "String"; +} + +TypeKind ASTStringType::GetTypeKind() +{ + return TypeKind::TYPE_STRING; +} + +String ASTStringType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "char*"; + case TypeMode::PARAM_IN: + return "const char*"; + case TypeMode::PARAM_OUT: + return "char**"; + case TypeMode::LOCAL_VAR: + return "char*"; + default: + return "unknow type"; + } +} + +String ASTStringType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "std::string"; + case TypeMode::PARAM_IN: + return "const std::string&"; + case TypeMode::PARAM_OUT: + return "std::string&"; + case TypeMode::LOCAL_VAR: + return "std::string"; + default: + return "unknow type"; + } +} + +String ASTStringType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return "String"; +} + +void ASTStringType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteString(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteString(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("const char *%s = HdfSbufReadString(%s);\n", + name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("const char *%s = HdfSbufReadString(%s);\n", + name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteString(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadString();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadString();\n", name.string(), parcelName.string()); + } +} + +void ASTStringType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteString(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("const char *%s = HdfSbufReadString(data);\n", name.string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteString(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadString();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadString();\n", + name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_string_type.h b/tools/hdi-gen/ast/ast_string_type.h new file mode 100755 index 000000000..84f4ff7b0 --- /dev/null +++ b/tools/hdi-gen/ast/ast_string_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTSTRINGTYPE_H +#define OHOS_HDI_ASTSTRINGTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTStringType : public ASTType { +public: + bool IsStringType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTSTRINGTYPE_H diff --git a/tools/hdi-gen/ast/ast_struct_type.cpp b/tools/hdi-gen/ast/ast_struct_type.cpp new file mode 100755 index 000000000..9ce8920aa --- /dev/null +++ b/tools/hdi-gen/ast/ast_struct_type.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_struct_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTStructType::AddMember(const AutoPtr& typeName, String name) +{ + for (auto it : members_) { + if (std::get<0>(it).Equals(name)) { + return; + } + } + members_.push_back(std::make_tuple(name, typeName)); +} + +bool ASTStructType::IsStructType() +{ + return true; +} + +String ASTStructType::ToString() +{ + return "struct " + name_; +} + +String ASTStructType::Dump(const String& prefix) +{ + StringBuilder sb; + sb.Append(prefix); + + std::vector attributes; + if (isFull_) attributes.push_back("full"); + if (isLite_) attributes.push_back("lite"); + if (attributes.size() > 0) { + sb.Append("["); + for (size_t i = 0; i < attributes.size(); i++) { + sb.Append(attributes[i]); + if (i < attributes.size() - 1) { + sb.Append(','); + } + } + sb.Append("] "); + } + + sb.AppendFormat("struct %s {\n", name_.string()); + + if (members_.size() > 0) { + for (auto it : members_) { + sb.Append(prefix + " "); + sb.AppendFormat("%s %s;\n", std::get<1>(it)->ToString().string(), std::get<0>(it).string()); + } + } + + sb.Append(prefix).Append("};\n"); + + return sb.ToString(); +} + +TypeKind ASTStructType::GetTypeKind() +{ + return TypeKind::TYPE_STRUCT; +} + +String ASTStructType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("struct %s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const struct %s*", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("struct %s**", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("struct %s*", name_.string()); + default: + return "unknow type"; + } +} + +String ASTStructType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const %s&", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("%s&", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("%s", name_.string()); + default: + return "unknow type"; + } +} + +String ASTStructType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // currently, Java does not support the struct type. + return "/"; +} + +String ASTStructType::EmitCTypeDecl() const +{ + StringBuilder sb; + sb.AppendFormat("struct %s {\n", name_.string()); + + for (auto it : members_) { + AutoPtr member = std::get<1>(it); + String memberName = std::get<0>(it); + sb.Append(" ").AppendFormat("%s %s;\n", member->EmitCType().string(), memberName.string()); + if (member->GetTypeKind() == TypeKind::TYPE_ARRAY || member->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.Append(" ").AppendFormat("uint32_t %sLen;\n", memberName.string()); + } + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTStructType::EmitCppTypeDecl() const +{ + StringBuilder sb; + sb.AppendFormat("struct %s {\n", name_.string()); + + for (auto it : members_) { + AutoPtr member = std::get<1>(it); + String memberName = std::get<0>(it); + sb.Append(" ").AppendFormat("%s %s;\n", member->EmitCppType().string(), memberName.string()); + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTStructType::EmitJavaTypeDecl() const +{ + StringBuilder sb; + + return sb.ToString(); +} + +void ASTStructType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockMarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockMarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockUnmarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockUnmarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).AppendFormat("}\n"); +} + +void ASTStructType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockMarshalling(%s, %s)) {\n", + EmitCppType().string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat("if (!%sBlockUnmarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockMarshalling(data, &%s)) {\n", + name_.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockUnmarshalling(data, %s)) {\n", + name_.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockMarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockUnmarshalling(data, %s)) {\n", + EmitCppType().string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_struct_type.h b/tools/hdi-gen/ast/ast_struct_type.h new file mode 100755 index 000000000..fb69c3207 --- /dev/null +++ b/tools/hdi-gen/ast/ast_struct_type.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTSTRUCTTYPE_H +#define OHOS_HDI_ASTSTRUCTTYPE_H + +#include +#include +#include "ast/ast_type.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class ASTStructType : public ASTType { +public: + inline void SetName(const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetFull(bool full) + { + isFull_ = full; + } + + inline bool IsFull() + { + return isFull_; + } + + inline void SetLite(bool lite) + { + isLite_ = lite; + } + + inline bool IsLite() + { + return isLite_; + } + + void AddMember(const AutoPtr& typeName, String name); + + inline size_t GetMemberNumber() + { + return members_.size(); + } + + inline String GetMemberName(size_t index) + { + if (index >= members_.size()) { + return String(""); + } + return std::get<0>(members_[index]); + } + + inline AutoPtr GetMemberType(size_t index) + { + if (index >= members_.size()) { + return nullptr; + } + return std::get<1>(members_[index]); + } + + bool IsStructType() override; + + String ToString() override; + + String Dump(const String& prefix) override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + String EmitCTypeDecl() const; + + String EmitCppTypeDecl() const; + + String EmitJavaTypeDecl() const; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + bool isFull_ = false; + bool isLite_ = false; + std::vector>> members_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTSTRUCTTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_type.cpp b/tools/hdi-gen/ast/ast_type.cpp new file mode 100755 index 000000000..6e18d8e08 --- /dev/null +++ b/tools/hdi-gen/ast/ast_type.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +const char* ASTType::TAB = " "; + +void ASTType::SetName(const String& name) +{ + name_ = name; +} + +String ASTType::GetName() +{ + return name_; +} + +void ASTType::SetNamespace(const AutoPtr& nspace) +{ + namespace_ = nspace; +} + +AutoPtr ASTType::GetNamespace() +{ + return namespace_; +} + +bool ASTType::IsBooleanType() +{ + return false; +} + +bool ASTType::IsByteType() +{ + return false; +} + +bool ASTType::IsShortType() +{ + return false; +} + +bool ASTType::IsIntegerType() +{ + return false; +} + +bool ASTType::IsLongType() +{ + return false; +} + +bool ASTType::IsUcharType() +{ + return false; +} + +bool ASTType::IsUshortType() +{ + return false; +} + +bool ASTType::IsUintType() +{ + return false; +} + +bool ASTType::IsUlongType() +{ + return false; +} + +bool ASTType::IsFloatType() +{ + return false; +} + +bool ASTType::IsDoubleType() +{ + return false; +} + +bool ASTType::IsStringType() +{ + return false; +} + +bool ASTType::IsListType() +{ + return false; +} + +bool ASTType::IsMapType() +{ + return false; +} + +bool ASTType::IsEnumType() +{ + return false; +} + +bool ASTType::IsStructType() +{ + return false; +} + +bool ASTType::IsUnionType() +{ + return false; +} + +bool ASTType::IsInterfaceType() +{ + return false; +} + +bool ASTType::IsSequenceableType() +{ + return false; +} + +bool ASTType::IsVoidType() +{ + return false; +} + +bool ASTType::IsArrayType() +{ + return false; +} + +bool ASTType::IsFdType() +{ + return false; +} + +String ASTType::ToShortString() +{ + return name_; +} + +String ASTType::ToString() +{ + return (namespace_ == nullptr) ? name_ : (namespace_->ToString() + name_); +} + +TypeKind ASTType::GetTypeKind() +{ + return TypeKind::TYPE_UNKNOWN; +} + +String ASTType::EmitCType(TypeMode mode) const +{ + return "unknow"; +} + +String ASTType::EmitCppType(TypeMode mode) const +{ + return "unknow"; +} + +String ASTType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return "unknow"; +} + +void ASTType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("//Writeing \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitFreeStatements(const std::vector& freeObjStatements, StringBuilder& sb, + const String& prefix) const +{ + for (auto it = freeObjStatements.rbegin(); it != freeObjStatements.rend(); it++) { + sb.Append(prefix).Append(*it); + } +} + +void ASTType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.string()); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_type.h b/tools/hdi-gen/ast/ast_type.h new file mode 100755 index 000000000..d2fee8085 --- /dev/null +++ b/tools/hdi-gen/ast/ast_type.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTTYPE_H +#define OHOS_HDI_ASTTYPE_H + +#include "ast/ast_namespace.h" +#include "ast/ast_node.h" +#include "util/autoptr.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +enum class TypeKind { + TYPE_UNKNOWN = 0, + TYPE_BOOLEAN, + TYPE_BYTE, + TYPE_SHORT, + TYPE_INT, + TYPE_LONG, + TYPE_FLOAT, + TYPE_DOUBLE, + TYPE_UCHAR, + TYPE_USHORT, + TYPE_UINT, + TYPE_ULONG, + TYPE_STRING, + TYPE_FILEDESCRIPTOR, + TYPE_VOID, + TYPE_SEQUENCEABLE, + TYPE_INTERFACE, + TYPE_LIST, + TYPE_MAP, + TYPE_ARRAY, + TYPE_ENUM, + TYPE_STRUCT, + TYPE_UNION, +}; + +enum class TypeMode { + NO_MODE, // only type + PARAM_IN, // type of the in attribute parameter + PARAM_OUT, // type of the out attribute parameter + LOCAL_VAR, // type of the local variable +}; + +enum class LanguageType { + LANG_C, + LANG_CPP, + LANG_JAVA, +}; + +class ASTType : public ASTNode { +public: + virtual void SetName(const String& name); + + virtual String GetName(); + + virtual void SetNamespace(const AutoPtr& nspace); + + virtual AutoPtr GetNamespace(); + + virtual bool IsBooleanType(); + + virtual bool IsByteType(); + + virtual bool IsShortType(); + + virtual bool IsIntegerType(); + + virtual bool IsLongType(); + + virtual bool IsUcharType(); + + virtual bool IsUshortType(); + + virtual bool IsUintType(); + + virtual bool IsUlongType(); + + virtual bool IsFloatType(); + + virtual bool IsDoubleType(); + + virtual bool IsStringType(); + + virtual bool IsListType(); + + virtual bool IsMapType(); + + virtual bool IsEnumType(); + + virtual bool IsStructType(); + + virtual bool IsUnionType(); + + virtual bool IsInterfaceType(); + + virtual bool IsSequenceableType(); + + virtual bool IsVoidType(); + + virtual bool IsArrayType(); + + virtual bool IsFdType(); + + virtual String ToShortString(); + + String ToString() override; + + virtual TypeKind GetTypeKind(); + + virtual String EmitCType(TypeMode mode = TypeMode::NO_MODE) const; + + virtual String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const; + + virtual String EmitJavaType(TypeMode mode, bool isInnerType = false) const; + + virtual void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const; + + virtual void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const; + + virtual void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const; + + virtual void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const; + + virtual void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const; + + virtual void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const; + + virtual void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const; + + virtual void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const; + + void EmitFreeStatements(const std::vector& freeObjStatements, StringBuilder& sb, + const String& prefix) const; + + virtual void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const; + + virtual void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const; +protected: + static const char* TAB; + String name_; + AutoPtr namespace_; + TypeKind typeKind_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTTYPE_H diff --git a/tools/hdi-gen/ast/ast_uchar_type.cpp b/tools/hdi-gen/ast/ast_uchar_type.cpp new file mode 100755 index 000000000..50e70e516 --- /dev/null +++ b/tools/hdi-gen/ast/ast_uchar_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_uchar_type.h" + +namespace OHOS { +namespace HDI { +bool ASTUcharType::IsUcharType() +{ + return true; +} + +String ASTUcharType::ToString() +{ + return "unsigned char"; +} + +TypeKind ASTUcharType::GetTypeKind() +{ + return TypeKind::TYPE_UCHAR; +} + +String ASTUcharType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint8_t"; + case TypeMode::PARAM_IN: + return "uint8_t"; + case TypeMode::PARAM_OUT: + return "uint8_t*"; + case TypeMode::LOCAL_VAR: + return "uint8_t"; + default: + return "unknow type"; + } +} + +String ASTUcharType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint8_t"; + case TypeMode::PARAM_IN: + return "uint8_t"; + case TypeMode::PARAM_OUT: + return "uint8_t&"; + case TypeMode::LOCAL_VAR: + return "uint8_t"; + default: + return "unknow type"; + } +} + +String ASTUcharType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // unsupported type + return "/"; +} + +void ASTUcharType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint8(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint8(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint8(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint8(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint8(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint8();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint8();\n", name.string(), parcelName.string()); + } +} + +void ASTUcharType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint8(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint8(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint8(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint8();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint8();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_uchar_type.h b/tools/hdi-gen/ast/ast_uchar_type.h new file mode 100755 index 000000000..825b503c6 --- /dev/null +++ b/tools/hdi-gen/ast/ast_uchar_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTUCHARTYPE_H +#define OHOS_HDI_ASTUCHARTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTUcharType : public ASTType { +public: + bool IsUcharType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTUCHARTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_uint_type.cpp b/tools/hdi-gen/ast/ast_uint_type.cpp new file mode 100755 index 000000000..6d27b5499 --- /dev/null +++ b/tools/hdi-gen/ast/ast_uint_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_uint_type.h" + +namespace OHOS { +namespace HDI { +bool ASTUintType::IsUintType() +{ + return true; +} + +String ASTUintType::ToString() +{ + return "unsigned int"; +} + +TypeKind ASTUintType::GetTypeKind() +{ + return TypeKind::TYPE_UINT; +} + +String ASTUintType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint32_t"; + case TypeMode::PARAM_IN: + return "uint32_t"; + case TypeMode::PARAM_OUT: + return "uint32_t*"; + case TypeMode::LOCAL_VAR: + return "uint32_t"; + default: + return "unknow type"; + } +} + +String ASTUintType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint32_t"; + case TypeMode::PARAM_IN: + return "uint32_t"; + case TypeMode::PARAM_OUT: + return "uint32_t&"; + case TypeMode::LOCAL_VAR: + return "uint32_t"; + default: + return "unknow type"; + } +} + +String ASTUintType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // unsupported type + return "/"; +} + +void ASTUintType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint32();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint32();\n", name.string(), parcelName.string()); + } +} + +void ASTUintType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint32();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint32();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_uint_type.h b/tools/hdi-gen/ast/ast_uint_type.h new file mode 100755 index 000000000..97458c444 --- /dev/null +++ b/tools/hdi-gen/ast/ast_uint_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTUINTTYPE_H +#define OHOS_HDI_ASTUINTTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTUintType : public ASTType { +public: + bool IsUintType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTUINTTYPE_H diff --git a/tools/hdi-gen/ast/ast_ulong_type.cpp b/tools/hdi-gen/ast/ast_ulong_type.cpp new file mode 100755 index 000000000..d42fe90b8 --- /dev/null +++ b/tools/hdi-gen/ast/ast_ulong_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_ulong_type.h" + +namespace OHOS { +namespace HDI { +bool ASTUlongType::IsUlongType() +{ + return true; +} + +String ASTUlongType::ToString() +{ + return "unsigned long"; +} + +TypeKind ASTUlongType::GetTypeKind() +{ + return TypeKind::TYPE_ULONG; +} + +String ASTUlongType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint64_t"; + case TypeMode::PARAM_IN: + return "uint64_t"; + case TypeMode::PARAM_OUT: + return "uint64_t*"; + case TypeMode::LOCAL_VAR: + return "uint64_t"; + default: + return "unknow type"; + } +} + +String ASTUlongType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint64_t"; + case TypeMode::PARAM_IN: + return "uint64_t"; + case TypeMode::PARAM_OUT: + return "uint64_t&"; + case TypeMode::LOCAL_VAR: + return "uint64_t"; + default: + return "unknow type"; + } +} + +String ASTUlongType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // unsupported type + return "/"; +} + +void ASTUlongType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint64(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint64(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint64(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint64(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint64(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint64();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint64();\n", name.string(), parcelName.string()); + } +} + +void ASTUlongType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint64(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint64(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint64(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint64();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint64();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_ulong_type.h b/tools/hdi-gen/ast/ast_ulong_type.h new file mode 100755 index 000000000..599ccd294 --- /dev/null +++ b/tools/hdi-gen/ast/ast_ulong_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTULONGTYPE_H +#define OHOS_HDI_ASTULONGTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTUlongType : public ASTType { +public: + bool IsUlongType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTULONGTYPE_H diff --git a/tools/hdi-gen/ast/ast_union_type.cpp b/tools/hdi-gen/ast/ast_union_type.cpp new file mode 100755 index 000000000..dfdf7bd9e --- /dev/null +++ b/tools/hdi-gen/ast/ast_union_type.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_union_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTUnionType::AddMember(const AutoPtr& typeName, String name) +{ + for (auto it : members_) { + if (std::get<0>(it).Equals(name)) { + return; + } + } + members_.push_back(std::make_tuple(name, typeName)); +} + +bool ASTUnionType::IsUnionType() +{ + return true; +} + +String ASTUnionType::ToString() +{ + return "union " + name_; +} + +String ASTUnionType::Dump(const String& prefix) +{ + StringBuilder sb; + sb.Append(prefix); + + std::vector attributes; + if (isFull_) attributes.push_back("full"); + if (isLite_) attributes.push_back("lite"); + if (attributes.size() > 0) { + sb.Append("["); + for (size_t i = 0; i < attributes.size(); i++) { + sb.Append(attributes[i]); + if (i < attributes.size() - 1) { + sb.Append(','); + } + } + sb.Append("] "); + } + + sb.AppendFormat("union %s {\n", name_.string()); + + if (members_.size() > 0) { + for (auto it : members_) { + sb.Append(prefix + " "); + sb.AppendFormat("%s %s;\n", std::get<1>(it)->ToString().string(), std::get<0>(it).string()); + } + } + + sb.Append(prefix).Append("};\n"); + + return sb.ToString(); +} + +TypeKind ASTUnionType::GetTypeKind() +{ + return TypeKind::TYPE_UNION; +} + +String ASTUnionType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("union %s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const union %s*", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("union %s**", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("union %s*", name_.string()); + default: + return "unknow type"; + } +} + +String ASTUnionType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const %s&", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("%s&", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("%s", name_.string()); + default: + return "unknow type"; + } +} + +String ASTUnionType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // unsupported type + return "/"; +} + +String ASTUnionType::EmitCTypeDecl() const +{ + StringBuilder sb; + sb.AppendFormat("union %s {\n", name_.string()); + + for (auto it : members_) { + AutoPtr member = std::get<1>(it); + String memberName = std::get<0>(it); + sb.Append(" ").AppendFormat("%s %s;\n", member->EmitCType().string(), memberName.string()); + if (member->GetTypeKind() == TypeKind::TYPE_ARRAY || member->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.Append(" ").AppendFormat("uint32_t %sLen;\n", memberName.string()); + } + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTUnionType::EmitCppTypeDecl() const +{ + StringBuilder sb; + sb.AppendFormat("union %s {\n", name_.string()); + + for (auto it : members_) { + AutoPtr member = std::get<1>(it); + String memberName = std::get<0>(it); + sb.Append(" ").AppendFormat("%s %s;\n", member->EmitCppType().string(), memberName.string()); + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTUnionType::EmitJavaTypeDecl() const +{ + StringBuilder sb; + + return sb.ToString(); +} + +void ASTUnionType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUnpadBuffer(%s, (const uint8_t *)%s, sizeof(%s))) {\n", + parcelName.string(), name.string(), EmitCType().string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUnpadBuffer(%s, (const uint8_t *)%s, sizeof(%s))) {\n", + parcelName.string(), name.string(), EmitCType().string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("const %s *%s = (%s *)HdfSbufReadUnpadBuffer(%s, sizeof(%s));\n", + EmitCType().string(), name.string(), EmitCType().string(), parcelName.string(), + EmitCType().string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("const %s *%s = (%s *)HdfSbufReadUnpadBuffer(%s, sizeof(%s));\n", + EmitCType().string(), name.string(), EmitCType().string(), parcelName.string(), + EmitCType().string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUnpadBuffer((const uint8_t *)&%s, sizeof(%s))) {\n", + parcelName.string(), name.string(), EmitCppType().string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat( + "const %s *%sCp = reinterpret_cast(%s.ReadUnpadBuffer(sizeof(%s)));\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string(), + EmitCppType().string()); + sb.Append(prefix).AppendFormat("if (%sCp == nullptr) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %sCp, sizeof(%s));\n", + name.string(), EmitCppType().string(), name.string(), EmitCppType().string()); +} + +void ASTUnionType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUnpadBuffer(data, (const uint8_t *)&%s, sizeof(%s))) {\n", + name.string(), EmitCType().string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("const %s *%s = (const %s *)HdfSbufReadUnpadBuffer(data, sizeof(%s));\n", + EmitCType().string(), name.string(), EmitCType().string(), EmitCType().string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUnpadBuffer((const void*)&%s, sizeof(%s))) {\n", + parcelName.string(), name.string(), EmitCppType().string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat( + "const %s *%s = reinterpret_cast(%s.ReadUnpadBuffer(sizeof(%s)));\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string(), + EmitCppType().string()); + sb.Append(prefix).AppendFormat("if (%s == nullptr) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_union_type.h b/tools/hdi-gen/ast/ast_union_type.h new file mode 100755 index 000000000..4d494896a --- /dev/null +++ b/tools/hdi-gen/ast/ast_union_type.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTUNIONTYPE_H +#define OHOS_HDI_ASTUNIONTYPE_H + +#include +#include +#include "ast/ast_type.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class ASTUnionType : public ASTType { +public: + inline void SetName(const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetFull(bool full) + { + isFull_ = full; + } + + inline bool IsFull() + { + return isFull_; + } + + inline void SetLite(bool lite) + { + isLite_ = lite; + } + + inline bool IsLite() + { + return isLite_; + } + + void AddMember(const AutoPtr& typeName, String name); + + inline size_t GetMemberNumber() + { + return members_.size(); + } + + inline String GetMemberName(size_t index) + { + if (index >= members_.size()) { + return String(""); + } + return std::get<0>(members_[index]); + } + + inline AutoPtr GetMemberType(size_t index) + { + if (index >= members_.size()) { + return nullptr; + } + return std::get<1>(members_[index]); + } + + bool IsUnionType() override; + + String ToString() override; + + String Dump(const String& prefix) override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + String EmitCTypeDecl() const; + + String EmitCppTypeDecl() const; + + String EmitJavaTypeDecl() const; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + bool isFull_ = false; + bool isLite_ = false; + std::vector>> members_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTUNIONTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_ushort_type.cpp b/tools/hdi-gen/ast/ast_ushort_type.cpp new file mode 100755 index 000000000..5e81653c6 --- /dev/null +++ b/tools/hdi-gen/ast/ast_ushort_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_ushort_type.h" + +namespace OHOS { +namespace HDI { +bool ASTUshortType::IsUshortType() +{ + return true; +} + +String ASTUshortType::ToString() +{ + return "unsigned short"; +} + +TypeKind ASTUshortType::GetTypeKind() +{ + return TypeKind::TYPE_USHORT; +} + +String ASTUshortType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint16_t"; + case TypeMode::PARAM_IN: + return "uint16_t"; + case TypeMode::PARAM_OUT: + return "uint16_t*"; + case TypeMode::LOCAL_VAR: + return "uint16_t"; + default: + return "unknow type"; + } +} + +String ASTUshortType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint16_t"; + case TypeMode::PARAM_IN: + return "uint16_t"; + case TypeMode::PARAM_OUT: + return "uint16_t&"; + case TypeMode::LOCAL_VAR: + return "uint16_t"; + default: + return "unknow type"; + } +} + +String ASTUshortType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // unsupported type + return "/"; +} + +void ASTUshortType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint16(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint16(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint16(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint16(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint16(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint16();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint16();\n", name.string(), parcelName.string()); + } +} + +void ASTUshortType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint16(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint16(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint16(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint16();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint16();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_ushort_type.h b/tools/hdi-gen/ast/ast_ushort_type.h new file mode 100755 index 000000000..08489189f --- /dev/null +++ b/tools/hdi-gen/ast/ast_ushort_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTUSHORTTYPE_H +#define OHOS_HDI_ASTUSHORTTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTUshortType : public ASTType { +public: + bool IsUshortType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTUSHORTTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_void_type.cpp b/tools/hdi-gen/ast/ast_void_type.cpp new file mode 100755 index 000000000..6c89ee3b4 --- /dev/null +++ b/tools/hdi-gen/ast/ast_void_type.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_void_type.h" + +namespace OHOS { +namespace HDI { +bool ASTVoidType::IsVoidType() +{ + return true; +} + +String ASTVoidType::ToString() +{ + return "void"; +} + +TypeKind ASTVoidType::GetTypeKind() +{ + return TypeKind::TYPE_VOID; +} + +String ASTVoidType::EmitCType(TypeMode mode) const +{ + return "void"; +} + +String ASTVoidType::EmitCppType(TypeMode mode) const +{ + return "void"; +} + +String ASTVoidType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return "void"; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_void_type.h b/tools/hdi-gen/ast/ast_void_type.h new file mode 100755 index 000000000..44a3966ed --- /dev/null +++ b/tools/hdi-gen/ast/ast_void_type.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTVOIDTYPE_H +#define OHOS_HDI_ASTVOIDTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTVoidType : public ASTType { +public: + bool IsVoidType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTBOOLEANTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/Makefile b/tools/hdi-gen/codegen/Makefile new file mode 100755 index 000000000..64ac5af8d --- /dev/null +++ b/tools/hdi-gen/codegen/Makefile @@ -0,0 +1,12 @@ +OBJS_DIR:=$(BUILD_DIR)/codegen +TARGET = $(OBJS_DIR)/codegen.a +SOURCE:=$(wildcard *.cpp) +OBJS:=$(patsubst %.cpp, $(OBJS_DIR)/%.o, $(SOURCE)) + +$(TARGET):$(OBJS) + $(Q) echo $(TARGET) + $(Q) ar -rc $@ $^ + +$(OBJS_DIR)/%.o:%.cpp + $(Q) mkdir -p $(dir $@) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_client_interface_code_emitter.cpp b/tools/hdi-gen/codegen/c_client_interface_code_emitter.cpp new file mode 100755 index 000000000..75aec71e4 --- /dev/null +++ b/tools/hdi-gen/codegen/c_client_interface_code_emitter.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_client_interface_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void CClientInterfaceCodeEmitter::EmitCode() +{ + EmitInterfaceHeaderFile(); +} + +void CClientInterfaceCodeEmitter::EmitInterfaceHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sclient/%s.h", directory_.string(), FileName(interfaceName_).string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(interfaceName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CClientInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, interfaceFullName_); + sb.Append("\n"); + EmitImportInclusions(sb); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitForwardDecls(sb); + sb.Append("\n"); + EmitInterfaceMethodCommands(sb); + sb.Append("\n"); + EmitInterfaceDecl(sb); + sb.Append("\n"); + EmitTailExternC(sb); + sb.Append("\n"); + EmitTailMacro(sb, interfaceFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CClientInterfaceCodeEmitter::EmitImportInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + for (const auto& importPair : ast_->GetImports()) { + AutoPtr importAst = importPair.second; + + String fileName; + if (importAst->GetASTFileType() == ASTFileType::AST_ICALLBACK && importAst->GetInterfaceDef() != nullptr) { + String ifaceName = importAst->GetInterfaceDef()->GetName(); + String name = ifaceName.StartsWith("I") ? ifaceName.Substring(1) : ifaceName; + String stubName = name + "Stub"; + fileName = FileName(importAst->GetInterfaceDef()->GetNamespace()->ToString() + stubName); + } else { + fileName = FileName(importAst->GetFullName()); + } + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } +} + +void CClientInterfaceCodeEmitter::EmitForwardDecls(StringBuilder& sb) +{ + sb.Append("struct HdfRemoteService;\n"); +} + +void CClientInterfaceCodeEmitter::EmitInterfaceDecl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s {\n", interfaceName_.string()); + sb.Append(TAB).Append("struct HdfRemoteService *remote;\n"); + sb.Append("\n"); + EmitInterfaceMethodsDecl(sb, TAB); + sb.Append("};\n"); + if (!isCallbackInterface()) { + sb.Append("\n"); + EmitInterfaceInstanceMethod(sb); + } +} + +void CClientInterfaceCodeEmitter::EmitInterfaceMethodsDecl(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitInterfaceMethodDecl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CClientInterfaceCodeEmitter::EmitInterfaceMethodDecl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t (*%s)(struct %s *self);\n", + method->GetName().string(), interfaceName_.string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t (*%s)(", method->GetName().string()); + paramStr.AppendFormat("struct %s *self, ", interfaceName_.string()); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(");"); + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void CClientInterfaceCodeEmitter::EmitInterfaceInstanceMethod(StringBuilder& sb) +{ + sb.AppendFormat("struct %s *Hdi%sGet();\n", interfaceName_.string(), infName_.string()); + sb.Append("\n"); + sb.AppendFormat("void Hdi%sRelease(struct %s *instance);\n", infName_.string(), interfaceName_.string()); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_client_interface_code_emitter.h b/tools/hdi-gen/codegen/c_client_interface_code_emitter.h new file mode 100755 index 000000000..edf0b2068 --- /dev/null +++ b/tools/hdi-gen/codegen/c_client_interface_code_emitter.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_CLIENT_INTERFACE_CODE_EMITTER_H +#define OHOS_HDI_C_CLIENT_INTERFACE_CODE_EMITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CClientInterfaceCodeEmitter : public CCodeEmitter { +public: + CClientInterfaceCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CCodeEmitter(ast, targetDirectory) {} + + virtual ~CClientInterfaceCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitInterfaceHeaderFile(); + + void EmitImportInclusions(StringBuilder& sb); + + void EmitForwardDecls(StringBuilder& sb); + + void EmitInterfaceDecl(StringBuilder& sb); + + void EmitInterfaceMethodsDecl(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodDecl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitInterfaceInstanceMethod(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_CLIENT_INTERFACE_CODE_EMITTER_H diff --git a/tools/hdi-gen/codegen/c_client_proxy_code_emitter.cpp b/tools/hdi-gen/codegen/c_client_proxy_code_emitter.cpp new file mode 100755 index 000000000..4b9ff996c --- /dev/null +++ b/tools/hdi-gen/codegen/c_client_proxy_code_emitter.cpp @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_client_proxy_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CClientProxyCodeEmitter::CClientProxyCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CCodeEmitter(ast, targetDirectory) +{ + String infFullName = String::Format("%sclient.%s", + interface_->GetNamespace()->ToString().string(), infName_.string()); + sourceFileName_ = String::Format("%s_proxy.c", FileName(infFullName).string()); +} + +void CClientProxyCodeEmitter::EmitCode() +{ + if (isCallbackInterface()) { + EmitCbProxyHeaderFile(); + } + EmitProxySourceFile(); +} + +void CClientProxyCodeEmitter::EmitCbProxyHeaderFile() +{ + String filePath = String::Format("%s%s.h", directory_.string(), FileName(proxyName_).string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("CClientProxyCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, proxyFullName_); + sb.Append("\n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitCbProxyMethodsDcl(sb); + sb.Append("\n"); + EmitTailExternC(sb); + sb.Append("\n"); + EmitTailMacro(sb, proxyFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CClientProxyCodeEmitter::EmitCbProxyMethodsDcl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s *%sProxyObtain(struct HdfRemoteService *remote);\n", + interfaceName_.string(), infName_.string()); + sb.Append("\n"); + sb.AppendFormat("void %sProxyRelease(struct %s *callback);\n", infName_.string(), interfaceName_.string()); +} + +void CClientProxyCodeEmitter::EmitProxySourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sclient/%s.c", directory_.string(), FileName(proxyName_).string()); + } else { + filePath = String::Format("%s%s.c", directory_.string(), FileName(proxyName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CClientProxyCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitProxyInclusions(sb); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitProxyCallMethodImpl(sb); + sb.Append("\n"); + EmitProxyMethodImpls(sb); + sb.Append("\n"); + EmitProxyConstruction(sb); + if (!isCallbackInterface()) { + sb.Append("\n"); + EmitProxyGetMethodImpl(sb); + sb.Append("\n"); + EmitProxyReleaseMethodImpl(sb); + } else { + sb.Append("\n"); + EmitCbProxyObtainMethodImpl(sb); + sb.Append("\n"); + EmitCbProxyReleaseMethodImpl(sb); + } + + sb.Append("\n"); + EmitTailExternC(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CClientProxyCodeEmitter::EmitProxyInclusions(StringBuilder& sb) +{ + if (!isCallbackInterface()) { + EmitProxyStdlibInclusions(sb); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + } else { + sb.AppendFormat("#include \"%s.h\"\n", FileName(proxyName_).string()); + EmitProxyStdlibInclusions(sb); + } +} + +void CClientProxyCodeEmitter::EmitProxyStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CClientProxyCodeEmitter::EmitProxyCallMethodImpl(StringBuilder& sb) +{ + sb.AppendFormat("static int32_t %sProxyCall(struct %s *self, int32_t id, struct HdfSBuf *data,\n", + infName_.string(), interfaceName_.string()); + sb.Append(TAB).Append("struct HdfSBuf *reply)\n"); + sb.Append("{\n"); + sb.Append(TAB).Append("if (self->remote == NULL\n"); + sb.Append(TAB).Append(TAB).Append("|| self->remote->dispatcher == NULL\n"); + sb.Append(TAB).Append(TAB).Append("|| self->remote->dispatcher->Dispatch == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: obj is null\", __func__);\n"); + sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_OBJECT;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append(TAB).Append("return self->remote->dispatcher->Dispatch(self->remote, id, data, reply);\n"); + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder& sb) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitProxyMethodImpl(method, sb); + if (i + 1 != interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb) +{ + if (method->GetParameterNumber() == 0) { + sb.AppendFormat("static int32_t %sProxy%s(struct %s *self)\n", + infName_.string(), method->GetName().string(), interfaceName_.string()); + } else { + StringBuilder paramStr; + paramStr.AppendFormat("static int32_t %sProxy%s(", infName_.string(), method->GetName().string()); + paramStr.AppendFormat("struct %s *self, ", interfaceName_.string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(")"); + sb.Append(SpecificationParam(paramStr, TAB)); + sb.Append("\n"); + } + EmitProxyMethodBody(method, sb, ""); +} + +void CClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("int32_t ec = HDF_FAILURE;\n"); + sb.Append("\n"); + + sb.Append(prefix + TAB).Append("struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_IPC);\n"); + sb.Append(prefix + TAB).Append("struct HdfSBuf *reply = HdfSBufTypedObtain(SBUF_IPC);\n"); + sb.Append("\n"); + + sb.Append(prefix + TAB).Append("if (data == NULL || reply == NULL) {\n"); + sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: HdfSubf malloc failed!\", __func__);\n"); + sb.Append(prefix + TAB + TAB).Append("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB + TAB).Append("goto finished;\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("\n"); + + String gotoName = GetGotLabel(method); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_IN) { + EmitWriteProxyMethodParameter(param, "data", gotoName, sb, prefix + TAB); + sb.Append("\n"); + } + } + + sb.Append(prefix + TAB).AppendFormat("ec = %sCall(self, CMD_%s, data, reply);\n", + proxyName_.string(), ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB).Append("if (ec != HDF_SUCCESS) {\n"); + sb.Append(prefix + TAB + TAB).Append( + "HDF_LOGE(\"%{public}s: call failed! error code is %{public}d\", __func__, ec);\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", gotoName.string()); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("\n"); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_OUT) { + EmitReadProxyMethodParameter(param, "reply", gotoName, sb, prefix + TAB); + sb.Append("\n"); + } + } + + EmitErrorHandle(method, sb, prefix); + + sb.Append(prefix).Append("finished:\n"); + sb.Append(prefix + TAB).Append("if (data != NULL) {\n"); + sb.Append(prefix + TAB + TAB).Append("HdfSBufRecycle(data);\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("if (reply != NULL) {\n"); + sb.Append(prefix + TAB + TAB).Append("HdfSBufRecycle(reply);\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("return ec;\n"); + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitWriteProxyMethodParameter(const AutoPtr& param, + const String& parcelName, const String& gotoLabel, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + type->EmitCProxyWriteVar(parcelName, param->GetName(), gotoLabel, sb, prefix); +} + +void CClientProxyCodeEmitter::EmitReadProxyMethodParameter(const AutoPtr& param, + const String& parcelName, const String& gotoLabel, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + if (type->GetTypeKind() == TypeKind::TYPE_STRING) { + String cloneName = String::Format("%sCopy", param->GetName().string()); + type->EmitCProxyReadVar(parcelName, cloneName, false, gotoLabel, sb, prefix); + String leftVar = String::Format("*%s", param->GetName().string()); + sb.Append(prefix).AppendFormat("%s = strdup(%s);\n", leftVar.string(), cloneName.string()); + } else if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String name = String::Format("*%s", param->GetName().string()); + sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemAlloc(sizeof(%s));\n", + name.string(), type->EmitCType().string(), type->EmitCType().string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + type->EmitCProxyReadVar(parcelName, name, false, gotoLabel, sb, prefix); + } else if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + String cpName = String::Format("%sCp", param->GetName().string()); + type->EmitCProxyReadVar(parcelName, cpName, false, gotoLabel, sb, prefix); + sb.Append(prefix).AppendFormat("*%s = (%s*)OsalMemAlloc(sizeof(%s));\n", + param->GetName().string(), type->EmitCType().string(), type->EmitCType().string()); + sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", param->GetName().string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("(void)memcpy_s(*%s, sizeof(%s), %s, sizeof(%s));\n", + param->GetName().string(), type->EmitCType().string(), cpName.string(), type->EmitCType().string()); + } else { + type->EmitCProxyReadVar(parcelName, param->GetName(), false, gotoLabel, sb, prefix); + } +} + +String CClientProxyCodeEmitter::GetGotLabel(const AutoPtr& method) +{ + String labelName = "finished"; + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + AutoPtr paramType = param->GetType(); + if (param->GetAttribute() == ParamAttr::PARAM_OUT && + (paramType->GetTypeKind() == TypeKind::TYPE_STRING + || paramType->GetTypeKind() == TypeKind::TYPE_ARRAY + || paramType->GetTypeKind() == TypeKind::TYPE_LIST + || paramType->GetTypeKind() == TypeKind::TYPE_STRUCT + || paramType->GetTypeKind() == TypeKind::TYPE_UNION)) { + labelName = "errors"; + break; + } + } + + return labelName; +} + +void CClientProxyCodeEmitter::EmitErrorHandle(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + bool errorLabel = false; + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + AutoPtr paramType = param->GetType(); + if (param->GetAttribute() == ParamAttr::PARAM_OUT && + (paramType->GetTypeKind() == TypeKind::TYPE_STRING + || paramType->GetTypeKind() == TypeKind::TYPE_ARRAY + || paramType->GetTypeKind() == TypeKind::TYPE_LIST + || paramType->GetTypeKind() == TypeKind::TYPE_STRUCT + || paramType->GetTypeKind() == TypeKind::TYPE_UNION)) { + if (!errorLabel) { + sb.Append(prefix + TAB).Append("goto finished;\n"); + sb.Append("\n"); + sb.Append(prefix).Append("errors:\n"); + errorLabel = true; + } + + EmitError(paramType, param->GetName(), sb, prefix + TAB); + sb.Append("\n"); + } + } +} + +void CClientProxyCodeEmitter::EmitError(const AutoPtr& type, const String& name, StringBuilder& sb, + const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: + case TypeKind::TYPE_UNION: { + sb.Append(prefix).AppendFormat("if (*%s != NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(*%s);\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("*%s = NULL;\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (*%s > 0 && *%s != NULL) {\n", lenName.string(), name.string()); + + AutoPtr arrayType = dynamic_cast(type.Get()); + AutoPtr elementType = arrayType->GetElementType(); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < *%s; i++) {\n", lenName.string()); + String elementName = String::Format("(*%s)[i]", name.string()); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else { + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(&%s, false);\n", + elementType->GetName().string(), elementName.string()); + } + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(*%s);\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("*%s = NULL;\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_LIST: { + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (*%s > 0 && *%s != NULL) {\n", lenName.string(), name.string()); + + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < *%s; i++) {\n", lenName.string()); + String elementName = String::Format("(*%s)[i]", name.string()); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else { + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(&%s, false);\n", + elementType->GetName().string(), elementName.string()); + } + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(*%s);\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("*%s = NULL;\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + sb.Append(prefix).AppendFormat("if (*%s != NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("%sFree(*%s, true);\n", type->GetName().string(), name.string()); + sb.Append(prefix + TAB).AppendFormat("*%s = NULL;\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + default: + break; + } +} + + +void CClientProxyCodeEmitter::EmitProxyConstruction(StringBuilder& sb) +{ + String objName; + if (!isCallbackInterface()) { + objName = "inst"; + sb.AppendFormat("static void %sConstruct(struct %s *%s)\n", + infName_.string(), interfaceName_.string(), objName.string()); + } else { + objName = "callback"; + sb.AppendFormat("static void %sProxyConstruct(struct %s *%s)\n", + infName_.string(), interfaceName_.string(), objName.string()); + } + sb.Append("{\n"); + + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + ASTMethod* method = interface_->GetMethod(i); + sb.Append(TAB).AppendFormat("%s->%s = %sProxy%s;\n", + objName.string(), method->GetName().string(), infName_.string(), method->GetName().string()); + } + + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitProxyGetMethodImpl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s *Hdi%sGet()\n", interfaceName_.string(), infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).Append("struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();\n"); + sb.Append(TAB).Append("if (serviceMgr == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: HDIServiceManager not found!\", __func__);\n"); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + + sb.Append(TAB).Append("struct HdfRemoteService *remote = "); + sb.AppendFormat("serviceMgr->GetService(serviceMgr, \"%sService\");\n", infName_.string()); + sb.Append(TAB).Append("HDIServiceManagerRelease(serviceMgr);\n"); + sb.Append(TAB).Append("if (remote == NULL) {\n"); + sb.Append(TAB).Append(TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: %sService not found!\", __func__);\n", infName_.string()); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + + sb.Append(TAB).AppendFormat("struct %s *%sClient = (struct %s *)OsalMemAlloc(sizeof(struct %s));\n", + interfaceName_.string(), infName_.string(), interfaceName_.string(), interfaceName_.string()); + sb.Append(TAB).AppendFormat("if (%sClient == NULL) {\n", infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: malloc %s instance failed!\", __func__);\n", interfaceName_.string()); + sb.Append(TAB).Append(TAB).Append("HdfRemoteServiceRecycle(remote);\n"); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + + sb.Append(TAB).AppendFormat("%sClient->remote = remote;\n", infName_.string()); + sb.Append(TAB).AppendFormat("%sConstruct(%sClient);\n", infName_.string(), infName_.string()); + sb.Append(TAB).AppendFormat("return %sClient;\n", infName_.string()); + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitProxyReleaseMethodImpl(StringBuilder& sb) +{ + sb.AppendFormat("void Hdi%sRelease(struct %s *instance)\n", infName_.string(), interfaceName_.string()); + sb.Append("{\n"); + sb.Append(TAB).Append("if (instance == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("return;\n"); + sb.Append(TAB).Append("}\n"); + + sb.Append(TAB).Append("HdfRemoteServiceRecycle(instance->remote);\n"); + sb.Append(TAB).Append("OsalMemFree(instance);\n"); + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitCbProxyObtainMethodImpl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s *%sProxyObtain(struct HdfRemoteService *remote)\n", + interfaceName_.string(), infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct %s *callback = (struct %s*)OsalMemAlloc(sizeof(struct %s));\n", + interfaceName_.string(), interfaceName_.string(), interfaceName_.string()); + sb.Append(TAB).Append("if (callback == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: OsalMemAlloc failed!\", __func__);\n"); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n\n"); + sb.Append(TAB).Append("callback->remote = remote;\n"); + sb.Append(TAB).AppendFormat("%sProxyConstruct(callback);\n", infName_.string()); + sb.Append(TAB).Append("return callback;\n"); + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitCbProxyReleaseMethodImpl(StringBuilder& sb) +{ + sb.AppendFormat("void %sProxyRelease(struct %s *callback)\n", infName_.string(), interfaceName_.string()); + sb.Append("{\n"); + sb.Append(TAB).Append("if (callback == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("return;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append(TAB).Append("OsalMemFree(callback);\n"); + sb.Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_client_proxy_code_emitter.h b/tools/hdi-gen/codegen/c_client_proxy_code_emitter.h new file mode 100755 index 000000000..8594cfc20 --- /dev/null +++ b/tools/hdi-gen/codegen/c_client_proxy_code_emitter.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_CLIENT_PROXY_CODE_EMITTER_H +#define OHOS_HDI_C_CLIENT_PROXY_CODE_EMITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CClientProxyCodeEmitter : public CCodeEmitter { +public: + CClientProxyCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CClientProxyCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitCbProxyHeaderFile(); + + void EmitProxySourceFile(); + + void EmitCbProxyMethodsDcl(StringBuilder& sb); + + void EmitProxyInclusions(StringBuilder& sb); + + void EmitProxyStdlibInclusions(StringBuilder& sb); + + void EmitProxyCallMethodImpl(StringBuilder& sb); + + void EmitProxyMethodImpls(StringBuilder& sb); + + void EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb); + + void EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitWriteProxyMethodParameter(const AutoPtr& param, const String& parcelName, + const String& gotoLabel, StringBuilder& sb, const String& prefix); + + void EmitReadProxyMethodParameter(const AutoPtr& param, const String& parcelName, + const String& gotoLabel, StringBuilder& sb, const String& prefix); + + String GetGotLabel(const AutoPtr& method); + + void EmitErrorHandle(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitError(const AutoPtr& type, const String& name, StringBuilder& sb, const String& prefix); + + void EmitProxyConstruction(StringBuilder&); + + void EmitProxyGetMethodImpl(StringBuilder& sb); + + void EmitProxyReleaseMethodImpl(StringBuilder& sb); + + void EmitCbProxyObtainMethodImpl(StringBuilder& sb); + + void EmitCbProxyReleaseMethodImpl(StringBuilder& sb); + + std::vector freeObjStatements_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_CLIENT_PROXY_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_code_emitter.cpp b/tools/hdi-gen/codegen/c_code_emitter.cpp new file mode 100755 index 000000000..03c5edcd3 --- /dev/null +++ b/tools/hdi-gen/codegen/c_code_emitter.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_code_emitter.h" +#include +#include +#include + +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +const char* CCodeEmitter::TAB = " "; + +CCodeEmitter::CCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :LightRefCountBase(), ast_(ast), directory_(targetDirectory) +{ + if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) { + interface_ = ast_->GetInterfaceDef(); + } + + if (interface_ != nullptr) { + interfaceName_ = interface_->GetName(); + interfaceFullName_ = interface_->GetNamespace()->ToString() + interfaceName_; + infName_ = interfaceName_.StartsWith("I") ? interfaceName_.Substring(1) : interfaceName_; + proxyName_ = infName_ + "Proxy"; + proxyFullName_ = interface_->GetNamespace()->ToString() + proxyName_; + + stubName_ = infName_ + "Stub"; + stubFullName_ = interface_->GetNamespace()->ToString() + stubName_; + + ImplName_ = infName_ + "Service"; + ImplFullName_ = interface_->GetNamespace()->ToString() + ImplName_; + } else { + infName_ = ast_->GetName(); + } +} + +String CCodeEmitter::FileName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + StringBuilder sb; + + for (int i = 0; i < name.GetLength(); i++) { + char c = name[i]; + if (isupper(c) != 0) { + // 2->Index of the last char array. + if (i > 1 && name[i - 1] != '.' && name[i - 2] != '.') { + sb.Append('_'); + } + sb.Append(tolower(c)); + } else { + sb.Append(c); + } + } + + return sb.ToString().Replace('.', '/'); +} + +void CCodeEmitter::EmitInterfaceMethodCommands(StringBuilder& sb) +{ + sb.Append("enum {\n"); + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(TAB).AppendFormat("CMD_%s,\n", ConstantName(method->GetName()).string()); + } + sb.Append("};\n"); +} + +void CCodeEmitter::EmitInterfaceMethodParameter(const AutoPtr& parameter, StringBuilder& sb, + const String& prefix) +{ + AutoPtr type = parameter->GetType(); + sb.Append(prefix).Append(parameter->EmitCParameter()); +} + +void CCodeEmitter::EmitLicense(StringBuilder& sb) +{ + if (ast_->GetLicense().IsEmpty()) { + return; + } + sb.Append(ast_->GetLicense()).Append("\n\n"); +} + +void CCodeEmitter::EmitHeadMacro(StringBuilder& sb, const String& fullName) +{ + String macroName = MacroName(fullName); + sb.Append("#ifndef ").Append(macroName).Append("\n"); + sb.Append("#define ").Append(macroName).Append("\n"); +} + +void CCodeEmitter::EmitTailMacro(StringBuilder& sb, const String& fullName) +{ + String macroName = MacroName(fullName); + sb.Append("#endif // ").Append(macroName); +} + +void CCodeEmitter::EmitHeadExternC(StringBuilder& sb) +{ + sb.Append("#ifdef __cplusplus\n"); + sb.Append("extern \"C\" {\n"); + sb.Append("#endif /* __cplusplus */\n"); +} + +void CCodeEmitter::EmitTailExternC(StringBuilder& sb) +{ + sb.Append("#ifdef __cplusplus\n"); + sb.Append("}\n"); + sb.Append("#endif /* __cplusplus */\n"); +} + +String CCodeEmitter::MacroName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + String macro = name.Replace('.', '_').ToUpperCase() + "_H"; + return macro; +} + +String CCodeEmitter::ConstantName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + StringBuilder sb; + + for (int i = 0; i < name.GetLength(); i++) { + char c = name[i]; + if (isupper(c) != 0) { + if (i > 1) { + sb.Append('_'); + } + sb.Append(c); + } else { + sb.Append(toupper(c)); + } + } + + return sb.ToString(); +} + +String CCodeEmitter::SpecificationParam(StringBuilder& paramSb, const String& prefix) +{ + int maxLineLen = 120; + int replaceLen = 2; + String paramStr = paramSb.ToString(); + int preIndex = 0; + int curIndex = 0; + + String insertStr = String::Format("\n%s", prefix.string()); + for (; curIndex < paramStr.GetLength(); curIndex++) { + if (curIndex == maxLineLen && preIndex > 0) { + paramStr.Replace(preIndex, replaceLen, ","); + paramStr.insert(preIndex + 1, insertStr); + } else { + if (paramStr[curIndex] == ',') { + preIndex = curIndex; + } + } + } + return paramStr; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_code_emitter.h b/tools/hdi-gen/codegen/c_code_emitter.h new file mode 100755 index 000000000..a067ff799 --- /dev/null +++ b/tools/hdi-gen/codegen/c_code_emitter.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_CODE_EMITTER_H +#define OHOS_HDI_C_CODE_EMITTER_H + +#include +#include "ast/ast.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/string.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +class CCodeEmitter : public LightRefCountBase { +public: + CCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CCodeEmitter() = default; + + virtual void EmitCode() = 0; + + inline String GetSourceFile() + { + return sourceFileName_; + } + + inline bool isInvaildDir() + { + return directory_.Equals(""); + } + + static String FileName(const String& name); + +protected: + + void EmitInterfaceMethodCommands(StringBuilder& sb); + + void EmitInterfaceMethodParameter(const AutoPtr& parameter, StringBuilder& sb, const String& prefix); + + void EmitLicense(StringBuilder& sb); + + void EmitHeadMacro(StringBuilder& sb, const String& fullName); + + void EmitTailMacro(StringBuilder& sb, const String& fullName); + + void EmitHeadExternC(StringBuilder& sb); + + void EmitTailExternC(StringBuilder& sb); + + String MacroName(const String& name); + + String ConstantName(const String& name); + + bool isCallbackInterface() + { + if (interface_ == nullptr) { + return false; + } + + return interface_->IsCallback(); + } + + String SpecificationParam(StringBuilder& sb, const String& prefix); + + static const char* TAB; + + AutoPtr ast_; + AutoPtr interface_; + + String directory_; + String sourceFileName_; + + String interfaceName_; + String interfaceFullName_; + String infName_; + String proxyName_; + String proxyFullName_; + String stubName_; + String stubFullName_; + String ImplName_; + String ImplFullName_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_CODE_EMITTER_H diff --git a/tools/hdi-gen/codegen/c_code_generator.cpp b/tools/hdi-gen/codegen/c_code_generator.cpp new file mode 100755 index 000000000..2fadd06aa --- /dev/null +++ b/tools/hdi-gen/codegen/c_code_generator.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "c_code_generator.h" +#include +#include +#include +#include "codegen/c_client_interface_code_emitter.h" +#include "codegen/c_client_proxy_code_emitter.h" +#include "codegen/c_custom_types_code_emitter.h" +#include "codegen/c_service_driver_code_emitter.h" +#include "codegen/c_service_impl_code_emitter.h" +#include "codegen/c_service_interface_code_emitter.h" +#include "codegen/c_service_stub_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +const char* CCodeGenerator::TAG = "CCodeGenerator"; + +bool CCodeGenerator::Initializate(const AutoPtr& ast, const String& targetDirectory) +{ + ast_ = ast; + targetDirectory_ = targetDirectory; + + if (!ResolveDirectory()) { + return false; + } + + if (ast_->GetASTFileType() == ASTFileType::AST_TYPES) { + AutoPtr customTypesCodeEmitter = new CCustomTypesCodeEmitter(ast_, targetDirectory_); + emitters_.push_back(customTypesCodeEmitter); + return true; + } + + AutoPtr clientInterfaceCodeEmitter = new CClientInterfaceCodeEmitter(ast_, targetDirectory_); + AutoPtr clientProxyCodeEmitter = new CClientProxyCodeEmitter(ast_, targetDirectory_); + + AutoPtr serviceInterfaceCodeEmitter = new CServiceInterfaceCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceDriverCodeEmitter = new CServiceDriverCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceStubCodeEmitter = new CServiceStubCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceImplCodeEmitter = new CServiceImplCodeEmitter(ast_, targetDirectory_); + + emitters_.push_back(clientInterfaceCodeEmitter); + emitters_.push_back(clientProxyCodeEmitter); + emitters_.push_back(serviceInterfaceCodeEmitter); + emitters_.push_back(serviceDriverCodeEmitter); + emitters_.push_back(serviceStubCodeEmitter); + emitters_.push_back(serviceImplCodeEmitter); + + return true; +} + +bool CCodeGenerator::Generate() const +{ + for (auto emitter : emitters_) { + if (!emitter->isInvaildDir()) { + emitter->EmitCode(); + } + } + + return true; +} + +bool CCodeGenerator::ResolveDirectory() +{ + String packageFilePath = String::Format("%s/%s/", + targetDirectory_.string(), CCodeEmitter::FileName(ast_->GetPackageName()).string()); + targetDirectory_ = packageFilePath; + + if (!File::CreateParentDir(targetDirectory_)) { + Logger::E(TAG, "create '%s' directory failed!", targetDirectory_); + return false; + } + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_code_generator.h b/tools/hdi-gen/codegen/c_code_generator.h new file mode 100755 index 000000000..bfdd046de --- /dev/null +++ b/tools/hdi-gen/codegen/c_code_generator.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_CODE_GENERATOR_H +#define OHOS_HDI_C_CODE_GENERATOR_H + +#include "codegen/c_code_emitter.h" +#include "codegen/code_generator.h" + +namespace OHOS { +namespace HDI { +class CCodeGenerator : public CodeGenerator { +public: + CCodeGenerator() : CodeGenerator(), + emitters_() {} + + virtual ~CCodeGenerator() = default; + + bool Initializate(const AutoPtr& ast, const String& targetDirectory) override; + bool Generate() const override; +private: + bool ResolveDirectory() override; + + static const char* TAG; + std::vector> emitters_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_CODE_GENERATOR_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_custom_types_code_emitter.cpp b/tools/hdi-gen/codegen/c_custom_types_code_emitter.cpp new file mode 100755 index 000000000..4cecdd681 --- /dev/null +++ b/tools/hdi-gen/codegen/c_custom_types_code_emitter.cpp @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_custom_types_code_emitter.h" +#include "util/file.h" + +namespace OHOS { +namespace HDI { +void CCustomTypesCodeEmitter::EmitCode() +{ + EmitCustomTypesHeaderFile(); + EmitCustomTypesSourceFile(); +} + +void CCustomTypesCodeEmitter::EmitCustomTypesHeaderFile() +{ + String filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, infName_); + sb.Append("\n"); + EmitHeaderInclusions(sb); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitCustomTypeDecls(sb); + sb.Append("\n"); + EmitCustomTypeFuncDecl(sb); + sb.Append("\n"); + EmitTailExternC(sb); + sb.Append("\n"); + EmitTailMacro(sb, infName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CCustomTypesCodeEmitter::EmitHeaderInclusions(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append("#include \n"); + break; + } + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + EmitCustomTypeDecl(sb, type); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeDecl(StringBuilder& sb, const AutoPtr& type) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_ENUM: { + AutoPtr enumType = dynamic_cast(type.Get()); + sb.Append(enumType->EmitCTypeDecl()).Append("\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + AutoPtr structType = dynamic_cast(type.Get()); + sb.Append(structType->EmitCTypeDecl()).Append("\n"); + break; + } + case TypeKind::TYPE_UNION: { + AutoPtr unionType = dynamic_cast(type.Get()); + sb.Append(unionType->EmitCTypeDecl()).Append("\n"); + break; + } + default: + break; + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + AutoPtr structType = dynamic_cast(type.Get()); + EmitCustomTypeMarshallingDecl(sb, structType); + sb.Append("\n"); + EmitCustomTypeUnmarshallingDecl(sb, structType); + sb.Append("\n"); + EmitCustomTypeFreeDecl(sb, structType); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeMarshallingDecl(StringBuilder& sb, + const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("bool %sBlockMarshalling(struct HdfSBuf *data, const %s *%s);\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); +} + +void CCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingDecl(StringBuilder& sb, + const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("bool %sBlockUnmarshalling(struct HdfSBuf *data, %s *%s);\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); +} + +void CCustomTypesCodeEmitter::EmitCustomTypeFreeDecl(StringBuilder& sb, + const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("void %sFree(%s *%s, bool freeSelf);\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); +} + +void CCustomTypesCodeEmitter::EmitCustomTypesSourceFile() +{ + String filePath = String::Format("%s%s.c", directory_.string(), FileName(infName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitSoucreIncludsions(sb); + sb.Append("\n"); + EmitCustomTypeDataProcess(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CCustomTypesCodeEmitter::EmitSoucreIncludsions(StringBuilder& sb) +{ + sb.AppendFormat("#include \"%s.h\"\n", FileName(infName_).string()); + EmitSourceStdlibInclusions(sb); +} + +void CCustomTypesCodeEmitter::EmitSourceStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT + || type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + AutoPtr structType = dynamic_cast(type.Get()); + EmitCustomTypeMarshallingImpl(sb, structType); + sb.Append("\n"); + EmitCustomTypeUnmarshallingImpl(sb, structType); + sb.Append("\n"); + EmitCustomTypeFreeImpl(sb, structType); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("bool %sBlockMarshalling(struct HdfSBuf *data, const %s *%s)\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); + sb.Append("{\n"); + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + String memberName = type->GetMemberName(i); + AutoPtr memberType = type->GetMemberType(i); + String name = String::Format("%s->%s", objName.string(), memberName.string()); + memberType->EmitCMarshalling(name, sb, TAB); + sb.Append("\n"); + } + + sb.Append(TAB).Append("return true;\n"); + sb.Append("}\n"); +} + +void CCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + freeObjStatements_.clear(); + + sb.AppendFormat("bool %sBlockUnmarshalling(struct HdfSBuf *data, %s *%s)\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); + sb.Append("{\n"); + + sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.string()); + sb.Append(TAB).Append(TAB).Append("return false;\n"); + sb.Append(TAB).Append("}\n"); + + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + AutoPtr memberType = type->GetMemberType(i); + String memberName = type->GetMemberName(i); + String name = String::Format("%s->%s", objName.string(), memberName.string()); + + if (memberType->GetTypeKind() == TypeKind::TYPE_STRING) { + String tmpName = String::Format("%sCp", memberName.string()); + memberType->EmitCUnMarshalling(tmpName, sb, TAB, freeObjStatements_); + sb.Append(TAB).AppendFormat("%s = strdup(%s);\n", name.string(), tmpName.string()); + sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(TAB).Append(TAB).Append("goto errors;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + } else if (memberType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String paramName = String::Format("&%s", name.string()); + memberType->EmitCUnMarshalling(paramName, sb, TAB, freeObjStatements_); + sb.Append("\n"); + } else if (memberType->GetTypeKind() == TypeKind::TYPE_UNION) { + String tmpName = String::Format("%sCp", memberName.string()); + memberType->EmitCUnMarshalling(tmpName, sb, TAB, freeObjStatements_); + sb.Append(TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + name.string(), memberType->EmitCType().string(), + tmpName.string(), memberType->EmitCType().string()); + sb.Append("\n"); + } else if (memberType->GetTypeKind() == TypeKind::TYPE_ARRAY) { + String tmpName = String::Format("%sCp", memberName.string()); + AutoPtr arrayType = dynamic_cast(memberType.Get()); + AutoPtr elementType = arrayType->GetElementType(); + sb.Append(TAB).AppendFormat("%s* %s = NULL;\n", elementType->EmitCType().string(), tmpName.string()); + sb.Append(TAB).AppendFormat("uint32_t %sLen = 0;\n", tmpName.string()); + memberType->EmitCUnMarshalling(tmpName, sb, TAB, freeObjStatements_); + sb.Append(TAB).AppendFormat("%s = %s;\n", name.string(), tmpName.string()); + sb.Append(TAB).AppendFormat("%sLen = %sLen;\n", name.string(), tmpName.string()); + sb.Append("\n"); + } else if (memberType->GetTypeKind() == TypeKind::TYPE_LIST) { + String tmpName = String::Format("%sCp", memberName.string()); + AutoPtr listType = dynamic_cast(memberType.Get()); + AutoPtr elementType = listType->GetElementType(); + sb.Append(TAB).AppendFormat("%s* %s = NULL;\n", elementType->EmitCType().string(), tmpName.string()); + sb.Append(TAB).AppendFormat("uint32_t %sLen = 0;\n", tmpName.string()); + memberType->EmitCUnMarshalling(tmpName, sb, TAB, freeObjStatements_); + sb.Append(TAB).AppendFormat("%s = %s;\n", name.string(), tmpName.string()); + sb.Append(TAB).AppendFormat("%sLen = %sLen;\n", name.string(), tmpName.string()); + sb.Append("\n"); + } else { + memberType->EmitCUnMarshalling(name, sb, TAB, freeObjStatements_); + sb.Append("\n"); + } + } + + sb.Append(TAB).AppendFormat("return true;\n"); + sb.Append("errors:\n"); + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + AutoPtr memberType = type->GetMemberType(i); + String memberName = type->GetMemberName(i); + String name = String::Format("%s->%s", objName.string(), memberName.string()); + EmitError(name, memberType, sb, TAB); + } + + sb.Append(TAB).Append("return false;\n"); + sb.Append("}\n"); +} + + +void CCustomTypesCodeEmitter::EmitError(const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: { + sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + AutoPtr arrayType = dynamic_cast(type.Get()); + AutoPtr elementType = arrayType->GetElementType(); + String lenName = String::Format("%sLen", name.string()); + + sb.Append(prefix).AppendFormat("if (%s > 0 && %s != NULL) {\n", lenName.string(), name.string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + String elementName = String::Format("(%s)[i]", name.string()); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(&(%s), false);\n", + elementType->GetName().string(), elementName.string()); + } + + sb.Append(prefix + TAB).Append("}\n"); + } + + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + break; + } + case TypeKind::TYPE_LIST: { + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + String lenName = String::Format("%sLen", name.string()); + + sb.Append(prefix).AppendFormat("if (%s > 0 && %s != NULL) {\n", lenName.string(), name.string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + String elementName = String::Format("(%s)[i]", name.string()); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(&(%s), false);\n", + elementType->GetName().string(), elementName.string()); + } + + sb.Append(prefix + TAB).Append("}\n"); + } + + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + sb.Append(prefix).AppendFormat("%sFree(&%s, false);\n", type->GetName().string(), name.string()); + sb.Append(prefix).Append("\n"); + break; + } + default: + break; + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeFreeImpl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("void %sFree(%s *%s, bool freeSelf)\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.string()); + sb.Append(TAB).Append(TAB).Append("return;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + AutoPtr memberType = type->GetMemberType(i); + String memberName = type->GetMemberName(i); + String name = String::Format("%s->%s", objName.string(), memberName.string()); + EmitCustomTypeMemberFree(sb, name, memberType, TAB); + } + + sb.Append(TAB).Append("if (freeSelf) {\n"); + sb.Append(TAB).Append(TAB).Append("OsalMemFree(dataBlock);\n"); + sb.Append(TAB).Append("}\n"); + + sb.Append("}\n"); +} + +void CCustomTypesCodeEmitter::EmitCustomTypeMemberFree(StringBuilder& sb, const String& name, + const AutoPtr& type, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: { + sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + AutoPtr arrayType = dynamic_cast(type.Get()); + AutoPtr elementType = arrayType->GetElementType(); + + sb.Append(prefix).AppendFormat("if (%sLen > 0 && %s != NULL) {\n", name.string(), name.string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("OsalMemFree(%s[i]);\n", name.string()); + sb.Append(prefix + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(%s, false);\n", + elementType->GetName().string(), name.string()); + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + case TypeKind::TYPE_LIST: { + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + + sb.Append(prefix).AppendFormat("if (%sLen > 0 && %s != NULL) {\n", name.string(), name.string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("OsalMemFree(%s[i]);\n", name.string()); + sb.Append(prefix + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(%s, false);\n", + elementType->GetName().string(), name.string()); + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + sb.Append(prefix).AppendFormat("%sFree(&%s, false);\n\n", type->GetName().string(), name.string()); + break; + } + default: + break; + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_custom_types_code_emitter.h b/tools/hdi-gen/codegen/c_custom_types_code_emitter.h new file mode 100755 index 000000000..2473df8a1 --- /dev/null +++ b/tools/hdi-gen/codegen/c_custom_types_code_emitter.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_CUSTOM_TYPES_CODE_EMITTER_H +#define OHOS_HDI_C_CUSTOM_TYPES_CODE_EMITTER_H +#include +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CCustomTypesCodeEmitter : public CCodeEmitter { +public: + CCustomTypesCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CCodeEmitter(ast, targetDirectory) {} + + virtual ~CCustomTypesCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitCustomTypesHeaderFile(); + + void EmitHeaderInclusions(StringBuilder& sb); + + void EmitCustomTypeDecls(StringBuilder& sb); + + void EmitCustomTypeDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeFuncDecl(StringBuilder& sb); + + void EmitCustomTypeMarshallingDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeUnmarshallingDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeFreeDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypesSourceFile(); + + void EmitSoucreIncludsions(StringBuilder& sb); + + void EmitSourceStdlibInclusions(StringBuilder& sb); + + void EmitCustomTypeDataProcess(StringBuilder& sb); + + void EmitCustomTypeMarshallingImpl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeUnmarshallingImpl(StringBuilder& sb, const AutoPtr& type); + + void EmitError(const String& name, const AutoPtr& type, StringBuilder& sb, const String& prefix); + + void EmitCustomTypeFreeImpl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeMemberFree(StringBuilder& sb, const String& name, const AutoPtr& type, + const String& prefix); + + std::vector freeObjStatements_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_CUSTOM_TYPES_CODE_EMITTER_H diff --git a/tools/hdi-gen/codegen/c_service_driver_code_emitter.cpp b/tools/hdi-gen/codegen/c_service_driver_code_emitter.cpp new file mode 100755 index 000000000..d67c84584 --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_driver_code_emitter.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_service_driver_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CServiceDriverCodeEmitter::CServiceDriverCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CCodeEmitter(ast, targetDirectory) +{ + String infFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), infName_.string()); + sourceFileName_ = String::Format("%s_driver.c", FileName(infFullName).string()); +} + +void CServiceDriverCodeEmitter::EmitCode() +{ + // the callback interface have no driver file. + if (!isCallbackInterface()) { + EmitDriverSourceFile(); + } +} + +void CServiceDriverCodeEmitter::EmitDriverSourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.c", directory_.string(), FileName(infName_ + "Driver").string()); + } else { + filePath = String::Format("%s%s.c", directory_.string(), FileName(infName_ + "Driver").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceDriverCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitDriverIncluions(sb); + sb.Append("\n"); + EmitDriverServiceDecl(sb); + sb.Append("\n"); + EmitDriverDispatch(sb); + sb.Append("\n"); + EmitDriverInit(sb); + sb.Append("\n"); + EmitDriverBind(sb); + sb.Append("\n"); + EmitDriverRelease(sb); + sb.Append("\n"); + EmitDriverEntryDefinition(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceDriverCodeEmitter::EmitDriverIncluions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); +} + +void CServiceDriverCodeEmitter::EmitDriverServiceDecl(StringBuilder& sb) +{ + sb.AppendFormat("struct Hdf%sService {\n", infName_.string()); + sb.Append(TAB).AppendFormat("struct IDeviceIoService ioservice;\n"); + sb.Append(TAB).Append("void *instance;\n"); + sb.Append("};\n"); +} + +void CServiceDriverCodeEmitter::EmitDriverDispatch(StringBuilder& sb) +{ + sb.AppendFormat("static int32_t %sServiceDispatch(struct HdfDeviceIoClient *client, int cmdId,\n", + infName_.string()); + sb.Append(TAB).Append("struct HdfSBuf *data, struct HdfSBuf *reply)\n"); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct Hdf%sService *hdf%sService = CONTAINER_OF(\n", + infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("client->device->service, struct Hdf%sService, ioservice);\n", + infName_.string()); + sb.Append(TAB).AppendFormat("return %sServiceOnRemoteRequest(hdf%sService->instance, cmdId, data, reply);\n", + infName_.string(), infName_.string()); + sb.Append("}\n"); +} + +void CServiceDriverCodeEmitter::EmitDriverInit(StringBuilder& sb) +{ + sb.AppendFormat("int Hdf%sDriverInit(struct HdfDeviceObject *deviceObject)\n", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverInit enter, new hdi impl.\");\n", infName_.string()); + sb.Append(TAB).Append("return HDF_SUCCESS;\n"); + sb.Append("}\n"); +} + +void CServiceDriverCodeEmitter::EmitDriverBind(StringBuilder& sb) +{ + sb.AppendFormat("int Hdf%sDriverBind(struct HdfDeviceObject *deviceObject)\n", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverBind enter.\");\n", infName_.string()); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("struct Hdf%sService *hdf%sService = (struct Hdf%sService *)OsalMemAlloc(\n", + infName_.string(), infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("sizeof(struct Hdf%sService));\n", infName_.string()); + sb.Append(TAB).AppendFormat("if (hdf%sService == NULL) {\n", infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat( + "HDF_LOGE(\"Hdf%sDriverBind OsalMemAlloc Hdf%sService failed!\");\n", infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Dispatch = %sServiceDispatch;\n", + infName_.string(), infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Open = NULL;\n", infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Release = NULL;\n", infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->instance = Hdi%sInstance();\n", infName_.string(), infName_.string()); + sb.Append(TAB).AppendFormat("if (hdf%sService->instance == NULL) {\n", infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(hdf%sService);\n", infName_.string()); + sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("deviceObject->service = &hdf%sService->ioservice;\n", infName_.string()); + sb.Append(TAB).Append("return HDF_SUCCESS;\n"); + sb.Append("}\n"); +} + +void CServiceDriverCodeEmitter::EmitDriverRelease(StringBuilder& sb) +{ + sb.AppendFormat("void Hdf%sDriverRelease(struct HdfDeviceObject *deviceObject)\n", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct Hdf%sService *hdf%sService = CONTAINER_OF(\n", + infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("deviceObject->service, struct Hdf%sService, ioservice);\n", + infName_.string()); + sb.Append(TAB).AppendFormat("Hdi%sRelease(hdf%sService->instance);\n", infName_.string(), infName_.string()); + sb.Append(TAB).AppendFormat("OsalMemFree(hdf%sService);\n", infName_.string()); + sb.Append("}\n"); +} + +void CServiceDriverCodeEmitter::EmitDriverEntryDefinition(StringBuilder& sb) +{ + sb.AppendFormat("struct HdfDriverEntry g_%sDriverEntry = {\n", infName_.ToLowerCase().string()); + sb.Append(TAB).Append(".moduleVersion = 1,\n"); + sb.Append(TAB).Append(".moduleName = \"sample\", /* please change the moduleName */\n"); + sb.Append(TAB).AppendFormat(".Bind = Hdf%sDriverBind,\n", infName_.string()); + sb.Append(TAB).AppendFormat(".Init = Hdf%sDriverInit,\n", infName_.string()); + sb.Append(TAB).AppendFormat(".Release = Hdf%sDriverRelease,\n", infName_.string()); + sb.Append("};\n\n"); + sb.AppendFormat("HDF_INIT(g_%sDriverEntry);", infName_.ToLowerCase().string()); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_driver_code_emitter.h b/tools/hdi-gen/codegen/c_service_driver_code_emitter.h new file mode 100755 index 000000000..02a0aab74 --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_driver_code_emitter.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_SERVICE_DRIVER_CODE_EMITTER_H +#define OHOS_HDI_C_SERVICE_DRIVER_CODE_EMITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CServiceDriverCodeEmitter : public CCodeEmitter { +public: + + CServiceDriverCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CServiceDriverCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitDriverSourceFile(); + + void EmitDriverIncluions(StringBuilder& sb); + + void EmitDriverServiceDecl(StringBuilder& sb); + + void EmitDriverDispatch(StringBuilder& sb); + + void EmitDriverInit(StringBuilder& sb); + + void EmitDriverBind(StringBuilder& sb); + + void EmitDriverRelease(StringBuilder& sb); + + void EmitDriverEntryDefinition(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_SERVICE_DRIVER_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_impl_code_emitter.cpp b/tools/hdi-gen/codegen/c_service_impl_code_emitter.cpp new file mode 100755 index 000000000..ae876957a --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_impl_code_emitter.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_service_impl_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CServiceImplCodeEmitter::CServiceImplCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CCodeEmitter(ast, targetDirectory) +{ + String infFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), infName_.string()); + sourceFileName_ = String::Format("%s_service.c", FileName(infFullName).string()); +} + +void CServiceImplCodeEmitter::EmitCode() +{ + if (isCallbackInterface()) { + EmitServiceImplHeaderFile(); + } + EmitServiceImplSourceFile(); +} + +void CServiceImplCodeEmitter::EmitServiceImplHeaderFile() +{ + String filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_ + "Service").string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceDriverCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, ImplFullName_); + sb.Append("\n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitServiceImplConstructDecl(sb); + sb.Append("\n"); + EmitTailExternC(sb); + sb.Append("\n"); + EmitTailMacro(sb, ImplFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceImplCodeEmitter::EmitServiceImplConstructDecl(StringBuilder& sb) +{ + sb.AppendFormat("void %sServiceConstruct(struct %s* service);\n", infName_.string(), interfaceName_.string()); +} + +void CServiceImplCodeEmitter::EmitServiceImplSourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.c", directory_.string(), FileName(infName_ + "Service").string()); + } else { + filePath = String::Format("%s%s.c", directory_.string(), FileName(infName_ + "Service").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceDriverCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitServiceImplInclusions(sb); + sb.Append("\n"); + EmitServiceImplMethodImpls(sb, ""); + sb.Append("\n"); + EmitServiceImplConstruct(sb); + if (!isCallbackInterface()) { + sb.Append("\n"); + EmitServiceImplInstance(sb); + sb.Append("\n"); + EmitServiceImplRelease(sb); + } + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceImplCodeEmitter::EmitServiceImplInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); +} + +void CServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitServiceImplMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CServiceImplCodeEmitter::EmitServiceImplMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t %s%s(struct %s *self)\n", + infName_.string(), method->GetName().string(), interfaceName_.string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t %s%s(struct %s *self, ", + infName_.string(), method->GetName().string(), interfaceName_.string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(")"); + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } + + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n"); + sb.Append(prefix).Append("}\n"); +} + +void CServiceImplCodeEmitter::EmitServiceImplConstruct(StringBuilder& sb) +{ + String objName("instance"); + sb.AppendFormat("void %sServiceConstruct(struct %s *%s)\n", + infName_.string(), interfaceName_.string(), objName.string()); + sb.Append("{\n"); + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(TAB).AppendFormat("%s->%s = %s%s;\n", + objName.string(), method->GetName().string(), infName_.string(), method->GetName().string()); + } + sb.Append("}\n"); +} + +void CServiceImplCodeEmitter::EmitServiceImplInstance(StringBuilder& sb) +{ + String objName("instance"); + sb.AppendFormat("struct %s *Hdi%sInstance()\n", interfaceName_.string(), infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s*)OsalMemAlloc(sizeof(struct %s));\n", + interfaceName_.string(), objName.string(), interfaceName_.string(), interfaceName_.string()); + sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.string()); + sb.Append(TAB).Append(TAB).AppendFormat("HDF_LOGE(\"%%{public}s: OsalMemAlloc struct %s %s failed!\", __func__);\n", + interfaceName_.string(), objName.string()); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append(TAB).AppendFormat("%sServiceConstruct(%s);\n", infName_.string(), objName.string()); + sb.Append(TAB).AppendFormat("return %s;\n", objName.string()); + sb.Append("}\n"); +} + +void CServiceImplCodeEmitter::EmitServiceImplRelease(StringBuilder& sb) +{ + sb.AppendFormat("void Hdi%sRelease(struct %s *instance)\n", infName_.string(), interfaceName_.string()); + sb.Append("{\n"); + sb.Append(TAB).Append("if (instance == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("return;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append(TAB).Append("OsalMemFree(instance);\n"); + sb.Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_impl_code_emitter.h b/tools/hdi-gen/codegen/c_service_impl_code_emitter.h new file mode 100755 index 000000000..99cc5ca1a --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_impl_code_emitter.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_SERVICE_IMPL_CODE_EMITTER_H +#define OHOS_HDI_C_SERVICE_IMPL_CODE_EMITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CServiceImplCodeEmitter : public CCodeEmitter { +public: + CServiceImplCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CServiceImplCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitServiceImplHeaderFile(); + + void EmitServiceImplConstructDecl(StringBuilder& sb); + + void EmitServiceImplSourceFile(); + + void EmitServiceImplInclusions(StringBuilder& sb); + + void EmitServiceImplMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitServiceImplMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitServiceImplConstruct(StringBuilder& sb); + + void EmitServiceImplInstance(StringBuilder& sb); + + void EmitServiceImplRelease(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_SERVICE_IMPL_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_interface_code_emitter.cpp b/tools/hdi-gen/codegen/c_service_interface_code_emitter.cpp new file mode 100755 index 000000000..a38821b7d --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_interface_code_emitter.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_service_interface_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void CServiceInterfaceCodeEmitter::EmitCode() +{ + if (!isCallbackInterface()) { + EmitInterfaceHeadrFile(); + } +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceHeadrFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.h", directory_.string(), FileName(interfaceName_).string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(interfaceName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, interfaceFullName_); + sb.Append("\n"); + EmitImportInclusions(sb); + sb.Append("\n"); + EmitInterfaceDataDecls(sb); + sb.Append("\n"); + EmitInterfaceMethodCommands(sb); + sb.Append("\n"); + EmitInterfaceDefinition(sb); + sb.Append("\n"); + EmitTailMacro(sb, interfaceFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceInterfaceCodeEmitter::EmitImportInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + for (const auto& importPair : ast_->GetImports()) { + AutoPtr importAst = importPair.second; + + String fileName; + if (importAst->GetASTFileType() == ASTFileType::AST_ICALLBACK && importAst->GetInterfaceDef() != nullptr) { + String ifaceName = importAst->GetInterfaceDef()->GetName(); + String name = ifaceName.StartsWith("I") ? ifaceName.Substring(1) : ifaceName; + String stubName = name + "Proxy"; + fileName = FileName(importAst->GetInterfaceDef()->GetNamespace()->ToString() + stubName); + } else { + fileName = FileName(importAst->GetFullName()); + } + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceDataDecls(StringBuilder& sb) +{ + sb.Append("struct HdfSBuf;\n"); + sb.Append("struct HdfDeviceObject;\n"); + sb.Append("struct HdfDeviceIoClient;\n"); +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder& sb) +{ + sb.AppendFormat("struct %s {\n", interfaceName_.string()); + EmitInterfaceMethods(sb, TAB); + sb.Append("};\n\n"); + EmitInterfaceInstanceMethodDecl(sb); + sb.Append("\n"); + EmitInterfaceReleaseMethodDecl(sb); + sb.Append("\n"); + EmitInterfaceRequestMethodDecl(sb); +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceMethods(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitInterfaceMethod(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t (*%s)(struct %s *self);\n", + method->GetName().string(), interfaceName_.string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t (*%s)(struct %s *self, ", + method->GetName().string(), interfaceName_.string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(");"); + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceInstanceMethodDecl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s *Hdi%sInstance();\n", interfaceName_.string(), infName_.string()); +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceReleaseMethodDecl(StringBuilder& sb) +{ + sb.AppendFormat("void Hdi%sRelease(struct %s *instance);\n", + infName_.string(), interfaceName_.string()); +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceRequestMethodDecl(StringBuilder& sb) +{ + sb.AppendFormat("int32_t %sServiceOnRemoteRequest(void *service, int cmdId,\n", infName_.string()); + sb.Append(TAB).Append("struct HdfSBuf *data, struct HdfSBuf *reply);\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_interface_code_emitter.h b/tools/hdi-gen/codegen/c_service_interface_code_emitter.h new file mode 100755 index 000000000..b1b6f7a95 --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_interface_code_emitter.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_SERVICE_INTERFACE_CODEE_MITTER_H +#define OHOS_HDI_C_SERVICE_INTERFACE_CODEE_MITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CServiceInterfaceCodeEmitter : public CCodeEmitter { +public: + CServiceInterfaceCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CCodeEmitter(ast, targetDirectory) {} + + virtual ~CServiceInterfaceCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitInterfaceHeadrFile(); + + void EmitImportInclusions(StringBuilder& sb); + + void EmitInterfaceDataDecls(StringBuilder& sb); + + void EmitInterfaceDefinition(StringBuilder& sb); + + void EmitInterfaceMethods(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitInterfaceInstanceMethodDecl(StringBuilder& sb); + + void EmitInterfaceReleaseMethodDecl(StringBuilder& sb); + + void EmitInterfaceRequestMethodDecl(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_SERVICE_INTERFACE_CODEE_MITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_stub_code_emitter.cpp b/tools/hdi-gen/codegen/c_service_stub_code_emitter.cpp new file mode 100755 index 000000000..e4d7794aa --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_stub_code_emitter.cpp @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_service_stub_code_emitter.h" + +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CServiceStubCodeEmitter::CServiceStubCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CCodeEmitter(ast, targetDirectory) +{ + String infFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), infName_.string()); + sourceFileName_ = String::Format("%s_stub.c", FileName(infFullName).string()); +} + +void CServiceStubCodeEmitter::EmitCode() +{ + if (isCallbackInterface()) { + EmitCbServiceStubHeaderFile(); + } + EmitServiceStubSourceFile(); +} + +void CServiceStubCodeEmitter::EmitCbServiceStubHeaderFile() +{ + String filePath = String::Format("%s%s.h", directory_.string(), FileName(stubName_).string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceStubCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, stubFullName_); + sb.Append("\n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitCbServiceStubMethodsDcl(sb); + sb.Append("\n"); + EmitTailExternC(sb); + sb.Append("\n"); + EmitTailMacro(sb, stubFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceStubCodeEmitter::EmitCbServiceStubMethodsDcl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s* %sStubObtain();\n", interfaceName_.string(), infName_.string()); + sb.Append("\n"); + sb.AppendFormat("void %sStubRelease(struct %s *callback);\n", infName_.string(), interfaceName_.string()); +} + +void CServiceStubCodeEmitter::EmitServiceStubSourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.c", directory_.string(), FileName(stubName_).string()); + } else { + filePath = String::Format("%s%s.c", directory_.string(), FileName(stubName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceStubCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitServiceStubInclusions(sb); + sb.Append("\n"); + EmitServiceStubMethodImpls(sb, ""); + sb.Append("\n"); + EmitServiceStubOnRequestMethodImpl(sb, ""); + if (isCallbackInterface()) { + sb.Append("\n"); + EmitCbStubDefinitions(sb); + sb.Append("\n"); + EmitCbStubObtainImpl(sb); + sb.Append("\n"); + EmitCbStubReleaseImpl(sb); + } + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceStubCodeEmitter::EmitServiceStubInclusions(StringBuilder& sb) +{ + if (!isCallbackInterface()) { + EmitServiceStubStdlibInclusions(sb); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + } else { + sb.AppendFormat("#include \"%s.h\"\n", FileName(stubFullName_).string()); + EmitServiceStubStdlibInclusions(sb); + sb.Append("#include \n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(ImplName_).string()); + } +} + +void CServiceStubCodeEmitter::EmitServiceStubStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + + const AST::TypeStringMap& types = ast_->GetTypes(); + int i = 0; + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CServiceStubCodeEmitter::EmitServiceStubMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitServiceStubMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CServiceStubCodeEmitter::EmitServiceStubMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).AppendFormat( + "static int32_t SerStub%s(struct %s *serviceImpl, struct HdfSBuf *data, struct HdfSBuf *reply)\n", + method->GetName().string(), interfaceName_.string()); + sb.Append(prefix).Append("{\n"); + + sb.Append(prefix + TAB).Append("int32_t ec = HDF_FAILURE;\n"); + + if (method->GetParameterNumber() > 0) { + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitStubLocalVariable(param, sb, prefix + TAB); + } + + sb.Append("\n"); + for (int i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_IN) { + EmitReadStubMethodParameter(param, "data", sb, prefix + TAB); + sb.Append("\n"); + } + } + } + + if (method->GetParameterNumber() == 0) { + sb.Append(prefix + TAB).AppendFormat("ec = serviceImpl->%s(serviceImpl);\n", method->GetName().string()); + } else { + sb.Append(prefix + TAB).AppendFormat("ec = serviceImpl->%s(serviceImpl, ", method->GetName().string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitCallParameter(sb, param->GetType(), param->GetAttribute(), param->GetName()); + if (i + 1 < method->GetParameterNumber()) { + sb.Append(", "); + } + } + sb.AppendFormat(");\n", method->GetName().string()); + } + + sb.Append(prefix + TAB).Append("if (ec != HDF_SUCCESS) {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: call %s function failed!\", __func__);\n", method->GetName().string()); + sb.Append(prefix + TAB + TAB).Append("goto errors;\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("\n"); + + for (int i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_OUT) { + EmitWriteStubMethodParameter(param, "reply", sb, prefix + TAB); + sb.Append("\n"); + } + } + + sb.Append(prefix).Append("errors:\n"); + for (int i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitError(param, sb, prefix + TAB); + } + + sb.Append(prefix + TAB).Append("return ec;\n"); + sb.Append(prefix).Append("}\n"); +} + +void CServiceStubCodeEmitter::EmitStubLocalVariable(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + AutoPtr type = param->GetType(); + sb.Append(prefix).Append(param->EmitCLocalVar()).Append("\n"); + if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.Append(prefix).AppendFormat("uint32_t %sLen = 0;\n", param->GetName().string()); + } +} + +void CServiceStubCodeEmitter::EmitReadStubMethodParameter(const AutoPtr& param, + const String& parcelName, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + + if (type->GetTypeKind() == TypeKind::TYPE_STRING) { + String cloneName = String::Format("%sCp", param->GetName().string()); + type->EmitCStubReadVar(parcelName, cloneName, sb, prefix); + sb.Append(prefix).AppendFormat("%s = strdup(%s);\n", param->GetName().string(), cloneName.string()); + } else if (type->GetTypeKind() == TypeKind::TYPE_INTERFACE) { + type->EmitCStubReadVar(parcelName, param->GetName(), sb, prefix); + } else if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemAlloc(sizeof(%s));\n", param->GetName().string(), + type->EmitCType(TypeMode::NO_MODE).string(), type->EmitCType(TypeMode::NO_MODE).string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + type->EmitCStubReadVar(parcelName, param->GetName(), sb, prefix); + } else if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + String cpName = String::Format("%sCp", param->GetName().string()); + type->EmitCStubReadVar(parcelName, cpName, sb, prefix); + sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemAlloc(sizeof(%s));\n", param->GetName().string(), + type->EmitCType(TypeMode::NO_MODE).string(), type->EmitCType(TypeMode::NO_MODE).string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("(void)memcpy_s(%s, sizeof(%s), %s, sizeof(%s));\n", param->GetName().string(), + type->EmitCType(TypeMode::NO_MODE).string(), cpName.string(), type->EmitCType(TypeMode::NO_MODE).string()); + } else if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) { + type->EmitCStubReadVar(parcelName, param->GetName(), sb, prefix); + } else if (type->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR) { + type->EmitCStubReadVar(parcelName, param->GetName(), sb, prefix); + } else { + String name = String::Format("&%s", param->GetName().string()); + type->EmitCStubReadVar(parcelName, name, sb, prefix); + } +} + +void CServiceStubCodeEmitter::EmitWriteStubMethodParameter(const AutoPtr& param, + const String& parcelName, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + type->EmitCStubWriteVar(parcelName, param->GetName(), sb, prefix); +} + +void CServiceStubCodeEmitter::EmitCallParameter(StringBuilder& sb, const AutoPtr& type, ParamAttr attribute, + const String& name) +{ + if (attribute == ParamAttr::PARAM_OUT) { + sb.AppendFormat("&%s", name.string()); + if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.AppendFormat(", &%sLen", name.string()); + } + } else { + sb.AppendFormat("%s", name.string()); + if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.AppendFormat(", %sLen", name.string()); + } + } +} + + +void CServiceStubCodeEmitter::EmitError(const AutoPtr& param, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: + case TypeKind::TYPE_UNION: { + sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", param->GetName().string()); + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", param->GetName().string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + String lenName = String::Format("%sLen", param->GetName().string()); + sb.Append(prefix).AppendFormat("if (%s > 0 && %s != NULL) {\n", + lenName.string(), param->GetName().string()); + + AutoPtr arrayType = dynamic_cast(type.Get()); + AutoPtr elementType = arrayType->GetElementType(); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + String elementName = String::Format("%s[i]", param->GetName().string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("%sFree(&%s, false);\n", + elementType->GetName().string(), elementName.string()); + } + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", param->GetName().string()); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + break; + } + case TypeKind::TYPE_LIST: { + String lenName = String::Format("%sLen", param->GetName().string()); + sb.Append(prefix).AppendFormat("if (%s > 0 && %s != NULL) {\n", + lenName.string(), param->GetName().string()); + + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + String elementName = String::Format("%s[i]", param->GetName().string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("%sFree(&%s, false);\n", + elementType->GetName().string(), elementName.string()); + } + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", param->GetName().string()); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", param->GetName().string()); + sb.Append(prefix + TAB).AppendFormat("%sFree(%s, true);\n", + type->GetName().string(), param->GetName().string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + default: + break; + } +} + +void CServiceStubCodeEmitter::EmitServiceStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix) +{ + String codeName; + if (!isCallbackInterface()) { + codeName = "cmdId"; + sb.Append(prefix).AppendFormat("int32_t %sServiceOnRemoteRequest(void *service, int %s,\n", + infName_.string(), codeName.string()); + } else { + codeName = "code"; + sb.Append(prefix).AppendFormat("int32_t %sServiceOnRemoteRequest(struct HdfRemoteService *service, int %s,\n", + infName_.string(), codeName.string()); + } + sb.Append(prefix + TAB).Append("struct HdfSBuf *data, struct HdfSBuf *reply)\n"); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("struct %s *serviceImpl = (struct %s*)service;\n", + interfaceName_.string(), interfaceName_.string()); + sb.Append(prefix + TAB).AppendFormat("switch (%s) {\n", codeName.string()); + + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(prefix + TAB + TAB).AppendFormat("case CMD_%s:\n", ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("return SerStub%s(serviceImpl, data, reply);\n", + method->GetName().string()); + } + + sb.Append(prefix + TAB + TAB).Append("default: {\n"); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: not support cmd %%{public}d\", __func__, %s);\n", codeName.string()); + sb.Append(prefix + TAB + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("}\n"); +} + +void CServiceStubCodeEmitter::EmitCbStubDefinitions(StringBuilder& sb) +{ + sb.AppendFormat("struct %sStub {\n", infName_.string()); + sb.Append(TAB).AppendFormat("struct %s service;\n", interfaceName_.string()); + sb.Append(TAB).Append("struct HdfRemoteDispatcher dispatcher;\n"); + sb.Append("};\n"); +} + +void CServiceStubCodeEmitter::EmitCbStubObtainImpl(StringBuilder& sb) +{ + String stubTypeName = String::Format("%sStub", infName_.string()); + String objName = "stub"; + sb.AppendFormat("struct %s* %sStubObtain()\n", interfaceName_.string(), infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct %s* %s = (struct %s*)OsalMemAlloc(sizeof(struct %s));\n", + stubTypeName.string(), objName.string(), stubTypeName.string(), stubTypeName.string()); + sb.Append(TAB).AppendFormat("if (stub == NULL) {\n", objName.string()); + sb.Append(TAB).Append(TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: OsalMemAlloc %s obj failed!\", __func__);\n", stubTypeName.string()); + sb.Append(TAB).Append(TAB).AppendFormat("return NULL;\n"); + sb.Append(TAB).Append("}\n\n"); + sb.Append(TAB).AppendFormat("%s->dispatcher.Dispatch = %sServiceOnRemoteRequest;\n", + objName.string(), infName_.string()); + sb.Append(TAB).AppendFormat( + "%s->service.remote = HdfRemoteServiceObtain((struct HdfObject*)%s, &(%s->dispatcher));\n", + objName.string(), objName.string(), objName.string()); + sb.Append(TAB).AppendFormat("if (%s->service.remote == NULL) {\n", objName.string()); + sb.Append(TAB).Append(TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: %s->service.remote is null\", __func__);\n", objName.string()); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n\n"); + sb.Append(TAB).AppendFormat("%sServiceConstruct(&%s->service);\n", infName_.string(), objName.string()); + sb.Append(TAB).AppendFormat("return &%s->service;\n", objName.string()); + sb.Append("}\n"); +} + +void CServiceStubCodeEmitter::EmitCbStubReleaseImpl(StringBuilder& sb) +{ + sb.AppendFormat("void %sStubRelease(struct %s *stub)\n", infName_.string(), interfaceName_.string()); + sb.Append("{\n"); + sb.Append(TAB).Append("if (stub == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("return;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append(TAB).Append("OsalMemFree(stub);\n"); + sb.Append("}"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_stub_code_emitter.h b/tools/hdi-gen/codegen/c_service_stub_code_emitter.h new file mode 100755 index 000000000..38bad234a --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_stub_code_emitter.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_SERVICE_STUB_CODEE_MITTER_H +#define OHOS_HDI_C_SERVICE_STUB_CODEE_MITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CServiceStubCodeEmitter : public CCodeEmitter { +public: + CServiceStubCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CServiceStubCodeEmitter() = default; + + void EmitCode() override; +private: + + void EmitCbServiceStubHeaderFile(); + + void EmitCbServiceStubMethodsDcl(StringBuilder& sb); + + void EmitServiceStubSourceFile(); + + void EmitServiceStubInclusions(StringBuilder& sb); + + void EmitServiceStubStdlibInclusions(StringBuilder& sb); + + void EmitServiceStubMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitServiceStubMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitStubLocalVariable(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + void EmitReadStubMethodParameter(const AutoPtr& param, const String& parcelName, StringBuilder& sb, + const String& prefix); + + void EmitReadStubVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitWriteStubMethodParameter(const AutoPtr& param, const String& parcelName, StringBuilder& sb, + const String& prefix); + + void EmitWriteStubVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitCallParameter(StringBuilder& sb, const AutoPtr& type, ParamAttr attribute, const String& name); + + void EmitError(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + void EmitServiceStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitCbStubDefinitions(StringBuilder& sb); + + void EmitCbStubObtainImpl(StringBuilder& sb); + + void EmitCbStubReleaseImpl(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_SERVICE_STUB_CODEE_MITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/code_generator.h b/tools/hdi-gen/codegen/code_generator.h new file mode 100755 index 000000000..da57088f2 --- /dev/null +++ b/tools/hdi-gen/codegen/code_generator.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CODEGENERATOR_H +#define OHOS_HDI_CODEGENERATOR_H + +#include "ast/ast.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class CodeGenerator : public LightRefCountBase { +public: + CodeGenerator() : LightRefCountBase(), + targetDirectory_(), + ast_(nullptr) {} + + virtual ~CodeGenerator() = default; + + virtual bool Initializate(const AutoPtr& ast, const String& targetDirectory) = 0; + + virtual bool Generate() const = 0; +protected: + virtual bool ResolveDirectory() = 0; + + String targetDirectory_; + AutoPtr ast_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CODEGENERATOR_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.cpp new file mode 100755 index 000000000..82f75824b --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_client_interface_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void CppClientInterfaceCodeEmitter::EmitCode() +{ + EmitInterfaceHeaderFile(); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sclient/%s.h", directory_.string(), FileName(interfaceName_).string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(interfaceName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppClientInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitClientInfHeadMacro(sb); + sb.Append("\n"); + EmitInterfaceInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitUsingNamespace(sb); + sb.Append("\n"); + EmitInterfaceMethodCommands(sb, ""); + sb.Append("\n"); + EmitInterfaceDecl(sb); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); + EmitClientInfTailMacro(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppClientInterfaceCodeEmitter::EmitClientInfHeadMacro(StringBuilder& sb) +{ + String clientMacroName(interfaceFullName_); + if (!isCallbackInterface()) { + clientMacroName += ".client"; + } + EmitHeadMacro(sb, clientMacroName); +} + +void CppClientInterfaceCodeEmitter::EmitClientInfTailMacro(StringBuilder& sb) +{ + String clientMacroName(interfaceFullName_); + if (!isCallbackInterface()) { + clientMacroName += ".client"; + } + EmitTailMacro(sb, clientMacroName); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceInclusions(StringBuilder& sb) +{ + EmitInterfaceStdlibInclusions(sb); + EmitInterfaceDBinderInclusions(sb); + EmitInterfaceSelfDefinedTypeInclusions(sb); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceStdlibInclusions(StringBuilder& sb) +{ + bool includeString = false; + bool includeList = false; + bool includeMap = false; + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: { + if (!includeString) { + sb.Append("#include \n"); + includeString = true; + } + break; + } + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: { + if (!includeList) { + sb.Append("#include \n"); + includeList = true; + } + break; + } + case TypeKind::TYPE_MAP: { + if (!includeMap) { + sb.Append("#include \n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceDBinderInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceSelfDefinedTypeInclusions(StringBuilder& sb) +{ + for (const auto& importPair : ast_->GetImports()) { + AutoPtr importAst = importPair.second; + + String fileName; + if (importAst->GetASTFileType() == ASTFileType::AST_ICALLBACK && importAst->GetInterfaceDef() != nullptr) { + String ifaceName = importAst->GetInterfaceDef()->GetName(); + String name = ifaceName.StartsWith("I") ? ifaceName.Substring(1) : ifaceName; + String stubName = name + "Service"; + fileName = FileName(importAst->GetInterfaceDef()->GetNamespace()->ToString() + stubName); + } else { + fileName = FileName(importAst->GetFullName()); + } + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceDecl(StringBuilder& sb) +{ + sb.AppendFormat("class %s : public IRemoteBroker {\n", interface_->GetName().string()); + sb.Append("public:\n"); + EmitInterfaceBody(sb, TAB); + sb.Append("};\n\n"); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceBody(StringBuilder& sb, const String& prefix) +{ + sb.Append(TAB).AppendFormat("DECLARE_INTERFACE_DESCRIPTOR(u\"%s\");\n", interfaceFullName_.string()); + sb.Append("\n"); + EmitInterfaceDestruction(sb, TAB); + sb.Append("\n"); + if (!isCallbackInterface()) { + EmitInterfaceGetMethodDecl(sb, TAB); + sb.Append("\n"); + } + EmitInterfaceMethodsDecl(sb, TAB); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceDestruction(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", interface_->GetName().string()); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceGetMethodDecl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("static sptr<%s> Get();\n", interface_->GetName().string()); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceMethodsDecl(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitInterfaceMethodDecl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceMethodDecl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("virtual int32_t %s() = 0;\n", method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("virtual int32_t %s(", method->GetName().string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(") = 0;"); + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append(param->EmitCppParameter()); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.h b/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.h new file mode 100755 index 000000000..27e5662de --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_CLIENT_INTERFACE_CODE_EMITTER_H +#define OHOS_HDI_CPP_CLIENT_INTERFACE_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppClientInterfaceCodeEmitter : public CppCodeEmitter { +public: + CppClientInterfaceCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CppCodeEmitter(ast, targetDirectory) {} + + virtual ~CppClientInterfaceCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitInterfaceHeaderFile(); + + void EmitClientInfHeadMacro(StringBuilder& sb); + + void EmitClientInfTailMacro(StringBuilder& sb); + + void EmitInterfaceInclusions(StringBuilder& sb); + + void EmitInterfaceStdlibInclusions(StringBuilder& sb); + + void EmitInterfaceDBinderInclusions(StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeInclusions(StringBuilder& sb); + + void EmitInterfaceDecl(StringBuilder& sb); + + void EmitInterfaceBody(StringBuilder& sb, const String& prefix); + + void EmitInterfaceDestruction(StringBuilder& sb, const String& prefix); + + void EmitInterfaceGetMethodDecl(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodsDecl(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodDecl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_CLIENT_INTERFACE_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.cpp new file mode 100755 index 000000000..5905a3510 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_client_proxy_code_emitter.h" +#include "util/file.h" + +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CppClientProxyCodeEmitter::CppClientProxyCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CppCodeEmitter(ast, targetDirectory) +{ + String proxyName = String::Format("%sclient.%s", + interface_->GetNamespace()->ToString().string(), proxyName_.string()); + sourceFileName_ = String::Format("%s.cpp", FileName(proxyName).string()); +} + +void CppClientProxyCodeEmitter::EmitCode() +{ + EmitProxyHeaderFile(); + EmitProxySourceFile(); +} + +void CppClientProxyCodeEmitter::EmitProxyHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sclient/%s.h", directory_.string(), FileName(infName_ + "Proxy").string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_ + "Proxy").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppClientProxyCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, proxyFullName_); + sb.Append("\n"); + EmitProxyHeadrInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitProxyDecl(sb, ""); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); + EmitTailMacro(sb, proxyFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppClientProxyCodeEmitter::EmitProxyHeadrInclusions(StringBuilder& sb) +{ + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + sb.Append("#include \n"); +} + +void CppClientProxyCodeEmitter::EmitProxyDecl(StringBuilder& sb, const String& prefix) +{ + sb.AppendFormat("class %s : public IRemoteProxy<%s> {\n", + proxyName_.string(), interfaceName_.string()); + sb.Append("public:\n"); + EmitProxyConstructor(sb, TAB); + sb.Append("\n"); + EmitProxyMethodDecls(sb, TAB); + sb.Append("\n"); + sb.Append("private:\n"); + EmitProxyConstants(sb, TAB); + sb.Append("};\n"); +} + +void CppClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("explicit %s(\n", proxyName_.string()); + sb.Append(prefix + TAB).Append("const sptr& remote)\n"); + sb.Append(prefix + TAB).AppendFormat(": IRemoteProxy<%s>(remote)\n", interfaceName_.string()); + sb.Append(prefix).Append("{}\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat("virtual ~%s() {}\n", proxyName_.string()); +} + +void CppClientProxyCodeEmitter::EmitProxyMethodDecls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitProxyMethodDecl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppClientProxyCodeEmitter::EmitProxyMethodDecl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().string()); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitProxyMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(") override;"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void CppClientProxyCodeEmitter::EmitProxyConstants(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("static inline BrokerDelegator<%s> delegator_;\n", proxyName_.string()); +} + +void CppClientProxyCodeEmitter::EmitProxyMethodParameter(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append(param->EmitCppParameter()); +} + +void CppClientProxyCodeEmitter::EmitProxySourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sclient/%s.cpp", directory_.string(), FileName(infName_ + "Proxy").string()); + } else { + filePath = String::Format("%s%s.cpp", directory_.string(), FileName(infName_ + "Proxy").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppClientProxyCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitProxySourceInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + if (!isCallbackInterface()) { + EmitGetMethodImpl(sb, ""); + sb.Append("\n"); + } + EmitProxyMethodImpls(sb, ""); + sb.Append("\n"); + EmitEndNamespace(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppClientProxyCodeEmitter::EmitProxySourceInclusions(StringBuilder& sb) +{ + sb.AppendFormat("#include \"%s.h\"\n", FileName(proxyName_).string()); + EmitProxySourceStdlibInclusions(sb); +} + +void CppClientProxyCodeEmitter::EmitProxySourceStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CppClientProxyCodeEmitter::EmitGetMethodImpl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("sptr<%s> %s::Get()\n", + interface_->GetName().string(), interface_->GetName().string()); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("do {\n"); + sb.Append(prefix + TAB + TAB).Append("using namespace OHOS::HDI::ServiceManager::V1_0;\n"); + sb.Append(prefix + TAB + TAB).Append("auto servMgr = IServiceManager::Get();\n"); + sb.Append(prefix + TAB + TAB).Append("if (servMgr == nullptr) {\n"); + sb.Append(prefix + TAB + TAB + TAB).Append("HDF_LOGE(\"%{public}s:get IServiceManager failed!\", __func__);\n"); + sb.Append(prefix + TAB + TAB + TAB).Append("break;\n"); + sb.Append(prefix + TAB + TAB).Append("}\n\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("sptr remote = servMgr->GetService(\"%sService\");\n", + infName_.string()); + sb.Append(prefix + TAB + TAB).Append("if (remote != nullptr) {\n"); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("return iface_cast<%s>(remote);\n", + interface_->GetName().string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("} while(false);\n"); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: get %sService failed!\", __func__);\n", infName_.string()); + sb.Append(prefix + TAB).Append("return nullptr;\n"); + sb.Append(prefix).Append("}\n"); +} + + +void CppClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitProxyMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t %s::%s()\n", proxyName_.string(), method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t %s::%s(", proxyName_.string(), method->GetName().string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitProxyMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(")"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } + EmitProxyMethodBody(method, sb, prefix); +} + +void CppClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("MessageParcel data;\n"); + sb.Append(prefix + TAB).Append("MessageParcel reply;\n"); + sb.Append(prefix + TAB).Append("MessageOption option(MessageOption::TF_SYNC);\n"); + sb.Append("\n"); + + if (method->GetParameterNumber() > 0) { + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_IN) { + EmitWriteMethodParameter(param, "data", sb, prefix + TAB); + } + } + sb.Append("\n"); + } + + sb.Append(prefix + TAB).AppendFormat("int32_t ec = Remote()->SendRequest(CMD_%s, data, reply, option);\n", + ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB).Append("if (ec != HDF_SUCCESS) {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s failed, error code is %%d\", ec);\n", method->GetName().string()); + sb.Append(prefix + TAB + TAB).Append("return ec;\n"); + sb.Append(prefix + TAB).Append("}\n"); + + if (!method->IsOneWay()) { + sb.Append("\n"); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_OUT) { + EmitReadMethodParameter(param, "reply", false, sb, prefix + TAB); + sb.Append("\n"); + } + } + } + + sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n"); + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.h b/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.h new file mode 100755 index 000000000..9e97982e7 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_CLIENT_PROXY_CODE_EMITTER_H +#define OHOS_HDI_CPP_CLIENT_PROXY_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppClientProxyCodeEmitter : public CppCodeEmitter { +public: + CppClientProxyCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CppClientProxyCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitProxyHeaderFile(); + + void EmitProxyHeadrInclusions(StringBuilder& sb); + + void EmitProxyDecl(StringBuilder& sb, const String& prefix); + + void EmitProxyConstructor(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodDecls(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodDecl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitProxyConstants(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodParameter(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + void EmitProxySourceFile(); + + void EmitProxySourceInclusions(StringBuilder& sb); + + void EmitProxySourceStdlibInclusions(StringBuilder& sb); + + void EmitGetMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_CLIENT_PROXY_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_code_emitter.cpp new file mode 100755 index 000000000..9b79a26ca --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_code_emitter.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_code_emitter.h" +#include +#include +#include +#include + +namespace OHOS { +namespace HDI { +const char* CppCodeEmitter::TAB = " "; + +CppCodeEmitter::CppCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : LightRefCountBase(), ast_(ast), directory_(targetDirectory) +{ + if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) { + interface_ = ast_->GetInterfaceDef(); + } + + if (interface_ != nullptr) { + interfaceName_ = interface_->GetName(); + interfaceFullName_ = interface_->GetNamespace()->ToString() + interfaceName_; + infName_ = interfaceName_.StartsWith("I") ? interfaceName_.Substring(1) : interfaceName_; + proxyName_ = infName_ + "Proxy"; + proxyFullName_ = interface_->GetNamespace()->ToString() + proxyName_; + + stubName_ = infName_ + "Stub"; + stubFullName_ = interface_->GetNamespace()->ToString() + stubName_; + + ImplName_ = infName_ + "Service"; + ImplFullName_ = interface_->GetNamespace()->ToString() + ImplName_; + } else { + infName_ = ast_->GetName(); + } +} + +String CppCodeEmitter::FileName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + StringBuilder sb; + + for (int i = 0; i < name.GetLength(); i++) { + char c = name[i]; + if (isupper(c) != 0) { + // 2->Index of the last char array. + if (i > 1 && name[i - 1] != '.' && name[i - 2] != '.') { + sb.Append('_'); + } + sb.Append(tolower(c)); + } else { + sb.Append(c); + } + } + + return sb.ToString().Replace('.', '/'); +} + +void CppCodeEmitter::EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).Append("enum {\n"); + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(TAB).AppendFormat("CMD_%s,\n", ConstantName(method->GetName()).string()); + } + sb.Append(prefix).Append("};\n"); +} + +void CppCodeEmitter::EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).AppendFormat(param->EmitCppParameter()); +} + +void CppCodeEmitter::EmitLicense(StringBuilder& sb) +{ + if (ast_->GetLicense().IsEmpty()) { + return; + } + sb.Append(ast_->GetLicense()).Append("\n\n"); +} + +void CppCodeEmitter::EmitHeadMacro(StringBuilder& sb, const String& fullName) +{ + String macroName = MacroName(fullName); + sb.Append("#ifndef ").Append(macroName).Append("\n"); + sb.Append("#define ").Append(macroName).Append("\n"); +} + +void CppCodeEmitter::EmitTailMacro(StringBuilder& sb, const String& fullName) +{ + String macroName = MacroName(fullName); + sb.Append("#endif // ").Append(macroName).Append("\n\n"); +} + +void CppCodeEmitter::EmitBeginNamespace(StringBuilder& sb) +{ + String nspace = interface_->GetNamespace()->ToString(); + int index = nspace.IndexOf('.'); + while (index != -1) { + sb.AppendFormat("namespace %s {\n", nspace.Substring(0, index).string()); + nspace = nspace.Substring(index + 1); + index = nspace.IndexOf('.'); + } +} + +void CppCodeEmitter::EmitEndNamespace(StringBuilder& sb) +{ + String nspace = interface_->GetNamespace()->ToString(); + nspace = nspace.Substring(0, nspace.GetLength() - 1); + while (!nspace.IsEmpty()) { + int index = nspace.LastIndexOf('.'); + sb.AppendFormat("} // %s\n", + (index != -1) ? nspace.Substring(index + 1, nspace.GetLength()).string() : nspace.string()); + nspace = nspace.Substring(0, index); + } +} + +void CppCodeEmitter::EmitUsingNamespace(StringBuilder& sb) +{ + sb.Append("using namespace OHOS;\n"); + EmitImportUsingNamespace(sb); +} + +void CppCodeEmitter::EmitImportUsingNamespace(StringBuilder& sb) +{ + using StringSet = std::unordered_set; + StringSet namespaceSet; + String selfNameSpace = CppNameSpace(ast_->GetFullName()); + + for (const auto& importPair : ast_->GetImports()) { + AutoPtr import = importPair.second; + String nameSpace = CppNameSpace(import->GetFullName()); + if (nameSpace.Equals(selfNameSpace)) { + continue; + } + namespaceSet.emplace(nameSpace); + } + + for (const auto& nspace : namespaceSet) { + sb.Append("using namespace ").AppendFormat("%s;\n", nspace.string()); + } +} + +void CppCodeEmitter::EmitWriteMethodParameter(const AutoPtr& param, const String& parcelName, + StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + type->EmitCppWriteVar(parcelName, param->GetName(), sb, prefix); +} + +void CppCodeEmitter::EmitReadMethodParameter(const AutoPtr& param, const String& parcelName, + bool initVariable, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + type->EmitCppReadVar(parcelName, param->GetName(), sb, prefix, initVariable); +} + +void CppCodeEmitter::EmitLocalVariable(const AutoPtr& param, StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).Append(param->EmitCppLocalVar()).Append("\n"); +} + +String CppCodeEmitter::MacroName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + String macro = name.Replace('.', '_').ToUpperCase() + "_H"; + return macro; +} + +String CppCodeEmitter::CppFullName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + return name.Replace(".", "::"); +} + +String CppCodeEmitter::ConstantName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + StringBuilder sb; + + for (int i = 0; i < name.GetLength(); i++) { + char c = name[i]; + if (isupper(c) != 0) { + if (i > 1) { + sb.Append('_'); + } + sb.Append(c); + } else { + sb.Append(toupper(c)); + } + } + + return sb.ToString(); +} + +String CppCodeEmitter::CppNameSpace(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + String space; + int lastIndex = name.LastIndexOf('.'); + if (lastIndex != -1) { + space = name.Substring(0, lastIndex); + } else { + space = name; + } + + return CppFullName(space); +} + +String CppCodeEmitter::SpecificationParam(StringBuilder& paramSb, const String& prefix) +{ + int maxLineLen = 120; + int replaceLen = 2; + String paramStr = paramSb.ToString(); + int preIndex = 0; + int curIndex = 0; + + String insertStr = String::Format("\n%s", prefix.string()); + for (; curIndex < paramStr.GetLength(); curIndex++) { + if (curIndex == maxLineLen && preIndex > 0) { + paramStr.Replace(preIndex, replaceLen, ","); + paramStr.insert(preIndex + 1, insertStr); + } else { + if (paramStr[curIndex] == ',') { + preIndex = curIndex; + } + } + } + return paramStr; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_code_emitter.h b/tools/hdi-gen/codegen/cpp_code_emitter.h new file mode 100755 index 000000000..a519a6def --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_code_emitter.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_CODE_EMITTER_H +#define OHOS_HDI_CPP_CODE_EMITTER_H + +#include "ast/ast.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/string.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +class CppCodeEmitter : public LightRefCountBase { +public: + CppCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CppCodeEmitter() = default; + + virtual void EmitCode() = 0; + + inline String GetSourceFile() + { + return sourceFileName_; + } + + inline bool isInvaildDir() + { + return directory_.Equals(""); + } + + static String FileName(const String& name); +protected: + + void EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + void EmitLicense(StringBuilder& sb); + + void EmitHeadMacro(StringBuilder& sb, const String& fullName); + + void EmitTailMacro(StringBuilder& sb, const String& fullName); + + virtual void EmitBeginNamespace(StringBuilder& sb); + + virtual void EmitEndNamespace(StringBuilder& sb); + + void EmitUsingNamespace(StringBuilder& sb); + + void EmitImportUsingNamespace(StringBuilder& sb); + + void EmitWriteMethodParameter(const AutoPtr& param, const String& parcelName, StringBuilder& sb, + const String& prefix); + + void EmitReadMethodParameter(const AutoPtr& param, const String& parcelName, bool initVariable, + StringBuilder& sb, const String& prefix); + + void EmitLocalVariable(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + String MacroName(const String& name); + + String CppFullName(const String& name); + + String ConstantName(const String& name); + + String CppNameSpace(const String& name); + + bool isCallbackInterface() + { + if (interface_ == nullptr) { + return false; + } + + return interface_->IsCallback(); + } + + String SpecificationParam(StringBuilder& sb, const String& prefix); + + static const char* TAB; + + AutoPtr ast_; + AutoPtr interface_; + + String directory_; + String sourceFileName_; + + String interfaceName_; + String interfaceFullName_; + String infName_; + String proxyName_; + String proxyFullName_; + String stubName_; + String stubFullName_; + String ImplName_; + String ImplFullName_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_code_generator.cpp b/tools/hdi-gen/codegen/cpp_code_generator.cpp new file mode 100755 index 000000000..01452799b --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_code_generator.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "cpp_code_generator.h" +#include +#include +#include +#include "codegen/cpp_client_interface_code_emitter.h" +#include "codegen/cpp_client_proxy_code_emitter.h" +#include "codegen/cpp_custom_types_code_emitter.h" +#include "codegen/cpp_service_driver_code_emitter.h" +#include "codegen/cpp_service_impl_code_emitter.h" +#include "codegen/cpp_service_interface_code_emitter.h" +#include "codegen/cpp_service_stub_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +const char* CppCodeGenerator::TAG = "CppCodeGenerator"; + +bool CppCodeGenerator::Initializate(const AutoPtr& ast, const String& targetDirectory) +{ + ast_ = ast; + targetDirectory_ = targetDirectory; + + if (!ResolveDirectory()) { + return false; + } + + if (ast_->GetASTFileType() == ASTFileType::AST_TYPES) { + AutoPtr customTypesCodeEmitter = new CppCustomTypesCodeEmitter(ast_, targetDirectory_); + emitters_.push_back(customTypesCodeEmitter); + return true; + } + + AutoPtr clientInterfaceCodeEmitter = new CppClientInterfaceCodeEmitter(ast_, targetDirectory_); + AutoPtr clientProxyCodeEmitter = new CppClientProxyCodeEmitter(ast_, targetDirectory_); + + AutoPtr serviceInterfaceCodeEmitter = new CppServiceInterfaceCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceDriverCodeEmitter = new CppServiceDriverCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceStubCodeEmitter = new CppServiceStubCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceImplCodeEmitter = new CppServiceImplCodeEmitter(ast_, targetDirectory_); + + emitters_.push_back(clientInterfaceCodeEmitter); + emitters_.push_back(clientProxyCodeEmitter); + emitters_.push_back(serviceInterfaceCodeEmitter); + emitters_.push_back(serviceDriverCodeEmitter); + emitters_.push_back(serviceStubCodeEmitter); + emitters_.push_back(serviceImplCodeEmitter); + + return true; +} + +bool CppCodeGenerator::Generate() const +{ + for (auto emitter : emitters_) { + if (!emitter->isInvaildDir()) { + emitter->EmitCode(); + } + } + + return true; +} + +bool CppCodeGenerator::ResolveDirectory() +{ + String packageFilePath = String::Format("%s/%s/", + targetDirectory_.string(), CppCodeEmitter::FileName(ast_->GetPackageName()).string()); + targetDirectory_ = packageFilePath; + + if (!File::CreateParentDir(targetDirectory_)) { + Logger::E(TAG, "create '%s' directory failed!", targetDirectory_); + return false; + } + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_code_generator.h b/tools/hdi-gen/codegen/cpp_code_generator.h new file mode 100755 index 000000000..3a36abf3b --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_code_generator.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_CODE_GENERATOR_H +#define OHOS_HDI_CPP_CODE_GENERATOR_H + +#include "codegen/code_generator.h" +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppCodeGenerator : public CodeGenerator { +public: + CppCodeGenerator() : CodeGenerator(), + emitters_() {} + + ~CppCodeGenerator() override {}; + + bool Initializate(const AutoPtr& ast, const String& targetDirectory) override; + bool Generate() const override; +private: + bool ResolveDirectory() override; + + static const char* TAG; + std::vector> emitters_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_CODE_GENERATOR_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.cpp new file mode 100755 index 000000000..0ed77382b --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.cpp @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_custom_types_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void CppCustomTypesCodeEmitter::EmitCode() +{ + EmitCustomTypesHeaderFile(); + EmitCustomTypesSourceFile(); +} + +void CppCustomTypesCodeEmitter::EmitCustomTypesHeaderFile() +{ + String filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_).string()); + File file(filePath, File::WRITE); + String marcoName = String::Format("%s.%s", ast_->GetPackageName().string(), infName_.string()); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, marcoName); + sb.Append("\n"); + EmitHeaderFileInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitUsingNamespace(sb); + sb.Append("\n"); + EmitCustomTypeDecls(sb); + sb.Append("\n"); + EmitCustomTypeFuncDecl(sb); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); + EmitTailMacro(sb, marcoName); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppCustomTypesCodeEmitter::EmitHeaderFileInclusions(StringBuilder& sb) +{ + EmitCustomTypesStdlibInclusions(sb); + sb.Append("#include \n"); + EmitImportInclusions(sb); +} + +void CppCustomTypesCodeEmitter::EmitCustomTypesStdlibInclusions(StringBuilder& sb) +{ + bool includeString = false; + bool includeList = false; + bool includeMap = false; + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: { + if (!includeString) { + sb.Append("#include \n"); + includeString = true; + } + break; + } + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: { + if (!includeList) { + sb.Append("#include \n"); + includeList = true; + } + break; + } + case TypeKind::TYPE_MAP: { + if (!includeMap) { + sb.Append("#include \n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void CppCustomTypesCodeEmitter::EmitImportInclusions(StringBuilder& sb) +{ + for (const auto& importPair : ast_->GetImports()) { + AutoPtr importAst = importPair.second; + String fileName = FileName(importAst->GetFullName()); + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + EmitCustomTypeDecl(sb, type); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeDecl(StringBuilder& sb, const AutoPtr& type) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_ENUM: { + AutoPtr enumType = dynamic_cast(type.Get()); + sb.Append(enumType->EmitCppTypeDecl()).Append("\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + AutoPtr structType = dynamic_cast(type.Get()); + sb.Append(structType->EmitCppTypeDecl()).Append("\n"); + break; + } + case TypeKind::TYPE_UNION: { + AutoPtr unionType = dynamic_cast(type.Get()); + sb.Append(unionType->EmitCppTypeDecl()).Append("\n"); + break; + } + default: + break; + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + AutoPtr structType = dynamic_cast(type.Get()); + EmitCustomTypeMarshallingDecl(sb, structType); + sb.Append("\n"); + EmitCustomTypeUnmarshallingDecl(sb, structType); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingDecl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel &data, const %s& %s);\n", + type->GetName().string(), type->EmitCppType().string(), objName.string()); +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingDecl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel &data, %s& %s);\n", + type->GetName().string(), type->EmitCppType().string(), objName.string()); +} + +void CppCustomTypesCodeEmitter::EmitCustomTypesSourceFile() +{ + String filePath = String::Format("%s%s.cpp", directory_.string(), FileName(infName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitSourceFileInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitCustomTypeDataProcess(sb); + sb.Append("\n"); + EmitEndNamespace(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppCustomTypesCodeEmitter::EmitSourceFileInclusions(StringBuilder& sb) +{ + sb.AppendFormat("#include \"%s.h\"\n", FileName(infName_).string()); + EmitSourceStdlibInclusions(sb); +} + +void CppCustomTypesCodeEmitter::EmitSourceStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT || type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + AutoPtr structType = dynamic_cast(type.Get()); + EmitCustomTypeMarshallingImpl(sb, structType); + sb.Append("\n"); + EmitCustomTypeUnmarshallingImpl(sb, structType); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + + sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel& data, const %s& %s)\n", + type->EmitCppType().string(), type->EmitCppType().string(), objName.string()); + sb.Append("{\n"); + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + AutoPtr memberType = type->GetMemberType(i); + String memberName = type->GetMemberName(i); + + String name = String::Format("%s.%s", objName.string(), memberName.string()); + memberType->EmitCppMarshalling("data", name, sb, TAB); + if (i + 1 < type->GetMemberNumber()) { + sb.Append("\n"); + } + } + + sb.Append(TAB).Append("return true;\n"); + sb.Append("}\n"); +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + + sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel& data, %s& %s)\n", + type->GetName().string(), type->EmitCppType().string(), objName.string()); + sb.Append("{\n"); + + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + AutoPtr memberType = type->GetMemberType(i); + String memberName = type->GetMemberName(i); + String name = String::Format("%s.%s", objName.string(), memberName.string()); + + if (i > 0 && + (memberType->GetTypeKind() == TypeKind::TYPE_STRUCT + || memberType->GetTypeKind() == TypeKind::TYPE_UNION + || memberType->GetTypeKind() == TypeKind::TYPE_ARRAY + || memberType->GetTypeKind() == TypeKind::TYPE_LIST)) { + sb.Append("\n"); + } + + if (memberType->GetTypeKind() == TypeKind::TYPE_UNION) { + String cpName = String::Format("%sCp", memberName.string()); + memberType->EmitCppUnMarshalling("data", cpName, sb, TAB, false); + sb.Append(TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", name.string(), + memberType->EmitCppType().string(), cpName.string(), memberType->EmitCppType().string()); + } else { + memberType->EmitCppUnMarshalling("data", name, sb, TAB, false); + } + } + + sb.Append(TAB).AppendFormat("return true;\n", objName.string()); + sb.Append("}\n"); +} + +void CppCustomTypesCodeEmitter::EmitBeginNamespace(StringBuilder& sb) +{ + String nspace = ast_->GetPackageName(); + int index = nspace.IndexOf('.'); + while (index != -1) { + sb.AppendFormat("namespace %s {\n", nspace.Substring(0, index).string()); + nspace = nspace.Substring(index + 1); + index = nspace.IndexOf('.'); + } + + if (!nspace.IsEmpty()) { + sb.AppendFormat("namespace %s {\n", nspace.string()); + } +} + +void CppCustomTypesCodeEmitter::EmitEndNamespace(StringBuilder& sb) +{ + String nspace = ast_->GetPackageName(); + nspace = nspace.Substring(0, nspace.GetLength() - 1); + while (!nspace.IsEmpty()) { + int index = nspace.LastIndexOf('.'); + sb.AppendFormat("} // %s\n", + (index != -1) ? nspace.Substring(index + 1, nspace.GetLength()).string() : nspace.string()); + nspace = nspace.Substring(0, index); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.h b/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.h new file mode 100755 index 000000000..d8e3be78f --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_CUSTOM_TYPES_CODE_EMITTER_H +#define OHOS_HDI_CPP_CUSTOM_TYPES_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppCustomTypesCodeEmitter : public CppCodeEmitter { +public: + CppCustomTypesCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CppCodeEmitter(ast, targetDirectory) {} + + virtual ~CppCustomTypesCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitCustomTypesHeaderFile(); + + void EmitHeaderFileInclusions(StringBuilder& sb); + + void EmitCustomTypesStdlibInclusions(StringBuilder& sb); + + void EmitImportInclusions(StringBuilder& sb); + + void EmitCustomTypeDecls(StringBuilder& sb); + + void EmitCustomTypeDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeFuncDecl(StringBuilder& sb); + + void EmitCustomTypeMarshallingDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeUnmarshallingDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypesSourceFile(); + + void EmitSourceFileInclusions(StringBuilder& sb); + + void EmitSourceStdlibInclusions(StringBuilder& sb); + + void EmitCustomTypeDataProcess(StringBuilder& sb); + + void EmitCustomTypeMarshallingImpl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeUnmarshallingImpl(StringBuilder& sb, const AutoPtr& type); + + void EmitBeginNamespace(StringBuilder& sb) override; + + void EmitEndNamespace(StringBuilder& sb) override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_CUSTOM_TYPES_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.cpp new file mode 100755 index 000000000..244255264 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_service_driver_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CppServiceDriverCodeEmitter::CppServiceDriverCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CppCodeEmitter(ast, targetDirectory) +{ + String infFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), infName_.string()); + sourceFileName_ = String::Format("%s_driver.cpp", FileName(infFullName).string()); +} + +void CppServiceDriverCodeEmitter::EmitCode() +{ + // the callback interface have no driver file. + if (!isCallbackInterface()) { + EmitDriverSourceFile(); + } +} + +void CppServiceDriverCodeEmitter::EmitDriverSourceFile() +{ + String filePath = String::Format("%sserver/%s.cpp", directory_.string(), FileName(infName_ + "Driver").string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceDriverCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitDriverIncluions(sb); + sb.Append("\n"); + EmitDriverUsings(sb); + sb.Append("\n"); + EmitDriverServiceDecl(sb); + sb.Append("\n"); + EmitDriverDispatch(sb); + sb.Append("\n"); + EmitDriverInit(sb); + sb.Append("\n"); + EmitDriverBind(sb); + sb.Append("\n"); + EmitDriverRelease(sb); + sb.Append("\n"); + EmitDriverEntryDefinition(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceDriverCodeEmitter::EmitDriverIncluions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(stubName_).string()); +} + +void CppServiceDriverCodeEmitter::EmitDriverUsings(StringBuilder& sb) +{ + String nspace(interface_->GetNamespace()->ToString()); + int index = nspace.LastIndexOf('.'); + if (index > 0) { + nspace = nspace.Substring(0, index); + } + + String fullName = CppFullName(nspace); + sb.AppendFormat("using namespace %s;\n", fullName.string()); +} + +void CppServiceDriverCodeEmitter::EmitDriverServiceDecl(StringBuilder& sb) +{ + sb.AppendFormat("struct Hdf%s%s {\n", infName_.string(), "Service"); + sb.Append(TAB).Append("struct IDeviceIoService ioservice;\n"); + sb.Append(TAB).Append("void *instance;\n"); + sb.Append("};\n"); +} + +void CppServiceDriverCodeEmitter::EmitDriverDispatch(StringBuilder& sb) +{ + sb.AppendFormat("static int32_t %sServiceDispatch(struct HdfDeviceIoClient *client, int cmdId,\n", + infName_.string()); + sb.Append(TAB).Append("struct HdfSBuf *data, struct HdfSBuf *reply)\n"); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct Hdf%sService *hdf%sService = CONTAINER_OF(\n", + infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("client->device->service, struct Hdf%sService, ioservice);\n", + infName_.string()); + sb.Append(TAB).AppendFormat("return %sServiceOnRemoteRequest(hdf%sService->instance, cmdId, data, reply);\n", + infName_.string(), infName_.string()); + sb.Append("}\n"); +} + +void CppServiceDriverCodeEmitter::EmitDriverInit(StringBuilder& sb) +{ + sb.AppendFormat("int Hdf%sDriverInit(struct HdfDeviceObject *deviceObject)\n", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverInit enter, new hdi impl.\");\n", infName_.string()); + sb.Append(TAB).Append("return HDF_SUCCESS;\n"); + sb.Append("}\n"); +} + +void CppServiceDriverCodeEmitter::EmitDriverBind(StringBuilder& sb) +{ + sb.AppendFormat("int Hdf%sDriverBind(struct HdfDeviceObject *deviceObject)\n", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverBind enter.\");\n", infName_.string()); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("struct Hdf%sService *hdf%sService = (struct Hdf%sService *)OsalMemAlloc(\n", + infName_.string(), infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("sizeof(struct Hdf%sService));\n", infName_.string()); + sb.Append(TAB).AppendFormat("if (hdf%sService == nullptr) {\n", infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("HDF_LOGE(\"Hdf%sDriverBind OsalMemAlloc Hdf%sService failed!\");\n", + infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Dispatch = %sServiceDispatch;\n", + infName_.string(), infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Open = NULL;\n", infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Release = NULL;\n", infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->instance = %sStubInstance();\n", infName_.string(), infName_.string()); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("deviceObject->service = &hdf%sService->ioservice;\n", infName_.string()); + sb.Append(TAB).Append("return HDF_SUCCESS;\n"); + sb.Append("}\n"); +} + +void CppServiceDriverCodeEmitter::EmitDriverRelease(StringBuilder& sb) +{ + sb.AppendFormat("void Hdf%sDriverRelease(struct HdfDeviceObject *deviceObject)", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverRelease enter.\");\n", interfaceName_.string()); + sb.Append("}\n"); +} + +void CppServiceDriverCodeEmitter::EmitDriverEntryDefinition(StringBuilder& sb) +{ + sb.AppendFormat("struct HdfDriverEntry g_%sDriverEntry = {\n", infName_.ToLowerCase().string()); + sb.Append(TAB).Append(".moduleVersion = 1,\n"); + sb.Append(TAB).AppendFormat(".moduleName = \"%s\",\n", infName_.ToLowerCase().string()); + sb.Append(TAB).AppendFormat(".Bind = Hdf%sDriverBind,\n", infName_.string()); + sb.Append(TAB).AppendFormat(".Init = Hdf%sDriverInit,\n", infName_.string()); + sb.Append(TAB).AppendFormat(".Release = Hdf%sDriverRelease,\n", infName_.string()); + sb.Append("};\n"); + sb.Append("\n"); + sb.Append("#ifndef __cplusplus\n"); + sb.Append("extern \"C\" {\n"); + sb.Append("#endif\n"); + sb.AppendFormat("HDF_INIT(g_%sDriverEntry);\n", infName_.ToLowerCase().string()); + sb.Append("#ifndef __cplusplus\n"); + sb.Append("}\n"); + sb.Append("#endif\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.h b/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.h new file mode 100755 index 000000000..2d67cbf27 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_SERVICE_DRIVER_CODE_EMITTER_H +#define OHOS_HDI_CPP_SERVICE_DRIVER_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppServiceDriverCodeEmitter : public CppCodeEmitter { +public: + CppServiceDriverCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CppServiceDriverCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitDriverSourceFile(); + + void EmitDriverIncluions(StringBuilder& sb); + + void EmitDriverUsings(StringBuilder& sb); + + void EmitDriverServiceDecl(StringBuilder& sb); + + void EmitDriverDispatch(StringBuilder& sb); + + void EmitDriverInit(StringBuilder& sb); + + void EmitDriverBind(StringBuilder& sb); + + void EmitDriverRelease(StringBuilder& sb); + + void EmitDriverEntryDefinition(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_SERVICE_DRIVER_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.cpp new file mode 100755 index 000000000..486c5fe09 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_service_impl_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CppServiceImplCodeEmitter::CppServiceImplCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CppCodeEmitter(ast, targetDirectory) +{ + String ImplFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), ImplName_.string()); + sourceFileName_ = String::Format("%s.cpp", FileName(ImplFullName).string()); +} + +void CppServiceImplCodeEmitter::EmitCode() +{ + EmitImplHeaderFile(); + EmitImplSourceFile(); +} + +void CppServiceImplCodeEmitter::EmitImplHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.h", directory_.string(), FileName(infName_ + "Service").string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_ + "Service").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceImplCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, ImplFullName_); + sb.Append("\n"); + EmitServiceImplInclusions(sb); + sb.Append("\n"); + EmitServiceImplDecl(sb); + sb.Append("\n"); + EmitTailMacro(sb, ImplFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceImplCodeEmitter::EmitServiceImplInclusions(StringBuilder& sb) +{ + if (!isCallbackInterface()) { + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + } else { + sb.AppendFormat("#include \"%s.h\"\n", FileName(stubName_).string()); + } + sb.Append("#include \n"); +} + +void CppServiceImplCodeEmitter::EmitServiceImplDecl(StringBuilder& sb) +{ + EmitBeginNamespace(sb); + sb.Append("\n"); + if (!isCallbackInterface()) { + sb.AppendFormat("class %sService : public %s {\n", infName_.string(), interfaceName_.string()); + } else { + sb.AppendFormat("class %sService : public %s {\n", infName_.string(), stubName_.string()); + } + sb.Append("public:\n"); + EmitServiceImplBody(sb, TAB); + sb.Append("};\n"); + + sb.Append("\n"); + EmitEndNamespace(sb); +} + +void CppServiceImplCodeEmitter::EmitServiceImplBody(StringBuilder& sb, const String& prefix) +{ + EmitServiceImplDestruction(sb, TAB); + sb.Append("\n"); + EmitServiceImplMethodDecls(sb, TAB); +} + +void CppServiceImplCodeEmitter::EmitServiceImplDestruction(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("virtual ~%sService() {}\n", infName_.string()); +} + +void CppServiceImplCodeEmitter::EmitServiceImplMethodDecls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitServiceImplMethodDecl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppServiceImplCodeEmitter::EmitServiceImplMethodDecl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(") override;"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void CppServiceImplCodeEmitter::EmitImplSourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.cpp", directory_.string(), FileName(infName_ + "Service").string()); + } else { + filePath = String::Format("%s%s.cpp", directory_.string(), FileName(infName_ + "Service").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceImplCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + sb.AppendFormat("#include \"%s_service.h\"\n", FileName(infName_).string()); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitServiceImplMethodImpls(sb, ""); + sb.Append("\n"); + EmitEndNamespace(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitServiceImplMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppServiceImplCodeEmitter::EmitServiceImplMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t %sService::%s()\n", infName_.string(), method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t %sService::%s(", infName_.string(), method->GetName().string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.AppendFormat(")"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } + + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n"); + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.h b/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.h new file mode 100755 index 000000000..e93c7b899 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_SERVICE_IMPL_CODE_EMITTER_H +#define OHOS_HDI_CPP_SERVICE_IMPL_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppServiceImplCodeEmitter : public CppCodeEmitter { +public: + CppServiceImplCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CppServiceImplCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitImplHeaderFile(); + + void EmitServiceImplInclusions(StringBuilder& sb); + + void EmitServiceImplDecl(StringBuilder& sb); + + void EmitServiceImplBody(StringBuilder& sb, const String& prefix); + + void EmitServiceImplDestruction(StringBuilder& sb, const String& prefix); + + void EmitServiceImplMethodDecls(StringBuilder& sb, const String& prefix); + + void EmitServiceImplMethodDecl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitImplSourceFile(); + + void EmitServiceImplMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitServiceImplMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_SERVICE_IMPL_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.cpp new file mode 100755 index 000000000..289d0e782 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_service_interface_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void CppServiceInterfaceCodeEmitter::EmitCode() +{ + if (!isCallbackInterface()) { + EmitInterfaceHeaderFile(); + } +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.h", directory_.string(), FileName(interfaceName_).string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(interfaceName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitServiceInfHeadMacro(sb); + sb.Append("\n"); + EmitInterfaceInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitUsingNamespace(sb); + sb.Append("\n"); + EmitInterfaceDecl(sb); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); + EmitServiceInfTailMacro(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceInterfaceCodeEmitter::EmitServiceInfHeadMacro(StringBuilder& sb) +{ + String serviceMacroName(interfaceFullName_); + if (!isCallbackInterface()) { + serviceMacroName += ".service"; + } + EmitHeadMacro(sb, serviceMacroName); +} + +void CppServiceInterfaceCodeEmitter::EmitServiceInfTailMacro(StringBuilder& sb) +{ + String serviceMacroName(interfaceFullName_); + if (!isCallbackInterface()) { + serviceMacroName += ".service"; + } + EmitTailMacro(sb, serviceMacroName); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceInclusions(StringBuilder& sb) +{ + EmitInterfaceStdlibInclusions(sb); + EmitInterfaceDBinderInclusions(sb); + EmitInterfaceSelfDefinedTypeInclusions(sb); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceStdlibInclusions(StringBuilder& sb) +{ + bool includeString = false; + bool includeList = false; + bool includeMap = false; + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: { + if (!includeString) { + sb.Append("#include \n"); + includeString = true; + } + break; + } + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: { + if (!includeList) { + sb.Append("#include \n"); + includeList = true; + } + break; + } + case TypeKind::TYPE_MAP: { + if (!includeMap) { + sb.Append("#include \n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceDBinderInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceSelfDefinedTypeInclusions(StringBuilder& sb) +{ + for (const auto& importPair : ast_->GetImports()) { + AutoPtr importAst = importPair.second; + + String fileName; + if (importAst->GetASTFileType() == ASTFileType::AST_ICALLBACK && importAst->GetInterfaceDef() != nullptr) { + String ifaceName = importAst->GetInterfaceDef()->GetName(); + String name = ifaceName.StartsWith("I") ? ifaceName.Substring(1) : ifaceName; + String stubName = name + "Proxy"; + fileName = FileName(importAst->GetInterfaceDef()->GetNamespace()->ToString() + stubName); + } else { + fileName = FileName(importAst->GetFullName()); + } + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceDecl(StringBuilder& sb) +{ + EmitInterfaceMethodCommands(sb, ""); + sb.Append("\n"); + + sb.AppendFormat("class %s {\n", interface_->GetName().string()); + sb.Append("public:\n"); + EmitInterfaceBody(sb, TAB); + sb.Append("};\n"); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceBody(StringBuilder& sb, const String& prefix) +{ + EmitInterfaceDestruction(sb, TAB); + sb.Append("\n"); + EmitInterfaceMethods(sb, TAB); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceDestruction(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("virtual ~%s() {}\n", interface_->GetName().string()); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceMethods(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitInterfaceMethod(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("virtual int32_t %s() = 0;\n", method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("virtual int32_t %s(", method->GetName().string()); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(") = 0;"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.h b/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.h new file mode 100755 index 000000000..7e648887e --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_SERVICE_INTERFACE_CODE_EMITTER_H +#define OHOS_HDI_CPP_SERVICE_INTERFACE_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppServiceInterfaceCodeEmitter : public CppCodeEmitter { +public: + CppServiceInterfaceCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CppCodeEmitter(ast, targetDirectory) {} + + virtual ~CppServiceInterfaceCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitInterfaceHeaderFile(); + + void EmitServiceInfHeadMacro(StringBuilder& sb); + + void EmitServiceInfTailMacro(StringBuilder& sb); + + void EmitInterfaceInclusions(StringBuilder& sb); + + void EmitInterfaceStdlibInclusions(StringBuilder& sb); + + void EmitInterfaceDBinderInclusions(StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeInclusions(StringBuilder& sb); + + void EmitInterfaceUsings(StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeUsings(StringBuilder& sb); + + void EmitInterfaceDecl(StringBuilder& sb); + + void EmitInterfaceBody(StringBuilder& sb, const String& prefix); + + void EmitInterfaceDestruction(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethods(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_SERVICE_INTERFACE_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.cpp new file mode 100755 index 000000000..572189656 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.cpp @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_service_stub_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CppServiceStubCodeEmitter::CppServiceStubCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CppCodeEmitter(ast, targetDirectory) +{ + String stubFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), stubName_.string()); + sourceFileName_ = String::Format("%s.cpp", FileName(stubFullName).string()); +} + +void CppServiceStubCodeEmitter::EmitCode() +{ + EmitStubHeaderFile(); + EmitStubSourceFile(); +} + +void CppServiceStubCodeEmitter::EmitStubHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.h", directory_.string(), FileName(infName_ + "Stub").string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_ + "Stub").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceStubCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, stubFullName_); + sb.Append("\n"); + EmitStubHeaderInclusions(sb); + sb.Append("\n"); + + if (!isCallbackInterface()) { + EmitStubDecl(sb); + } else { + EmitCbStubDecl(sb); + } + sb.Append("\n"); + EmitTailMacro(sb, stubFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceStubCodeEmitter::EmitStubHeaderInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + if (!isCallbackInterface()) { + sb.AppendFormat("#include \"%s_service.h\"\n", FileName(infName_).string()); + } else { + sb.Append("#include \n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + } +} + +void CppServiceStubCodeEmitter::EmitStubDecl(StringBuilder& sb) +{ + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitStubUsingNamespace(sb); + sb.Append("\n"); + sb.AppendFormat("class %s {\n", stubName_.string()); + sb.Append("public:\n"); + EmitStubBody(sb, TAB); + sb.Append("};\n"); + + sb.Append("\n"); + EmitEndNamespace(sb); + + sb.Append("\n"); + EmitStubExternalsMethodsDel(sb); +} + +void CppServiceStubCodeEmitter::EmitCbStubDecl(StringBuilder& sb) +{ + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitStubUsingNamespace(sb); + sb.Append("\n"); + sb.AppendFormat("class %s : public IRemoteStub<%s> {\n", stubName_.string(), interfaceName_.string()); + EmitCbStubBody(sb, TAB); + sb.Append("};\n"); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); +} + +void CppServiceStubCodeEmitter::EmitStubUsingNamespace(StringBuilder& sb) +{ + sb.Append("using namespace OHOS;\n"); +} + +void CppServiceStubCodeEmitter::EmitStubBody(StringBuilder& sb, const String& prefix) +{ + sb.Append("public:\n"); + EmitStubDestruction(sb, prefix); + sb.Append("\n"); + EmitStubMethodDecls(sb, prefix); + sb.Append("\n"); + EmitStubOnRequestMethodDecl(sb, prefix); + sb.Append("\n"); + EmitStubMembers(sb, prefix); +} + +void CppServiceStubCodeEmitter::EmitCbStubBody(StringBuilder& sb, const String& prefix) +{ + sb.Append("public:\n"); + EmitStubDestruction(sb, prefix); + sb.Append("\n"); + EmitCbStubOnRequestDecl(sb, prefix); + EmitStubMethodDecls(sb, prefix); +} + +void CppServiceStubCodeEmitter::EmitStubDestruction(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("virtual ~%s() {}\n", stubName_.string()); +} + +void CppServiceStubCodeEmitter::EmitCbStubOnRequestDecl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).Append("int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,\n"); + sb.Append(prefix + TAB).Append("MessageOption &option) override;\n"); +} + +void CppServiceStubCodeEmitter::EmitStubMethodDecls(StringBuilder& sb, const String& prefix) +{ + if (interface_->GetMethodNumber() > 0) { + if (isCallbackInterface()) { + sb.Append("private:\n"); + } + + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitStubMethodDecl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } + } +} + +void CppServiceStubCodeEmitter::EmitStubMethodDecl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).AppendFormat("int32_t %s%s(MessageParcel& data, MessageParcel& reply, MessageOption& option);\n", + stubName_.string(), method->GetName().string()); +} + +void CppServiceStubCodeEmitter::EmitStubOnRequestMethodDecl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("int32_t %sOnRemoteRequest(int cmdId, MessageParcel& data, MessageParcel& reply,\n", + stubName_.string()); + sb.Append(prefix).Append(TAB).Append("MessageOption& option);\n"); +} + +void CppServiceStubCodeEmitter::EmitStubMembers(StringBuilder& sb, const String& prefix) +{ + sb.Append("private:\n"); + sb.Append(prefix).AppendFormat("%sService service;\n", infName_.string()); +} + +void CppServiceStubCodeEmitter::EmitStubExternalsMethodsDel(StringBuilder& sb) +{ + sb.AppendFormat("void *%sInstance();\n", stubName_.string()); + sb.Append("\n"); + sb.AppendFormat("void %sRelease(void *obj);\n", stubName_.string()); + sb.Append("\n"); + sb.AppendFormat( + "int32_t %sServiceOnRemoteRequest(void *stub, int cmdId, struct HdfSBuf* data, struct HdfSBuf* reply);\n", + infName_.string()); +} + +void CppServiceStubCodeEmitter::EmitStubSourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.cpp", directory_.string(), FileName(infName_ + "Stub").string()); + } else { + filePath = String::Format("%s%s.cpp", directory_.string(), FileName(infName_ + "Stub").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceStubCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitStubSourceInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + if (!isCallbackInterface()) { + EmitStubOnRequestMethodImpl(sb, ""); + } else { + EmitCbStubOnRequestMethodImpl(sb, ""); + } + sb.Append("\n"); + EmitStubMethodImpls(sb, ""); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); + + if (!isCallbackInterface()) { + EmitStubExternalsMethodsImpl(sb, ""); + } + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceStubCodeEmitter::EmitStubSourceInclusions(StringBuilder& sb) +{ + sb.AppendFormat("#include \"%s.h\"\n", FileName(stubName_).string()); + EmitStubSourceStdlibInclusions(sb); +} + +void CppServiceStubCodeEmitter::EmitStubSourceStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CppServiceStubCodeEmitter::EmitStubMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitStubMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppServiceStubCodeEmitter::EmitStubMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).AppendFormat( + "int32_t %s::%s%s(MessageParcel& data, MessageParcel& reply, MessageOption& option)\n", + stubName_.string(), stubName_.string(), method->GetName().string()); + sb.Append(prefix).Append("{\n"); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_IN) { + EmitReadMethodParameter(param, "data", true, sb, prefix + TAB); + sb.Append("\n"); + } else { + EmitLocalVariable(param, sb, prefix + TAB); + sb.Append("\n"); + } + } + + if (method->GetParameterNumber() == 0) { + if (!isCallbackInterface()) { + sb.Append(prefix + TAB).AppendFormat("int32_t ec = service.%s();\n", method->GetName().string()); + } else { + sb.Append(prefix + TAB).AppendFormat("int32_t ec = %s();\n", method->GetName().string()); + } + } else { + if (!isCallbackInterface()) { + sb.Append(prefix + TAB).AppendFormat("int32_t ec = service.%s(", method->GetName().string()); + } else { + sb.Append(prefix + TAB).AppendFormat("int32_t ec = %s(", method->GetName().string()); + } + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + sb.Append(param->GetName()); + if (i + 1 < method->GetParameterNumber()) { + sb.Append(", "); + } + } + sb.Append(");\n"); + } + + sb.Append(prefix + TAB).Append("if (ec != HDF_SUCCESS) {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s failed, error code is %%d\", ec);\n", method->GetName().string()); + sb.Append(prefix + TAB + TAB).Append("return ec;\n"); + sb.Append(prefix + TAB).Append("}\n\n"); + + if (!method->IsOneWay()) { + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_OUT) { + EmitWriteMethodParameter(param, "reply", sb, prefix + TAB); + sb.Append("\n"); + } + } + } + + sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n"); + sb.Append("}\n"); +} + +void CppServiceStubCodeEmitter::EmitStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("int32_t %s::%sOnRemoteRequest(int cmdId,\n", + stubName_.string(), stubName_.string()); + sb.Append(prefix + TAB).Append("MessageParcel& data, MessageParcel& reply, MessageOption& option)\n"); + sb.Append(prefix).Append("{\n"); + + sb.Append(prefix + TAB).Append("switch (cmdId) {\n"); + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(prefix + TAB + TAB).AppendFormat("case CMD_%s:\n", ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("return %sStub%s(data, reply, option);\n", + infName_.string(), method->GetName().string()); + } + + sb.Append(prefix + TAB + TAB).Append("default: {\n"); + sb.Append(prefix + TAB + TAB + TAB).Append( + "HDF_LOGE(\"%{public}s: not support cmd %{public}d\", __func__, cmdId);\n"); + sb.Append(prefix + TAB + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("}\n"); +} + +void CppServiceStubCodeEmitter::EmitCbStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("int32_t %s::OnRemoteRequest(uint32_t code,\n", stubName_.string()); + sb.Append(prefix + TAB).Append("MessageParcel& data, MessageParcel& reply, MessageOption& option)\n"); + sb.Append(prefix).Append("{\n"); + + sb.Append(prefix + TAB).Append("switch (code) {\n"); + + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(prefix + TAB + TAB).AppendFormat("case CMD_%s:\n", ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("return %sStub%s(data, reply, option);\n", + infName_.string(), method->GetName().string()); + } + + sb.Append(prefix + TAB + TAB).Append("default: {\n"); + sb.Append(prefix + TAB + TAB + TAB).Append( + "HDF_LOGE(\"%{public}s: not support cmd %{public}d\", __func__, code);\n"); + sb.Append(prefix + TAB + TAB + TAB).Append("return IPCObjectStub::OnRemoteRequest(code, data, reply, option);\n"); + sb.Append(prefix + TAB + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("}\n"); +} + +void CppServiceStubCodeEmitter::EmitStubExternalsMethodsImpl(StringBuilder& sb, const String& prefix) +{ + EmitStubInstanceMethodImpl(sb, prefix); + sb.Append("\n"); + EmitStubReleaseMethodImpl(sb, prefix); + sb.Append("\n"); + EmitServiceOnRemoteRequest(sb, prefix); +} + +void CppServiceStubCodeEmitter::EmitStubInstanceMethodImpl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("void *%sInstance()\n", stubName_.string()); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("using namespace %s;\n", + EmitStubServiceUsings(interface_->GetNamespace()->ToString()).string()); + sb.Append(prefix + TAB).AppendFormat("return reinterpret_cast(new %s());\n", stubName_.string()); + sb.Append(prefix).Append("}\n"); +} + +void CppServiceStubCodeEmitter::EmitStubReleaseMethodImpl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("void %sRelease(void *obj)\n", stubName_.string()); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("using namespace %s;\n", + EmitStubServiceUsings(interface_->GetNamespace()->ToString()).string()); + sb.Append(prefix + TAB).AppendFormat("delete reinterpret_cast<%s *>(obj);\n", stubName_.string()); + sb.Append(prefix).Append("}\n"); +} + +void CppServiceStubCodeEmitter::EmitServiceOnRemoteRequest(StringBuilder& sb, const String& prefix) +{ + String stubObjName = String::Format("%sStub", infName_.ToLowerCase().string()); + sb.Append(prefix).AppendFormat( + "int32_t %sServiceOnRemoteRequest(void *stub, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)\n", + infName_.string()); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("using namespace %s;\n", + EmitStubServiceUsings(interface_->GetNamespace()->ToString()).string()); + sb.Append(prefix + TAB).AppendFormat("%s *%s = reinterpret_cast<%s *>(stub);\n", + stubName_.string(), stubObjName.string(), stubName_.string()); + sb.Append(prefix + TAB).Append("OHOS::MessageParcel *dataParcel = nullptr;\n"); + sb.Append(prefix + TAB).Append("OHOS::MessageParcel *replyParcel = nullptr;\n"); + sb.Append("\n"); + + sb.Append(prefix + TAB).Append("(void)SbufToParcel(reply, &replyParcel);\n"); + sb.Append(prefix + TAB).Append("if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {\n"); + sb.Append(prefix + TAB + TAB).Append( + "HDF_LOGE(\"%{public}s:invalid data sbuf object to dispatch\", __func__);\n"); + sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("}\n\n"); + sb.Append(prefix + TAB).Append("OHOS::MessageOption option;\n"); + sb.Append(prefix + TAB).AppendFormat("return %s->%sOnRemoteRequest(cmdId, *dataParcel, *replyParcel, option);\n", + stubObjName.string(), stubName_.string()); + sb.Append(prefix).Append("}\n"); +} + +String CppServiceStubCodeEmitter::EmitStubServiceUsings(String nameSpace) +{ + int index = nameSpace.LastIndexOf('.'); + if (index > 0) { + nameSpace = nameSpace.Substring(0, index); + } + return CppFullName(nameSpace); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.h b/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.h new file mode 100755 index 000000000..12f7ce1af --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_SERVICE_STUB_CODE_EMITTER_H +#define OHOS_HDI_CPP_SERVICE_STUB_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppServiceStubCodeEmitter : public CppCodeEmitter { +public: + CppServiceStubCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CppServiceStubCodeEmitter() = default; + + void EmitCode() override; +private: + + // ISample.idl -> sample_service_stub.h + void EmitStubHeaderFile(); + + void EmitStubHeaderInclusions(StringBuilder& sb); + + void EmitStubUsingNamespace(StringBuilder& sb); + + void EmitStubDecl(StringBuilder& sb); + + void EmitCbStubDecl(StringBuilder& sb); + + void EmitStubBody(StringBuilder& sb, const String& prefix); + + void EmitCbStubBody(StringBuilder& sb, const String& prefix); + + void EmitStubDestruction(StringBuilder& sb, const String& prefix); + + void EmitCbStubOnRequestDecl(StringBuilder& sb, const String& prefix); + + void EmitStubMethodDecls(StringBuilder& sb, const String& prefix); + + void EmitStubMethodDecl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitStubOnRequestMethodDecl(StringBuilder& sb, const String& prefix); + + void EmitStubMembers(StringBuilder& sb, const String& prefix); + + void EmitStubExternalsMethodsDel(StringBuilder& sb); + + // ISample.idl -> sample_service_stub.cpp + void EmitStubSourceFile(); + + void EmitStubSourceInclusions(StringBuilder& sb); + + void EmitStubSourceStdlibInclusions(StringBuilder& sb); + + void EmitStubMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitStubMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitCbStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitStubExternalsMethodsImpl(StringBuilder& sb, const String& prefix); + + void EmitStubInstanceMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitStubReleaseMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitServiceOnRemoteRequest(StringBuilder& sb, const String& prefix); + + String EmitStubServiceUsings(String nameSpace); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_SERVICE_STUB_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/generator_factory.cpp b/tools/hdi-gen/codegen/generator_factory.cpp new file mode 100755 index 000000000..73418e738 --- /dev/null +++ b/tools/hdi-gen/codegen/generator_factory.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/generator_factory.h" +#include "codegen/c_code_generator.h" +#include "codegen/cpp_code_generator.h" +#include "codegen/java_code_generator.h" + +namespace OHOS { +namespace HDI { +AutoPtr GeneratorFactory::GetCodeGenerator(const String& targetLanuage) +{ + if (targetLanuage.Equals("c")) { + return new CCodeGenerator(); + } else if (targetLanuage.Equals("cpp")) { + return new CppCodeGenerator(); + } else if (targetLanuage.Equals("java")) { + return new JavaCodeGenerator(); + } + + return nullptr; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/generator_factory.h b/tools/hdi-gen/codegen/generator_factory.h new file mode 100755 index 000000000..8b99621fb --- /dev/null +++ b/tools/hdi-gen/codegen/generator_factory.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_GENERATORFACTORY_H +#define OHOS_HDI_GENERATORFACTORY_H + +#include "codegen/code_generator.h" + +namespace OHOS { +namespace HDI { +class GeneratorFactory { +public: + AutoPtr GetCodeGenerator(const String& targetLanuage); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_GENERATORFACTORY_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_client_interface_code_emitter.cpp b/tools/hdi-gen/codegen/java_client_interface_code_emitter.cpp new file mode 100755 index 000000000..abbe81f12 --- /dev/null +++ b/tools/hdi-gen/codegen/java_client_interface_code_emitter.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/java_client_interface_code_emitter.h" +#include +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void JavaClientInterfaceCodeEmitter::EmitCode() +{ + EmitInterfaceFile(); +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceFile() +{ + String filePath = String::Format("%s/%s.java", directory_.string(), FileName(interfaceName_).string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("JavaClientInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitPackage(sb); + sb.Append("\n"); + EmitInterfaceImports(sb); + sb.Append("\n"); + EmitInterfaceDefinition(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceImports(StringBuilder& sb) +{ + EmitInterfaceCorelibImports(sb); + EmitInterfaceSelfDefinedTypeImports(sb); + EmitInterfaceDBinderImports(sb); +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceCorelibImports(StringBuilder& sb) +{ + bool includeList = false; + bool includeMap = false; + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + switch (type->GetTypeKind()) { + case TypeKind::TYPE_LIST: { + if (!includeList) { + sb.Append("import java.util.List;\n"); + includeList = true; + } + break; + } + case TypeKind::TYPE_MAP: { + if (!includeMap) { + sb.Append("import java.util.Map;\n"); + sb.Append("import java.util.HashMap;\n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceDBinderImports(StringBuilder& sb) +{ + sb.Append("import ohos.rpc.IRemoteBroker;\n"); + sb.Append("import ohos.rpc.RemoteException;\n"); +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceSelfDefinedTypeImports(StringBuilder& sb) +{ + for (const auto& importPair : ast_->GetImports()) { + AutoPtr import = importPair.second; + sb.AppendFormat("import %s;\n", import->GetFullName().string()); + } +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder& sb) +{ + sb.AppendFormat("public interface %s extends IRemoteBroker {\n", interface_->GetName().string()); + EmitInterfaceMethods(sb, TAB); + sb.Append("}"); +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceMethods(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitInterfaceMethod(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int %s() throws RemoteException;\n", MethodName(method->GetName()).string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int %s(", MethodName(method->GetName()).string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(") throws RemoteException;"); + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceMethodParameter(const AutoPtr& param, + StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).Append(param->EmitJavaParameter()); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_client_interface_code_emitter.h b/tools/hdi-gen/codegen/java_client_interface_code_emitter.h new file mode 100755 index 000000000..9ffecd245 --- /dev/null +++ b/tools/hdi-gen/codegen/java_client_interface_code_emitter.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_JAVA_CLIENT_INTERFACE_CODE_EMITTER_H +#define OHOS_HDI_JAVA_CLIENT_INTERFACE_CODE_EMITTER_H + +#include "java_code_emitter.h" + +namespace OHOS { +namespace HDI { +class JavaClientInterfaceCodeEmitter : public JavaCodeEmitter { +public: + JavaClientInterfaceCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : JavaCodeEmitter(ast, targetDirectory) {} + + virtual ~JavaClientInterfaceCodeEmitter() = default; + + void EmitCode() override; +private: + + void EmitInterfaceFile(); + + void EmitInterfaceImports(StringBuilder& sb); + + void EmitInterfaceCorelibImports(StringBuilder& sb); + + void EmitInterfaceDBinderImports(StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeImports(StringBuilder& sb); + + void EmitInterfaceDefinition(StringBuilder& sb); + + void EmitInterfaceMethods(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_JAVA_CLIENT_INTERFACE_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_client_proxy_code_emitter.cpp b/tools/hdi-gen/codegen/java_client_proxy_code_emitter.cpp new file mode 100755 index 000000000..798be2741 --- /dev/null +++ b/tools/hdi-gen/codegen/java_client_proxy_code_emitter.cpp @@ -0,0 +1,668 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/java_client_proxy_code_emitter.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void JavaClientProxyCodeEmitter::EmitCode() +{ + EmitProxyFile(); +} + +void JavaClientProxyCodeEmitter::EmitProxyFile() +{ + String filePath = String::Format("%s/%s.java", directory_.string(), FileName(proxyName_).string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("CppClientInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitPackage(sb); + sb.Append("\n"); + EmitProxyImports(sb); + sb.Append("\n"); + EmitProxyImpl(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void JavaClientProxyCodeEmitter::EmitProxyImports(StringBuilder& sb) +{ + EmitProxyCorelibImports(sb); + EmitProxySelfDefinedTypeImports(sb); + EmitProxyDBinderImports(sb); +} + +void JavaClientProxyCodeEmitter::EmitProxyCorelibImports(StringBuilder& sb) +{ + bool includeList = false; + bool includeMap = false; + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + switch (type->GetTypeKind()) { + case TypeKind::TYPE_LIST: { + if (!includeList) { + sb.Append("import java.util.List;\n"); + includeList = true; + } + break; + } + case TypeKind::TYPE_MAP: { + if (!includeMap) { + sb.Append("import java.util.Map;\n"); + sb.Append("import java.util.HashMap;\n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void JavaClientProxyCodeEmitter::EmitProxySelfDefinedTypeImports(StringBuilder& sb) +{ + for (const auto& importPair : ast_->GetImports()) { + AutoPtr import = importPair.second; + sb.AppendFormat("import %s;\n", import->GetFullName().string()); + } +} + +void JavaClientProxyCodeEmitter::EmitProxyDBinderImports(StringBuilder& sb) +{ + sb.Append("import ohos.hiviewdfx.HiLog;\n"); + sb.Append("import ohos.hiviewdfx.HiLogLabel;\n"); + sb.Append("import ohos.rpc.IRemoteObject;\n"); + sb.Append("import ohos.rpc.RemoteException;\n"); + sb.Append("import ohos.rpc.MessageParcel;\n"); + sb.Append("import ohos.rpc.MessageOption;\n"); +} + +void JavaClientProxyCodeEmitter::EmitProxyImpl(StringBuilder& sb) +{ + sb.AppendFormat("public class %s implements %s {\n", proxyName_.string(), interfaceName_.string()); + EmitProxyConstants(sb, TAB); + sb.Append("\n"); + sb.Append(TAB).AppendFormat( + "private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_CORE, 0xD001510, \"%s\");\n", + interfaceFullName_.string()); + sb.Append(TAB).Append("private final IRemoteObject remote;\n"); + sb.Append(TAB).Append("private static final int ERR_OK = 0;\n"); + sb.Append("\n"); + EmitProxyConstructor(sb, TAB); + sb.Append("\n"); + EmitProxyMethodImpls(sb, TAB); + sb.Append("};"); +} + +void JavaClientProxyCodeEmitter::EmitProxyConstants(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("private static final String DESCRIPTOR = \"%s\";\n\n", + interfaceFullName_.string()); + EmitInterfaceMethodCommands(sb, prefix); +} + +void JavaClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("public %s(IRemoteObject remote) {\n", proxyName_.string()); + sb.Append(prefix + TAB).Append("this.remote = remote;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat("@Override\n"); + sb.Append(prefix).Append("public IRemoteObject asObject() {\n"); + sb.Append(prefix + TAB).Append("return remote;\n"); + sb.Append(prefix).Append("}\n"); +} + +void JavaClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitProxyMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void JavaClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append("@Override\n"); + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("public int %s() throws RemoteException ", + MethodName(method->GetName()).string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("public int %s(", MethodName(method->GetName()).string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + paramStr.Append(") throws RemoteException"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } + EmitProxyMethodBody(method, sb, prefix); +} + +void JavaClientProxyCodeEmitter::EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append(param->EmitJavaParameter()); +} + +void JavaClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("MessageParcel data = MessageParcel.obtain();\n"); + sb.Append(prefix + TAB).Append("MessageParcel reply = MessageParcel.obtain();\n"); + sb.Append(prefix + TAB).AppendFormat("MessageOption option = new MessageOption(MessageOption.TF_SYNC);\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat(" data.writeInterfaceToken(DESCRIPTOR);\n"); + + bool needBlankLine = false; + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_IN) { + EmitWriteMethodParameter(param, "data", sb, prefix + TAB); + needBlankLine = true; + } else { + AutoPtr type = param->GetType(); + if (type->GetTypeKind() == TypeKind::TYPE_ARRAY) { + EmitWriteOutArrayVariable("data", param->GetName(), type, sb, prefix + TAB); + } + } + } + if (needBlankLine) { + sb.Append("\n"); + } + + sb.Append(prefix + TAB).Append("try {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("if (remote.sendRequest(COMMAND_%s, data, reply, option)) {\n", + ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB + TAB + TAB).Append("return 1;\n"); + sb.Append(prefix + TAB + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append(" reply.readException();\n"); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_OUT) { + EmitReadMethodParameter(param, "reply", sb, prefix + TAB + TAB); + } + } + + sb.Append(prefix + TAB).Append("} finally {\n"); + sb.Append(prefix + TAB + TAB).Append("data.reclaim();\n"); + sb.Append(prefix + TAB + TAB).Append("reply.reclaim();\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("return 0;\n"); + sb.Append(prefix).Append("}\n"); +} + +void JavaClientProxyCodeEmitter::EmitWriteMethodParameter(const AutoPtr& param, const String& parcelName, + StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + EmitWriteVariable(parcelName, param->GetName(), type, sb, prefix); +} + +void JavaClientProxyCodeEmitter::EmitReadMethodParameter(const AutoPtr& param, const String& parcelName, + StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + EmitReadOutVariable(parcelName, param->GetName(), type, sb, prefix); +} + +void JavaClientProxyCodeEmitter::EmitWriteVariable(const String& parcelName, const String& name, + const AutoPtr& type, StringBuilder& sb, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s.writeBoolean(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s.writeByte(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s.writeShort(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s.writeInt(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s.writeLong(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s.writeFloat(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s.writeDouble(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s.writeString(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + if (type->EmitJavaType(TypeMode::NO_MODE).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s);\n", parcelName.string(), name.string()); + break; + } + sb.Append(prefix).AppendFormat("%s.writeSequenceable(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_INTERFACE: + sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s.asObject());\n", parcelName.string(), + name.string()); + break; + case TypeKind::TYPE_LIST: { + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + + sb.Append(prefix).AppendFormat("%s.writeInt(%s.size());\n", parcelName.string(), name.string()); + sb.Append(prefix).AppendFormat("for (%s element : %s) {\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string()); + EmitWriteVariable(parcelName, "element", elementType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_MAP: { + AutoPtr mapType = dynamic_cast(type.Get()); + AutoPtr keyType = mapType->GetKeyType(); + AutoPtr valueType = mapType->GetValueType(); + + sb.Append(prefix).AppendFormat("%s.writeInt(%s.size());\n", parcelName.string(), name.string()); + sb.Append(prefix).AppendFormat("for (Map.Entry<%s, %s> entry : %s.entrySet()) {\n", + keyType->EmitJavaType(TypeMode::NO_MODE, true).string(), + valueType->EmitJavaType(TypeMode::NO_MODE, true).string(), name.string()); + EmitWriteVariable(parcelName, "entry.getKey()", keyType, sb, prefix + TAB); + EmitWriteVariable(parcelName, "entry.getValue()", valueType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + AutoPtr arrayType = dynamic_cast(type.Get()); + AutoPtr elementType = arrayType->GetElementType(); + + sb.Append(prefix).AppendFormat("if (%s == null) {\n", name.string()); + sb.Append(prefix).AppendFormat(" %s.writeInt(-1);\n", parcelName.string()); + sb.Append(prefix).Append("} else { \n"); + EmitWriteArrayVariable(parcelName, name, elementType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitWriteArrayVariable(const String& parcelName, const String& name, + const AutoPtr& type, StringBuilder& sb, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s.writeBooleanArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s.writeByteArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s.writeShortArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s.writeIntArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s.writeLongArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s.writeFloatArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s.writeDoubleArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s.writeStringArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + sb.Append(prefix).AppendFormat("%s.writeSequenceableArray(%s);\n", parcelName.string(), name.string()); + break; + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitWriteOutArrayVariable(const String& parcelName, const String& name, + const AutoPtr& type, StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("if (%s == null) {\n", name.string()); + sb.Append(prefix).AppendFormat(" %s.writeInt(-1);\n", parcelName.string()); + sb.Append(prefix).Append("} else {\n"); + sb.Append(prefix).AppendFormat(" %s.writeInt(%s.length);\n", parcelName.string(), name.string()); + sb.Append(prefix).Append("}\n"); +} + +void JavaClientProxyCodeEmitter::EmitReadVariable(const String& parcelName, const String& name, + const AutoPtr& type, ParamAttr attribute, StringBuilder& sb, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s %s = %s.readBoolean();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s %s = %s.readByte();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s %s = %s.readShort();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s %s = %s.readInt();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s %s = %s.readLong();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s %s = %s.readFloat();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s %s = %s.readDouble();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s %s = %s.readString();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + if (attribute == ParamAttr::PARAM_OUT && type->EmitJavaType(TypeMode::NO_MODE).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("IRemoteObject %s = %s.readRemoteObject();\n", + name.string(), parcelName.string()); + break; + } + if (attribute == ParamAttr::PARAM_OUT) { + sb.Append(prefix).AppendFormat("%s %s = new %s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + } + sb.Append(prefix).AppendFormat("%s.readSequenceable(%s);\n", parcelName.string(), name.string()); + + break; + case TypeKind::TYPE_INTERFACE: + sb.Append(prefix).AppendFormat("%s %s = %s.asInterface(%s.readRemoteObject());\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), + StubName(type->EmitJavaType(TypeMode::NO_MODE)).string(), parcelName.string()); + break; + case TypeKind::TYPE_LIST: { + sb.Append(prefix).AppendFormat("%s %s = new Array%s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.string()); + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + EmitReadVariable(parcelName, "value", elementType, ParamAttr::PARAM_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.add(value);\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_MAP: { + sb.Append(prefix).AppendFormat("%s %s = new Hash%s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.string()); + + AutoPtr mapType = dynamic_cast(type.Get()); + AutoPtr keyType = mapType->GetKeyType(); + AutoPtr valueType = mapType->GetValueType(); + + EmitReadVariable(parcelName, "key", keyType, ParamAttr::PARAM_IN, sb, prefix + TAB); + EmitReadVariable(parcelName, "value", valueType, ParamAttr::PARAM_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.put(key, value);\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + AutoPtr arrayType = dynamic_cast(type.Get()); + if (attribute == ParamAttr::PARAM_OUT) { + EmitReadOutArrayVariable(parcelName, name, arrayType, sb, prefix); + } else { + EmitReadArrayVariable(parcelName, name, arrayType, attribute, sb, prefix); + } + break; + } + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitReadArrayVariable(const String& parcelName, const String& name, + const AutoPtr& arrayType, ParamAttr attribute, StringBuilder& sb, const String& prefix) +{ + AutoPtr elementType = arrayType->GetElementType(); + switch (elementType->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readBooleanArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readByteArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readShortArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readIntArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readLongArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readFloatArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readDoubleArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readStringArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + sb.Append(prefix).AppendFormat("int size = %s.readInt();\n", parcelName.string()); + sb.Append(prefix).AppendFormat("%s %s = new %s[size];\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), + elementType->EmitJavaType(TypeMode::NO_MODE).string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < size; ++i) {\n"); + EmitReadVariable(parcelName, "value", elementType, ParamAttr::PARAM_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s[i] = value;\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitReadOutArrayVariable(const String& parcelName, const String& name, + const AutoPtr& arrayType, StringBuilder& sb, const String& prefix) +{ + AutoPtr elementType = arrayType->GetElementType(); + switch (elementType->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s.readBooleanArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s.readByteArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s.readShortArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s.readIntArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s.readLongArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s.readFloatArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s.readDoubleArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s.readStringArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + sb.Append(prefix).AppendFormat("%s.readSequenceableArray(%s);\n", parcelName.string(), name.string()); + break; + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitReadOutVariable(const String& parcelName, const String& name, + const AutoPtr& type, StringBuilder& sb, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s = %s.readBoolean();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s = %s.readByte();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s = %s.readShort();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s = %s.readInt();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s = %s.readLong();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s = %s.readFloat();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s = %s.readDouble();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s = %s.readString();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + if (type->EmitJavaType(TypeMode::NO_MODE).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("%s = %s.readRemoteObject();\n", name.string(), parcelName.string()); + break; + } + sb.Append(prefix).AppendFormat("%s.readSequenceable(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_INTERFACE: + sb.Append(prefix).AppendFormat("%s = %s.asInterface(%s.readRemoteObject());\n", name.string(), + StubName(type->EmitJavaType(TypeMode::NO_MODE)).string(), parcelName.string()); + break; + case TypeKind::TYPE_LIST: { + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.string()); + + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + + EmitReadVariable(parcelName, "value", elementType, ParamAttr::PARAM_OUT, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.add(value);\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_MAP: { + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.string()); + + AutoPtr mapType = dynamic_cast(type.Get()); + AutoPtr keyType = mapType->GetKeyType(); + AutoPtr valueType = mapType->GetValueType(); + + EmitReadVariable(parcelName, "key", keyType, ParamAttr::PARAM_OUT, sb, prefix + TAB); + EmitReadVariable(parcelName, "value", valueType, ParamAttr::PARAM_OUT, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.put(key, value);\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + AutoPtr arrayType = dynamic_cast(type.Get()); + EmitReadOutArrayVariable(parcelName, name, arrayType, sb, prefix); + break; + } + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitLocalVariable(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + AutoPtr type = param->GetType(); + if (type->GetTypeKind() == TypeKind::TYPE_SEQUENCEABLE) { + sb.Append(prefix).AppendFormat("%s %s = new %s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), param->GetName().string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + } else if (type->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.Append(prefix).AppendFormat("%s %s = new Array%s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), param->GetName().string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + } else if (type->GetTypeKind() == TypeKind::TYPE_MAP) { + sb.Append(prefix).AppendFormat("%s %s = new Hash%s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), param->GetName().string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + } else { + sb.Append(prefix).AppendFormat("%s %s;\n", type->EmitJavaType(TypeMode::NO_MODE).string(), + param->GetName().string()); + } +} + +String JavaClientProxyCodeEmitter::StubName(const String& name) +{ + return name.StartsWith("I") ? (name.Substring(1) + "Stub") : (name + "Stub"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_client_proxy_code_emitter.h b/tools/hdi-gen/codegen/java_client_proxy_code_emitter.h new file mode 100755 index 000000000..bc077cb3b --- /dev/null +++ b/tools/hdi-gen/codegen/java_client_proxy_code_emitter.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_JAVA_CLIENT_PROXY_CODE_EMITTER_H +#define OHOS_HDI_JAVA_CLIENT_PROXY_CODE_EMITTER_H + +#include "java_code_emitter.h" +#include "util/file.h" + +namespace OHOS { +namespace HDI { +class JavaClientProxyCodeEmitter : public JavaCodeEmitter { +public: + JavaClientProxyCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : JavaCodeEmitter(ast, targetDirectory) {} + + virtual ~JavaClientProxyCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitProxyFile(); + + void EmitProxyImports(StringBuilder& sb); + + void EmitProxyCorelibImports(StringBuilder& sb); + + void EmitProxySelfDefinedTypeImports(StringBuilder& sb); + + void EmitProxyDBinderImports(StringBuilder& sb); + + void EmitProxyImpl(StringBuilder& sb); + + void EmitProxyConstants(StringBuilder& sb, const String& prefix); + + void EmitProxyConstructor(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + void EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitWriteMethodParameter(const AutoPtr& param, const String& parcelName, StringBuilder& sb, + const String& prefix); + + void EmitReadMethodParameter(const AutoPtr& param, const String& parcelName, StringBuilder& sb, + const String& prefix); + + void EmitWriteVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitWriteArrayVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitWriteOutArrayVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitReadVariable(const String& parcelName, const String& name, const AutoPtr& type, + ParamAttr attribute, StringBuilder& sb, const String& prefix); + + void EmitReadArrayVariable(const String& parcelName, const String& name, const AutoPtr& arrayType, + ParamAttr attribute, StringBuilder& sb, const String& prefix); + + void EmitReadOutArrayVariable(const String& parcelName, const String& name, const AutoPtr& arrayType, + StringBuilder& sb, const String& prefix); + + void EmitReadOutVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitLocalVariable(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + String StubName(const String& name); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_JAVA_CLIENT_PROXY_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_code_emitter.cpp b/tools/hdi-gen/codegen/java_code_emitter.cpp new file mode 100755 index 000000000..cc9adc685 --- /dev/null +++ b/tools/hdi-gen/codegen/java_code_emitter.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/java_code_emitter.h" +#include +#include +#include + +namespace OHOS { +namespace HDI { +const char* JavaCodeEmitter::TAB = " "; + +JavaCodeEmitter::JavaCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :LightRefCountBase(), ast_(ast), directory_(targetDirectory) +{ + if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) { + interface_ = ast_->GetInterfaceDef(); + } + + if (interface_ != nullptr) { + interfaceName_ = interface_->GetName(); + interfaceFullName_ = interface_->GetNamespace()->ToString() + interfaceName_; + infName_ = interfaceName_.StartsWith("I") ? interfaceName_.Substring(1) : interfaceName_; + proxyName_ = infName_ + "Proxy"; + proxyFullName_ = interface_->GetNamespace()->ToString() + proxyName_; + } else { + infName_ = ast_->GetName(); + } +} + +String JavaCodeEmitter::FileName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + return name.Replace('.', '/'); +} + +void JavaCodeEmitter::EmitLicense(StringBuilder& sb) +{ + if (ast_->GetLicense().IsEmpty()) { + return; + } + sb.Append(ast_->GetLicense()).Append("\n\n"); +} + +void JavaCodeEmitter::EmitPackage(StringBuilder& sb) +{ + sb.AppendFormat("package %s;\n", ast_->GetPackageName().string()); +} + +void JavaCodeEmitter::EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(prefix).AppendFormat( + "private static final int COMMAND_%s = IRemoteObject.MIN_TRANSACTION_ID + %d;\n", + ConstantName(method->GetName()).string(), i); + } +} + +String JavaCodeEmitter::MethodName(const String& name) +{ + if (name.IsEmpty() || islower(name[0])) { + return name; + } + return String::Format("%c%s", tolower(name[0]), name.Substring(1).string()); +} + +String JavaCodeEmitter::ConstantName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + StringBuilder sb; + + for (int i = 0; i < name.GetLength(); i++) { + char c = name[i]; + if (isupper(c) != 0) { + if (i > 1) { + sb.Append('_'); + } + sb.Append(c); + } else { + sb.Append(toupper(c)); + } + } + + return sb.ToString(); +} + +String JavaCodeEmitter::SpecificationParam(StringBuilder& paramSb, const String& prefix) +{ + int maxLineLen = 120; + int replaceLen = 2; + String paramStr = paramSb.ToString(); + int preIndex = 0; + int curIndex = 0; + + String insertStr = String::Format("\n%s", prefix.string()); + for (; curIndex < paramStr.GetLength(); curIndex++) { + if (curIndex == maxLineLen && preIndex > 0) { + paramStr.Replace(preIndex, replaceLen, ","); + paramStr.insert(preIndex + 1, insertStr); + } else { + if (paramStr[curIndex] == ',') { + preIndex = curIndex; + } + } + } + return paramStr; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_code_emitter.h b/tools/hdi-gen/codegen/java_code_emitter.h new file mode 100755 index 000000000..5dc400034 --- /dev/null +++ b/tools/hdi-gen/codegen/java_code_emitter.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_JAVA_CODE_EMITTER_H +#define OHOS_HDI_JAVA_CODE_EMITTER_H + +#include "ast/ast.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/string.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +class JavaCodeEmitter : public LightRefCountBase { +public: + JavaCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~JavaCodeEmitter() = default; + + virtual void EmitCode() = 0; + + inline String GetSourceFile() + { + return sourceFileName_; + } + + inline bool isInvaildDir() + { + return directory_.Equals(""); + } + + static String FileName(const String& name); +protected: + + bool CreateDirectory(); + + void EmitLicense(StringBuilder& sb); + + void EmitPackage(StringBuilder& sb); + + void EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix); + + String MethodName(const String& name); + + String ConstantName(const String& name); + + String SpecificationParam(StringBuilder& paramSb, const String& prefix); + + static const char* TAB; + + AutoPtr ast_; + AutoPtr interface_; + + String directory_; + String sourceFileName_; + + String interfaceName_; + String interfaceFullName_; + String infName_; + String proxyName_; + String proxyFullName_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_JAVA_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_code_generator.cpp b/tools/hdi-gen/codegen/java_code_generator.cpp new file mode 100755 index 000000000..853aee68d --- /dev/null +++ b/tools/hdi-gen/codegen/java_code_generator.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "java_code_generator.h" +#include +#include +#include +#include "codegen/java_client_interface_code_emitter.h" +#include "codegen/java_client_proxy_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +const char* JavaCodeGenerator::TAG = "JavaCodeGenerator"; + +bool JavaCodeGenerator::Initializate(const AutoPtr& ast, const String& targetDirectory) +{ + if (ast->GetASTFileType() == ASTFileType::AST_TYPES) { + Logger::E(TAG, "java has no types idl."); + return false; + } + + ast_ = ast; + targetDirectory_ = targetDirectory; + + if (!ResolveDirectory()) { + return false; + } + + AutoPtr clientInterfaceCodeEmitter = new JavaClientInterfaceCodeEmitter(ast_, targetDirectory_); + AutoPtr clientProxyCodeEmitter = new JavaClientProxyCodeEmitter(ast_, targetDirectory_); + + emitters_.push_back(clientInterfaceCodeEmitter); + emitters_.push_back(clientProxyCodeEmitter); + return true; +} + +bool JavaCodeGenerator::Generate() const +{ + for (auto emitter : emitters_) { + if (!emitter->isInvaildDir()) { + emitter->EmitCode(); + } + } + + return true; +} + +bool JavaCodeGenerator::ResolveDirectory() +{ + String packageFilePath = String::Format("%s/%s/", + targetDirectory_.string(), JavaCodeEmitter::FileName(ast_->GetPackageName()).string()); + targetDirectory_ = packageFilePath; + + if (!File::CreateParentDir(targetDirectory_)) { + Logger::E(TAG, "create '%s' directory failed!", targetDirectory_); + return false; + } + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_code_generator.h b/tools/hdi-gen/codegen/java_code_generator.h new file mode 100755 index 000000000..0fea5d53b --- /dev/null +++ b/tools/hdi-gen/codegen/java_code_generator.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_JAVA_CODE_GENERATOR_H +#define OHOS_HDI_JAVA_CODE_GENERATOR_H + +#include "codegen/code_generator.h" +#include "codegen/java_code_emitter.h" + +namespace OHOS { +namespace HDI { +class JavaCodeGenerator : public CodeGenerator { +public: + JavaCodeGenerator() : CodeGenerator(), + emitters_() {} + + ~JavaCodeGenerator() override {}; + + bool Initializate(const AutoPtr& ast, const String& targetDirectory) override; + bool Generate() const override; +private: + bool ResolveDirectory() override; + + static const char* TAG; + std::vector> emitters_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_JAVA_CODE_GENERATOR_H \ No newline at end of file diff --git a/tools/hdi-gen/main.cpp b/tools/hdi-gen/main.cpp new file mode 100755 index 000000000..907efed68 --- /dev/null +++ b/tools/hdi-gen/main.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/code_generator.h" +#include "codegen/generator_factory.h" +#include "parser/module_parser.h" +#include "util/file.h" +#include "util/logger.h" +#include "util/options.h" + +using namespace OHOS::HDI; + +int main(int argc, char** argv) +{ + Options& options = Options::GetInstance().Parse(argc, argv); + + if (options.HasErrors()) { + options.ShowErrors(); + return 0; + } + + if (options.DoShowUsage()) { + options.ShowUsage(); + return 0; + } + + if (options.DoShowVersion()) { + options.ShowVersion(); + return 0; + } + + if (!options.DoCompile()) { + return 0; + } + + if (options.DoGetHashKey()) { + std::unique_ptr idlFile = std::make_unique(options.GetSourceFile(), int(File::READ)); + if (!idlFile->IsValid()) { + Logger::E("hdi-gen", "open idl file failed!"); + return -1; + } + + printf("%s:%lu\n", idlFile->GetPath().string(), idlFile->GetHashKey()); + return 0; + } + + ModuleParser moduleParser(options); + if (!moduleParser.ParserDependencies()) { + Logger::E("hdi-gen", "Parsing dependencies failed."); + return -1; + } + + if (!moduleParser.CompileFiles()) { + Logger::E("hdi-gen", "Parsing .idl failed."); + return -1; + } + + AutoPtr astModule = moduleParser.GetAStModule(); + + if (!options.DoGenerateCode()) { + return 0; + } + + for (auto& astPair : astModule->GetAllAsts()) { + AutoPtr ast = astPair.second; + GeneratorFactory factory; + AutoPtr codeGen = factory.GetCodeGenerator(options.GetTargetLanguage()); + if (codeGen == nullptr) { + Logger::E("hdi-gen", "new Generate failed."); + return -1; + } + + if (!codeGen->Initializate(ast, options.GetGenerationDirectory())) { + Logger::E("hdi-gen", "Generate initializate failed."); + return -1; + } + + if (!codeGen->Generate()) { + Logger::E("hdi-gen", "Generate \"%s\" codes failed.", options.GetTargetLanguage().string()); + return -1; + } + } + + return 0; +} \ No newline at end of file diff --git a/tools/hdi-gen/parser/Makefile b/tools/hdi-gen/parser/Makefile new file mode 100755 index 000000000..186125b56 --- /dev/null +++ b/tools/hdi-gen/parser/Makefile @@ -0,0 +1,12 @@ +OBJS_DIR:=$(BUILD_DIR)/parser +TARGET = $(OBJS_DIR)/parser.a +SOURCE:=$(wildcard *.cpp) +OBJS:=$(patsubst %.cpp, $(OBJS_DIR)/%.o, $(SOURCE)) + +$(TARGET):$(OBJS) + $(Q) echo $(TARGET) + $(Q) ar -rc $@ $^ + +$(OBJS_DIR)/%.o:%.cpp + $(Q) mkdir -p $(dir $@) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ \ No newline at end of file diff --git a/tools/hdi-gen/parser/file_detail.cpp b/tools/hdi-gen/parser/file_detail.cpp new file mode 100755 index 000000000..019f95438 --- /dev/null +++ b/tools/hdi-gen/parser/file_detail.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "parser/file_detail.h" + +namespace OHOS { +namespace HDI { +void FileDetail::SetFilePath(const String& filePath) +{ + idlFilePath_ = filePath; +#ifdef __MINGW32__ + int index = idlFilePath_.LastIndexOf('\\'); +#else + int index = idlFilePath_.LastIndexOf('/'); +#endif + int end = ((idlFilePath_.LastIndexOf(".idl") == -1) ? + idlFilePath_.LastIndexOf(".idl") : idlFilePath_.LastIndexOf(".idl")); + idlName_ = idlFilePath_.Substring((index == -1) ? 0 : (index + 1), end); +} + +bool FileDetail::AddImport(const String& packageName) +{ + if (imports_.find(packageName) != imports_.end()) { + return false; + } + + imports_.emplace(packageName); + return true; +} + +String FileDetail::Dump() +{ + StringBuilder sb; + sb.AppendFormat("filePath:%s\n", idlFilePath_.string()); + sb.AppendFormat("package:%s\n", packageName_.string()); + sb.AppendFormat("import number:%d\n", imports_.size()); + for (const auto& importName : imports_) { + sb.AppendFormat("import %s\n", importName.string()); + } + return sb.ToString(); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/parser/file_detail.h b/tools/hdi-gen/parser/file_detail.h new file mode 100755 index 000000000..7f78afdd4 --- /dev/null +++ b/tools/hdi-gen/parser/file_detail.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_FILE_DETAIL_H +#define OHOS_HDI_FILE_DETAIL_H + +#include +#include "util/string_builder.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +class FileDetail { +public: + using StringSet = std::unordered_set; + + void SetFilePath(const String& filePath); + + inline String GetFilePath() const + { + return idlFilePath_; + } + + void SetPackageName(const String& packageName) + { + packageName_ = packageName; + } + + inline String GetPackageName() const + { + return packageName_; + } + + inline String GetName() const + { + return idlName_; + } + + inline String GetFullName() const + { + return packageName_ + "." + idlName_; + } + + bool AddImport(const String& packageName); + + void DelImport(const String& packageName) + { + imports_.erase(packageName); + } + + inline size_t GetImportSize() const + { + return imports_.size(); + } + + inline const StringSet& GetImports() const + { + return imports_; + } + + inline static String ImportsToPath(const String& importPkgName) + { + return importPkgName.Replace('.', '/') + ".idl"; + } + + String Dump(); + +private: + String idlFilePath_; + String packageName_; + String idlName_; + StringSet imports_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_FILE_DETAIL_H \ No newline at end of file diff --git a/tools/hdi-gen/parser/lexer.cpp b/tools/hdi-gen/parser/lexer.cpp new file mode 100755 index 000000000..81677a968 --- /dev/null +++ b/tools/hdi-gen/parser/lexer.cpp @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "parser/lexer.h" +#include +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +Lexer::Lexer() +{ + InitializeKeywords(); +} + +Lexer::~Lexer() +{ + if (currentFile_ != nullptr) { + currentFile_->Close(); + } +} + +void Lexer::InitializeKeywords() +{ + keywords_ = { + { "boolean", Token::BOOLEAN }, { "byte", Token::BYTE }, { "callback", Token::CALLBACK }, + { "char", Token::CHAR}, { "double", Token::DOUBLE }, { "enum", Token::ENUM }, + { "extends", Token::EXTENDS }, { "float", Token::FLOAT }, { "full", Token::FULL }, + { "import", Token::IMPORT }, { "in", Token::IN }, { "int", Token::INTEGER }, { "interface", Token::INTERFACE }, + { "List", Token::LIST }, { "lite", Token::LITE }, { "long", Token::LONG }, + { "Map", Token::MAP }, { "oneway", Token::ONEWAY }, { "out", Token::OUT }, + { "package", Token::PACKAGE}, { "sequenceable", Token::SEQUENCEABLE }, { "short", Token::SHORT }, + { "String", Token::STRING }, { "struct", Token::STRUCT }, { "union", Token::UNION }, + { "unsigned", Token::UNSIGNED }, { "FileDescriptor", Token::FILEDESCRIPTOR } + }; + + delimiters_ = { + {'<', Token::ANGLE_BRACKETS_LEFT}, {'>', Token::ANGLE_BRACKETS_RIGHT}, + {'{', Token::BRACES_LEFT}, {'}', Token::BRACES_RIGHT}, + {'[', Token::BRACKETS_LEFT}, {']', Token::BRACKETS_RIGHT}, + {',', Token::COMMA}, {'(', Token::PARENTHESES_LEFT}, + {')', Token::PARENTHESES_RIGHT}, {'.', Token::DOT}, + {':', Token::COLON}, {';', Token::SEMICOLON}, + {'=', Token::ASSIGN} + }; + + tokenDumps_ = { + { Token::ANGLE_BRACKETS_LEFT, "<" }, { Token::ANGLE_BRACKETS_RIGHT, ">"}, { Token::BOOLEAN, "boolean"}, + { Token::BRACES_LEFT, "{"}, { Token::BRACES_RIGHT, "}"}, { Token::BRACKETS_LEFT, "["}, + { Token::BRACKETS_RIGHT, "]"}, { Token::BYTE, "byte"}, { Token::CALLBACK, "callback"}, + { Token::CHAR, "char"}, { Token::COLON, ":"}, { Token::COMMA, ","}, + { Token::DOT, "."}, { Token::DOUBLE, "double"}, { Token::END_OF_FILE, "eof"}, + { Token::ENUM, "enum"}, { Token::EXTENDS, "extends"}, { Token::FLOAT, "float"}, + { Token::FULL, "full"}, { Token::IMPORT, "import"}, { Token::IN, "in"}, + { Token::INTEGER, "int"}, { Token::INTERFACE, "interface"}, { Token::LITE, "lite"}, + { Token::LIST, "List"}, { Token::LONG, "long"}, { Token::MAP, "Map"}, + { Token::ONEWAY, "oneway"}, { Token::OUT, "out"}, { Token::PACKAGE, "package"}, + { Token::SEQUENCEABLE, "sequenceable"}, { Token::STRUCT, "struct"}, { Token::PARENTHESES_LEFT, "("}, + { Token::PARENTHESES_RIGHT, ")"}, { Token::SEMICOLON, ";"}, { Token::SHORT, "short"}, + { Token::STRING, "String"}, { Token::UNION, "union"}, { Token::UNSIGNED, "unsigned"}, + { Token::FILEDESCRIPTOR, "FileDescriptor"} + }; +} + +bool Lexer::OpenSourceFile(const String& filePath) +{ + currentFile_ = std::make_unique(filePath, int(File::READ)); + if (!currentFile_->IsValid()) { + return false; + } + + return true; +} + +Token Lexer::GetToken(bool skipComment) +{ + if (!havePeek_) { + currentToken_ = ReadToken(skipComment); + } + havePeek_ = false; + return currentToken_; +} + +Token Lexer::PeekToken(bool skipComment) +{ + if (!havePeek_) { + currentToken_ = ReadToken(skipComment); + havePeek_ = true; + } + return currentToken_; +} + +Token Lexer::ReadToken(bool skipComment) +{ + while (!currentFile_->IsEof()) { + char c = currentFile_->GetChar(); + tokenLineNo_ = currentFile_->GetCharLineNumber(); + tokenColumnNo_ = currentFile_->GetCharColumnNumber(); + if (IsSpace(c)) { + continue; + } else if (IsAlphabet(c) || c == '_') { + Token t = ReadIdentifier(c); + return t; + } else if (IsDecimalDigital(c)) { + Token t = ReadDecimalDigital(c); + return t; + } + + auto iter = delimiters_.find(c); + if (iter != delimiters_.end()) { + return iter->second; + } + + if (c == '/') { + if (currentFile_->PeekChar() == '/') { + ReadLineComment(c); + if (!skipComment) { + return currentToken_; + } + continue; + } else if (currentFile_->PeekChar() == '*') { + ReadBlockComment(c); + if (!skipComment) { + return currentToken_; + } + continue; + } + currentToken_ = Token::UNKNOWN; + return currentToken_; + } + + currentToken_ = Token::UNKNOWN; + return currentToken_; + } + currentToken_ = Token::END_OF_FILE; + return currentToken_; +} + +Token Lexer::ReadIdentifier(char c) +{ + StringBuilder sb; + + sb.Append(c); + while (!currentFile_->IsEof()) { + c = currentFile_->PeekChar(); + if (IsAlphabet(c) || c == '_' || IsDecimalDigital(c) || c == '.') { + c = currentFile_->GetChar(); + sb.Append(c); + continue; + } + if (IsSpace(c)) { + currentFile_->GetChar(); + } + break; + } + String key = sb.ToString(); + auto it = keywords_.find(key); + if (it == keywords_.end()) { + identifier_ = key; + currentToken_ = Token::IDENTIFIER; + } else { + currentToken_ = it->second; + } + + return currentToken_; +} + +Token Lexer::ReadDecimalDigital(char c) +{ + StringBuilder sb; + sb.Append(c); + while (!currentFile_->IsEof()) { + c = currentFile_->PeekChar(); + if (IsDecimalDigital(c)) { + c = currentFile_->GetChar(); + sb.Append(c); + continue; + } else { + break; + } + } + digit_ = sb.ToString(); + currentToken_ = Token::DIGIT; + return currentToken_; +} + +Token Lexer::ReadLineComment(char c) +{ + StringBuilder sb; + + sb.Append(c); + while (!currentFile_->IsEof()) { + c = currentFile_->GetChar(); + if (c == '\n') { + break; + } + sb.Append(c); + } + comment_ = sb.ToString(); + currentToken_ = Token::COMMENT_LINE; + return currentToken_; +} + +Token Lexer::ReadBlockComment(char c) +{ + StringBuilder sb; + + sb.Append(c); + while (!currentFile_->IsEof()) { + c = currentFile_->GetChar(); + sb.Append(c); + if (c == '*' && currentFile_->PeekChar() == '/') { + c = currentFile_->GetChar(); + sb.Append(c); + break; + } + } + comment_ = sb.ToString(); + currentToken_ = Token::COMMENT_BLOCK; + return currentToken_; +} + +void Lexer::SkipCurrentLine() +{ + while (!currentFile_->IsEof()) { + char c = currentFile_->GetChar(); + if (c == '\n') { + currentFile_->GetChar(); + return; + } + } +} + +bool Lexer::SkipCurrentLine(char untilChar) +{ + while (!currentFile_->IsEof()) { + int c = currentFile_->GetChar(); + if (c == untilChar) { + return true; + } + if (c == '\n') { + currentFile_->GetChar(); + return false; + } + } + return true; +} + +void Lexer::Skip(char untilChar) +{ + while (!currentFile_->IsEof()) { + int c = currentFile_->GetChar(); + if (c == untilChar) { + return; + } + } +} + +void Lexer::SkipEof() +{ + while (!currentFile_->IsEof()) {} +} + +int Lexer::TokenToChar(Token token) +{ + switch (token) { + case Token::ANGLE_BRACKETS_LEFT: + return '<'; + case Token::ANGLE_BRACKETS_RIGHT: + return '>'; + case Token::BRACES_LEFT: + return '{'; + case Token::BRACES_RIGHT: + return '}'; + case Token::BRACKETS_LEFT: + return '['; + case Token::BRACKETS_RIGHT: + return ']'; + case Token::COMMA: + return ','; + case Token::DOT: + return '.'; + case Token::PARENTHESES_LEFT: + return '('; + case Token::PARENTHESES_RIGHT: + return ')'; + case Token::COLON: + return ':'; + case Token::SEMICOLON: + return ';'; + case Token::BOOLEAN: + case Token::BYTE: + case Token::CHAR: + case Token::COMMENT_BLOCK: + case Token::COMMENT_LINE: + case Token::DOUBLE: + case Token::END_OF_FILE: + case Token::FLOAT: + case Token::IDENTIFIER: + case Token::IN: + case Token::INTEGER: + case Token::LIST: + case Token::LONG: + case Token::MAP: + case Token::ONEWAY: + case Token::OUT: + case Token::SEQUENCEABLE: + case Token::SHORT: + case Token::STRING: + default: + return -1; + } +} + +String Lexer::DumpToken() const +{ + auto iter = tokenDumps_.find(currentToken_); + if (iter != tokenDumps_.end()) { + return iter->second; + } + + if (currentToken_ == Token::COMMENT_BLOCK || currentToken_ == Token::COMMENT_LINE) { + return comment_; + } + + if (currentToken_ == Token::IDENTIFIER) { + return identifier_; + } + + return "unknown token"; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/parser/lexer.h b/tools/hdi-gen/parser/lexer.h new file mode 100755 index 000000000..dde09fda6 --- /dev/null +++ b/tools/hdi-gen/parser/lexer.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_LEXER_H +#define OHOS_HDI_LEXER_H + +#include +#include +#include +#include +#include "parser/token.h" +#include "util/file.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class Lexer { +public: + Lexer(); + + ~Lexer(); + + bool OpenSourceFile(const String& filePath); + + Token GetToken(bool skipComment = true); + + Token PeekToken(bool skipComment = true); + + inline String GetIdentifier() const + { + return identifier_; + } + + inline unsigned long GetDigit() const + { + return std::atoll(digit_.string()); + } + + inline String GetComment() const + { + return comment_; + } + + void SkipCurrentLine(); + + bool SkipCurrentLine(char untilChar); + + void Skip(char untilChar); + + void SkipEof(); + + inline String GetFilePath() const + { + if (currentFile_ == nullptr) { + return String(""); + } + + return currentFile_->GetPath(); + } + + String DumpToken() const; + + inline int GetTokenLineNumber() const + { + return tokenLineNo_; + } + + inline int GetTokenColumnNumber() const + { + return tokenColumnNo_; + } + + static int TokenToChar(Token token); + +private: + void InitializeKeywords(); + + Token ReadToken(bool skipComment); + + Token ReadIdentifier(char c); + + Token ReadDecimalDigital(char c); + + Token ReadLineComment(char c); + + Token ReadBlockComment(char c); + + inline static bool IsAlphabet(char c) + { + return isalpha(c); + } + + inline static bool IsDecimalDigital(char c) + { + return isdigit(c); + } + + inline static bool IsSpace(char c) + { + return isspace(c); + } + + static const char* TAG; + std::unordered_map keywords_; + std::unordered_map delimiters_; + std::unordered_map tokenDumps_; + Token currentToken_ = Token::UNKNOWN; + int tokenLineNo_ = 0; + int tokenColumnNo_ = 0; + String identifier_; + String digit_; + String comment_; + bool havePeek_ = false; + std::unique_ptr currentFile_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_LEXER_H \ No newline at end of file diff --git a/tools/hdi-gen/parser/module_parser.cpp b/tools/hdi-gen/parser/module_parser.cpp new file mode 100755 index 000000000..d2f3b2586 --- /dev/null +++ b/tools/hdi-gen/parser/module_parser.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "parser/module_parser.h" +#include + +namespace OHOS { +namespace HDI { +const char* ModuleParser::TAG = "ModuleParser"; + +bool ModuleParser::ParserDependencies() +{ + if (!ParserAllImports(option_.GetSourceFile())) { + Logger::E(TAG, "Parsing all idl file failed."); + return false; + } + + if (!CheckCircularReference()) { + Logger::E(TAG, "has circle reference."); + return false; + } + + return true; +} + +bool ModuleParser::CompileFiles() +{ + std::unique_ptr parserPtr = std::make_unique(option_, module_); + + for (const auto& filePath : compileFiles_) { + if (!parserPtr->Parse(filePath)) { + Logger::E(TAG, "parse %s failed", filePath.string()); + return false; + } + } + + return true; +} + +bool ModuleParser::ParserAllImports(const String& rootFilePath) +{ + std::unique_ptr parserPtr = std::make_unique(option_); + std::shared_ptr fileInfo = nullptr; + + if (!parserPtr->Parse(rootFilePath, fileInfo)) { + return false; + } + + if (fileInfo == nullptr) { + return false; + } + + sourceFiles_[fileInfo->GetFullName()] = fileInfo; + return ParserAllImportsRecursion(fileInfo); +} + +bool ModuleParser::ParserAllImportsRecursion(const std::shared_ptr& fileInfo) +{ + for (const auto& importName : fileInfo->GetImports()) { + if (sourceFiles_.find(importName) != sourceFiles_.end()) { + continue; + } + + String filePath = FileDetail::ImportsToPath(importName); + + std::unique_ptr parserPtr = std::make_unique(option_); + std::shared_ptr file = nullptr; + if (!parserPtr->Parse(filePath, file)) { + Logger::E(TAG, "Parsing %s failed.", filePath.string()); + return false; + } + + if (file == nullptr) { + Logger::E(TAG, "Parsing %s failed, generator filedetail is nullptr.", filePath.string()); + return false; + } + + sourceFiles_[file->GetFullName()] = file; + + if (!ParserAllImportsRecursion(file)) { + Logger::E(TAG, "Parsing %s file's import failed.", file->GetFilePath().string()); + return false; + } + } + + return true; +} + +bool ModuleParser::CheckCircularReference() +{ + std::queue> fileQueue; + for (const auto& filePair : sourceFiles_) { + std::shared_ptr fileNode = filePair.second; + if (fileNode->GetImportSize() == 0) { + fileQueue.push(fileNode); + } + } + + compileFiles_.clear(); + while (!fileQueue.empty()) { + std::shared_ptr importFile = fileQueue.front(); + fileQueue.pop(); + compileFiles_.push_back(importFile->GetFilePath()); + + for (const auto& filePair : sourceFiles_) { + std::shared_ptr fileNode = filePair.second; + if (fileNode->GetImportSize() > 0) { + fileNode->DelImport(importFile->GetFullName()); + if (fileNode->GetImportSize() == 0) { + fileQueue.push(fileNode); + } + } + } + } + + if (compileFiles_.size() < sourceFiles_.size()) { + return false; + } + + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/parser/module_parser.h b/tools/hdi-gen/parser/module_parser.h new file mode 100755 index 000000000..ba94b8f34 --- /dev/null +++ b/tools/hdi-gen/parser/module_parser.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_MODULE_PARSER_H +#define OHOS_HDI_MODULE_PARSER_H + +#include +#include "parser/file_detail.h" +#include "parser/parser.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +class ModuleParser { +public: + using FileDetailMap = std::unordered_map, StringHashFunc, StringEqualFunc>; + + explicit ModuleParser(const Options& option) : option_(option), + sourceFiles_(), + searchedFile_(), + traceFilePtr_(nullptr), + allCirclesFile_(), + compileFiles_(), + module_(new ASTModule()) {} + + ~ModuleParser() {} + + // parser file and circular reference + bool ParserDependencies(); + + bool CompileFiles(); + + inline AutoPtr GetAStModule() const + { + return module_; + } + +private: + // parse all idl file involved in compilation. + bool ParserAllImports(const String& rootFilePath); + + bool ParserAllImportsRecursion(const std::shared_ptr& fileInfo); + + // check circular reference and reverse topology sorting of all idl file + bool CheckCircularReference(); + + static const char* TAG; + const Options& option_; + FileDetailMap sourceFiles_; + + std::set searchedFile_; + std::shared_ptr> traceFilePtr_; + std::vector> allCirclesFile_; + + std::vector compileFiles_; + + AutoPtr module_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_MODULE_PARSER_H \ No newline at end of file diff --git a/tools/hdi-gen/parser/parser.cpp b/tools/hdi-gen/parser/parser.cpp new file mode 100755 index 000000000..73a1499db --- /dev/null +++ b/tools/hdi-gen/parser/parser.cpp @@ -0,0 +1,1443 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "parser/parser.h" +#include "ast/ast_array_type.h" +#include "ast/ast_enum_type.h" +#include "ast/ast_list_type.h" +#include "ast/ast_map_type.h" +#include "ast/ast_parameter.h" +#include "ast/ast_sequenceable_type.h" +#include "ast/ast_struct_type.h" +#include "ast/ast_union_type.h" +#include "util/logger.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +const char* Parser::TAG = "Parser"; + +Parser::Parser(const Options& options, const AutoPtr& module) + :options_(options), lexer_(nullptr), errors_(nullptr), ast_(nullptr), astModule_(module) +{} + +bool Parser::Parse(const String& sourceFile) +{ + lexer_ = std::make_shared(); + bool ret = lexer_->OpenSourceFile(sourceFile); + if (!ret) { + Logger::E(TAG, "Fail to open file '%s'.", sourceFile.string()); + return false; + } + + ret = ParseFile(); + ret = CheckIntegrity() && ret; + ret = AddAst() && ret; + if (!ret || errors_ != nullptr) { + ShowError(); + return false; + } + + if (options_.DoDumpAST()) { + String astStr = ast_->Dump(""); + printf("%s\n", astStr.string()); + } + + return ret; +} + +bool Parser::Parse(const String& sourceFile, std::shared_ptr& fileDetailPtr) +{ + lexer_ = std::make_shared(); + bool ret = lexer_->OpenSourceFile(sourceFile); + if (!ret) { + Logger::E(TAG, "Fail to open file '%s'.", sourceFile.string()); + return false; + } + + ret = ParseIdlDetail(fileDetailPtr); + if (!ret) { + ShowError(); + return false; + } + + return ret; +} + +bool Parser::ParseIdlDetail(std::shared_ptr& fileDetailPtr) +{ + bool ret = true; + fileDetailPtr = std::make_shared(); + fileDetailPtr->SetFilePath(lexer_->GetFilePath()); + + Token token; + while ((token = lexer_->PeekToken()) != Token::END_OF_FILE) { + switch (token) { + case Token::PACKAGE: + ret = ParseIdlPackage(fileDetailPtr) && ret; + break; + case Token::IMPORT: + ret = ParseIdlImport(fileDetailPtr) && ret; + break; + default: + lexer_->GetToken(); + break; + } + } + lexer_->GetToken(); + return ret; +} + +bool Parser::ParseIdlPackage(std::shared_ptr& fileDetailPtr) +{ + lexer_->GetToken(); + String packageName; + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + if (token == Token::SEMICOLON) { + LogError(String::Format("expected identifier before ';'.")); + lexer_->GetToken(); + } else { + LogError(String::Format("'%s' is an invalid package name.", lexer_->DumpToken().string())); + } + lexer_->SkipCurrentLine(); + return false; + } else { + lexer_->GetToken(); + packageName = lexer_->GetIdentifier(); + token = lexer_->PeekToken(); + } + + if (token != Token::SEMICOLON) { + LogError(String::Format("expected ';' before '%s'", lexer_->DumpToken().string())); + return false; + } + + // read ';' + lexer_->GetToken(); + + if (packageName.IsEmpty()) { + LogError(String("Package name is not expected.")); + return false; + } else if (!IsValidTypeName(packageName)) { + LogError(String::Format("Package name '%s' is illegal.", packageName.string())); + return false; + } else if (!CheckPackageName(lexer_->GetFilePath(), packageName)) { + LogError(String::Format("Package name '%s' does not match file apth '%s'.", + packageName.string(), lexer_->GetFilePath().string())); + return false; + } + + fileDetailPtr->SetPackageName(packageName); + + return true; +} + +bool Parser::ParseIdlImport(std::shared_ptr& fileDetailPtr) +{ + lexer_->GetToken(); + + String importPkgName; + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + if (token == Token::SEMICOLON) { + LogError(String::Format("expected identifier before ';'.")); + lexer_->GetToken(); + } else { + LogError(String::Format("'%s' is an invalid import package name.", lexer_->DumpToken().string())); + } + lexer_->SkipCurrentLine(); + return false; + } + lexer_->GetToken(); + importPkgName = lexer_->GetIdentifier(); + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("expected ';' before '%s'.", lexer_->DumpToken().string())); + return false; + } + + // read ';' + lexer_->GetToken(); + if (importPkgName.IsEmpty()) { + LogError(String("import package name is not expected.")); + return false; + } else if (!IsValidTypeName(importPkgName)) { + LogError(String::Format("import package name '%s' is illegal.", importPkgName.string())); + return false; + } + + if (!fileDetailPtr->AddImport(importPkgName)) { + LogError(String::Format("the package of '%s' has been imported.", importPkgName.string())); + return false; + } + + return true; +} + +bool Parser::ParseFile() +{ + bool ret = true; + + ast_ = new AST(); + ast_->SetIdlFile(lexer_->GetFilePath()); + + ParseLicense(); + + Token token; + while ((token = lexer_->PeekToken()) != Token::END_OF_FILE) { + switch (token) { + case Token::PACKAGE: + ret = ParsePackageName() && ret; + continue; + case Token::IMPORT: + ret = ParseImport() && ret; + continue; + case Token::SEQUENCEABLE: + ret = ParseSequenceable() && ret; + continue; + case Token::BRACKETS_LEFT: + ret = ParseAttribute() && ret; + continue; + case Token::INTERFACE: + ret = ParseInterface() && ret; + continue; + case Token::COMMENT_LINE: + lexer_->GetToken(); + continue; + case Token::ENUM: + ret = ParseEnumDefine() && ret; + continue; + case Token::STRUCT: + ret = ParseStructDefine() && ret; + continue; + case Token::UNION: + ret = ParseUnionDefine() && ret; + continue; + default: + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->GetToken(); + ret = false; + continue; + } + } + lexer_->GetToken(); + + // here, ast_ cannot be a sequenceable idl + if (ast_->GetInterfaceDef() != nullptr) { + if (ast_->GetInterfaceDef()->IsCallback()) { + ast_->SetAStFileType(ASTFileType::AST_ICALLBACK); + } else { + ast_->SetAStFileType(ASTFileType::AST_IFACE); + } + } else { + ast_->SetAStFileType(ASTFileType::AST_TYPES); + } + + return ret; +} + +bool Parser::ParseLicense() +{ + Token token = lexer_->PeekToken(false); + if (token != Token::COMMENT_BLOCK) { + return false; + } + + lexer_->GetToken(false); + + ast_->SetLicense(lexer_->GetComment()); + + return true; +} + +bool Parser::ParsePackageName() +{ + lexer_->GetToken(); + + String packageFullName; + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + if (token == Token::SEMICOLON) { + LogError(String::Format("expected identifier before ';'.")); + } else { + LogError(String::Format("'%s' is an invalid package name.", lexer_->DumpToken().string())); + } + lexer_->SkipCurrentLine(); + lexer_->GetToken(); + return false; + } else { + lexer_->GetToken(); + packageFullName = lexer_->GetIdentifier(); + token = lexer_->PeekToken(); + } + + if (token != Token::SEMICOLON) { + LogError(String::Format("expected ';' before '%s'", lexer_->DumpToken().string())); + return false; + } + + // read ';' + lexer_->GetToken(); + + if (packageFullName.IsEmpty()) { + LogError(String("Package name is not expected.")); + return false; + } else if (!IsValidTypeName(packageFullName)) { + LogError(String::Format("Package name '%s' is illegal.", packageFullName.string())); + return false; + } else if (!CheckPackageName(lexer_->GetFilePath(), packageFullName)) { + LogError(String::Format("Package name '%s' does not match file apth '%s'.", + packageFullName.string(), lexer_->GetFilePath().string())); + return false; + } + + ast_->SetPackageName(packageFullName); + + return true; +} + +bool Parser::ParseImport() +{ + lexer_->GetToken(); + + String packageFullName; + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + if (token == Token::SEMICOLON) { + LogError(String::Format("expected identifier before ';'.")); + } else { + LogError(String::Format("%s is an invalid import package name.", lexer_->DumpToken().string())); + } + lexer_->SkipCurrentLine(); + lexer_->GetToken(); + return false; + } + lexer_->GetToken(); + packageFullName = lexer_->GetIdentifier(); + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("expected ';' before '%s'.", lexer_->DumpToken().string())); + return false; + } + + // read ';' + lexer_->GetToken(); + if (packageFullName.IsEmpty()) { + LogError(String("import package name is not expected.")); + return false; + } else if (!IsValidTypeName(packageFullName)) { + LogError(String::Format("import package name '%s' is illegal.", packageFullName.string())); + return false; + } + + AutoPtr importAst = astModule_->GetAst(packageFullName); + if (importAst == nullptr) { + LogError(String("not find import ast.")); + return false; + } + + if (!ast_->AddImport(importAst)) { + LogError(String::Format("the package '%s' has been import", packageFullName.string())); + return false; + } + + return true; +} + +bool Parser::ParseSequenceable() +{ + lexer_->GetToken(); + String classFullName; + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + if (token == Token::SEMICOLON) { + LogError(String::Format("expected identifier before ';'.")); + } else { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + } + lexer_->SkipCurrentLine(); + lexer_->GetToken(); + return false; + } + lexer_->GetToken(); + classFullName = lexer_->GetIdentifier(); + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("expected ';' before '%s'.", lexer_->DumpToken().string())); + return false; + } + // read ';' + lexer_->GetToken(); + + if (classFullName.IsEmpty()) { + LogError(String("class name is not expected.")); + return false; + } else if (!IsValidTypeName(classFullName)) { + LogError(String::Format("class name '%s' is illegal.", classFullName.string())); + return false; + } + + AutoPtr sequenceable = new ASTSequenceableType(); + int index = classFullName.LastIndexOf('.'); + if (index != -1) { + sequenceable->SetName(classFullName.Substring(index + 1)); + sequenceable->SetNamespace(ast_->ParseNamespace(classFullName.Substring(0, index + 1))); + } else { + sequenceable->SetName(classFullName); + } + + AutoPtr sequenceableAst = new AST(); + sequenceableAst->SetFullName(classFullName); + sequenceableAst->AddSequenceableDef(sequenceable); + sequenceableAst->SetAStFileType(ASTFileType::AST_SEQUENCEABLE); + ast_->AddImport(sequenceableAst); + + return true; +} + +bool Parser::ParseAttribute() +{ + bool ret = true; + AutoPtr attributes = nullptr; + + // read '[' + Token token = lexer_->GetToken(); + if (token == Token::BRACKETS_LEFT) { + attributes = new Attribute(); + token = lexer_->PeekToken(); + while (token != Token::BRACKETS_RIGHT) { + switch (token) { + case Token::ONEWAY: + attributes->isOneWay = true; + break; + case Token::CALLBACK: + attributes->isCallback = true; + break; + case Token::FULL: + attributes->isFull = true; + break; + case Token::LITE: + attributes->isLite = true; + break; + default: { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(Lexer::TokenToChar(Token::BRACKETS_RIGHT)); + lexer_->GetToken(); + return false; + } + } + lexer_->GetToken(); + token = lexer_->PeekToken(); + if (token == Token::COMMA) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token == Token::BRACKETS_RIGHT) { + break; + } else { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + return false; + } + } + lexer_->GetToken(); + } + + token = lexer_->PeekToken(); + switch (token) { + case Token::ENUM: + ret = ParseEnumDefine(attributes) && ret; + break; + case Token::STRUCT: + ret = ParseStructDefine(attributes) && ret; + break; + case Token::UNION: + ret = ParseUnionDefine(attributes) && ret; + break; + case Token::INTERFACE: + ret = ParseInterface(attributes) && ret; + break; + default: { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + return false; + } + } + return ret; +} + +bool Parser::ParseInterface(const AutoPtr& attributes) +{ + lexer_->GetToken(); + bool ret = true; + bool isOneWay = false; + bool isCallback = false; + bool isFull = false; + bool isLite = false; + String interfaceName; + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->Skip('}'); + lexer_->GetToken(); + return false; + } + lexer_->GetToken(); + + interfaceName = lexer_->GetIdentifier(); + + token = lexer_->PeekToken(); + if (token != Token::BRACES_LEFT) { + LogError(String::Format("expected '{' after the '%s'.", lexer_->DumpToken().string())); + lexer_->Skip('}'); + lexer_->GetToken(); + return false; + } + + // read '{' + lexer_->GetToken(); + + if (interfaceName.IsEmpty()) { + LogError(String("interface name is expected.")); + return false; + } + + AutoPtr interface = new ASTInterfaceType(); + interface->SetName(interfaceName); + interface->SetNamespace(ast_->ParseNamespace(ast_->GetFullName())); + + if (!interface->GetName().Equals(ast_->GetName())) { + LogError(String::Format("Module name '%s' is not equal to interface name '%s'.", + ast_->GetName().string(), interface->GetName().string())); + } + + interface->SetLicense(ast_->GetLicense()); + if (attributes != nullptr) { + interface->SetOneWay(attributes->isOneWay); + interface->SetCallback(attributes->isCallback); + interface->SetFull(attributes->isFull); + interface->SetLite(attributes->isLite); + } + + while (token != Token::BRACES_RIGHT && token != Token::END_OF_FILE) { + ret = ParseMethod(interface) && ret; + token = lexer_->PeekToken(); + } + + if (token != Token::BRACES_RIGHT) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipEof(); + return false; + } + + lexer_->GetToken(); + + if (ast_->GetInterfaceDef() != nullptr) { + LogError(String::Format("an interface class already exists int idl file.")); + lexer_->SkipEof(); + return false; + } + + ast_->AddInterfaceDef(interface); + + return ret; +} + +bool Parser::ParseMethod(const AutoPtr& interface) +{ + bool ret = true; + AutoPtr attributes = new Attribute(); + ret = ParseMethodAttr(interface, attributes) && ret; + if (!ret) { + return false; + } + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("Method name is expected.")); + if (token == Token::BRACES_RIGHT) { + return false; + } + // jump over colon + lexer_->GetToken(); + while (token != Token::SEMICOLON && token != Token::END_OF_FILE) { + token = lexer_->PeekToken(); + if (token == Token::BRACES_RIGHT) { + break; + } + lexer_->GetToken(); + } + return false; + } + token = lexer_->GetToken(); + + AutoPtr method = new ASTMethod(); + method->SetName(lexer_->GetIdentifier()); + + if (attributes != nullptr) { + method->SetOneWay(attributes->isOneWay); + method->SetFull(attributes->isFull); + method->SetLite(attributes->isLite); + } + + token = lexer_->PeekToken(); + if (token != Token::PARENTHESES_LEFT) { + LogError(String("'(' is expected.")); + if (token == Token::BRACES_RIGHT) { + return false; + } + // jump over colon + lexer_->GetToken(); + while (token != Token::SEMICOLON && token != Token::END_OF_FILE) { + token = lexer_->PeekToken(); + if (token == Token::BRACES_RIGHT) { + break; + } + lexer_->GetToken(); + } + return false; + } + token = lexer_->GetToken(); + + token = lexer_->PeekToken(); + while (token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) { + ret = ParseParameter(method) && ret; + token = lexer_->PeekToken(); + if (token == Token::COMMA) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token != Token::PARENTHESES_RIGHT) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(';'); + lexer_->GetToken(); + return false; + } + } + + lexer_->GetToken(); + if (!ret) { + lexer_->SkipCurrentLine(); + return false; + } + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String("';' is expected.")); + return false; + } + lexer_->GetToken(); + interface->AddMethod(method); + return ret; +} + +bool Parser::ParseMethodAttr(const AutoPtr& interface, const AutoPtr& attributes) +{ + if (interface == nullptr || attributes == nullptr) { + return false; + } + + Token token = lexer_->PeekToken(); + if (token == Token::BRACES_RIGHT) { + LogError(String::Format("%s has no method.", interface->GetName().string())); + lexer_->SkipCurrentLine(Lexer::TokenToChar(Token::BRACES_RIGHT)); + lexer_->GetToken(); + return false; + } + + if (token == Token::BRACKETS_LEFT) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + while (token != Token::BRACKETS_RIGHT) { + switch (token) { + case Token::ONEWAY: + attributes->isOneWay = true; + break; + case Token::FULL: + attributes->isFull = true; + break; + case Token::LITE: + attributes->isLite = true; + break; + default: { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(Lexer::TokenToChar(Token::BRACKETS_RIGHT)); + lexer_->GetToken(); + return false; + } + } + lexer_->GetToken(); + token = lexer_->PeekToken(); + if (token == Token::COMMA) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token == Token::BRACKETS_RIGHT) { + } else { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(Lexer::TokenToChar(Token::BRACKETS_RIGHT)); + lexer_->GetToken(); + return false; + } + } + lexer_->GetToken(); + } + return true; +} + +bool Parser::ParseParameter(const AutoPtr& method) +{ + Token token = lexer_->PeekToken(); + if (token != Token::BRACKETS_LEFT) { + LogError(String("'[' is expected.")); + while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } + return false; + } + lexer_->GetToken(); + + AutoPtr parameter = new ASTParameter(); + if (!ParseParamAttr(parameter)) { + return false; + } + + token = lexer_->PeekToken(); + if (token != Token::BRACKETS_RIGHT) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + while (token != Token::SEMICOLON && token != Token::END_OF_FILE) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } + return false; + } + lexer_->GetToken(); + AutoPtr type = ParseType(); + if (type == nullptr) { + while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } + return false; + } + + token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("Parameter name is expected.")); + while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } + return false; + } + lexer_->GetToken(); + parameter->SetName(lexer_->GetIdentifier()); + parameter->SetType(type); + method->AddParameter(parameter); + return true; +} + +bool Parser::ParseParamAttr(const AutoPtr& parameter) +{ + if (parameter == nullptr) { + return false; + } + Token token = lexer_->PeekToken(); + if (token == Token::IN) { + lexer_->GetToken(); + parameter->SetAttribute(ParamAttr::PARAM_IN); + } else if (token == Token::OUT) { + lexer_->GetToken(); + parameter->SetAttribute(ParamAttr::PARAM_OUT); + } else { + LogError(String::Format("'%s' is not a parameter property, it must be 'in' or 'out'.", + lexer_->DumpToken().string())); + while (token != Token::SEMICOLON && token != Token::END_OF_FILE) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } + return false; + } + return true; +} + +AutoPtr Parser::ParseType() +{ + int typeLineNo = lexer_->GetTokenLineNumber(); + int typeColumnNo = lexer_->GetTokenColumnNumber(); + AutoPtr type; + + Token token = lexer_->PeekToken(); + if (IsPrimitiveType(token)) { + lexer_->GetToken(); + type = ast_->FindType(lexer_->DumpToken()); + } else if (token == Token::LIST) { + type = ParseList(); + } else if (token == Token::MAP) { + type = ParseMap(); + } else if (token == Token::ENUM || token == Token::STRUCT || token == Token::UNION) { + type = ParseCustomType(); + } else if (token == Token::IDENTIFIER) { + lexer_->GetToken(); + type = ast_->FindType(lexer_->GetIdentifier()); + } else if (token == Token::UNSIGNED) { + String unsignedStr = lexer_->DumpToken(); + lexer_->GetToken(); + token = lexer_->PeekToken(); + switch (token) { + case Token::CHAR: + case Token::SHORT: + case Token::INTEGER: + case Token::LONG: { + type = ast_->FindType(unsignedStr + " " + lexer_->DumpToken()); + lexer_->GetToken(); + break; + } + default: { + LogError(typeLineNo, typeColumnNo, + String::Format("'unsigned %s' type was not declared in the idl file.", + lexer_->DumpToken().string())); + return nullptr; + } + } + } else { + LogError(typeLineNo, typeColumnNo, String("Invalid type name.")); + return nullptr; + } + + if (type == nullptr) { + LogError(typeLineNo, typeColumnNo, String::Format("Type '%s' was not declared in any idl file.", + lexer_->DumpToken().string())); + } + + token = lexer_->PeekToken(); + if (token == Token::BRACKETS_LEFT) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + if (token != Token::BRACKETS_RIGHT) { + LogError(typeLineNo, typeColumnNo, String("']' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + if (type != nullptr) { + AutoPtr arrayType = new ASTArrayType(); + arrayType->SetElementType(type); + + type = ast_->FindType(arrayType->ToString()); + if (type == nullptr) { + ast_->AddType(arrayType.Get()); + type = static_cast(arrayType.Get()); + } + } + } + + if (!CheckType(typeLineNo, typeColumnNo, type)) { + return nullptr; + } + + return type; +} + +AutoPtr Parser::ParseList() +{ + lexer_->GetToken(); + + Token token = lexer_->PeekToken(); + if (token != Token::ANGLE_BRACKETS_LEFT) { + LogError(String("'<' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + AutoPtr type = ParseType(); + if (type == nullptr) { + lexer_->SkipCurrentLine('>'); + lexer_->GetToken(); + return nullptr; + } + + token = lexer_->PeekToken(); + if (token != Token::ANGLE_BRACKETS_RIGHT) { + LogError(String("'>' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + AutoPtr list = new ASTListType(); + list->SetElementType(type); + + AutoPtr ret = ast_->FindType(list->ToString()); + if (ret == nullptr) { + ast_->AddType(list.Get()); + ret = list.Get(); + } + + return ret; +} + +AutoPtr Parser::ParseMap() +{ + lexer_->GetToken(); + + Token token = lexer_->PeekToken(); + if (token != Token::ANGLE_BRACKETS_LEFT) { + LogError(String("'<' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + AutoPtr keyType = ParseType(); + if (keyType == nullptr) { + lexer_->SkipCurrentLine('>'); + return nullptr; + } + + token = lexer_->PeekToken(); + if (token != Token::COMMA) { + LogError(String("',' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + AutoPtr valueType = ParseType(); + if (valueType == nullptr) { + lexer_->SkipCurrentLine('>'); + return nullptr; + } + + token = lexer_->PeekToken(); + if (token != Token::ANGLE_BRACKETS_RIGHT) { + LogError(String("'>' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + AutoPtr map = new ASTMapType(); + map->SetKeyType(keyType); + map->SetValueType(valueType); + + AutoPtr ret = ast_->FindType(map->ToString()); + if (ret == nullptr) { + ast_->AddType(map.Get()); + ret = map.Get(); + } + + return ret; +} + +AutoPtr Parser::ParseCustomType() +{ + Token token = lexer_->GetToken(); + String typePrefix; + if (token == Token::ENUM) { + typePrefix = "enum"; + } else if (token == Token::STRUCT) { + typePrefix = "struct"; + } else if (token == Token::UNION) { + typePrefix = "union"; + } + + token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("custom type name is expected.")); + return nullptr; + } + + String typeName = typePrefix + " " + lexer_->GetIdentifier(); + lexer_->GetToken(); + AutoPtr type = ast_->FindType(typeName); + if (type != nullptr) { + ast_->AddType(type); + } + + return type; +} + +bool Parser::ParseEnumDefine(const AutoPtr& attributes) +{ + lexer_->GetToken(); + AutoPtr type = new ASTEnumType(); + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("custom enum type name is expected.")); + return false; + } + type->SetName(lexer_->GetIdentifier()); + lexer_->GetToken(); + + if (!ParseEnumBaseType(type)) { + return false; + } + + token = lexer_->PeekToken(); + if (token != Token::BRACES_LEFT) { + lexer_->SkipCurrentLine(';'); + return false; + } + lexer_->GetToken(); + + if (!ParseEnumMember(type)) { + return false; + } + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(); + return false; + } + lexer_->GetToken(); + + if (attributes != nullptr) { + type->SetFull(attributes->isFull); + type->SetLite(attributes->isLite); + } + + ast_->AddTypeDefinition(type.Get()); + return true; +} + +bool Parser::ParseEnumBaseType(const AutoPtr& type) +{ + Token token = lexer_->PeekToken(); + if (token == Token::COLON) { + lexer_->GetToken(); + AutoPtr baseType = ParseType(); + if (baseType == nullptr) { + LogError("no base type of enum type"); + lexer_->SkipCurrentLine(';'); + return false; + } + if (baseType->IsByteType() || + baseType->IsShortType() || + baseType->IsIntegerType() || + baseType->IsLongType() || + baseType->IsUcharType() || + baseType->IsUshortType() || + baseType->IsUintType() || + baseType->IsUlongType()) { + ast_->AddType(baseType); + type->SetBaseType(baseType); + type->SetDisplayBase(true); + } else { + LogError("invaild base type of enum type"); + lexer_->SkipCurrentLine(';'); + return false; + } + } + + if (type->GetBaseType() == nullptr) { + AutoPtr baseType = ast_->FindType("int"); + if (baseType == nullptr) { + ast_->AddType(new ASTIntegerType()); + baseType = ast_->FindType("int"); + } + type->SetBaseType(baseType); + } + return true; +} + +bool Parser::ParseEnumMember(const AutoPtr& type) +{ + Token token = lexer_->PeekToken(); + while (token != Token::BRACES_RIGHT) { + if (token != Token::IDENTIFIER) { + lexer_->SkipCurrentLine(';'); + return false; + } + AutoPtr enumValue = new ASTEnumValue(lexer_->GetIdentifier()); + lexer_->GetToken(); + + token = lexer_->PeekToken(); + if (token == Token::ASSIGN) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + if (token == Token::DIGIT) { + enumValue->SetValue(lexer_->GetDigit()); + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else { + return false; + } + } + + if (token == Token::COMMA) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token == Token::BRACES_RIGHT) { + } else { + lexer_->SkipCurrentLine(';'); + return false; + } + enumValue->SetType(type->GetBaseType()); + type->AddMember(enumValue); + } + lexer_->GetToken(); + return true; +} + +bool Parser::ParseStructDefine(const AutoPtr& attributes) +{ + lexer_->GetToken(); + + AutoPtr type = new ASTStructType(); + if (type == nullptr) { + lexer_->SkipCurrentLine(';'); + return false; + } + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("custom struct type name is expected.")); + return false; + } + type->SetName(lexer_->GetIdentifier()); + lexer_->GetToken(); + + token = lexer_->PeekToken(); + if (token != Token::BRACES_LEFT) { + lexer_->SkipCurrentLine(';'); + return false; + } + lexer_->GetToken(); + + token = lexer_->PeekToken(); + while (token != Token::BRACES_RIGHT) { + AutoPtr member = ParseType(); + if (member == nullptr) { + lexer_->SkipCurrentLine(';'); + return false; + } + String typeName = member->ToString(); + + token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("member name is expected.")); + return false; + } + String memberName = lexer_->GetIdentifier(); + lexer_->GetToken(); + + type->AddMember(member, memberName); + + token = lexer_->PeekToken(); + if (token == Token::SEMICOLON) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token == Token::BRACES_RIGHT) { + break; + } else { + lexer_->SkipCurrentLine(';'); + return false; + } + } + lexer_->GetToken(); + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(); + return false; + } + lexer_->GetToken(); + + if (attributes != nullptr) { + type->SetFull(attributes->isFull); + type->SetLite(attributes->isLite); + } + + ast_->AddTypeDefinition(type.Get()); + return true; +} + +bool Parser::ParseUnionDefine(const AutoPtr& attributes) +{ + lexer_->GetToken(); + + AutoPtr type = new ASTUnionType(); + if (type == nullptr) { + lexer_->SkipCurrentLine(';'); + return false; + } + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("custom union type name is expected.")); + return false; + } + type->SetName(lexer_->GetIdentifier()); + lexer_->GetToken(); + + token = lexer_->PeekToken(); + if (token != Token::BRACES_LEFT) { + lexer_->SkipCurrentLine(';'); + return false; + } + lexer_->GetToken(); + + token = lexer_->PeekToken(); + while (token != Token::BRACES_RIGHT) { + AutoPtr member = ParseType(); + if (member == nullptr) { + lexer_->SkipCurrentLine(';'); + return false; + } + String typeName = member->ToString(); + + token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("member name is expected.")); + return false; + } + String memberName = lexer_->GetIdentifier(); + lexer_->GetToken(); + + type->AddMember(member, memberName); + + token = lexer_->PeekToken(); + if (token == Token::SEMICOLON) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token == Token::BRACES_RIGHT) { + break; + } else { + lexer_->SkipCurrentLine(';'); + return false; + } + } + lexer_->GetToken(); + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(); + return false; + } + lexer_->GetToken(); + + if (attributes != nullptr) { + type->SetFull(attributes->isFull); + type->SetLite(attributes->isLite); + } + + ast_->AddTypeDefinition(type.Get()); + return true; +} + +bool Parser::CheckType(int lineNo, int columnNo, const AutoPtr& type) +{ + if (type == nullptr) { + return false; + } + + if (options_.GetTargetLanguage().Equals("c")) { + if (type->IsSequenceableType()) { + LogError(lineNo, columnNo, String::Format("The sequenceable type is not supported by c language.")); + return false; + } + } else if (options_.GetTargetLanguage().Equals("java")) { + switch (type->GetTypeKind()) { + case TypeKind::TYPE_UCHAR: + case TypeKind::TYPE_USHORT: + case TypeKind::TYPE_UINT: + case TypeKind::TYPE_ULONG: + case TypeKind::TYPE_ENUM: + case TypeKind::TYPE_STRUCT: + case TypeKind::TYPE_UNION: + case TypeKind::TYPE_UNKNOWN: + LogError(lineNo, columnNo, String::Format("The '%s' type is not supported by java language.", + lexer_->DumpToken().string())); + return false; + default: + break; + } + } + + return true; +} + +bool Parser::CheckIntegrity() +{ + if (ast_ == nullptr) { + LogError(String("ast is nullptr.")); + return false; + } + + if (ast_->GetName().IsEmpty()) { + LogError(String("ast's name is empty.")); + return false; + } + + if (ast_->GetPackageName().IsEmpty()) { + LogError(String("ast's package name is empty.")); + return false; + } + + switch (ast_->GetASTFileType()) { + case ASTFileType::AST_IFACE: { + AutoPtr interface = ast_->GetInterfaceDef(); + if (interface == nullptr) { + LogError(String("ast's interface is empty.")); + return false; + } + + if (ast_->GetTypeDefinitionNumber() > 0) { + LogError(String("interface ast cannot has custom types.")); + return false; + } + + if (interface->GetMethodNumber() == 0) { + LogError(String("interface ast has no method.")); + return false; + } + + break; + } + case ASTFileType::AST_ICALLBACK: { + AutoPtr interface = ast_->GetInterfaceDef(); + if (interface == nullptr) { + LogError(String("ast's interface is empty.")); + return false; + } + + if (!interface->IsCallback()) { + LogError(String("ast is callback, but ast's interface is not callback.")); + return false; + } + break; + } + case ASTFileType::AST_SEQUENCEABLE: { + LogError(String("it's impossible that ast is sequenceable.")); + return false; + } + case ASTFileType::AST_TYPES: { + if (ast_->GetInterfaceDef() != nullptr) { + LogError(String("custom ast cannot has interface.")); + return false; + } + break; + } + default: + break; + } + + return true; +} + +bool Parser::IsValidTypeName(const String& typeName) +{ + if (typeName[0] == '.') { + return false; + } + + if (typeName[typeName.GetLength() - 1] == '.') { + return false; + } + + return true; +} + +/* +* For example +* filePath: ./test/cpp_test/data_test/v1_0/IDataTest.idl +* package test.cpp_test.data_test.v1_0; +*/ +bool Parser::CheckPackageName(const String& filePath, const String& packageName) +{ + String pkgToPath = packageName.Replace('.', '/'); + int index = filePath.LastIndexOf('/'); + if (index == -1) { + return false; + } + + String parentDir = filePath.Substring(0, index); + if (parentDir.IndexOf(pkgToPath) == -1) { + return false; + } + + return true; +} + +bool Parser::AddAst() +{ + if (ast_ == nullptr) { + LogError(String("ast is nullptr.")); + return false; + } + astModule_->AddAST(ast_->GetFullName(), ast_); + return true; +} + +void Parser::LogError(const String& message) +{ + AutoPtr error = new ErrorInfo(); + + String sourceFile = lexer_->GetFilePath(); +#ifdef __MINGW32__ + error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('\\') + 1); +#else + error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('/') + 1); +#endif + error->lineNo_ = lexer_->GetTokenLineNumber(); + error->columnNo_ = lexer_->GetTokenColumnNumber(); + error->message_ = message; + + if (errors_ == nullptr) { + errors_ = error; + } else { + AutoPtr pos = errors_; + while (pos->next_ != nullptr) { + pos = pos->next_; + } + pos->next_ = error; + } +} + +void Parser::LogError(int lineNo, int columnNo, const String& message) +{ + AutoPtr error = new ErrorInfo(); + + String sourceFile = lexer_->GetFilePath(); +#ifdef __MINGW32__ + error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('\\') + 1); +#else + error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('/') + 1); +#endif + error->lineNo_ = lineNo; + error->columnNo_ = columnNo; + error->message_ = message; + + if (errors_ == nullptr) { + errors_ = error; + } else { + AutoPtr pos = errors_; + while (pos->next_ != nullptr) { + pos = pos->next_; + } + pos->next_ = error; + } +} + +void Parser::ShowError() +{ + AutoPtr error = errors_; + while (error != nullptr) { + Logger::E(TAG, "%s[line %d, column %d] %s", error->file_.string(), + error->lineNo_, error->columnNo_, error->message_.string()); + error = error->next_; + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/parser/parser.h b/tools/hdi-gen/parser/parser.h new file mode 100755 index 000000000..578bb8364 --- /dev/null +++ b/tools/hdi-gen/parser/parser.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_PARSER_H +#define OHOS_HDI_PARSER_H + +#include +#include +#include "ast/ast_module.h" +#include "ast/ast_interface_type.h" +#include "ast/ast_method.h" +#include "ast/ast.h" +#include "ast/ast_type.h" +#include "parser/lexer.h" +#include "parser/token.h" +#include "parser/file_detail.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/options.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class Parser { +public: + Parser(const Options& options, const AutoPtr& module = nullptr); + + ~Parser() = default; + + bool Parse(const String& sourceFile); + + bool Parse(const String& sourceFile, std::shared_ptr& fileDetailPtr); + + inline AutoPtr GetAst() const + { + return ast_; + } + +private: + + class Attribute : public LightRefCountBase { + public: + bool isOneWay = false; + bool isCallback = false; + bool isFull = false; + bool isLite = false; + }; + + class ErrorInfo : public LightRefCountBase { + public: + String file_; + Token token_; + int lineNo_; + int columnNo_; + String message_; + AutoPtr next_; + }; + + bool ParseIdlDetail(std::shared_ptr& fileDetailPtr); + + bool ParseIdlPackage(std::shared_ptr& fileDetailPtr); + + bool ParseIdlImport(std::shared_ptr& fileDetailPtr); + + bool ParseFile(); + + bool ParseLicense(); + + bool ParsePackageName(); + + bool ParseImport(); + + bool ParseSequenceable(); + + bool ParseAttribute(); + + bool ParseInterface(const AutoPtr& attributes = nullptr); + + bool ParseMethod(const AutoPtr& interface); + + bool ParseMethodAttr(const AutoPtr& interface, const AutoPtr& attributes); + + bool ParseParameter(const AutoPtr& method); + + bool ParseParamAttr(const AutoPtr& parameter); + + AutoPtr ParseType(); + + AutoPtr ParseList(); + + AutoPtr ParseMap(); + + AutoPtr ParseCustomType(); + + bool ParseEnumDefine(const AutoPtr& attributes = nullptr); + + bool ParseEnumBaseType(const AutoPtr& type); + + bool ParseEnumMember(const AutoPtr& type); + + bool ParseStructDefine(const AutoPtr& attributes = nullptr); + + bool ParseUnionDefine(const AutoPtr& attributes = nullptr); + + bool CheckType(int lineNo, int columnNo, const AutoPtr& type); + + bool CheckIntegrity(); + + bool IsValidTypeName(const String& typeName); + + bool CheckPackageName(const String& filePath, const String& packageName); + + inline static bool IsPrimitiveType(Token token) + { + return token >= Token::BOOLEAN && token <= Token::FILEDESCRIPTOR; + } + + bool AddAst(); + + void LogError(const String& message); + + void LogError(int lineNo, int columnNo, const String& message); + + void ShowError(); + + static const char* TAG; + + const Options& options_; + std::shared_ptr lexer_; + AutoPtr errors_; + AutoPtr ast_; + AutoPtr astModule_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_PARSER_H \ No newline at end of file diff --git a/tools/hdi-gen/parser/token.h b/tools/hdi-gen/parser/token.h new file mode 100755 index 000000000..108ca1a2b --- /dev/null +++ b/tools/hdi-gen/parser/token.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_TOKEN_H +#define OHOS_HDI_TOKEN_H + +namespace OHOS { +namespace HDI { +enum class Token { + UNKNOWN = 0, + // types + VOID, + BOOLEAN, + BYTE, + SHORT, + INTEGER, + LONG, + STRING, + FLOAT, + DOUBLE, + FILEDESCRIPTOR, + LIST, + MAP, + CHAR, + // qualifier + UNSIGNED, + // custom types + STRUCT, + ENUM, + UNION, + // keywords + PACKAGE, + SEQUENCEABLE, + IMPORT, + INTERFACE, + EXTENDS, + ONEWAY, + CALLBACK, + FULL, + LITE, + IN, + OUT, + DOT, // '.' + COMMA, // ',' + COLON, // ':' + ASSIGN, // '=' + SEMICOLON, // ';' + BRACES_LEFT, // '{' + BRACES_RIGHT, // '}' + BRACKETS_LEFT, // '[' + BRACKETS_RIGHT, // ']' + PARENTHESES_LEFT, // '(' + PARENTHESES_RIGHT, // ')' + ANGLE_BRACKETS_LEFT, // '<' + ANGLE_BRACKETS_RIGHT, // '>' + // others + IDENTIFIER, + DIGIT, + COMMENT_BLOCK, + COMMENT_LINE, + END_OF_FILE, +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_TOKEN_H \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/array_test/v1_0/IArrayTest.idl b/tools/hdi-gen/test/c_test/array_test/v1_0/IArrayTest.idl new file mode 100755 index 000000000..5e42ce2c8 --- /dev/null +++ b/tools/hdi-gen/test/c_test/array_test/v1_0/IArrayTest.idl @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.array_test.v1_0; + +import test.c_test.types.v1_0.Types; + +interface IArrayTest { + + BoolArrayTest([in] boolean[] param1, [out] boolean[] param2); + + ByteArrayTest([in] byte[] param1, [out] byte[] param2); + + ShortArrayTest([in] short[] param1, [out] short[] param2); + + IntArrayTest([in] int[] param1, [out] int[] param2); + + LongArrayTest([in] long[] param1, [out] long[] param2); + + UCharArrayTest([in] unsigned char[] param1, [out] unsigned char[] param2); + + UShortArrayTest([in] unsigned short[] param1, [out] unsigned short[] param2); + + UIntArrayTest([in] unsigned int[] param1, [out] unsigned int[] param2); + + ULongArrayTest([in] unsigned long[] param1, [out] unsigned long[] param2); + + FloatArrayTest([in] float[] param1, [out] float[] param2); + + DoubleArrayTest([in] double[] param1, [out] double[] param2); + + StringArrayTest([in] String[] param1, [out] String[] param2); + + FdArrayTest([in] FileDescriptor[] param1, [out] FileDescriptor[] param2); + + EnumArrayTest([in] enum ESample[] param1, [out] enum ESample[] param2); + + StructArrayTest([in] struct SSample[] param1, [out] struct SSample[] param2); + + UnionArrayTest([in] union USample[] param1, [out] union USample[] param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/array_test/v1_0/c_array_test.cpp b/tools/hdi-gen/test/c_test/array_test/v1_0/c_array_test.cpp new file mode 100755 index 000000000..653f2910e --- /dev/null +++ b/tools/hdi-gen/test/c_test/array_test/v1_0/c_array_test.cpp @@ -0,0 +1,676 @@ +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include +#include +#include +#include "c_test/array_test/v1_0/client/iarray_test.h" + +using namespace OHOS; +using namespace testing::ext; + +struct IArrayTest *g_testClient = nullptr; + +class ArrayTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(){} + void TearDown(){} +}; + +void ArrayTest::SetUpTestCase() +{ + g_testClient = HdiArrayTestGet(); + if (g_testClient == nullptr) { + printf("ArrayTest: get g_testClient failed.\n"); + } +} + +void ArrayTest::TearDownTestCase() +{ + if (g_testClient != nullptr) { + HdiArrayTestRelease(g_testClient); + g_testClient = nullptr; + } +} + +HWTEST_F(ArrayTest, ArratTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(ArrayTest, ArratTest_002, TestSize.Level0) +{ + uint32_t inParamLen = 4; + bool *inParam = (bool*)OsalMemAlloc(sizeof(bool) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = false; + } else { + inParam[i] = true; + } + } + + bool *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->BoolArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ((inParam[i] ? 1 : 0), (outParam[i]? 1 : 0)); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_003, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int8_t *inParam = (int8_t*)OsalMemAlloc(sizeof(int8_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int8_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ByteArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_004, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int16_t *inParam = (int16_t*)OsalMemAlloc(sizeof(int16_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int16_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ShortArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_005, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int32_t *inParam = (int32_t*)OsalMemAlloc(sizeof(int32_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int32_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->IntArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_006, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int64_t *inParam = (int64_t*)OsalMemAlloc(sizeof(int64_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int64_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->LongArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_007, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint8_t *inParam = (uint8_t*)OsalMemAlloc(sizeof(uint8_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint8_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UCharArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_008, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint16_t *inParam = (uint16_t*)OsalMemAlloc(sizeof(uint16_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint16_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UShortArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_009, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint32_t *inParam = (uint32_t*)OsalMemAlloc(sizeof(uint32_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint32_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UIntArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_010, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint64_t *inParam = (uint64_t*)OsalMemAlloc(sizeof(uint64_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint64_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ULongArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_011, TestSize.Level0) +{ + uint32_t inParamLen = 4; + float *inParam = (float*)OsalMemAlloc(sizeof(float) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0.5; + } else { + inParam[i] = 1.5; + } + } + + float *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->FloatArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_012, TestSize.Level0) +{ + uint32_t inParamLen = 4; + double *inParam = (double*)OsalMemAlloc(sizeof(double) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0.5; + } else { + inParam[i] = 1.5; + } + } + + double *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->DoubleArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_013, TestSize.Level0) +{ + uint32_t inParamLen = 2; + char **inParam = (char**)OsalMemAlloc(sizeof(char*) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i] = strdup("inParam string array"); + } + + char **outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->StringArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_STREQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + for (uint32_t i = 0; i < inParamLen; i++) { + if (inParam[i] != nullptr) { + OsalMemFree(inParam[i]); + } + } + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + for (uint32_t i = 0; i < outParamLen; i++) { + if (outParam[i] != nullptr) { + OsalMemFree(outParam[i]); + } + } + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_014, TestSize.Level0) +{ + uint32_t inParamLen = 2; + + int fd1 = open("/cpp_array_test_014_0.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + int fd2 = open("/cpp_array_test_014_1.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + ASSERT_NE(fd1, -1); + ASSERT_NE(fd2, -1); + + int *inParam = (int*)OsalMemAlloc(sizeof(int) * inParamLen); + ASSERT_NE(inParam, nullptr); + + inParam[0] = fd1; + inParam[1] = fd2; + + int *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->FdArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + + std::cout << "inParam[0]:"<< inParam[0] << ", inParam[1]" << inParam[1] << std::endl; + std::cout << "outParam[0]:"<< outParam[0] << ", outParam[1]" << outParam[1] << std::endl; + close(fd1); + close(fd2); + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_015, TestSize.Level0) +{ + uint32_t inParamLen = 4; + enum ESample *inParam = (enum ESample*)OsalMemAlloc(sizeof(enum ESample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = MEM_ONE; + } else { + inParam[i] = MEM_TWO; + } + } + + enum ESample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->EnumArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_016, TestSize.Level0) +{ + uint32_t inParamLen = 2; + struct SSample *inParam = (struct SSample *)OsalMemAlloc(sizeof(struct SSample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i].m1 = true; + inParam[i].m2 = 1; + inParam[i].m3 = 1.5; + inParam[i].m4 = strdup("inParam.m4"); + ASSERT_NE(inParam[i].m4, nullptr); + } + + struct SSample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->StructArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + if (outParamLen > 0) { + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + EXPECT_EQ(inParam[i].m1, outParam[i].m1); + EXPECT_EQ(inParam[i].m2, outParam[i].m2); + EXPECT_DOUBLE_EQ(inParam[i].m3, outParam[i].m3); + EXPECT_STREQ(inParam[i].m4, outParam[i].m4); + } + } + + if (inParam != nullptr && inParamLen > 0) { + for (uint32_t i = 0; i < inParamLen; i++) { + if (inParam[i].m4 != nullptr) { + SSampleFree(&inParam[i], false); + } + } + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + for (uint32_t i = 0; i < outParamLen; i++) { + SSampleFree(&outParam[i], false); + } + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_017, TestSize.Level0) +{ + uint32_t inParamLen = 2; + union USample *inParam = (union USample *)OsalMemAlloc(sizeof(union USample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i].m1 = true; + inParam[i].m2 = 1; + } + + union USample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UnionArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + EXPECT_EQ(inParam[i].m1, outParam[i].m1); + EXPECT_EQ(inParam[i].m2, outParam[i].m2); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/cb_test/v1_0/ICallback.idl b/tools/hdi-gen/test/c_test/cb_test/v1_0/ICallback.idl new file mode 100755 index 000000000..c00b4e425 --- /dev/null +++ b/tools/hdi-gen/test/c_test/cb_test/v1_0/ICallback.idl @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.cb_test.v1_0; + +import test.c_test.types.v1_0.Types; + +[callback] interface ICallback { + Ping([in] String message); + Plus([in] int num1, [in] int num2, [out] int result); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/cb_test/v1_0/ICbTest.idl b/tools/hdi-gen/test/c_test/cb_test/v1_0/ICbTest.idl new file mode 100755 index 000000000..e7b314747 --- /dev/null +++ b/tools/hdi-gen/test/c_test/cb_test/v1_0/ICbTest.idl @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.cb_test.v1_0; + +import test.c_test.cb_test.v1_0.ICallback; + +interface ICbTest { + CallbackTest([in] ICallback callbackObj); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/cb_test/v1_0/c_cb_test.cpp b/tools/hdi-gen/test/c_test/cb_test/v1_0/c_cb_test.cpp new file mode 100755 index 000000000..51ba485a7 --- /dev/null +++ b/tools/hdi-gen/test/c_test/cb_test/v1_0/c_cb_test.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "c_test/cb_test/v1_0/client/icb_test.h" +#include "c_test/cb_test/v1_0/callback_stub.h" + +using namespace OHOS; +using namespace testing::ext; + +struct ICbTest *g_testClient = nullptr; +struct ICallback *g_callback = nullptr; + +class CbTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(){} + void TearDown(){} +}; + +void CbTest::SetUpTestCase() +{ + g_testClient = HdiCbTestGet(); + if (g_testClient == nullptr) { + printf("CbTest: get g_testClient failed.\n"); + } + + g_callback = CallbackStubObtain(); + if (g_callback == nullptr) { + printf("CbTest: get g_callback failed.\n"); + } +} + +void CbTest::TearDownTestCase() +{ + if (g_testClient != nullptr) { + HdiCbTestRelease(g_testClient); + g_testClient = nullptr; + } + + if (g_callback != nullptr) { + CallbackStubRelease(g_callback); + g_callback = nullptr; + } +} + +HWTEST_F(CbTest, CbTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); + ASSERT_NE(nullptr, g_callback); +} + +HWTEST_F(CbTest, CbTest_002, TestSize.Level0) +{ + int32_t ec = g_testClient->CallbackTest(g_testClient, g_callback); + ASSERT_EQ(ec, HDF_SUCCESS); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/data_test/v1_0/IDataTest.idl b/tools/hdi-gen/test/c_test/data_test/v1_0/IDataTest.idl new file mode 100755 index 000000000..ac113c2c9 --- /dev/null +++ b/tools/hdi-gen/test/c_test/data_test/v1_0/IDataTest.idl @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.data_test.v1_0; + +import test.c_test.types.v1_0.Types; + +interface IDataTest { + + BoolTest([in] boolean param1, [out] boolean param2); + + ByteTest([in] byte param1, [out] byte param2); + + ShortTest([in] short param1, [out] short param2); + + IntTest([in] int param1, [out] int param2); + + LongTest([in] long param1, [out] long param2); + + UCharTest([in] unsigned char param1, [out] unsigned char param2); + + UShortTest([in] unsigned short param1, [out] unsigned short param2); + + UIntTest([in] unsigned int param1, [out] unsigned int param2); + + ULongTest([in] unsigned long param1, [out] unsigned long param2); + + FloatTest([in] float param1, [out] float param2); + + DoubleTest([in] double param1, [out] double param2); + + StringTest([in] String param1, [out] String param2); + + FdTest([in] FileDescriptor fd); + + EnumTest([in] enum ESample param1, [out] enum ESample param2); + + StructTest([in] struct SSample param1, [out] struct SSample param2); + + UnionTest([in] union USample param1, [out] union USample param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/data_test/v1_0/c_data_test.cpp b/tools/hdi-gen/test/c_test/data_test/v1_0/c_data_test.cpp new file mode 100755 index 000000000..3c8d844b4 --- /dev/null +++ b/tools/hdi-gen/test/c_test/data_test/v1_0/c_data_test.cpp @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include +#include +#include +#include "test/c_test/data_test/v1_0/client/idata_test.h" + +using namespace OHOS; +using namespace testing::ext; + +struct IDataTest *g_testClient = nullptr; +struct ICallback *g_callback = nullptr; + +class DataTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(){} + void TearDown(){} +}; + +void DataTest::SetUpTestCase() +{ + g_testClient = HdiDataTestGet(); + if (g_testClient == nullptr) { + printf("DataTest: get g_testClient failed.\n"); + } +} + +void DataTest::TearDownTestCase() +{ + if (g_testClient != nullptr) { + HdiDataTestRelease(g_testClient); + g_testClient = nullptr; + } +} + +HWTEST_F(DataTest, DataTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(DataTest, DataTest_002, TestSize.Level0) +{ + bool inParam = true; + bool outParam = false; + + int32_t ec = g_testClient->BoolTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_TRUE(inParam); + EXPECT_TRUE(outParam); +} + + +HWTEST_F(DataTest, DataTest_003, TestSize.Level0) +{ + int8_t inParam = 10; + int8_t outParam = 0; + + int32_t ec = g_testClient->ByteTest(g_testClient, inParam, &outParam); + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_004, TestSize.Level0) +{ + int16_t inParam = 10; + int16_t outParam = 0; + + int32_t ec = g_testClient->ShortTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_005, TestSize.Level0) +{ + int32_t inParam = 10; + int32_t outParam = 0; + + int32_t ec = g_testClient->IntTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_006, TestSize.Level0) +{ + int64_t inParam = 10; + int64_t outParam = 0; + + int32_t ec = g_testClient->LongTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_007, TestSize.Level0) +{ + uint8_t inParam = 10; + uint8_t outParam = 0; + + int32_t ec = g_testClient->UCharTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_008, TestSize.Level0) +{ + uint16_t inParam = 10; + uint16_t outParam = 0; + + int32_t ec = g_testClient->UShortTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_009, TestSize.Level0) +{ + uint32_t inParam = 10; + uint32_t outParam = 0; + + int32_t ec = g_testClient->UIntTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_010, TestSize.Level0) +{ + uint64_t inParam = 10; + uint64_t outParam = 0; + + int32_t ec = g_testClient->ULongTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_011, TestSize.Level0) +{ + float inParam = 10.5; + float outParam = 0; + + int32_t ec = g_testClient->FloatTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_FLOAT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_012, TestSize.Level0) +{ + double inParam = 10.5; + double outParam = 0; + + int32_t ec = g_testClient->DoubleTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_DOUBLE_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_013, TestSize.Level0) +{ + const char* inParam = "hello"; + char* outParam = nullptr; + + int32_t ec = g_testClient->StringTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_STREQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_014, TestSize.Level0) +{ + int fd = open("/c_data_test_014.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + printf("file open, fd = %d\n", fd); + + + const char* oldMsg = "client:message\n"; + int size = 0; + if ((size = write(fd, oldMsg, strlen(oldMsg))) > 0) { + printf("write oldMsg success, size:%d\n", size); + } + + lseek(fd, 0, SEEK_SET); + + int32_t ec = g_testClient->FdTest(g_testClient, fd); + + ASSERT_EQ(ec, HDF_SUCCESS); + + lseek(fd, 0, SEEK_SET); + + char recvMsg[1024] = {0}; + ssize_t readSize = read(fd, recvMsg, sizeof(recvMsg)); + if (readSize < 0) { + printf("read failed\n"); + goto finished; + } else { + printf("read size:%d\n", readSize); + } + printf("recvMsg:%s", recvMsg); + +finished: + close(fd); +} + +HWTEST_F(DataTest, DataTest_015, TestSize.Level0) +{ + enum ESample inParam = MEM_ONE; + enum ESample outParam = MEM_TWO; + + int32_t ec = g_testClient->EnumTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_016, TestSize.Level0) +{ + struct SSample inParam; + inParam.m1 = true; + inParam.m2 = 1; + inParam.m3 = 1.5; + inParam.m4 = strdup("inParam string"); + ASSERT_NE(inParam.m4, nullptr); + + struct SSample *outParam = nullptr; + + int32_t ec = g_testClient->StructTest(g_testClient, &inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + EXPECT_EQ(inParam.m1? 1: 0, outParam->m1? 1:0); + EXPECT_EQ(inParam.m2, outParam->m2); + EXPECT_DOUBLE_EQ(inParam.m3, outParam->m3); + ASSERT_NE(outParam->m4, nullptr); + EXPECT_STREQ(inParam.m4, outParam->m4); + + + SSampleFree(&inParam, false); + + + if (outParam != nullptr) { + SSampleFree(outParam, true); + } +} + +HWTEST_F(DataTest, DataTest_017, TestSize.Level0) +{ + union USample inParam; + inParam.m2 = 10; + + union USample *outParam = nullptr; + + int32_t ec = g_testClient->UnionTest(g_testClient, &inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + EXPECT_EQ(inParam.m1? 1:0, outParam->m1? 1:0); + EXPECT_EQ(inParam.m2, outParam->m2); + + if (outParam != nullptr) { + OsalMemFree(outParam); + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/list_test/v1_0/IListTest.idl b/tools/hdi-gen/test/c_test/list_test/v1_0/IListTest.idl new file mode 100755 index 000000000..92ea6c3dd --- /dev/null +++ b/tools/hdi-gen/test/c_test/list_test/v1_0/IListTest.idl @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.list_test.v1_0; + +import test.c_test.types.v1_0.Types; + +interface IListTest { + + BoolListTest([in] List param1, [out] List param2); + + ByteListTest([in] List param1, [out] List param2); + + ShortListTest([in] List param1, [out] List param2); + + IntListTest([in] List param1, [out] List param2); + + LongListTest([in] List param1, [out] List param2); + + UCharListTest([in] List param1, [out] List param2); + + UShortListTest([in] List param1, [out] List param2); + + UIntListTest([in] List param1, [out] List param2); + + ULongListTest([in] List param1, [out] List param2); + + FloatListTest([in] List param1, [out] List param2); + + DoubleListTest([in] List param1, [out] List param2); + + StringListTest([in] List param1, [out] List param2); + + FdListTest([in] List param1, [out] List param2); + + EnumListTest([in] List param1, [out] List param2); + + StructListTest([in] List param1, [out] List param2); + + UnionListTest([in] List param1, [out] List param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/list_test/v1_0/c_list_test.cpp b/tools/hdi-gen/test/c_test/list_test/v1_0/c_list_test.cpp new file mode 100755 index 000000000..33cb6048e --- /dev/null +++ b/tools/hdi-gen/test/c_test/list_test/v1_0/c_list_test.cpp @@ -0,0 +1,676 @@ +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include +#include +#include +#include "c_test/list_test/v1_0/client/ilist_test.h" + +using namespace OHOS; +using namespace testing::ext; + +struct IListTest *g_testClient = nullptr; + +class ListTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(){} + void TearDown(){} +}; + +void ListTest::SetUpTestCase() +{ + g_testClient = HdiListTestGet(); + if (g_testClient == nullptr) { + printf("ListTest: get g_testClient failed.\n"); + } +} + +void ListTest::TearDownTestCase() +{ + if (g_testClient != nullptr) { + HdiListTestRelease(g_testClient); + g_testClient = nullptr; + } +} + +HWTEST_F(ListTest, ArratTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(ListTest, ArratTest_002, TestSize.Level0) +{ + uint32_t inParamLen = 4; + bool *inParam = (bool*)OsalMemAlloc(sizeof(bool) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = false; + } else { + inParam[i] = true; + } + } + + bool *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->BoolListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ((inParam[i] ? 1 : 0), (outParam[i]? 1 : 0)); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_003, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int8_t *inParam = (int8_t*)OsalMemAlloc(sizeof(int8_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int8_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ByteListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_004, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int16_t *inParam = (int16_t*)OsalMemAlloc(sizeof(int16_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int16_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ShortListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_005, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int32_t *inParam = (int32_t*)OsalMemAlloc(sizeof(int32_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int32_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->IntListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_006, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int64_t *inParam = (int64_t*)OsalMemAlloc(sizeof(int64_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int64_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->LongListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_007, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint8_t *inParam = (uint8_t*)OsalMemAlloc(sizeof(uint8_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint8_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UCharListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_008, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint16_t *inParam = (uint16_t*)OsalMemAlloc(sizeof(uint16_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint16_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UShortListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_009, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint32_t *inParam = (uint32_t*)OsalMemAlloc(sizeof(uint32_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint32_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UIntListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_010, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint64_t *inParam = (uint64_t*)OsalMemAlloc(sizeof(uint64_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint64_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ULongListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_011, TestSize.Level0) +{ + uint32_t inParamLen = 4; + float *inParam = (float*)OsalMemAlloc(sizeof(float) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0.5; + } else { + inParam[i] = 1.5; + } + } + + float *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->FloatListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_012, TestSize.Level0) +{ + uint32_t inParamLen = 4; + double *inParam = (double*)OsalMemAlloc(sizeof(double) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0.5; + } else { + inParam[i] = 1.5; + } + } + + double *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->DoubleListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_013, TestSize.Level0) +{ + uint32_t inParamLen = 2; + char **inParam = (char**)OsalMemAlloc(sizeof(char*) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i] = strdup("inParam string array"); + } + + char **outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->StringListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_STREQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + for (uint32_t i = 0; i < inParamLen; i++) { + if (inParam[i] != nullptr) { + OsalMemFree(inParam[i]); + } + } + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + for (uint32_t i = 0; i < outParamLen; i++) { + if (outParam[i] != nullptr) { + OsalMemFree(outParam[i]); + } + } + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_014, TestSize.Level0) +{ + uint32_t inParamLen = 2; + + int fd1 = open("/ListTest_014_0.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + int fd2 = open("/ListTest_014_1.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + ASSERT_NE(fd1, -1); + ASSERT_NE(fd2, -1); + + int *inParam = (int*)OsalMemAlloc(sizeof(int) * inParamLen); + ASSERT_NE(inParam, nullptr); + + inParam[0] = fd1; + inParam[1] = fd2; + + int *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->FdListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + + std::cout << "inParam[0]:"<< inParam[0] << ", inParam[1]" << inParam[1] << std::endl; + std::cout << "outParam[0]:"<< outParam[0] << ", outParam[1]" << outParam[1] << std::endl; + close(fd1); + close(fd2); + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_015, TestSize.Level0) +{ + uint32_t inParamLen = 4; + enum ESample *inParam = (enum ESample*)OsalMemAlloc(sizeof(enum ESample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = MEM_ONE; + } else { + inParam[i] = MEM_TWO; + } + } + + enum ESample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->EnumListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_016, TestSize.Level0) +{ + uint32_t inParamLen = 2; + struct SSample *inParam = (struct SSample *)OsalMemAlloc(sizeof(struct SSample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i].m1 = true; + inParam[i].m2 = 1; + inParam[i].m3 = 1.5; + inParam[i].m4 = strdup("inParam.m4"); + ASSERT_NE(inParam[i].m4, nullptr); + } + + struct SSample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->StructListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + if (outParamLen > 0) { + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + EXPECT_EQ(inParam[i].m1, outParam[i].m1); + EXPECT_EQ(inParam[i].m2, outParam[i].m2); + EXPECT_DOUBLE_EQ(inParam[i].m3, outParam[i].m3); + EXPECT_STREQ(inParam[i].m4, outParam[i].m4); + } + } + + if (inParam != nullptr && inParamLen > 0) { + for (uint32_t i = 0; i < inParamLen; i++) { + if (inParam[i].m4 != nullptr) { + SSampleFree(&inParam[i], false); + } + } + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + for (uint32_t i = 0; i < outParamLen; i++) { + SSampleFree(&outParam[i], false); + } + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_017, TestSize.Level0) +{ + uint32_t inParamLen = 2; + union USample *inParam = (union USample *)OsalMemAlloc(sizeof(union USample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i].m1 = true; + inParam[i].m2 = 1; + } + + union USample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UnionListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + EXPECT_EQ(inParam[i].m1, outParam[i].m1); + EXPECT_EQ(inParam[i].m2, outParam[i].m2); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/struct_test/v1_0/IStructTest.idl b/tools/hdi-gen/test/c_test/struct_test/v1_0/IStructTest.idl new file mode 100755 index 000000000..70efe9d8f --- /dev/null +++ b/tools/hdi-gen/test/c_test/struct_test/v1_0/IStructTest.idl @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.struct_test.v1_0; + +import test.c_test.types.v1_0.Types; + +interface IStructTest { + SSampleTest([in] struct SSample param1, [out] struct SSample param2); + SSample2Test([in] struct SSample2 param1, [out] struct SSample2 param2); + SSample3Test([in] struct SSample3 param1, [out] struct SSample3 param2); + SSample4Test([in] struct SSample4 param1, [out] struct SSample4 param2); + SSample5Test([in] struct SSample5 param1, [out] struct SSample5 param2); + SSample6Test([in] struct SSample6 param1, [out] struct SSample6 param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/struct_test/v1_0/c_struct_test.cpp b/tools/hdi-gen/test/c_test/struct_test/v1_0/c_struct_test.cpp new file mode 100755 index 000000000..de94bc630 --- /dev/null +++ b/tools/hdi-gen/test/c_test/struct_test/v1_0/c_struct_test.cpp @@ -0,0 +1,823 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "c_test/struct_test/v1_0/client/istruct_test.h" + +using namespace OHOS; +using namespace testing::ext; + +struct IStructTest* g_testClient = nullptr; + +class StructTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void StructTest::SetUpTestCase() +{ + g_testClient = HdiStructTestGet(); + if (g_testClient == nullptr) { + printf("StructTest: get g_testClient failed.\n"); + } +} + +void TearDownTestCase() +{ + if (g_testClient != nullptr) { + HdiStructTestRelease(g_testClient); + g_testClient = nullptr; + } +} + +HWTEST_F(StructTest, StructTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + + +static std::string ESampleToStr(ESample obj) +{ + switch (obj) { + case MEM_ONE: + return "MEM_ONE"; + case MEM_TWO: + return "MEM_TWO"; + case MEM_THREE: + return "MEM_THREE"; + } +} + +static void PrintSSample(const struct SSample* obj) +{ + std::cout << "{"; + std::cout << (obj->m1?1:0) << ","; + std::cout << obj->m2 << ","; + std::cout << obj->m3 << ","; + std::cout << obj->m4; + std::cout << "}"; +} + +static void PrintUSample(const union USample* obj) +{ + std::cout << "{"; + std::cout << (obj->m1?1:0) << ","; + std::cout << obj->m2; + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_002, TestSize.Level0) +{ + struct SSample* srcObj = (struct SSample*)OsalMemCalloc(sizeof(struct SSample)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1 = true; + srcObj->m2 = 1; + srcObj->m3 = 10.125; + srcObj->m4 = strdup("hello world"); + + PrintSSample(srcObj); + std::cout << "\n"; + + struct SSample* destObj = nullptr; + int32_t ec = g_testClient->SSampleTest(g_testClient, srcObj, &destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + + EXPECT_EQ(srcObj->m1?1:0, destObj->m1?1:0); + EXPECT_EQ(srcObj->m2, destObj->m2); + EXPECT_DOUBLE_EQ(srcObj->m3, destObj->m3); + EXPECT_STREQ(srcObj->m4, destObj->m4); + + PrintSSample(destObj); + std::cout << "\n"; + + SSampleFree(srcObj, true); + SSampleFree(destObj, true); +} + +static void PrintSSample2(const struct SSample2* obj) +{ + std::cout << "{"; + std::cout << (obj->m1?1:0) << ","; + std::cout << obj->m2 << ","; + std::cout << obj->m3 << ","; + std::cout << obj->m4 << ","; + std::cout << obj->m5 << ","; + std::cout << obj->m6 << ","; + std::cout << obj->m7 << ","; + std::cout << obj->m8 << ","; + std::cout << obj->m9 << ","; + std::cout << obj->m10 << ","; + std::cout << obj->m11; + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_003, TestSize.Level0) +{ + + struct SSample2* srcObj = (struct SSample2*)OsalMemCalloc(sizeof(struct SSample2)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1 = true; + srcObj->m2 = 65; + srcObj->m3 = 10; + srcObj->m4 = 20; + srcObj->m5 = 30; + srcObj->m6 = 97; + srcObj->m7 = 100; + srcObj->m8 = 200; + srcObj->m9 = 300; + srcObj->m10 = 10.5; + srcObj->m11 = 20.125; + + PrintSSample2(srcObj); + std::cout << "\n"; + + struct SSample2* destObj = nullptr; + int32_t ec = g_testClient->SSample2Test(g_testClient, srcObj, &destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(srcObj->m1?1:0, destObj->m1?1:0); + EXPECT_EQ(srcObj->m2, destObj->m2); + EXPECT_EQ(srcObj->m3, destObj->m3); + EXPECT_EQ(srcObj->m4, destObj->m4); + EXPECT_EQ(srcObj->m5, destObj->m5); + EXPECT_EQ(srcObj->m6, destObj->m6); + EXPECT_EQ(srcObj->m7, destObj->m7); + EXPECT_EQ(srcObj->m8, destObj->m8); + EXPECT_EQ(srcObj->m9, destObj->m9); + EXPECT_FLOAT_EQ(srcObj->m10, destObj->m10); + EXPECT_DOUBLE_EQ(srcObj->m11, destObj->m11); + + PrintSSample2(destObj); + std::cout << "\n"; + + SSample2Free(srcObj, true); + SSample2Free(destObj, true); +} + +static void PrintSSample3(const struct SSample3* obj) +{ + std::cout << "{"; + + std::cout << obj->m1 << ", "; + std::cout << ESampleToStr(obj->m2) << ", "; + + PrintSSample2(&obj->m3); + std::cout << ", "; + + std::cout << obj->m4; + + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_004, TestSize.Level0) +{ + struct SSample3* srcObj = (struct SSample3*)OsalMemCalloc(sizeof(struct SSample3)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1 = strdup("hello world"); + srcObj->m2 = MEM_THREE; + + srcObj->m3.m1 = true; + srcObj->m3.m2 = 65; + srcObj->m3.m3 = 10; + srcObj->m3.m4 = 20; + srcObj->m3.m5 = 30; + srcObj->m3.m6 = 97; + srcObj->m3.m7 = 100; + srcObj->m3.m8 = 200; + srcObj->m3.m9 = 300; + srcObj->m3.m10 = 10.5; + srcObj->m3.m11 = 20.125; + + srcObj->m4 = open("/fdtest1.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + + PrintSSample3(srcObj); + std::cout << "\n"; + + struct SSample3* destObj = nullptr; + int32_t ec = g_testClient->SSample3Test(g_testClient, srcObj, &destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_STREQ(srcObj->m1, destObj->m1); + EXPECT_EQ(srcObj->m2, destObj->m2); + + EXPECT_EQ(srcObj->m3.m1?1:0, destObj->m3.m1?1:0); + EXPECT_EQ(srcObj->m3.m2, destObj->m3.m2); + EXPECT_EQ(srcObj->m3.m3, destObj->m3.m3); + EXPECT_EQ(srcObj->m3.m4, destObj->m3.m4); + EXPECT_EQ(srcObj->m3.m5, destObj->m3.m5); + EXPECT_EQ(srcObj->m3.m6, destObj->m3.m6); + EXPECT_EQ(srcObj->m3.m7, destObj->m3.m7); + EXPECT_EQ(srcObj->m3.m8, destObj->m3.m8); + EXPECT_EQ(srcObj->m3.m9, destObj->m3.m9); + EXPECT_FLOAT_EQ(srcObj->m3.m10, destObj->m3.m10); + EXPECT_DOUBLE_EQ(srcObj->m3.m11, destObj->m3.m11); + + PrintSSample3(destObj); + std::cout << "\n"; + + SSample3Free(srcObj, true); + SSample3Free(destObj, true); +} + +static void PrintSSample4(struct SSample4* obj) +{ + std::cout << "{"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m1Len; i++) { + std::cout << (obj->m1[i]? 1:0) << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m2Len; i++) { + std::cout << obj->m2[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m3Len; i++) { + std::cout << obj->m3[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m4Len; i++) { + std::cout << obj->m4[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m5Len; i++) { + std::cout << obj->m5[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m6Len; i++) { + std::cout << obj->m6[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m7Len; i++) { + std::cout << obj->m7[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m8Len; i++) { + std::cout << obj->m8[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m9Len; i++) { + std::cout << obj->m9[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m10Len; i++) { + std::cout << obj->m10[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m11Len; i++) { + std::cout << obj->m11[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m12Len; i++) { + std::cout << obj->m12[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m13Len; i++) { + std::cout << ESampleToStr(obj->m13[i]) << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m14Len; i++) { + PrintSSample(&(obj->m14[i])); + std::cout << ","; + } + std::cout << "}"; + + std::cout << "}\n"; +} + +HWTEST_F(StructTest, StructTest_005, TestSize.Level0) +{ + struct SSample4* srcObj = (struct SSample4*)OsalMemCalloc(sizeof(struct SSample4)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1Len = 2; + srcObj->m1 = (bool*)OsalMemCalloc(sizeof(bool) * srcObj->m1Len); + for (uint32_t i = 0; i < srcObj->m1Len; i++) { + srcObj->m1[i] = true; + } + + srcObj->m2Len = 2; + srcObj->m2 = (int8_t*)OsalMemCalloc(sizeof(int8_t) * srcObj->m2Len); + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + srcObj->m2[i] = 65; + } + + srcObj->m3Len = 2; + srcObj->m3 = (int16_t*)OsalMemCalloc(sizeof(int16_t) * srcObj->m3Len); + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + srcObj->m3[i] = 3; + } + + srcObj->m4Len = 2; + srcObj->m4 = (int32_t*)OsalMemCalloc(sizeof(int32_t) * srcObj->m4Len); + for (uint32_t i = 0; i < srcObj->m4Len; i++) { + srcObj->m4[i] = 4; + } + + srcObj->m5Len = 2; + srcObj->m5 = (int64_t*)OsalMemCalloc(sizeof(int64_t) * srcObj->m5Len); + for (uint32_t i = 0; i < srcObj->m5Len; i++) { + srcObj->m5[i] = 5; + } + + srcObj->m6Len = 2; + srcObj->m6 = (uint8_t*)OsalMemCalloc(sizeof(uint8_t) * srcObj->m6Len); + for (uint32_t i = 0; i < srcObj->m6Len; i++) { + srcObj->m6[i] = 97; + } + + srcObj->m7Len = 2; + srcObj->m7 = (uint16_t*)OsalMemCalloc(sizeof(uint16_t) * srcObj->m7Len); + for (uint32_t i = 0; i < srcObj->m7Len; i++) { + srcObj->m7[i] = 7; + } + + srcObj->m8Len = 2; + srcObj->m8 = (uint32_t*)OsalMemCalloc(sizeof(uint32_t) * srcObj->m8Len); + for (uint32_t i = 0; i < srcObj->m8Len; i++) { + srcObj->m8[i] = 8; + } + + srcObj->m9Len = 2; + srcObj->m9 = (uint64_t*)OsalMemCalloc(sizeof(uint64_t) * srcObj->m9Len); + for (uint32_t i = 0; i < srcObj->m9Len; i++) { + srcObj->m9[i] = 9; + } + + srcObj->m10Len = 2; + srcObj->m10 = (float*)OsalMemCalloc(sizeof(float) * srcObj->m10Len); + for (uint32_t i = 0; i < srcObj->m10Len; i++) { + srcObj->m10[i] = 10.5; + } + + srcObj->m11Len = 2; + srcObj->m11 = (double*)OsalMemCalloc(sizeof(double) * srcObj->m11Len); + for (uint32_t i = 0; i < srcObj->m11Len; i++) { + srcObj->m11[i] = 11.55; + } + + srcObj->m12Len = 2; + srcObj->m12 = (char**)OsalMemCalloc(sizeof(char*) * srcObj->m12Len); + for (uint32_t i = 0; i < srcObj->m12Len; i++) { + const char* str = "hello world"; + srcObj->m12[i] = strdup(str); + } + + srcObj->m13Len = 2; + srcObj->m13 = (enum ESample*)OsalMemCalloc(sizeof(enum ESample) * srcObj->m13Len); + for (uint32_t i = 0; i < srcObj->m13Len; i++) { + srcObj->m13[i] = MEM_ONE; + } + + srcObj->m14Len = 2; + srcObj->m14 = (struct SSample*)OsalMemCalloc(sizeof(struct SSample) * srcObj->m14Len); + for (uint32_t i = 0; i < srcObj->m14Len; i++) { + srcObj->m14[i].m1 = true; + srcObj->m14[i].m2 = 2; + srcObj->m14[i].m3 = 3.55; + srcObj->m14[i].m4 = strdup("hello"); + } + + PrintSSample4(srcObj); + std::cout << "\n"; + + struct SSample4* destObj = nullptr; + int32_t ec = g_testClient->SSample4Test(g_testClient, srcObj, &destObj); + + ASSERT_EQ(ec, HDF_SUCCESS); + + + for (uint32_t i = 0; i < srcObj->m1Len; i++) { + EXPECT_EQ(srcObj->m1[i]?1:0, destObj->m1[i]?1:0); + } + + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + EXPECT_EQ(srcObj->m2[i], destObj->m2[i]); + } + + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + EXPECT_EQ(srcObj->m3[i], destObj->m3[i]); + } + + for (uint32_t i = 0; i < srcObj->m4Len; i++) { + EXPECT_EQ(srcObj->m4[i], destObj->m4[i]); + } + + for (uint32_t i = 0; i < srcObj->m5Len; i++) { + EXPECT_EQ(srcObj->m5[i], destObj->m5[i]); + } + + for (uint32_t i = 0; i < srcObj->m6Len; i++) { + EXPECT_EQ(srcObj->m6[i], destObj->m6[i]); + } + + for (uint32_t i = 0; i < srcObj->m7Len; i++) { + EXPECT_EQ(srcObj->m7[i], destObj->m7[i]); + } + + for (uint32_t i = 0; i < srcObj->m8Len; i++) { + EXPECT_EQ(srcObj->m8[i], destObj->m8[i]); + } + + for (uint32_t i = 0; i < srcObj->m9Len; i++) { + EXPECT_EQ(srcObj->m9[i], destObj->m9[i]); + } + + for (uint32_t i = 0; i < srcObj->m10Len; i++) { + EXPECT_FLOAT_EQ(srcObj->m10[i], destObj->m10[i]); + } + + for (uint32_t i = 0; i < srcObj->m11Len; i++) { + EXPECT_DOUBLE_EQ(srcObj->m11[i], destObj->m11[i]); + } + + for (uint32_t i = 0; i < srcObj->m12Len; i++) { + EXPECT_STREQ(srcObj->m12[i], destObj->m12[i]); + } + + for (uint32_t i = 0; i < srcObj->m13Len; i++) { + EXPECT_EQ(srcObj->m13[i], destObj->m13[i]); + } + + for (uint32_t i = 0; i < srcObj->m14Len; i++) { + EXPECT_EQ((srcObj->m14[i]).m1?1:0, (destObj->m14[i]).m1?1:0); + EXPECT_EQ((srcObj->m14[i]).m2, (destObj->m14[i]).m2); + EXPECT_DOUBLE_EQ((srcObj->m14[i]).m3, (destObj->m14[i]).m3); + EXPECT_STREQ((srcObj->m14[i]).m4, (destObj->m14[i]).m4); + } + + PrintSSample4(destObj); + std::cout << "\n"; + + SSample4Free(srcObj, true); + SSample4Free(destObj, true); +} + +static void PrintSSample5(struct SSample5* obj) +{ + std::cout << "{"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m1Len; i++) { + std::cout << (obj->m1[i]? 1:0) << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m2Len; i++) { + std::cout << obj->m2[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m3Len; i++) { + std::cout << obj->m3[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m4Len; i++) { + std::cout << obj->m4[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m5Len; i++) { + std::cout << obj->m5[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m6Len; i++) { + std::cout << obj->m6[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m7Len; i++) { + std::cout << obj->m7[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m8Len; i++) { + std::cout << obj->m8[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m9Len; i++) { + std::cout << obj->m9[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m10Len; i++) { + std::cout << obj->m10[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m11Len; i++) { + std::cout << obj->m11[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m12Len; i++) { + std::cout << obj->m12[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m13Len; i++) { + std::cout << ESampleToStr(obj->m13[i]) << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m14Len; i++) { + PrintSSample(&(obj->m14[i])); + std::cout << ","; + } + std::cout << "},"; + + std::cout << "}\n"; +} + +HWTEST_F(StructTest, StructTest_006, TestSize.Level0) +{ + struct SSample5* srcObj = (struct SSample5*)OsalMemCalloc(sizeof(struct SSample5)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1Len = 2; + srcObj->m1 = (bool*)OsalMemCalloc(sizeof(bool) * srcObj->m1Len); + for (uint32_t i = 0; i < srcObj->m1Len; i++) { + srcObj->m1[i] = true; + } + + srcObj->m2Len = 2; + srcObj->m2 = (int8_t*)OsalMemCalloc(sizeof(int8_t) * srcObj->m2Len); + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + srcObj->m2[i] = 65; + } + + srcObj->m3Len = 2; + srcObj->m3 = (int16_t*)OsalMemCalloc(sizeof(int16_t) * srcObj->m3Len); + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + srcObj->m3[i] = 3; + } + + srcObj->m4Len = 2; + srcObj->m4 = (int32_t*)OsalMemCalloc(sizeof(int32_t) * srcObj->m4Len); + for (uint32_t i = 0; i < srcObj->m4Len; i++) { + srcObj->m4[i] = 4; + } + + srcObj->m5Len = 2; + srcObj->m5 = (int64_t*)OsalMemCalloc(sizeof(int64_t) * srcObj->m5Len); + for (uint32_t i = 0; i < srcObj->m5Len; i++) { + srcObj->m5[i] = 5; + } + + srcObj->m6Len = 2; + srcObj->m6 = (uint8_t*)OsalMemCalloc(sizeof(uint8_t) * srcObj->m6Len); + for (uint32_t i = 0; i < srcObj->m6Len; i++) { + srcObj->m6[i] = 97; + } + + srcObj->m7Len = 2; + srcObj->m7 = (uint16_t*)OsalMemCalloc(sizeof(uint16_t) * srcObj->m7Len); + for (uint32_t i = 0; i < srcObj->m7Len; i++) { + srcObj->m7[i] = 7; + } + + srcObj->m8Len = 2; + srcObj->m8 = (uint32_t*)OsalMemCalloc(sizeof(uint32_t) * srcObj->m8Len); + for (uint32_t i = 0; i < srcObj->m8Len; i++) { + srcObj->m8[i] = 8; + } + + srcObj->m9Len = 2; + srcObj->m9 = (uint64_t*)OsalMemCalloc(sizeof(uint64_t) * srcObj->m9Len); + for (uint32_t i = 0; i < srcObj->m9Len; i++) { + srcObj->m9[i] = 9; + } + + srcObj->m10Len = 2; + srcObj->m10 = (float*)OsalMemCalloc(sizeof(float) * srcObj->m10Len); + for (uint32_t i = 0; i < srcObj->m10Len; i++) { + srcObj->m10[i] = 10.5; + } + + srcObj->m11Len = 2; + srcObj->m11 = (double*)OsalMemCalloc(sizeof(double) * srcObj->m11Len); + for (uint32_t i = 0; i < srcObj->m11Len; i++) { + srcObj->m11[i] = 11.55; + } + + srcObj->m12Len = 2; + srcObj->m12 = (char**)OsalMemCalloc(sizeof(char*) * srcObj->m12Len); + for (uint32_t i = 0; i < srcObj->m12Len; i++) { + const char* str = "hello world"; + srcObj->m12[i] = strdup(str); + } + + srcObj->m13Len = 2; + srcObj->m13 = (enum ESample*)OsalMemCalloc(sizeof(enum ESample) * srcObj->m13Len); + for (uint32_t i = 0; i < srcObj->m13Len; i++) { + srcObj->m13[i] = MEM_ONE; + } + + srcObj->m14Len = 2; + srcObj->m14 = (struct SSample*)OsalMemCalloc(sizeof(struct SSample) * srcObj->m14Len); + for (uint32_t i = 0; i < srcObj->m14Len; i++) { + srcObj->m14[i].m1 = true; + srcObj->m14[i].m2 = 2; + srcObj->m14[i].m3 = 3.55; + srcObj->m14[i].m4 = strdup("hello"); + } + + PrintSSample5(srcObj); + std::cout << "\n"; + + struct SSample5* destObj = nullptr; + int32_t ec = g_testClient->SSample5Test(g_testClient, srcObj, &destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + for (uint32_t i = 0; i < srcObj->m1Len; i++) { + EXPECT_EQ(srcObj->m1[i]?1:0, destObj->m1[i]?1:0); + } + + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + EXPECT_EQ(srcObj->m2[i], destObj->m2[i]); + } + + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + EXPECT_EQ(srcObj->m3[i], destObj->m3[i]); + } + + for (uint32_t i = 0; i < srcObj->m4Len; i++) { + EXPECT_EQ(srcObj->m4[i], destObj->m4[i]); + } + + for (uint32_t i = 0; i < srcObj->m5Len; i++) { + EXPECT_EQ(srcObj->m5[i], destObj->m5[i]); + } + + for (uint32_t i = 0; i < srcObj->m6Len; i++) { + EXPECT_EQ(srcObj->m6[i], destObj->m6[i]); + } + + for (uint32_t i = 0; i < srcObj->m7Len; i++) { + EXPECT_EQ(srcObj->m7[i], destObj->m7[i]); + } + + for (uint32_t i = 0; i < srcObj->m8Len; i++) { + EXPECT_EQ(srcObj->m8[i], destObj->m8[i]); + } + + for (uint32_t i = 0; i < srcObj->m9Len; i++) { + EXPECT_EQ(srcObj->m9[i], destObj->m9[i]); + } + + for (uint32_t i = 0; i < srcObj->m10Len; i++) { + EXPECT_FLOAT_EQ(srcObj->m10[i], destObj->m10[i]); + } + + for (uint32_t i = 0; i < srcObj->m11Len; i++) { + EXPECT_DOUBLE_EQ(srcObj->m11[i], destObj->m11[i]); + } + + for (uint32_t i = 0; i < srcObj->m12Len; i++) { + EXPECT_STREQ(srcObj->m12[i], destObj->m12[i]); + } + + for (uint32_t i = 0; i < srcObj->m13Len; i++) { + EXPECT_EQ(srcObj->m13[i], destObj->m13[i]); + } + + for (uint32_t i = 0; i < srcObj->m14Len; i++) { + EXPECT_EQ((srcObj->m14[i]).m1?1:0, (destObj->m14[i]).m1?1:0); + EXPECT_EQ((srcObj->m14[i]).m2, (destObj->m14[i]).m2); + EXPECT_DOUBLE_EQ((srcObj->m14[i]).m3, (destObj->m14[i]).m3); + EXPECT_STREQ((srcObj->m14[i]).m4, (destObj->m14[i]).m4); + } + + PrintSSample5(destObj); + std::cout << "\n"; + + SSample5Free(srcObj, true); + SSample5Free(destObj, true); +} + +static void PrintSSample6(struct SSample6* obj) +{ + std::cout << "{"; + + PrintUSample(&obj->m1); + std::cout << ",\n"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m2Len; i++) { + PrintUSample(&obj->m2[i]); + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m3Len; i++) { + PrintUSample(&obj->m3[i]); + } + std::cout << "}"; + + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_007, TestSize.Level0) +{ + struct SSample6* srcObj = (struct SSample6*)OsalMemCalloc(sizeof(struct SSample6)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1.m1 = true; + srcObj->m1.m2 = 1; + + srcObj->m2Len = 2; + srcObj->m2 = (union USample*)OsalMemCalloc(sizeof(union USample) * srcObj->m2Len); + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + (srcObj->m2[i]).m1 = true; + (srcObj->m2[i]).m2 = 2; + } + + srcObj->m3Len = 2; + srcObj->m3 = (union USample*)OsalMemCalloc(sizeof(union USample) * srcObj->m3Len); + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + (srcObj->m3[i]).m1 = true; + (srcObj->m3[i]).m2 = 2; + } + + PrintSSample6(srcObj); + std::cout << "\n"; + + struct SSample6* destObj = nullptr; + int32_t ec = g_testClient->SSample6Test(g_testClient, srcObj, &destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(srcObj->m1.m1?1:0, destObj->m1.m1?1:0); + EXPECT_EQ(srcObj->m1.m2, destObj->m1.m2); + + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + EXPECT_EQ((srcObj->m2[i]).m1?1:0, (destObj->m2[i]).m1?1:0); + EXPECT_EQ((srcObj->m2[i]).m2, (destObj->m2[i]).m2); + } + + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + EXPECT_EQ((srcObj->m3[i]).m1?1:0, (destObj->m3[i]).m1?1:0); + EXPECT_EQ((srcObj->m3[i]).m2, (destObj->m3[i]).m2); + } + + PrintSSample6(destObj); + std::cout << "\n"; + + SSample6Free(srcObj, true); + SSample6Free(destObj, true); +} + diff --git a/tools/hdi-gen/test/c_test/types/v1_0/Types.idl b/tools/hdi-gen/test/c_test/types/v1_0/Types.idl new file mode 100755 index 000000000..5de08a556 --- /dev/null +++ b/tools/hdi-gen/test/c_test/types/v1_0/Types.idl @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.types.v1_0; + +enum ESample +{ + MEM_ONE, + MEM_TWO, + MEM_THREE, +}; + +struct SSample +{ + boolean m1; + int m2; + double m3; + String m4; +}; + +union USample +{ + boolean m1; + int m2; +}; + +struct SSample2 +{ + boolean m1; + byte m2; + short m3; + int m4; + long m5; + unsigned char m6; + unsigned short m7; + unsigned int m8; + unsigned long m9; + float m10; + double m11; +}; + +struct SSample3 +{ + String m1; + enum ESample m2; + struct SSample2 m3; + FileDescriptor m4; +}; + +struct SSample4 +{ + boolean[] m1; + byte[] m2; + short[] m3; + int[] m4; + long[] m5; + unsigned char[] m6; + unsigned short[] m7; + unsigned int[] m8; + unsigned long[] m9; + float[] m10; + double[] m11; + String[] m12; + enum ESample[] m13; + struct SSample[] m14; +}; + +struct SSample5 +{ + List m1; + List m2; + List m3; + List m4; + List m5; + List m6; + List m7; + List m8; + List m9; + List m10; + List m11; + List m12; + List m13; + List m14; +}; + +struct SSample6 { + union USample m1; + union USample[] m2; + List m3; +}; \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/array_test/v1_0/IArrayTest.idl b/tools/hdi-gen/test/cpp_test/array_test/v1_0/IArrayTest.idl new file mode 100755 index 000000000..a65dfc69e --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/array_test/v1_0/IArrayTest.idl @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.array_test.v1_0; + +sequenceable test.cpp_test.types.v1_0.SequenceData; + +import test.cpp_test.types.v1_0.Types; + +interface IArrayTest { + + BoolArrayTest([in] boolean[] param1, [out] boolean[] param2); + + ByteArrayTest([in] byte[] param1, [out] byte[] param2); + + ShortArrayTest([in] short[] param1, [out] short[] param2); + + IntArrayTest([in] int[] param1, [out] int[] param2); + + LongArrayTest([in] long[] param1, [out] long[] param2); + + UCharArrayTest([in] unsigned char[] param1, [out] unsigned char[] param2); + + UShortArrayTest([in] unsigned short[] param1, [out] unsigned short[] param2); + + UIntArrayTest([in] unsigned int[] param1, [out] unsigned int[] param2); + + ULongArrayTest([in] unsigned long[] param1, [out] unsigned long[] param2); + + FloatArrayTest([in] float[] param1, [out] float[] param2); + + DoubleArrayTest([in] double[] param1, [out] double[] param2); + + StringArrayTest([in] String[] param1, [out] String[] param2); + + FdArrayTest([in] FileDescriptor[] param1, [out] FileDescriptor[] param2); + + EnumArrayTest([in] enum ESample[] param1, [out] enum ESample[] param2); + + StructArrayTest([in] struct SSample[] param1, [out] struct SSample[] param2); + + UnionArrayTest([in] union USample[] param1, [out] union USample[] param2); + + SeqDataArrayTest([in] SequenceData[] param1, [out] SequenceData[] param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/array_test/v1_0/cpp_array_test.cpp b/tools/hdi-gen/test/cpp_test/array_test/v1_0/cpp_array_test.cpp new file mode 100755 index 000000000..474956ac7 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/array_test/v1_0/cpp_array_test.cpp @@ -0,0 +1,416 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/cpp_test/array_test/v1_0/client/array_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::array_test::v1_0; +using namespace test::cpp_test::types::v1_0; + +sptr g_testClient = nullptr; + +class ArrayTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void ArrayTest::SetUpTestCase() +{ + g_testClient = IArrayTest::Get(); + if (g_testClient == nullptr) { + printf("ArrayTest: get g_testClient failed.\n"); + + } +} + +HWTEST_F(ArrayTest, ArrayTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(ArrayTest, ArrayTest_002, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + if ((i+1)/2 == 0) { + inParam.push_back(false); + } else { + inParam.push_back(true); + } + } + + std::vector outParam; + + int32_t ec = g_testClient->BoolArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ((inParam[i] ? 1 : 0), (outParam[i]? 1 : 0)); + } +} + +HWTEST_F(ArrayTest, ArrayTest_003, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ByteArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_004, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ShortArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_005, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->IntArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_006, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->LongArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_007, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UCharArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_008, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UShortArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_009, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UIntArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_010, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ULongArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_011, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->FloatArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_FLOAT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_012, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->DoubleArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_DOUBLE_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_013, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back("inParam string"); + } + + std::vector outParam; + + int32_t ec = g_testClient->StringArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_014, TestSize.Level0) +{ + int fd1 = open("/ArrayTest_014_0.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + int fd2 = open("/ArrayTest_014_1.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + ASSERT_NE(fd1, -1); + ASSERT_NE(fd2, -1); + + std::vector inParam; + inParam.push_back(fd1); + inParam.push_back(fd2); + + std::vector outParam; + + int32_t ec = g_testClient->FdArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + + std::cout << "inParam[0]:"<< inParam[0] << ", inParam[1]" << inParam[1] << std::endl; + std::cout << "outParam[0]:"<< outParam[0] << ", outParam[1]" << outParam[1] << std::endl; + close(fd1); + close(fd2); +} + +HWTEST_F(ArrayTest, ArrayTest_015, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(ESample::MEM_ONE); + } + + std::vector outParam; + + int32_t ec = g_testClient->EnumArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_016, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + SSample element; + element.m1 = true; + element.m2 = 1; + element.m3 = 10.5; + element.m4 = "hello"; + inParam.push_back(element); + } + + std::vector outParam; + + int32_t ec = g_testClient->StructArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i].m1? 1:0, outParam[i].m1? 1:0); + ASSERT_EQ(inParam[i].m2, outParam[i].m2); + ASSERT_DOUBLE_EQ(inParam[i].m3, outParam[i].m3); + ASSERT_EQ(inParam[i].m4, outParam[i].m4); + } +} + +HWTEST_F(ArrayTest, ArrayTest_017, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + USample element; + element.m2 = 10; + inParam.push_back(element); + } + + std::vector outParam; + + int32_t ec = g_testClient->UnionArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i].m1? 1:0, outParam[i].m1? 1:0); + ASSERT_EQ(inParam[i].m2, outParam[i].m2); + } +} + +HWTEST_F(ArrayTest, ArrayTest_018, TestSize.Level0) +{ + std::vector> inParam = { + sptr(new SequenceData(1, 1.2, "hello")), + sptr(new SequenceData(2, 2.2, "world")), + }; + + std::vector> outParam; + + int32_t ec = g_testClient->SeqDataArrayTest(inParam, outParam); + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_NE(outParam[i], nullptr); + EXPECT_EQ(inParam[i]->m1_, outParam[i]->m1_); + EXPECT_DOUBLE_EQ(inParam[i]->m2_, outParam[i]->m2_); + EXPECT_EQ(inParam[i]->m3_, outParam[i]->m3_); + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICallback.idl b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICallback.idl new file mode 100755 index 000000000..54e31db0f --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICallback.idl @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.cb_test.v1_0; + +[callback] interface ICallback { + Ping([in] String message); + Plus([in] int num1, [in] int num2, [out] int result); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICbTest.idl b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICbTest.idl new file mode 100755 index 000000000..e71ad6314 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICbTest.idl @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.cb_test.v1_0; + +import test.cpp_test.cb_test.v1_0.ICallback; + +interface ICbTest { + CallbackTest([in] ICallback callbackObj); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/cb_test/v1_0/cpp_cb_test.cpp b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/cpp_cb_test.cpp new file mode 100755 index 000000000..749e5aaab --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/cpp_cb_test.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include "test/cpp_test/cb_test/v1_0/client/cb_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::cb_test::v1_0; + +#define HDF_LOG_TAG sapmle_c_client_test + +sptr g_testClient = nullptr; + +sptr g_callbackObj = nullptr; + +class CbTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void CbTest::SetUpTestCase() +{ + g_testClient = ICbTest::Get(); + if (g_testClient == nullptr) { + printf("CbTest: get g_testClient failed.\n"); + } + g_callbackObj = new CallbackService(); + if (g_callbackObj == nullptr) { + printf("CbTest: get g_callbackObj failed.\n"); + } +} + +HWTEST_F(CbTest, CbTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(CbTest, CbTest_002, TestSize.Level0) +{ + int32_t ec = g_testClient->CallbackTest(g_callbackObj); + ASSERT_EQ(ec, HDF_SUCCESS); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/data_test/v1_0/IDataTest.idl b/tools/hdi-gen/test/cpp_test/data_test/v1_0/IDataTest.idl new file mode 100755 index 000000000..7639283e9 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/data_test/v1_0/IDataTest.idl @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.data_test.v1_0; + +sequenceable test.cpp_test.types.v1_0.SequenceData; + +import test.cpp_test.types.v1_0.Types; + +interface IDataTest { + + BoolTest([in] boolean param1, [out] boolean param2); + + ByteTest([in] byte param1, [out] byte param2); + + ShortTest([in] short param1, [out] short param2); + + IntTest([in] int param1, [out] int param2); + + LongTest([in] long param1, [out] long param2); + + UCharTest([in] unsigned char param1, [out] unsigned char param2); + + UShortTest([in] unsigned short param1, [out] unsigned short param2); + + UIntTest([in] unsigned int param1, [out] unsigned int param2); + + ULongTest([in] unsigned long param1, [out] unsigned long param2); + + FloatTest([in] float param1, [out] float param2); + + DoubleTest([in] double param1, [out] double param2); + + StringTest([in] String param1, [out] String param2); + + FdTest([in] FileDescriptor fd); + + EnumTest([in] enum ESample param1, [out] enum ESample param2); + + StructTest([in] struct SSample param1, [out] struct SSample param2); + + UnionTest([in] union USample param1, [out] union USample param2); + + SequenceDataTest([in] SequenceData param1, [out] SequenceData param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/data_test/v1_0/cpp_data_test.cpp b/tools/hdi-gen/test/cpp_test/data_test/v1_0/cpp_data_test.cpp new file mode 100755 index 000000000..2dbe1de8d --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/data_test/v1_0/cpp_data_test.cpp @@ -0,0 +1,265 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cpp_test/data_test/v1_0/client/data_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::data_test::v1_0; +using namespace test::cpp_test::types::v1_0; + +sptr g_testClient = nullptr; + +class DataTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void DataTest::SetUpTestCase() +{ + g_testClient = IDataTest::Get(); + if (g_testClient == nullptr) { + printf("DataTest: get g_testClient failed.\n"); + } +} + +HWTEST_F(DataTest, DataTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(DataTest, DataTest_002, TestSize.Level0) +{ + bool inParam = true; + bool outParam = false; + int32_t ec = g_testClient->BoolTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_TRUE(inParam); + EXPECT_TRUE(outParam); +} + +HWTEST_F(DataTest, DataTest_003, TestSize.Level0) +{ + int8_t inParam = 10; + int8_t outParam = 0; + + int32_t ec = g_testClient->ByteTest(inParam, outParam); + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_004, TestSize.Level0) +{ + int16_t inParam = 10; + int16_t outParam = 0; + + int32_t ec = g_testClient->ShortTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_005, TestSize.Level0) +{ + int32_t inParam = 10; + int32_t outParam = 0; + + int32_t ec = g_testClient->IntTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_006, TestSize.Level0) +{ + int64_t inParam = 10; + int64_t outParam = 0; + + int32_t ec = g_testClient->LongTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_007, TestSize.Level0) +{ + uint8_t inParam = 10; + uint8_t outParam = 0; + + int32_t ec = g_testClient->UCharTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_008, TestSize.Level0) +{ + uint16_t inParam = 10; + uint16_t outParam = 0; + + int32_t ec = g_testClient->UShortTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_009, TestSize.Level0) +{ + uint32_t inParam = 10; + uint32_t outParam = 0; + + int32_t ec = g_testClient->UIntTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_010, TestSize.Level0) +{ + uint64_t inParam = 10; + uint64_t outParam = 0; + + int32_t ec = g_testClient->ULongTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_011, TestSize.Level0) +{ + float inParam = 10.5; + float outParam = 0; + + int32_t ec = g_testClient->FloatTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_FLOAT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_012, TestSize.Level0) +{ + double inParam = 10.5; + double outParam = 0; + + int32_t ec = g_testClient->DoubleTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_DOUBLE_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_013, TestSize.Level0) +{ + std::string inParam("hello"); + std::string outParam; + + int32_t ec = g_testClient->StringTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_014, TestSize.Level0) +{ + int fd = open("/cpp_data_test_014.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + printf("file open, fd = %d\n", fd); + + + const char* oldMsg = "client:message\n"; + int size = 0; + if ((size = write(fd, oldMsg, strlen(oldMsg))) > 0) { + printf("write oldMsg success, size:%d\n", size); + } + + lseek(fd, 0, SEEK_SET); + + int32_t ec = g_testClient->FdTest(fd); + + ASSERT_EQ(ec, HDF_SUCCESS); + + lseek(fd, 0, SEEK_SET); + + char recvMsg[1024] = {0}; + ssize_t readSize = read(fd, recvMsg, sizeof(recvMsg)); + if (readSize < 0) { + printf("read failed\n"); + goto finished; + } else { + printf("read size:%d\n", readSize); + } + printf("recvMsg:%s", recvMsg); + +finished: + close(fd); +} + +HWTEST_F(DataTest, DataTest_015, TestSize.Level0) +{ + ESample inParam = ESample::MEM_ONE; + ESample outParam = ESample::MEM_TWO; + + int32_t ec = g_testClient->EnumTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_016, TestSize.Level0) +{ + SSample inParam; + inParam.m1 = true; + inParam.m2 = 1; + inParam.m3 = 10.5; + inParam.m4 = "inParam string"; + + SSample outParam; + + int32_t ec = g_testClient->StructTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(inParam.m1? 1:0, outParam.m1? 1:0); + EXPECT_EQ(inParam.m2, outParam.m2); + EXPECT_DOUBLE_EQ(inParam.m3, outParam.m3); + EXPECT_EQ(inParam.m4, outParam.m4); +} + +HWTEST_F(DataTest, DataTest_017, TestSize.Level0) +{ + USample inParam; + inParam.m2 = 10; + + USample outParam; + + int32_t ec = g_testClient->UnionTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(inParam.m1?1:0, outParam.m1?1:0); + EXPECT_DOUBLE_EQ(inParam.m2, outParam.m2); +} + +HWTEST_F(DataTest, DataTest_018, TestSize.Level0) +{ + sptr inParam(new SequenceData(1, 1.2, "hello")); + + sptr outParam = nullptr; + + int32_t ec = g_testClient->SequenceDataTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(inParam->m1_, outParam->m1_); + EXPECT_DOUBLE_EQ(inParam->m2_, outParam->m2_); + EXPECT_EQ(inParam->m3_, outParam->m3_); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/list_test/v1_0/IListTest.idl b/tools/hdi-gen/test/cpp_test/list_test/v1_0/IListTest.idl new file mode 100755 index 000000000..1cfa43c57 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/list_test/v1_0/IListTest.idl @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.list_test.v1_0; + +sequenceable test.cpp_test.types.v1_0.SequenceData; + +import test.cpp_test.types.v1_0.Types; + +interface IListTest { + + BoolListTest([in] List param1, [out] List param2); + + ByteListTest([in] List param1, [out] List param2); + + ShortListTest([in] List param1, [out] List param2); + + IntListTest([in] List param1, [out] List param2); + + LongListTest([in] List param1, [out] List param2); + + UCharListTest([in] List param1, [out] List param2); + + UShortListTest([in] List param1, [out] List param2); + + UIntListTest([in] List param1, [out] List param2); + + ULongListTest([in] List param1, [out] List param2); + + FloatListTest([in] List param1, [out] List param2); + + DoubleListTest([in] List param1, [out] List param2); + + StringListTest([in] List param1, [out] List param2); + + FdListTest([in] List param1, [out] List param2); + + EnumListTest([in] List param1, [out] List param2); + + StructListTest([in] List param1, [out] List param2); + + UnionListTest([in] List param1, [out] List param2); + + SeqDataListTest([in] List param1, [out] List param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/list_test/v1_0/cpp_list_test.cpp b/tools/hdi-gen/test/cpp_test/list_test/v1_0/cpp_list_test.cpp new file mode 100755 index 000000000..89a6276f0 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/list_test/v1_0/cpp_list_test.cpp @@ -0,0 +1,416 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/cpp_test/list_test/v1_0/client/list_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::list_test::v1_0; +using namespace test::cpp_test::types::v1_0; + +sptr g_testClient = nullptr; + +class ListTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void ListTest::SetUpTestCase() +{ + g_testClient = IListTest::Get(); + if (g_testClient == nullptr) { + printf("ListTest: get g_testClient failed.\n"); + + } +} + +HWTEST_F(ListTest, ListTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(ListTest, ListTest_002, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + if ((i+1)/2 == 0) { + inParam.push_back(false); + } else { + inParam.push_back(true); + } + } + + std::vector outParam; + + int32_t ec = g_testClient->BoolListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ((inParam[i] ? 1 : 0), (outParam[i]? 1 : 0)); + } +} + +HWTEST_F(ListTest, ListTest_003, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ByteListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_004, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ShortListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_005, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->IntListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_006, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->LongListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_007, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UCharListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_008, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UShortListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_009, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UIntListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_010, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ULongListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_011, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->FloatListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_FLOAT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_012, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->DoubleListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_DOUBLE_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_013, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back("inParam string"); + } + + std::vector outParam; + + int32_t ec = g_testClient->StringListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_014, TestSize.Level0) +{ + int fd1 = open("/ListTest_014_0.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + int fd2 = open("/ListTest_014_1.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + ASSERT_NE(fd1, -1); + ASSERT_NE(fd2, -1); + + std::vector inParam; + inParam.push_back(fd1); + inParam.push_back(fd2); + + std::vector outParam; + + int32_t ec = g_testClient->FdListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + + std::cout << "inParam[0]:"<< inParam[0] << ", inParam[1]" << inParam[1] << std::endl; + std::cout << "outParam[0]:"<< outParam[0] << ", outParam[1]" << outParam[1] << std::endl; + close(fd1); + close(fd2); +} + +HWTEST_F(ListTest, ListTest_015, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(ESample::MEM_ONE); + } + + std::vector outParam; + + int32_t ec = g_testClient->EnumListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_016, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + SSample element; + element.m1 = true; + element.m2 = 1; + element.m3 = 10.5; + element.m4 = "hello"; + inParam.push_back(element); + } + + std::vector outParam; + + int32_t ec = g_testClient->StructListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i].m1? 1:0, outParam[i].m1? 1:0); + ASSERT_EQ(inParam[i].m2, outParam[i].m2); + ASSERT_DOUBLE_EQ(inParam[i].m3, outParam[i].m3); + ASSERT_EQ(inParam[i].m4, outParam[i].m4); + } +} + +HWTEST_F(ListTest, ListTest_017, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + USample element; + element.m2 = 10; + inParam.push_back(element); + } + + std::vector outParam; + + int32_t ec = g_testClient->UnionListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i].m1? 1:0, outParam[i].m1? 1:0); + ASSERT_EQ(inParam[i].m2, outParam[i].m2); + } +} + +HWTEST_F(ListTest, ListTest_018, TestSize.Level0) +{ + std::vector> inParam = { + sptr(new SequenceData(1, 1.2, "hello")), + sptr(new SequenceData(2, 2.2, "world")), + }; + + std::vector> outParam; + + int32_t ec = g_testClient->SeqDataListTest(inParam, outParam); + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_NE(outParam[i], nullptr); + EXPECT_EQ(inParam[i]->m1_, outParam[i]->m1_); + EXPECT_DOUBLE_EQ(inParam[i]->m2_, outParam[i]->m2_); + EXPECT_EQ(inParam[i]->m3_, outParam[i]->m3_); + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/map_test/v1_0/IMapTest.idl b/tools/hdi-gen/test/cpp_test/map_test/v1_0/IMapTest.idl new file mode 100755 index 000000000..0a5071143 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/map_test/v1_0/IMapTest.idl @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.map_test.v1_0; + +sequenceable test.cpp_test.types.v1_0.SequenceData; + +import test.cpp_test.types.v1_0.Types; + +interface IMapTest { + MapIntByteTest([in] Map param1, [out] Map param2); + + MapIntShortTest([in] Map param1, [out] Map param2); + + MapIntIntTest([in] Map param1, [out] Map param2); + + MapIntLongTest([in] Map param1, [out] Map param2); + + MapIntFloatTest([in] Map param1, [out] Map param2); + + MapIntDoubleTest([in] Map param1, [out] Map param2); + + MapIntStringTest([in] Map param1, [out] Map param2); + + MapIntFdTest([in] Map param1, [out] Map param2); + + MapIntSeqTest([in] Map param1, [out] Map param2); + + MapIntEnumTest([in] Map param1, [out] Map param2); + + MapIntStructTest([in] Map param1, [out] Map param2); + + MapIntUnionTest([in] Map param1, [out] Map param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/map_test/v1_0/cpp_map_test.cpp b/tools/hdi-gen/test/cpp_test/map_test/v1_0/cpp_map_test.cpp new file mode 100755 index 000000000..3fc9bfa74 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/map_test/v1_0/cpp_map_test.cpp @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include +#include +#include +#include "cpp_test/map_test/v1_0/client/map_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::map_test::v1_0; +using namespace test::cpp_test::types::v1_0; + +sptr g_testClient = nullptr; + +class MapTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(){} + void TearDown(){} +}; + +void MapTest::SetUpTestCase() +{ + g_testClient = IMapTest::Get(); + if (g_testClient == nullptr) { + std::cout << "MapTest: get g_testClient failed." << std::endl; + } +} + +void MapTest::TearDownTestCase() +{ + if (g_testClient != nullptr) { + delete g_testClient; + g_testClient = nullptr; + } +} + +HWTEST_F(MapTest, MapTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(MapTest, MapTest_002, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 'A'; + inParam[2] = 'B'; + + std::map outParam; + + int32_t ec = g_testClient->MapIntByteTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_002 TestCase is failed!" << std::endl; + } + } +} + + +HWTEST_F(MapTest, MapTest_003, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 1; + inParam[2] = 2; + + std::map outParam; + + int32_t ec = g_testClient->MapIntShortTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_003 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_004, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 1; + inParam[2] = 2; + + std::map outParam; + + int32_t ec = g_testClient->MapIntIntTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_004 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_005, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 100; + inParam[2] = 200; + + std::map outParam; + + int32_t ec = g_testClient->MapIntLongTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_005 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_006, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 10.5; + inParam[2] = 20.5; + + std::map outParam; + + int32_t ec = g_testClient->MapIntFloatTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_006 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_007, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 10.55; + inParam[2] = 20.55; + + std::map outParam; + + int32_t ec = g_testClient->MapIntDoubleTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_DOUBLE_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_007 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_008, TestSize.Level0) +{ + std::map inParam; + inParam[1] = "hello"; + inParam[2] = "world"; + + std::map outParam; + + int32_t ec = g_testClient->MapIntStringTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_STREQ(inIter->second.c_str(), outIter->second.c_str()); + } else { + std::cout << "MapTest_008 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_009, TestSize.Level0) +{ + std::map inParam; + inParam[1] = open("/cpp_test_map_009.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + inParam[2] = open("/cpp_test_map_009.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + + std::map outParam; + + int32_t ec = g_testClient->MapIntFdTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + std::cout << "inParam[" << inIter->first << "]:" << inIter->second << std::endl; + std::cout << "outParam[" << outIter->first << "]:" << outIter->second << std::endl; + } else { + std::cout << "MapTest_009 TestCase is failed!" << std::endl; + } + } + + close(inParam[1]); + close(outParam[0]); +} + +HWTEST_F(MapTest, MapTest_010, TestSize.Level0) +{ + std::map> inParam = { + {0, sptr(new SequenceData(1, 1.2, "hello"))}, + {1, sptr(new SequenceData(2, 2.2, "world"))} + }; + + std::map> outParam; + + int32_t ec = g_testClient->MapIntSeqTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + EXPECT_EQ(inIter->second->m1_, outIter->second->m1_); + EXPECT_DOUBLE_EQ(inIter->second->m2_, outIter->second->m2_); + EXPECT_EQ(inIter->second->m3_, outIter->second->m3_); + } else { + std::cout << "MapTest_010 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_011, TestSize.Level0) +{ + std::map inParam; + inParam[1] = ESample::MEM_ONE; + inParam[2] = ESample::MEM_TWO; + + std::map outParam; + + int32_t ec = g_testClient->MapIntEnumTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_011 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_012, TestSize.Level0) +{ + std::map inParam; + for (int32_t i = 0; i < 2; i++) { + SSample value; + value.m1 = true; + value.m2 = 10; + value.m3 = 10.5; + value.m4 = "inParam string"; + inParam[i] = value; + } + + std::map outParam; + + int32_t ec = g_testClient->MapIntStructTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ((inIter->second).m1?1:0, (outIter->second).m1?1:0); + ASSERT_EQ((inIter->second).m2, (outIter->second).m2); + ASSERT_DOUBLE_EQ((inIter->second).m3, (outIter->second).m3); + ASSERT_EQ((inIter->second).m4, (outIter->second).m4); + } else { + std::cout << "MapTest_012 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_013, TestSize.Level0) +{ + std::map inParam; + for (int32_t i = 0; i < 2; i++) { + USample value; + value.m1 = true; + value.m2 = 10; + inParam[i] = value; + } + + std::map outParam; + + int32_t ec = g_testClient->MapIntUnionTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ((inIter->second).m1?1:0, (outIter->second).m1?1:0); + ASSERT_EQ((inIter->second).m2, (outIter->second).m2); + } else { + std::cout << "MapTest_013 TestCase is failed!" << std::endl; + } + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/struct_test/v1_0/IStructTest.idl b/tools/hdi-gen/test/cpp_test/struct_test/v1_0/IStructTest.idl new file mode 100755 index 000000000..fe002812f --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/struct_test/v1_0/IStructTest.idl @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.struct_test.v1_0; + +import test.cpp_test.types.v1_0.Types; + +interface IStructTest { + SSampleTest([in] struct SSample param1, [out] struct SSample param2); + SSample2Test([in] struct SSample2 param1, [out] struct SSample2 param2); + SSample3Test([in] struct SSample3 param1, [out] struct SSample3 param2); + SSample4Test([in] struct SSample4 param1, [out] struct SSample4 param2); + SSample5Test([in] struct SSample5 param1, [out] struct SSample5 param2); + SSample6Test([in] struct SSample6 param1, [out] struct SSample6 param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/struct_test/v1_0/cpp_struct_test.cpp b/tools/hdi-gen/test/cpp_test/struct_test/v1_0/cpp_struct_test.cpp new file mode 100755 index 000000000..3e87d5d8a --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/struct_test/v1_0/cpp_struct_test.cpp @@ -0,0 +1,719 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/cpp_test/struct_test/v1_0/client/struct_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::struct_test::v1_0; +using namespace test::cpp_test::types::v1_0; + +sptr g_testClient = nullptr; + +class StructTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void StructTest::SetUpTestCase() +{ + g_testClient = IStructTest::Get(); + if (g_testClient == nullptr) { + printf("StructTest: get g_testClient failed.\n"); + } +} + +HWTEST_F(StructTest, StructTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +static std::string ESampleToStr(ESample obj) +{ + switch (obj) { + case ESample::MEM_ONE: + return "MEM_ONE"; + case ESample::MEM_TWO: + return "MEM_TWO"; + case ESample::MEM_THREE: + return "MEM_THREE"; + } +} + +static void PrintSSample(const SSample& obj) +{ + std::cout << "{"; + std::cout << "m1:" << (obj.m1?1:0) << ", "; + std::cout << "m2:" << obj.m2 << ", "; + std::cout << "m3:" << obj.m3 << ", "; + std::cout << "m4:" << obj.m4; + std::cout << "}"; +} + +// static void PrintUSample(const USample& obj) +// { +// std::cout << "{"; +// std::cout << "m1:" << (obj.m1? 1:0) << ", "; +// std::cout << "m2:" << obj.m2; +// std::cout << "}"; +// } + +HWTEST_F(StructTest, StructTest_002, TestSize.Level0) +{ + SSample srcObj = {true, 1, 1000.125, "hello world"}; + + SSample destObj; + + int32_t ec = g_testClient->SSampleTest(srcObj, destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(srcObj.m1? 1:0 ,destObj.m1?1:0); + EXPECT_EQ(srcObj.m2, destObj.m2); + EXPECT_DOUBLE_EQ(srcObj.m3, destObj.m3); + EXPECT_EQ(srcObj.m4, destObj.m4); + + PrintSSample(srcObj); + std::cout << "\n"; + PrintSSample(destObj); + std::cout << "\n"; + std::cout << "----------------------------" << std::endl; +} + +static void PrintSSample2(const SSample2& obj) +{ + std::cout << "{"; + + std::cout << "m1:" << obj.m1 << ", "; + std::cout << "m2:" << (obj.m2? 1:0) << ", "; + std::cout << "m3:" << obj.m3 << ", "; + std::cout << "m4:" << obj.m4 << ", "; + std::cout << "m5:" << obj.m5 << ", "; + std::cout << "m6:" << obj.m6 << ", "; + std::cout << "m7:" << obj.m7 << ", "; + std::cout << "m8:" << obj.m8 << ", "; + std::cout << "m9:" << obj.m9 << ", "; + std::cout << "m10:" << obj.m10 << ", "; + std::cout << "m11:" << obj.m11; + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_003, TestSize.Level0) +{ + SSample2 srcObj = {true, 1, 2, 3, 4, 65, 20, 30, 40, 100.25, 1000.125}; + + SSample2 destObj; + + int32_t ec = g_testClient->SSample2Test(srcObj, destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(srcObj.m1? 1:0 ,destObj.m1?1:0); + EXPECT_EQ(srcObj.m2, destObj.m2); + EXPECT_EQ(srcObj.m3, destObj.m3); + EXPECT_EQ(srcObj.m4, destObj.m4); + EXPECT_EQ(srcObj.m5, destObj.m5); + EXPECT_EQ(srcObj.m6, destObj.m6); + EXPECT_EQ(srcObj.m7, destObj.m7); + EXPECT_EQ(srcObj.m8, destObj.m8); + EXPECT_EQ(srcObj.m9, destObj.m9); + EXPECT_FLOAT_EQ(srcObj.m10, destObj.m10); + EXPECT_DOUBLE_EQ(srcObj.m11, destObj.m11); + + PrintSSample2(srcObj); + std::cout << "\n"; + PrintSSample2(destObj); + std::cout << "\n"; + std::cout << "----------------------------" << std::endl; +} + +static void PrintSSample3(const SSample3& obj) +{ + std::cout << "{"; + std::cout << "m1:" << obj.m1 << ", "; + std::cout << "m2:" << ESampleToStr(obj.m2) << ", "; + + std::cout << "m3:"; + PrintSSample2(obj.m3); + std::cout << ", "; + + std::cout << "m4:" << obj.m4; +} + +HWTEST_F(StructTest, StructTest_004, TestSize.Level0) +{ + int fd = open("/fdtest3.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + SSample3 srcObj = { + "hello world", + ESample::MEM_ONE, + {true, 1, 2, 3, 4, 65, 20, 30, 40, 100.25, 1000.125}, + fd, + }; + + SSample3 destObj; + int32_t ec = g_testClient->SSample3Test(srcObj, destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(srcObj.m1, destObj.m1); + EXPECT_EQ(srcObj.m2, destObj.m2); + + EXPECT_EQ(srcObj.m3.m1? 1:0 ,destObj.m3.m1?1:0); + EXPECT_EQ(srcObj.m3.m2, destObj.m3.m2); + EXPECT_EQ(srcObj.m3.m3, destObj.m3.m3); + EXPECT_EQ(srcObj.m3.m4, destObj.m3.m4); + EXPECT_EQ(srcObj.m3.m5, destObj.m3.m5); + EXPECT_EQ(srcObj.m3.m6, destObj.m3.m6); + EXPECT_EQ(srcObj.m3.m7, destObj.m3.m7); + EXPECT_EQ(srcObj.m3.m8, destObj.m3.m8); + EXPECT_EQ(srcObj.m3.m9, destObj.m3.m9); + EXPECT_FLOAT_EQ(srcObj.m3.m10, destObj.m3.m10); + EXPECT_DOUBLE_EQ(srcObj.m3.m11, destObj.m3.m11); + + //m4 file descriptor + PrintSSample3(srcObj); + std::cout << "\n"; + PrintSSample3(destObj); + std::cout << "\n"; + std::cout << "----------------------------" << std::endl; + close(srcObj.m4); + close(destObj.m4); +} + +static void PrintSSample4(const SSample4& obj) +{ + std::cout << "{\n"; + + //m1 + std::cout << "m1:{"; + for (size_t i = 0; i < obj.m1.size(); i++) { + std::cout << (obj.m1[i]? 1:0) << ", "; + } + std::cout << "},\n"; + + //m2 + std::cout << "m2:{"; + for (size_t i = 0; i < obj.m2.size(); i++) { + std::cout << obj.m2[i] << ", "; + } + std::cout << "},\n"; + + //m3 + std::cout << "m3:{"; + for (size_t i = 0; i < obj.m3.size(); i++) { + std::cout << obj.m3[i] << ", "; + } + std::cout << "},\n"; + + //m4 + std::cout << "m4:{"; + for (size_t i = 0; i < obj.m4.size(); i++) { + std::cout << obj.m4[i] << ", "; + } + std::cout << "},\n"; + + //m5 + std::cout << "m5:{"; + for (size_t i = 0; i < obj.m5.size(); i++) { + std::cout << obj.m5[i] << ", "; + } + std::cout << "},\n"; + + //m6 + std::cout << "m6:{"; + for (size_t i = 0; i < obj.m6.size(); i++) { + std::cout << obj.m6[i] << ", "; + } + std::cout << "},\n"; + + //m7 + std::cout << "m7:{"; + for (size_t i = 0; i < obj.m7.size(); i++) { + std::cout << obj.m7[i] << ", "; + } + std::cout << "},\n"; + + //m8 + std::cout << "m8:{"; + for (size_t i = 0; i < obj.m8.size(); i++) { + std::cout << obj.m8[i] << ", "; + } + std::cout << "},\n"; + + //m9 + std::cout << "m9:{"; + for (size_t i = 0; i < obj.m9.size(); i++) { + std::cout << obj.m9[i] << ", "; + } + std::cout << "},\n"; + + //m10 + std::cout << "m10:{"; + for (size_t i = 0; i < obj.m10.size(); i++) { + std::cout << obj.m10[i] << ", "; + } + std::cout << "},\n"; + + //m11 + std::cout << "m11:{"; + for (size_t i = 0; i < obj.m11.size(); i++) { + std::cout << obj.m11[i] << ", "; + } + std::cout << "},\n"; + + //m12 + std::cout << "m12:{"; + for (size_t i = 0; i < obj.m12.size(); i++) { + std::cout << obj.m12[i] << ", "; + } + std::cout << "},\n"; + + //m13 + std::cout << "m13:{"; + for (size_t i = 0; i < obj.m13.size(); i++) { + std::cout << ESampleToStr(obj.m13[i]) << ", "; + } + std::cout << "},\n"; + + //m14 + std::cout << "m14:{"; + for (size_t i = 0; i < obj.m13.size(); i++) { + PrintSSample(obj.m14[i]); + std::cout << ", "; + } + std::cout << "},\n"; + + //m15 + std::cout << "m15:{"; + for (size_t i = 0; i < obj.m15.size(); i++) { + std::cout << obj.m15[i] << ", "; + } + std::cout << "}"; + std::cout << "}\n"; +} + +HWTEST_F(StructTest, StructTest_005, TestSize.Level0) +{ + SSample4 srcObj = { + {true, false}, + {65, 66}, + {3, 4}, + {5, 6}, + {7, 8}, + {97, 98}, + {30, 40}, + {50, 60}, + {70, 80}, + {10.5, 20.5}, + {30.125, 30.125}, + {"hello", "world"}, + {ESample::MEM_ONE, ESample::MEM_THREE}, + {{true, 1, 1000.125, "hello"}, {false, 1, 1000.125, "world"}}, + {sptr(new SequenceData(1, 1.2, "hello")), sptr(new SequenceData(2, 2.2, "world"))}, + }; + + SSample4 destObj; + + int32_t ec = g_testClient->SSample4Test(srcObj, destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + + //m1 + for (size_t i = 0; i < srcObj.m1.size(); i++) { + EXPECT_EQ(srcObj.m1[i]? 1:0, destObj.m1[i]? 1:0); + } + + //m2 + for (size_t i = 0; i < srcObj.m2.size(); i++) { + EXPECT_EQ(srcObj.m2[i], destObj.m2[i]); + } + + //m3 + for (size_t i = 0; i < srcObj.m3.size(); i++) { + EXPECT_EQ(srcObj.m3[i], destObj.m3[i]); + } + + //m4 + for (size_t i = 0; i < srcObj.m4.size(); i++) { + EXPECT_EQ(srcObj.m4[i], destObj.m4[i]); + } + + //m5 + for (size_t i = 0; i < srcObj.m5.size(); i++) { + EXPECT_EQ(srcObj.m5[i], destObj.m5[i]); + } + + //m6 + for (size_t i = 0; i < srcObj.m6.size(); i++) { + EXPECT_EQ(srcObj.m6[i], destObj.m6[i]); + } + + //m7 + for (size_t i = 0; i < srcObj.m7.size(); i++) { + EXPECT_EQ(srcObj.m7[i], destObj.m7[i]); + } + + //m8 + for (size_t i = 0; i < srcObj.m8.size(); i++) { + EXPECT_EQ(srcObj.m8[i], destObj.m8[i]); + } + + //m9 + for (size_t i = 0; i < srcObj.m9.size(); i++) { + EXPECT_EQ(srcObj.m9[i], destObj.m9[i]); + } + + //m10 + for (size_t i = 0; i < srcObj.m10.size(); i++) { + EXPECT_FLOAT_EQ(srcObj.m10[i], destObj.m10[i]); + } + + //m11 + for (size_t i = 0; i < srcObj.m11.size(); i++) { + EXPECT_DOUBLE_EQ(srcObj.m11[i], destObj.m11[i]); + } + + //m12 + for (size_t i = 0; i < srcObj.m12.size(); i++) { + EXPECT_EQ(srcObj.m12[i], destObj.m12[i]); + } + + //m13 + for (size_t i = 0; i < srcObj.m13.size(); i++) { + EXPECT_EQ(srcObj.m13[i], destObj.m13[i]); + } + + //m14 + for (size_t i = 0; i < srcObj.m14.size(); i++) { + EXPECT_EQ((srcObj.m14[i]).m1? 1:0 ,(destObj.m14[i]).m1?1:0); + EXPECT_EQ((srcObj.m14[i]).m2, (destObj.m14[i]).m2); + EXPECT_DOUBLE_EQ((srcObj.m14[i]).m3, (destObj.m14[i]).m3); + EXPECT_EQ((srcObj.m14[i]).m4, (destObj.m14[i]).m4); + } + + //m15 + for (size_t i = 0; i < srcObj.m15.size(); i++) { + sptr var1 = srcObj.m15[i]; + sptr var2 = destObj.m15[i]; + + if (var1 != nullptr && var2 != nullptr) { + EXPECT_EQ(var1->m1_, var2->m1_); + EXPECT_DOUBLE_EQ(var1->m2_, var2->m2_); + EXPECT_EQ(var1->m3_, var2->m3_); + } else { + std::cout << "var1 or var2 is nullptr" << std::endl; + } + } + + PrintSSample4(srcObj); + PrintSSample4(destObj); + std::cout << "\n"; + std::cout << "--------------------------------------\n"; +} + +static void PrintSSample5(const SSample5& obj) +{ + std::cout << "{\n"; + + //m1 + std::cout << "m1:{"; + for (size_t i = 0; i < obj.m1.size(); i++) { + std::cout << obj.m1[i] << ", "; + } + std::cout << "},\n"; + + //m2 + std::cout << "m2:{"; + for (size_t i = 0; i < obj.m2.size(); i++) { + std::cout << obj.m2[i] << ", "; + } + std::cout << "},\n"; + + //m3 + std::cout << "m3:{"; + for (size_t i = 0; i < obj.m3.size(); i++) { + std::cout << obj.m3[i] << ", "; + } + std::cout << "},\n"; + + //m4 + std::cout << "m4:{"; + for (size_t i = 0; i < obj.m4.size(); i++) { + std::cout << obj.m4[i] << ", "; + } + std::cout << "},\n"; + + //m5 + std::cout << "m5:{"; + for (size_t i = 0; i < obj.m5.size(); i++) { + std::cout << obj.m5[i] << ", "; + } + std::cout << "},\n"; + + //m6 + std::cout << "m6:{"; + for (size_t i = 0; i < obj.m6.size(); i++) { + std::cout << obj.m6[i] << ", "; + } + std::cout << "},\n"; + + //m7 + std::cout << "m7:{"; + for (size_t i = 0; i < obj.m7.size(); i++) { + std::cout << obj.m7[i] << ", "; + } + std::cout << "},\n"; + + //m8 + std::cout << "m8:{"; + for (size_t i = 0; i < obj.m8.size(); i++) { + std::cout << obj.m8[i] << ", "; + } + std::cout << "},\n"; + + //m9 + std::cout << "m9:{"; + for (size_t i = 0; i < obj.m9.size(); i++) { + std::cout << obj.m9[i] << ", "; + } + std::cout << "},\n"; + + //m10 + std::cout << "m10:{"; + for (size_t i = 0; i < obj.m10.size(); i++) { + std::cout << obj.m10[i] << ", "; + } + std::cout << "},\n"; + + //m11 + std::cout << "m11:{"; + for (size_t i = 0; i < obj.m11.size(); i++) { + std::cout << obj.m11[i] << ", "; + } + std::cout << "},\n"; + + //m12 + std::cout << "m12:{"; + for (size_t i = 0; i < obj.m12.size(); i++) { + std::cout << obj.m12[i] << ", "; + } + std::cout << "},\n"; + + //m13 + std::cout << "m13:{"; + for (size_t i = 0; i < obj.m13.size(); i++) { + std::cout << ESampleToStr(obj.m13[i]) << ", "; + } + std::cout << "},\n"; + + //m14 + std::cout << "m14:{"; + for (size_t i = 0; i < obj.m14.size(); i++) { + PrintSSample(obj.m14[i]); + std::cout << ", \n"; + } + std::cout << ",\n"; + + //m15 + std::cout << "m13:{"; + for (size_t i = 0; i < obj.m15.size(); i++) { + std::cout << obj.m15[i] << ", "; + } + std::cout << "},\n"; + + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_006, TestSize.Level0) +{ + SSample5 srcObj = { + {true, false}, + {65, 66}, + {3, 4}, + {5, 6}, + {7, 8}, + {97, 98}, + {30, 40}, + {50, 60}, + {70, 80}, + {10.5, 20.5}, + {30.125, 30.125}, + {"hello", "world"}, + {ESample::MEM_ONE, ESample::MEM_THREE}, + {{true, 1, 1000.125, "hello"}, {false, 1, 1000.125, "world"}}, + {sptr(new SequenceData(1, 1.2, "hello")), sptr(new SequenceData(2, 2.2, "world"))}, + }; + + SSample5 destObj; + + int32_t ec = g_testClient->SSample5Test(srcObj, destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + //m1 + for (size_t i = 0; i < srcObj.m1.size(); i++) { + EXPECT_EQ(srcObj.m1[i]? 1:0, destObj.m1[i]? 1:0); + } + + //m2 + for (size_t i = 0; i < srcObj.m2.size(); i++) { + EXPECT_EQ(srcObj.m2[i], destObj.m2[i]); + } + + //m3 + for (size_t i = 0; i < srcObj.m3.size(); i++) { + EXPECT_EQ(srcObj.m3[i], destObj.m3[i]); + } + + //m4 + for (size_t i = 0; i < srcObj.m4.size(); i++) { + EXPECT_EQ(srcObj.m4[i], destObj.m4[i]); + } + + //m5 + for (size_t i = 0; i < srcObj.m5.size(); i++) { + EXPECT_EQ(srcObj.m5[i], destObj.m5[i]); + } + + //m6 + for (size_t i = 0; i < srcObj.m6.size(); i++) { + EXPECT_EQ(srcObj.m6[i], destObj.m6[i]); + } + + //m7 + for (size_t i = 0; i < srcObj.m7.size(); i++) { + EXPECT_EQ(srcObj.m7[i], destObj.m7[i]); + } + + // m8 + for (size_t i = 0; i < srcObj.m8.size(); i++) { + EXPECT_EQ(srcObj.m8[i], destObj.m8[i]); + } + + // m9 + for (size_t i = 0; i < srcObj.m9.size(); i++) { + EXPECT_EQ(srcObj.m9[i], destObj.m9[i]); + } + + // m10 + for (size_t i = 0; i < srcObj.m10.size(); i++) { + EXPECT_FLOAT_EQ(srcObj.m10[i], destObj.m10[i]); + } + + //m11 + for (size_t i = 0; i < srcObj.m11.size(); i++) { + EXPECT_DOUBLE_EQ(srcObj.m11[i], destObj.m11[i]); + } + + //m12 + for (size_t i = 0; i < srcObj.m12.size(); i++) { + EXPECT_EQ(srcObj.m12[i], destObj.m12[i]); + } + + //m13 + for (size_t i = 0; i < srcObj.m13.size(); i++) { + EXPECT_EQ(srcObj.m13[i], destObj.m13[i]); + } + + //m14 + for (size_t i = 0; i < srcObj.m14.size(); i++) { + EXPECT_EQ((srcObj.m14[i]).m1? 1:0 ,(destObj.m14[i]).m1?1:0); + EXPECT_EQ((srcObj.m14[i]).m2, (destObj.m14[i]).m2); + EXPECT_DOUBLE_EQ((srcObj.m14[i]).m3, (destObj.m14[i]).m3); + EXPECT_EQ((srcObj.m14[i]).m4, (destObj.m14[i]).m4); + } + + //m15 + for (size_t i = 0; i < srcObj.m15.size(); i++) { + sptr var1 = srcObj.m15[i]; + sptr var2 = destObj.m15[i]; + + if (var1 != nullptr && var2 != nullptr) { + EXPECT_EQ(var1->m1_, var2->m1_); + EXPECT_DOUBLE_EQ(var1->m2_, var2->m2_); + EXPECT_EQ(var1->m3_, var2->m3_); + } else { + std::cout << "var1 or var2 is nullptr" << std::endl; + } + } + + PrintSSample5(srcObj); + PrintSSample5(destObj); + std::cout << "\n"; + std::cout << "--------------------------------------\n"; +} + +// static void PrintSSample6(const SSample6& obj) +// { +// std::cout << "{\n"; + +// PrintUSample(obj.m1); +// std::cout << ",\n"; + +// std::cout << "{"; +// for (size_t i = 0; i < obj.m2.size(); i++) { +// PrintUSample(obj.m2[i]); +// std::cout << ", "; +// } +// std::cout << "},\n"; + +// std::cout << "{"; +// for (size_t i = 0; i < obj.m3.size(); i++) { +// PrintUSample(obj.m3[i]); +// std::cout << ", "; +// } +// std::cout << "}\n"; + +// std::cout << "}"; +// } + +// HWTEST_F(StructTest, StructTest_007, TestSize.Level0) +// { +// SSample6 srcObj; +// srcObj.m1.m1 = true; +// srcObj.m1.m2 = 10; + +// for (int i = 0; i < 2; i++) { +// USample data; +// data.m1 = true; +// data.m2 = i; +// srcObj.m2.push_back(data); +// } + +// for (int i = 2; i < 4; i++) { +// USample data; +// data.m1 = false; +// data.m2 = i; +// srcObj.m2.push_back(data); +// } + +// SSample6 destObj; + +// int32_t ec = g_testClient->SSample6Test(srcObj, destObj); +// ASSERT_EQ(ec, HDF_SUCCESS); + +// EXPECT_EQ(srcObj.m1.m1? 1:0, destObj.m1.m1? 1:0); +// EXPECT_EQ(srcObj.m1.m2, destObj.m1.m2); + +// for (size_t i = 0; i < srcObj.m2.size(); i++) { +// EXPECT_EQ(srcObj.m2[i].m1? 1:0, destObj.m2[i].m1? 1:0); +// EXPECT_EQ(srcObj.m2[i].m2, destObj.m2[i].m2); +// } + +// for (size_t i = 0; i < srcObj.m3.size(); i++) { +// EXPECT_EQ(srcObj.m3[i].m1? 1:0, destObj.m3[i].m1? 1:0); +// EXPECT_EQ(srcObj.m3[i].m2, destObj.m3[i].m2); +// } + +// PrintSSample6(srcObj); +// std::cout << "\n"; +// PrintSSample6(destObj); +// std::cout << "\n"; +// std::cout << "---------------------\n"; +// } \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/types/v1_0/Types.idl b/tools/hdi-gen/test/cpp_test/types/v1_0/Types.idl new file mode 100755 index 000000000..f96b0d4b9 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/types/v1_0/Types.idl @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.types.v1_0; + +sequenceable test.cpp_test.types.v1_0.SequenceData; + +enum ESample +{ + MEM_ONE, + MEM_TWO, + MEM_THREE, +}; + +struct SSample +{ + boolean m1; + int m2; + double m3; + String m4; +}; + +union USample +{ + boolean m1; + int m2; +}; + +struct SSample2 +{ + boolean m1; + byte m2; + short m3; + int m4; + long m5; + unsigned char m6; + unsigned short m7; + unsigned int m8; + unsigned long m9; + float m10; + double m11; +}; + +struct SSample3 +{ + String m1; + enum ESample m2; + struct SSample2 m3; + FileDescriptor m4; +}; + +struct SSample4 +{ + boolean[] m1; + byte[] m2; + short[] m3; + int[] m4; + long[] m5; + unsigned char[] m6; + unsigned short[] m7; + unsigned int[] m8; + unsigned long[] m9; + float[] m10; + double[] m11; + String[] m12; + enum ESample[] m13; + struct SSample[] m14; + SequenceData[] m15; +}; + +struct SSample5 +{ + List m1; + List m2; + List m3; + List m4; + List m5; + List m6; + List m7; + List m8; + List m9; + List m10; + List m11; + List m12; + List m13; + List m14; + List m15; +}; + +struct SSample6 { + union USample m1; + union USample[] m2; + List m3; +}; \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/array_test/v1_0/IArrayTest.idl b/tools/hdi-gen/test/java_test/array_test/v1_0/IArrayTest.idl new file mode 100755 index 000000000..48cb6c50d --- /dev/null +++ b/tools/hdi-gen/test/java_test/array_test/v1_0/IArrayTest.idl @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.array_test.v1_0; + +sequenceable test.java_test.types.v1_0.SequenceData; + +interface IArrayTest { + + BoolArrayTest([in] boolean[] param1, [out] boolean[] param2); + + ByteArrayTest([in] byte[] param1, [out] byte[] param2); + + ShortArrayTest([in] short[] param1, [out] short[] param2); + + IntArrayTest([in] int[] param1, [out] int[] param2); + + LongArrayTest([in] long[] param1, [out] long[] param2); + + FloatArrayTest([in] float[] param1, [out] float[] param2); + + DoubleArrayTest([in] double[] param1, [out] double[] param2); + + StringArrayTest([in] String[] param1, [out] String[] param2); + + FdArrayTest([in] FileDescriptor[] param1, [out] FileDescriptor[] param2); + + SequenceArrayTest([in] SequenceData[] param1, [out] SequenceData[] param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/cb_test/v1_0/ICallback.idl b/tools/hdi-gen/test/java_test/cb_test/v1_0/ICallback.idl new file mode 100755 index 000000000..893e505ca --- /dev/null +++ b/tools/hdi-gen/test/java_test/cb_test/v1_0/ICallback.idl @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.cb_test.v1_0; + +[callback] interface ICallback { + Ping([in] String message); + Plus([in] int num1, [in] int num2, [out] int result); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/cb_test/v1_0/ICbTest.idl b/tools/hdi-gen/test/java_test/cb_test/v1_0/ICbTest.idl new file mode 100755 index 000000000..fe22cb4c5 --- /dev/null +++ b/tools/hdi-gen/test/java_test/cb_test/v1_0/ICbTest.idl @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.cb_test.v1_0; + +import test.java_test.cb_test.v1_0.ICallback; + +interface ICbTest { + CallbackTest([in] ICallback callbackObj); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/data_test/v1_0/IDataTest.idl b/tools/hdi-gen/test/java_test/data_test/v1_0/IDataTest.idl new file mode 100755 index 000000000..8e09eaa90 --- /dev/null +++ b/tools/hdi-gen/test/java_test/data_test/v1_0/IDataTest.idl @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.data_test.v1_0; + +sequenceable test.java_test.types.v1_0.SequenceData; + +interface IDataTest { + + BoolTest([in] boolean param1, [out] boolean param2); + + ByteTest([in] byte param1, [out] byte param2); + + ShortTest([in] short param1, [out] short param2); + + IntTest([in] int param1, [out] int param2); + + LongTest([in] long param1, [out] long param2); + + FloatTest([in] float param1, [out] float param2); + + DoubleTest([in] double param1, [out] double param2); + + StringTest([in] String param1, [out] String param2); + + FdTest([in] FileDescriptor fd); + + SequenceTest([in] SequenceData param1, [out] SequenceData param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/list_test/v1_0/IListTest.idl b/tools/hdi-gen/test/java_test/list_test/v1_0/IListTest.idl new file mode 100755 index 000000000..2ee789bd7 --- /dev/null +++ b/tools/hdi-gen/test/java_test/list_test/v1_0/IListTest.idl @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.list_test.v1_0; + +sequenceable test.java_test.types.v1_0.SequenceData; + +interface IListTest { + + BoolListTest([in] List param1, [out] List param2); + + ByteListTest([in] List param1, [out] List param2); + + ShortListTest([in] List param1, [out] List param2); + + IntListTest([in] List param1, [out] List param2); + + LongListTest([in] List param1, [out] List param2); + + FloatListTest([in] List param1, [out] List param2); + + DoubleListTest([in] List param1, [out] List param2); + + StringListTest([in] List param1, [out] List param2); + + FdListTest([in] List param1, [out] List param2); + + SequenceListTest([in] List param1, [out] List param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/map_test/v1_0/IMapTest.idl b/tools/hdi-gen/test/java_test/map_test/v1_0/IMapTest.idl new file mode 100755 index 000000000..6081c1da5 --- /dev/null +++ b/tools/hdi-gen/test/java_test/map_test/v1_0/IMapTest.idl @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.map_test.v1_0; + +sequenceable test.java_test.types.v1_0.SequenceData; + +interface IMapTest { + //same key + MapIntByteTest([in] Map param1, [out] Map param2); + + MapIntShortTest([in] Map param1, [out] Map param2); + + MapIntIntTest([in] Map param1, [out] Map param2); + + MapIntLongTest([in] Map param1, [out] Map param2); + + MapIntFloatTest([in] Map param1, [out] Map param2); + + MapIntDoubleTest([in] Map param1, [out] Map param2); + + MapIntStringTest([in] Map param1, [out] Map param2); + + MapIntFdTest([in] Map param1, [out] Map param2); + + MapIntSeqTest([in] Map param1, [out] Map param2); + + //same value + MapByteIntTest([in] Map param1, [out] Map param2); + + MapShortIntTest([in] Map param1, [out] Map param2); + + MapLongIntTest([in] Map param1, [out] Map param2); + + MapFloatIntTest([in] Map param1, [out] Map param2); + + MapDoubleIntTest([in] Map param1, [out] Map param2); + + MapStringIntTest([in] Map param1, [out] Map param2); + + MapFdIntTest([in] Map param1, [out] Map param2); + + MapSeqIntTest([in] Map param1, [out] Map param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/util/Makefile b/tools/hdi-gen/util/Makefile new file mode 100755 index 000000000..dfae7c273 --- /dev/null +++ b/tools/hdi-gen/util/Makefile @@ -0,0 +1,14 @@ +OBJS_DIR:=$(BUILD_DIR)/util +TARGET = $(OBJS_DIR)/util.a +SOURCE:=$(wildcard *.cpp) +OBJS:=$(patsubst %.cpp, $(OBJS_DIR)/%.o, $(SOURCE)) + + + +$(TARGET):$(OBJS) + $(Q) echo $(TARGET) + $(Q) ar -rc $@ $^ + +$(OBJS_DIR)/%.o:%.cpp + $(Q) mkdir -p $(dir $@) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ \ No newline at end of file diff --git a/tools/hdi-gen/util/autoptr.h b/tools/hdi-gen/util/autoptr.h new file mode 100755 index 000000000..4015109d7 --- /dev/null +++ b/tools/hdi-gen/util/autoptr.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_AUTOPTR_H +#define OHOS_HDI_AUTOPTR_H + +namespace OHOS { +namespace HDI { +template +class AutoPtr { +public: + inline AutoPtr() + : mPtr(nullptr) {} + + AutoPtr(T* other); + + AutoPtr(const AutoPtr& other); + + AutoPtr(AutoPtr && other); + + ~AutoPtr(); + + AutoPtr& operator=(T* other); + + AutoPtr& operator=(const AutoPtr& other); + + AutoPtr& operator=(AutoPtr && other); + + void MoveTo(T** other); + + inline operator T* () const; + + inline T** operator&(); + + inline T* operator->() const; + + inline T& operator*() const; + + inline T* Get() const; + + inline bool operator==(T* other) const; + + inline bool operator==(const AutoPtr& other) const; + + inline bool operator!=(T* other) const; + + inline bool operator!=(const AutoPtr& other) const; + + inline bool operator>(T* other) const; + + inline bool operator>(const AutoPtr& other) const; + + inline bool operator<(T* other) const; + + inline bool operator<(const AutoPtr& other) const; + + inline bool operator<=(T* other) const; + + inline bool operator<=(const AutoPtr& other) const; + + inline bool operator>=(T* other) const; + + inline bool operator>=(const AutoPtr& other) const; + +private: + T* mPtr; +}; + +template +AutoPtr::AutoPtr(T* other) + : mPtr(other) +{ + if (mPtr != nullptr) { + mPtr->AddRef(); + } +} + +template +AutoPtr::AutoPtr(const AutoPtr& other) + : mPtr(other.mPtr) +{ + if (mPtr != nullptr) { + mPtr->AddRef(); + } +} + +template +AutoPtr::AutoPtr(AutoPtr && other) + : mPtr(other.mPtr) +{ + other.mPtr = nullptr; +} + +template +AutoPtr::~AutoPtr() +{ + if (mPtr != nullptr) { + mPtr->Release(); + } +} + +template +AutoPtr& AutoPtr::operator=(T* other) +{ + if (mPtr == other) return *this; + + if (other != nullptr) { + other->AddRef(); + } + if (mPtr != nullptr) { + mPtr->Release(); + } + mPtr = other; + return *this; +} + +template +AutoPtr& AutoPtr::operator=(const AutoPtr& other) +{ + if (mPtr == other.mPtr) return *this; + + if (other.mPtr != nullptr) { + other.mPtr->AddRef(); + } + if (mPtr != nullptr) { + mPtr->Release(); + } + mPtr = other.mPtr; + return *this; +} + +template +AutoPtr& AutoPtr::operator=(AutoPtr && other) +{ + if (mPtr != nullptr) { + mPtr->Release(); + } + mPtr = other.mPtr; + other.mPtr = nullptr; + return *this; +} + +template +void AutoPtr::MoveTo(T** other) +{ + if (other != nullptr) { + *other = mPtr; + mPtr = nullptr; + } +} + +template +AutoPtr::operator T* () const +{ + return mPtr; +} + +template +T** AutoPtr::operator&() +{ + return &mPtr; +} + +template +T* AutoPtr::operator->() const +{ + return mPtr; +} + +template +T& AutoPtr::operator*() const +{ + return *mPtr; +} + +template +T* AutoPtr::Get() const +{ + return mPtr; +} + +template +bool AutoPtr::operator==(T* other) const +{ + return mPtr == other; +} + +template +bool AutoPtr::operator==(const AutoPtr& other) const +{ + return mPtr == other.mPtr; +} + +template +bool AutoPtr::operator!=(T* other) const +{ + return mPtr != other; +} + +template +bool AutoPtr::operator!=(const AutoPtr& other) const +{ + return mPtr != other.mPtr; +} + +template +bool AutoPtr::operator>(T* other) const +{ + return mPtr > other; +} + +template +bool AutoPtr::operator>(const AutoPtr& other) const +{ + return mPtr > other.mPtr; +} + +template +bool AutoPtr::operator<(T* other) const +{ + return mPtr < other; +} + +template +bool AutoPtr::operator<(const AutoPtr& other) const +{ + return mPtr < other.mPtr; +} + +template +bool AutoPtr::operator<=(T* other) const +{ + return mPtr <= other; +} + +template +bool AutoPtr::operator<=(const AutoPtr& other) const +{ + return mPtr <= other.mPtr; +} + +template +bool AutoPtr::operator>=(T* other) const +{ + return mPtr >= other; +} + +template +bool AutoPtr::operator>=(const AutoPtr& other) const +{ + return mPtr >= other.mPtr; +} +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_AUTOPTR_H \ No newline at end of file diff --git a/tools/hdi-gen/util/file.cpp b/tools/hdi-gen/util/file.cpp new file mode 100755 index 000000000..72bb17381 --- /dev/null +++ b/tools/hdi-gen/util/file.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "util/file.h" +#include +#include +#include +#include +#include +#include "securec.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +#ifdef __MINGW32__ +constexpr unsigned int File::READ; +constexpr unsigned int File::WRITE; +constexpr unsigned int File::APPEND; +#endif + +File::File(const String& path, unsigned int mode) + : mode_(mode) +{ + if (path.IsEmpty()) { + return; + } + + if (mode_ & READ) { + if (!CheckValid(path)) { + return; + } + fd_ = fopen(path.string(), "r"); + } else if (mode_ & WRITE) { + fd_ = fopen(path.string(), "w+"); + } else if (mode_ & APPEND) { + fd_ = fopen(path.string(), "a+"); + } + + if (fd_ != nullptr) { +#ifndef __MINGW32__ + char* absolutePath = realpath(path.string(), nullptr); + if (absolutePath != nullptr) { + path_ = absolutePath; + free(absolutePath); + } else { + path_ = path; + } +#else + char absolutePath[_MAX_PATH]; + _fullpath(absolutePath, path.string(), _MAX_PATH); + path_ = absolutePath; +#endif + } +} + +File::~File() +{ + Close(); +} + +char File::GetChar() +{ + char c = PeekChar(); + + if (position_ + 1 <= size_) { + position_++; + + if (c != '\n') { + columnNo_++; + } else { + columnNo_ = 0; + lineNo_++; + } + } + return c; +} + +char File::PeekChar() +{ + if (position_ + 1 > size_) { + int ret = Read(); + if (ret == -1) { + isEof_ = true; + } + } + + return buffer_[position_]; +} + +bool File::IsEof() const +{ + return isEof_ || buffer_[position_] == -1; +} + +int File::Read() +{ + if (isEof_ || isError_) { + return -1; + } + + (void)memset_s(buffer_, BUFFER_SIZE, 0, BUFFER_SIZE); + size_t count = fread(buffer_, 1, BUFFER_SIZE - 1, fd_); + if (count < BUFFER_SIZE - 1) { + isError_ = ferror(fd_) != 0; + buffer_[count] = -1; + } + size_ = count; + position_ = 0; + return (count != 0) ? count : -1; +} + +bool File::ReadData(void* data, size_t size) +{ + if (data == nullptr || size == 0) { + return true; + } + + if (fd_ == nullptr) { + return false; + } + + size_t count = fread(data, size, 1, fd_); + return count == 1; +} + +bool File::WriteData(const void* data, size_t size) +{ + if (data == nullptr || size == 0) { + return true; + } + + if (fd_ == nullptr || !(mode_ & (WRITE | APPEND))) { + return false; + } + + size_t count = fwrite(data, size, 1, fd_); + return count == 1; +} + +void File::Flush() +{ + if ((mode_ & (WRITE | APPEND)) && fd_ != nullptr) { + fflush(fd_); + } +} + +bool File::Reset() +{ + if (fd_ == nullptr) { + return false; + } + + return fseek(fd_, 0, SEEK_SET) == 0; +} + +bool File::Skip(long size) +{ + if (fd_ == nullptr) { + return false; + } + + return fseek(fd_, size, SEEK_CUR) == 0; +} + +void File::Close() +{ + if (fd_ != nullptr) { + fclose(fd_); + fd_ = nullptr; + } +} + +bool File::CreateParentDir(const String& path) +{ + if (!access(path.string(), F_OK | R_OK | W_OK)) { + return true; + } + + int pos = 1; + while ((pos = path.IndexOf('/', pos)) != -1) { + String partPath = path.Substring(0, pos); + + struct stat st; + if (stat(partPath.string(), &st) < 0) { + if (errno != ENOENT) { + return false; + } + + if (mkdir(partPath.string(), S_IRWXU | S_IRWXG | S_IRWXO) < 0) { + return false; + } + } else if (!S_ISDIR(st.st_mode)) { + return false; + } + pos += 1; + } + return true; +} + +size_t File::GetHashKey() +{ + StringBuilder fileStr; + while (!IsEof()) { + fileStr.Append(GetChar()); + } + + return std::hash()(fileStr.ToString().string()); +} + +bool File::CheckValid(const String& path) +{ + if (access(path.string(), F_OK | R_OK | W_OK)) { + return false; + } + + struct stat st; + if (stat(path.string(), &st) < 0) { + return false; + } + + if (S_ISDIR(st.st_mode)) { + return false; + } + + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/file.h b/tools/hdi-gen/util/file.h new file mode 100755 index 000000000..7120962cb --- /dev/null +++ b/tools/hdi-gen/util/file.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_FILE_H +#define OHOS_HDI_FILE_H + +#include +#include +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class File { +public: + File(const String& path, unsigned int mode); + + ~File(); + + inline bool IsValid() const + { + return fd_ != nullptr; + } + + inline String GetPath() const + { + return path_; + } + + char GetChar(); + + char PeekChar(); + + bool IsEof() const; + + inline int GetCharLineNumber() const + { + return lineNo_; + } + + inline int GetCharColumnNumber() const + { + return columnNo_; + } + + bool ReadData(void* data, size_t size); + + bool WriteData(const void* data, size_t size); + + void Flush(); + + bool Reset(); + + bool Skip(long size); + + void Close(); + + static bool CreateParentDir(const String& path); + + size_t GetHashKey(); + + static constexpr unsigned int READ = 0x1; + static constexpr unsigned int WRITE = 0x2; + static constexpr unsigned int APPEND = 0x4; + +private: + int Read(); + + bool CheckValid(const String& path); + + static constexpr int BUFFER_SIZE = 1024; + + char buffer_[BUFFER_SIZE] = {0}; + size_t size_ = 0; + size_t position_ = 0; + size_t columnNo_ = 1; + size_t lineNo_ = 1; + bool isEof_ = false; + bool isError_ = false; + + FILE* fd_ = nullptr; + String path_; + unsigned int mode_ = 0; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_FILE_H diff --git a/tools/hdi-gen/util/light_refcount_base.cpp b/tools/hdi-gen/util/light_refcount_base.cpp new file mode 100755 index 000000000..309fb4f06 --- /dev/null +++ b/tools/hdi-gen/util/light_refcount_base.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "util/light_refcount_base.h" + +namespace OHOS { +namespace HDI { +int LightRefCountBase::AddRef() +{ + const int beforeCount = refCount_.fetch_add(1, std::memory_order_relaxed); + return beforeCount + 1; +} + +int LightRefCountBase::Release() +{ + const int beforeCount = refCount_.fetch_sub(1, std::memory_order_release); + if (beforeCount - 1 == 0) { + delete this; + } + return beforeCount - 1; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/light_refcount_base.h b/tools/hdi-gen/util/light_refcount_base.h new file mode 100755 index 000000000..b0ea25471 --- /dev/null +++ b/tools/hdi-gen/util/light_refcount_base.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_LIGHTREFCOUNTBASE_H +#define OHOS_HDI_LIGHTREFCOUNTBASE_H + +#include + +namespace OHOS { +namespace HDI { +class LightRefCountBase { +public: + inline LightRefCountBase() + : refCount_(0) + {} + + int AddRef(); + + int Release(); + + inline int GetRefCount() const + { + return refCount_.load(std::memory_order_relaxed); + } + +protected: + inline virtual ~LightRefCountBase() + {} + +private: + std::atomic refCount_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_LIGHTREFCOUNTBASE_H diff --git a/tools/hdi-gen/util/logger.cpp b/tools/hdi-gen/util/logger.cpp new file mode 100755 index 000000000..697dbd29e --- /dev/null +++ b/tools/hdi-gen/util/logger.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "util/logger.h" +#include + +namespace OHOS { +namespace HDI { +int Logger::level_ = DEBUG; + +void Logger::D(const char* tag, const char* format, ...) +{ + if (level_ > DEBUG) return; + + va_list args; + va_start(args, format); + Log(tag, format, args); + va_end(args); +} + +void Logger::E(const char* tag, const char* format, ...) +{ + if (level_ > ERROR) return; + + va_list args; + va_start(args, format); + Err(tag, format, args); + va_end(args); +} + +void Logger::V(const char* tag, const char* format, ...) +{ + if (level_ > VERBOSE) return; + + va_list args; + va_start(args, format); + Log(tag, format, args); + va_end(args); +} + +void Logger::Log(const char* tag, const char* format, va_list args) +{ + printf("[%s]: ", tag); + vprintf(format, args); + printf("\n"); +} + +void Logger::Err(const char* tag, const char* format, va_list args) +{ + fprintf(stderr, "[%s]: ", tag); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/logger.h b/tools/hdi-gen/util/logger.h new file mode 100755 index 000000000..c2d6ad939 --- /dev/null +++ b/tools/hdi-gen/util/logger.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_LOGGER_H +#define OHOS_HDI_LOGGER_H + +#include + +namespace OHOS { +namespace HDI { +class Logger { +public: + + static void D(const char* tag, const char* format, ...); + + static void E(const char* tag, const char* format, ...); + + static void V(const char* tag, const char* format, ...); + + inline static void SetLevel(int level) + { + level_ = level; + } + + static constexpr int VERBOSE = 0; + static constexpr int DEBUG = 1; + static constexpr int ERROR = 2; + static constexpr int NOLOG = 3; + +private: + Logger(); + + ~Logger(); + + static void Log(const char* tag, const char* format, va_list args); + + static void Err(const char* tag, const char* format, va_list args); + + static int level_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_LOGGER_H diff --git a/tools/hdi-gen/util/options.cpp b/tools/hdi-gen/util/options.cpp new file mode 100755 index 000000000..8273ff67a --- /dev/null +++ b/tools/hdi-gen/util/options.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "options.h" +#include +#include +#include +#include +#include +#include + +namespace OHOS { +namespace HDI { +const char* Options::OPT_SUPPORT_ARGS = "c:d:"; +static struct option g_longOpts[] = { + {"help", no_argument, nullptr, 'h'}, + {"version", no_argument, nullptr, 'v'}, + {"gen-c", no_argument, nullptr, 'C'}, + {"gen-cpp", no_argument, nullptr, 'P'}, + {"gen-java", no_argument, nullptr, 'J'}, + {"hash", no_argument, nullptr, 'H'}, + {"dump-ast", no_argument, nullptr, 'D'}, + {nullptr, 0, nullptr, 0} +}; + +Options& Options::GetInstance() +{ + static Options option; + return option; +} + +Options& Options::Parse(int argc, char** argv) +{ + program_ = argv[0]; + opterr = 1; + int op = 0; + int optIndex = 0; + + while ((op = getopt_long(argc, argv, OPT_SUPPORT_ARGS, g_longOpts, &optIndex)) != OPT_END) { + switch (op) { + case 'c': + doCompile_ = true; + sourceFilePath_ = optarg; + break; + case 'd': + doOutDir_ = true; + generationDirectory_ = optarg; + break; + case 'h': + doShowUsage_ = true; + break; + case 'v': + doShowVersion_ = true; + break; + case 'C': + doGenerateCode_ = true; + targetLanguage_ = "c"; + break; + case 'P': + doGenerateCode_ = true; + targetLanguage_ = "cpp"; + break; + case 'J': + doGenerateCode_ = true; + targetLanguage_ = "java"; + break; + case 'H': + doGetHashKey_ = true; + break; + case 'D': + doDumpAST_ = true; + break; + case '?': + default: + doShowUsage_ = true; + break; + } + } + CheckOptions(); + return *this; +} + +void Options::CheckOptions() +{ + if (doShowUsage_ || doShowVersion_) { + return; + } + + if (doCompile_) { + if (!doGetHashKey_ && !doDumpAST_ && !doGenerateCode_ && !doOutDir_) { + errors_.push_back(String::Format("%s: nothing to do.", program_.string())); + return; + } + + if (!doGenerateCode_ && doOutDir_) { + errors_.push_back(String::Format("%s: no target language.", program_.string())); + return; + } + + if (doGenerateCode_ && !doOutDir_) { + errors_.push_back(String::Format("%s: no out directory.", program_.string())); + return; + } + } else { + if (doGetHashKey_ || doDumpAST_ || doGenerateCode_ || doOutDir_) { + errors_.push_back(String::Format("%s: no '-c' option.", program_.string())); + return; + } + } +} + +void Options::ShowErrors() const +{ + for (auto error : errors_) { + printf("%s\n", error.string()); + } + printf("Use \"--help\" to show usage.\n"); +} + +void Options::ShowVersion() const +{ + printf("HDI-GEN: %d.%d\n" + "Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.\n\n", + VERSION_MAJOR, VERSION_MINOR); +} + +void Options::ShowUsage() const +{ + printf("Compile a .idl file and generate C/C++ and Java codes.\n" + "Usage: idl [options] file\n" + "Options:\n" + " --help Display command line options\n" + " --version Display toolchain version information\n" + " --hash Display hash key of the idl file\n" + " --dump-ast Display the AST of the compiled file\n" + " -c Compile the .idl file\n" + " --gen-c Generate C codes\n" + " --gen-cpp Generate C++ codes\n" + " --gen-java Generate Java codes\n" + " -d Place generated codes into \n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/options.h b/tools/hdi-gen/util/options.h new file mode 100755 index 000000000..1eee4583a --- /dev/null +++ b/tools/hdi-gen/util/options.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_OPTION_H +#define OHOS_HDI_OPTION_H + +#include +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class Options { +public: + static Options& GetInstance(); + + Options(const Options& other) = delete; + Options operator=(const Options& other) = delete; + + Options& Parse(int argc, char** argv); + + ~Options() = default; + + inline bool DoShowUsage() const + { + return doShowUsage_; + } + + inline bool DoShowVersion() const + { + return doShowVersion_; + } + + inline bool DoCompile() const + { + return doCompile_; + } + + inline bool DoDumpAST() const + { + return doDumpAST_; + } + + inline bool DoGetHashKey() const + { + return doGetHashKey_; + } + + inline bool DoGenerateCode() const + { + return doGenerateCode_; + } + + inline bool HasErrors() const + { + return !errors_.empty(); + } + + inline String GetSourceFile() const + { + return sourceFilePath_; + } + + inline String GetTargetLanguage() const + { + return targetLanguage_; + } + + inline String GetGenerationDirectory() const + { + return generationDirectory_; + } + + void ShowErrors() const; + + void ShowVersion() const; + + void ShowUsage() const; + +private: + Options() : program_(), + sourceFilePath_(), + targetLanguage_(), + generationDirectory_(), + illegalOptions_(), + errors_(), + doShowUsage_(false), + doShowVersion_(false), + doCompile_(false), + doDumpAST_(false), + doGetHashKey_(false), + doGenerateCode_(false), + doOutDir_(false) {} + + void CheckOptions(); + + static const char* OPT_SUPPORT_ARGS; + static constexpr int OPT_END = -1; + + static constexpr int VERSION_MAJOR = 0; + static constexpr int VERSION_MINOR = 1; + + String program_; + String sourceFilePath_; + String targetLanguage_; + String generationDirectory_; + String illegalOptions_; + std::vector errors_; + + bool doShowUsage_ = false; + bool doShowVersion_ = false; + bool doCompile_ = false; + bool doDumpAST_ = false; + bool doGetHashKey_ = false; + bool doGenerateCode_ = false; + bool doOutDir_ = false; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDIL_OPTION_H diff --git a/tools/hdi-gen/util/string.cpp b/tools/hdi-gen/util/string.cpp new file mode 100755 index 000000000..9be249aeb --- /dev/null +++ b/tools/hdi-gen/util/string.cpp @@ -0,0 +1,748 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "util/string.h" +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "util/logger.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +constexpr int LINE_MAX_SIZE = 1024; + +using SharedData = struct SharedData { + SharedData(int refCount, int size) : refCount_(refCount), size_(size) {} + + static SharedData* Allocate(int size); + + static void AddRef(const void* handle); + + static void Release(const void* handle); + + inline static char* ToString(SharedData* header) + { + return reinterpret_cast(header + 1); + } + + inline static SharedData* GetHeader(const void* handle) + { + return reinterpret_cast(const_cast(handle)) - 1; + } + + std::atomic refCount_; + int size_; +}; + +SharedData* SharedData::Allocate(int size) +{ + if (size < 0) { + Logger::E(String::TAG, "Size %d is illegal.", size); + return nullptr; + } + if (size > String::MAX_SIZE) { + Logger::E(String::TAG, "The string is too large to alloc."); + return nullptr; + } + + auto handle = reinterpret_cast(malloc(sizeof(SharedData) + size + 1)); + if (handle == nullptr) { + Logger::E(String::TAG, "Fail to malloc %lu bytes memory", size); + return handle; + } + + new (handle)SharedData(1, size); + return handle; +} + +void SharedData::AddRef(const void* handle) +{ + if (handle == nullptr) { + return; + } + + SharedData* data = GetHeader(handle); + int before = data->refCount_.fetch_add(1); + if (before + 1 <= 1) { + Logger::E(String::TAG, "The refCount %d of %p is error in AddRef.", before, data); + }; +} + +void SharedData::Release(const void* handle) +{ + if (handle == nullptr) { + return; + } + + SharedData* data = GetHeader(handle); + int before = data->refCount_.fetch_sub(1); + if (before - 1 == 0) { + free(data); + } else if (before - 1 < 0) { + Logger::E(String::TAG, "The refCount %d of %p is error in Release.", before - 1, data); + }; +} + + +const char* String::TAG = "String"; + +String::String(const char* string) +{ + if (string != nullptr) { + string_ = SharedData::ToString(SharedData::Allocate(strlen(string))); + if (string_ == nullptr) { + return; + } + + if (strcpy_s(string_, strlen(string) + 1, string) != EOK) { + Logger::E(String::TAG, "The Construct of \"%s\" is failed.", string); + SharedData::Release(string_); + string_ = nullptr; + } + } +} + +String::String(const char* string, size_t length) +{ + if (string != nullptr) { + string_ = SharedData::ToString(SharedData::Allocate(length)); + if (string_ != nullptr) { + (void)memcpy_s(string_, length + 1, string, length); + string_[length] = '\0'; + } + } +} + +String::String(const String& other) +{ + string_ = other.string_; + SharedData::AddRef(string_); +} + +String::String(String && other) +{ + string_ = other.string_; + other.string_ = nullptr; +} + +String::String(int size) +{ + string_ = SharedData::ToString(SharedData::Allocate(size)); + if (string_ != nullptr) { + (void)memset_s(string_, size + 1, 0, size + 1); + } +} + +String::~String() +{ + SharedData::Release(string_); +} + +int String::GetLength() const +{ + if (string_ == nullptr) { + return 0; + } + + return SharedData::GetHeader(string_)->size_; +} + +char String::operator[](int index) const +{ + if (index < 0 || index >= GetLength()) { + return '\0'; + } + return string_[index]; +} + +bool String::Equals(const char* string) const +{ + if (string_ == nullptr && string == nullptr) { + return true; + } + + if (string != nullptr && string_ != nullptr) { + if ((size_t)GetLength() != strlen(string)) { + return false; + } + return strcmp(string, string_) == 0; + } + + return false; +} + +bool String::Equals(const String& other) const +{ + if (string_ == nullptr && other.string_ == nullptr) { + return true; + } + + if (string_ != nullptr && other.string_ != nullptr) { + if (GetLength() != other.GetLength()) { + return false; + } + return strcmp(string_, other.string_) == 0; + } + return false; +} + +int String::GetHashCode() const +{ + // BKDR Hash Function + unsigned int seed = 31; // 31 131 1313 13131 131313 etc.. + unsigned int hash = 0; + + const char* string = string_; + if (string != nullptr) { + for (; *string; ++string) { + hash = hash * seed + (*string); + } + } + return (hash & 0x7FFFFFFF); +} + +int String::IndexOf(char c, int fromIndex) const +{ + if (IsEmpty() || c == '\0') { + return -1; + } + + if (fromIndex < 0) { + fromIndex = 0; + } else if (fromIndex >= GetLength()) { + return -1; + } + + char* p = string_ + fromIndex; + char* end = string_ + GetLength(); + while (p != end) { + if (*p == c) { + return p - string_; + } + p++; + } + return -1; +} + +int String::IndexOf(const char* string, int fromIndex) const +{ + if (IsEmpty() || string == nullptr || string[0] == '\0') { + return -1; + } + + if (fromIndex < 0) { + fromIndex = 0; + } else if (fromIndex >= GetLength()) { + return -1; + } + + char* c = strstr(string_ + fromIndex, string); + return (c != nullptr) ? (c - string_) : -1; +} + +int String::IndexOf(const String& other, int fromIndex) const +{ + if (IsEmpty() || other.IsEmpty()) { + return -1; + } + + if (fromIndex < 0) { + fromIndex = 0; + } else if (fromIndex >= GetLength()) { + return -1; + } + + char* c = strstr(string_ + fromIndex, other.string_); + return (c != nullptr) ? (c - string_) : -1; +} + +int String::LastIndexOf(char c, int fromIndex) const +{ + if (IsEmpty() || c == '\0') { + return -1; + } + + if (fromIndex < 0) { + return -1; + } else if (fromIndex == 0 || fromIndex >= GetLength()) { + fromIndex = GetLength() - 1; + } + char* p = string_ + fromIndex; + while (p != string_) { + if (*p == c) { + return p - string_; + } + p--; + } + return -1; +} + +int String::LastIndexOf(const char* string, int fromIndex) const +{ + if (IsEmpty() || string == nullptr || string[0] == '\0') { + return -1; + } + + if (fromIndex < 0) { + return -1; + } else if (fromIndex == 0 || fromIndex >= GetLength()) { + fromIndex = GetLength() - 1; + } + + return LastIndexOfInternal(string, fromIndex); +} + +int String::LastIndexOf(const String& other, int fromIndex) const +{ + if (IsEmpty() || other.IsEmpty()) { + return -1; + } + + if (fromIndex < 0) { + return -1; + } else if (fromIndex == 0 || fromIndex >= GetLength()) { + fromIndex = GetLength() - 1; + } + + return LastIndexOfInternal(other.string(), fromIndex); +} + +int String::LastIndexOfInternal(const char* string, int fromIndex) const +{ + int sourceLen = GetLength(); + int stringLen = strlen(string); + int rightIndex = sourceLen - stringLen; + if (fromIndex > rightIndex) { + fromIndex = rightIndex; + } + + int stringLastIndex = stringLen - 1; + char stringLastChar = string[stringLastIndex]; + int min = stringLen - 1; + int i = min + fromIndex; + +startSearchLastChar: + while (true) { + while (i >= min && string_[i] != stringLastChar) { + i--; + } + if (i < min) { + return -1; + } + int j = i - 1; + int start = j - (stringLen - 1); + int k = stringLastIndex - 1; + + while (j > start) { + if (string_[j--] != string[k--]) { + i--; + goto startSearchLastChar; + } + } + return start + 1; + } +} + +bool String::StartsWith(const char* string) const +{ + if (string == nullptr || string_ == nullptr) { + return false; + } + + if (string[0] == '\0' && string_[0] == '\0') { + return true; + } + + size_t count = strlen(string); + if (count > (size_t)GetLength()) { + return false; + } + + return memcmp(string_, string, count) == 0; +} + +bool String::StartsWith(const String& other) const +{ + if (other.string_ == nullptr || string_ == nullptr) { + return false; + } + + if (other.string_[0] == '\0' && string_[0] == '\0') { + return true; + } + + size_t count = other.GetLength(); + if (count > (size_t)GetLength()) { + return false; + } + + return memcmp(string_, other.string_, count) == 0; +} + +bool String::EndsWith(const char* string) const +{ + if (string == nullptr || string_ == nullptr) { + return false; + } + + if (string[0] == '\0') { + return true; + } + + size_t count = strlen(string); + size_t len = GetLength(); + if (count > len) { + return false; + } + + return memcmp(string_ + len - count, string, count) == 0; +} + +bool String::EndsWith(const String& other) const +{ + if (other.string_ == nullptr || string_ == nullptr) { + return false; + } + + if (other.string_[0] == '\0') { + return true; + } + + size_t count = other.GetLength(); + size_t len = GetLength(); + if (count > len) { + return false; + } + + return memcmp(string_ + len - count, other.string_, count) == 0; +} + +String String::ToLowerCase() const +{ + if (IsEmpty()) { + return *this; + } + + size_t size = GetLength(); + for (size_t i = 0; i < size; i++) { + if (isupper(string_[i])) { + String newStr(string_); + for (size_t j = i; j < size; j++) { + newStr.string_[j] = tolower(newStr.string_[j]); + } + return newStr; + } + } + return *this; +} + +String String::ToUpperCase() const +{ + if (IsEmpty()) { + return *this; + } + + size_t size = GetLength(); + for (size_t i = 0; i < size; i++) { + if (islower(string_[i])) { + String newStr(string_); + for (size_t j = i; j < size; j++) { + newStr.string_[j] = toupper(newStr.string_[j]); + } + return newStr; + } + } + return *this; +} + +String String::Substring(int begin) const +{ + if (begin < 0 || begin >= GetLength()) { + return String(); + } + + return String(string_ + begin); +} + +String String::Substring(int begin, int end) const +{ + if (begin < 0 || end > GetLength() || begin > end) { + return String(); + } + + return String(string_ + begin, end - begin); +} + +String String::Replace(char oldChar, char newChar) const +{ + if (oldChar == newChar) { + return *this; + } + + size_t size = GetLength(); + for (size_t i = 0; i < size; i++) { + if (string_[i] != oldChar) { + continue; + } + + String newStr(string_); + for (size_t j = i; j < size; j++) { + if (newStr.string_[j] == oldChar) { + newStr.string_[j] = newChar; + } + } + return newStr; + } + return *this; +} + +String String::Replace(const char* target, const char* replacement) const +{ + if (target == nullptr || target[0] == '\0' || replacement == nullptr) { + return *this; + } + + int index = IndexOf(target); + if (index == -1) { + return *this; + } + + StringBuilder sb; + int begin = 0; + int step = strlen(target); + while (index != -1) { + sb.Append(Substring(begin, index)); + sb.Append(replacement); + begin = index + step; + index = IndexOf(target, begin); + } + sb.Append(Substring(begin)); + return sb.ToString(); +} + +String String::Replace(const String& target, const String& replacement) const +{ + if (target.IsEmpty() || replacement.IsNull()) { + return *this; + } + + int index = IndexOf(target); + if (index == -1) { + return *this; + } + + StringBuilder sb; + int begin = 0; + int step = target.GetLength(); + while (index != -1) { + sb.Append(Substring(begin, index)); + sb.Append(replacement); + begin = index + step; + index = IndexOf(target, begin); + } + sb.Append(Substring(begin)); + return sb.ToString(); +} + +String& String::Replace(int position, int len, const String& other) +{ + if (position < 0 || position > GetLength()) { + return *this; + } + + if (len < 0) { + return *this; + } + + if (other.IsEmpty()) { + return *this; + } + + String lStr = Substring(0, position); + String rStr = Substring(position + len); + String newStr; + newStr += lStr + other + rStr; + + SharedData::Release(string_); + SharedData::AddRef(newStr.string_); + string_ = newStr.string_; + return *this; +} + +String& String::insert(int index, const String& other) +{ + if (index < 0 || index > GetLength()) { + return *this; + } + + if (other.IsEmpty()) { + return *this; + } + + String newStr; + + String lStr = Substring(0, index); + String rStr = Substring(index); + + newStr += lStr + other + rStr; + + SharedData::Release(string_); + SharedData::AddRef(newStr.string_); + string_ = newStr.string_; + return *this; +} + +String& String::operator=(const char* string) +{ + SharedData::Release(string_); + + if (string == nullptr) { + string_ = nullptr; + return *this; + } + + string_ = SharedData::ToString(SharedData::Allocate(strlen(string))); + if (string_ == nullptr) { + return *this; + } + + if (strcpy_s(string_, strlen(string) + 1, string) != EOK) { + Logger::E(String::TAG, "The operator= of \"%s\" is failed.", string); + SharedData::Release(string_); + string_ = nullptr; + } + + return *this; +} + +String& String::operator=(const String& other) +{ + if (string_ == other.string_) { + return *this; + } + + SharedData::Release(string_); + SharedData::AddRef(other.string_); + string_ = other.string_; + return *this; +} + +String& String::operator=(String && other) +{ + SharedData::Release(string_); + string_ = other.string_; + other.string_ = nullptr; + return *this; +} + +String& String::operator+=(const char* other) +{ + if (other == nullptr || other[0] == '\0') { + return *this; + } + + int thisSize = GetLength(); + int newSize = thisSize + strlen(other); + String newString(newSize); + if (newString.string_ == nullptr) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed.", string_); + goto finished; + } + + if (string_ != nullptr && thisSize > 0) { + if (memcpy_s(newString.string_, newSize + 1, string_, thisSize) != EOK) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 2", string_); + goto finished; + } + } + + if (strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, other) != EOK) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed.", string_); + goto finished; + } + +finished: + SharedData::Release(string_); + SharedData::AddRef(newString.string_); + string_ = newString.string_; + return *this; +} + +String& String::operator+=(const String& other) +{ + if (other.IsEmpty()) { + return *this; + } + + int thisSize = GetLength(); + int newSize = thisSize + other.GetLength(); + String newString(newSize); + if (newString.string_ == nullptr) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 1", string_); + goto finished; + } + + if (string_ != nullptr && thisSize > 0) { + if (memcpy_s(newString.string_, newSize + 1, string_, thisSize) != EOK) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 2", string_); + goto finished; + } + } + + if (strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, other.string_) != EOK) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 3", string_); + goto finished; + } + +finished: + SharedData::Release(string_); + SharedData::AddRef(newString.string_); + string_ = newString.string_; + return *this; +} + +String String::Format(const char* format, ...) +{ + va_list args, argsCopy; + + va_start(args, format); + va_copy(argsCopy, args); + + char buf[LINE_MAX_SIZE] = {0}; + int len = vsnprintf_s(buf, LINE_MAX_SIZE, LINE_MAX_SIZE - 1, format, args); + String string; + if (len <= 0) { + va_end(args); + va_end(argsCopy); + return string; + } + + string = String(len); + if (string.string_ == nullptr) { + va_end(args); + va_end(argsCopy); + return string; + } + + if (vsnprintf_s(string.string_, len + 1, len, format, argsCopy) < 0) { + va_end(args); + va_end(argsCopy); + return string; + } + + va_end(args); + va_end(argsCopy); + return string; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/string.h b/tools/hdi-gen/util/string.h new file mode 100755 index 000000000..fc7acf67c --- /dev/null +++ b/tools/hdi-gen/util/string.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_STRING_H +#define OHOS_HDI_STRING_H + +#include +#include + +namespace OHOS { +namespace HDI { +class String { +public: + inline String() + {} + + String(const char* string); + + String(const char* string, size_t length); + + String(const String& other); + + String(String && other); + + ~String(); + + inline const char* string() const + { + return string_; + } + + inline operator const char* () const + { + return string_; + } + + inline bool IsNull() const + { + return string_ == nullptr; + } + + inline bool IsEmpty() const + { + return string_ == nullptr || string_[0] == '\0'; + } + + int GetLength() const; + + char operator[](int index) const; + + bool Equals(const char* string) const; + + bool Equals(const String& other) const; + + int GetHashCode() const; + + int IndexOf(char c, int fromIndex = 0) const; + + int IndexOf(const char* string, int fromIndex = 0) const; + + int IndexOf(const String& other, int fromIndex = 0) const; + + int LastIndexOf(char c, int fromIndex = 0) const; + + int LastIndexOf(const char* string, int fromIndex = 0) const; + + int LastIndexOf(const String& other, int fromIndex = 0) const; + + bool StartsWith(const char* string) const; + + bool StartsWith(const String& other) const; + + bool EndsWith(const char* string) const; + + bool EndsWith(const String& other) const; + + String ToLowerCase() const; + + String ToUpperCase() const; + + String Substring(int begin) const; + + String Substring(int begin, int end) const; + + String Replace(char oldChar, char newChar) const; + + String Replace(const char* target, const char* replacement) const; + + String Replace(const String& target, const String& replacement) const; + + String& Replace(int position, int len, const String& other); + + String& insert(int index, const String& other); + + String& operator=(const char* string); + + String& operator=(const String& other); + + String& operator=(String && other); + + String& operator+=(const char* string); + + String& operator+=(const String& other); + + static String Format(const char* format, ...); + + static const char* TAG; + static constexpr int MAX_SIZE = 262144; // 2^18 + +private: + String(int size); + + int LastIndexOfInternal(const char* string, int fromIndex) const; + + char* string_ = nullptr; +}; + +inline String operator+(const String& string1, const String& string2) +{ + String newStr; + newStr += string1; + newStr += string2; + return newStr; +} + +struct StringHashFunc { + int operator()(const String& key) const + { + return key.GetHashCode(); + } +}; + +struct StringEqualFunc { + bool operator()(const String& lhs, const String& rhs) const + { + return lhs.Equals(rhs); + } +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_STRING_H \ No newline at end of file diff --git a/tools/hdi-gen/util/string_builder.cpp b/tools/hdi-gen/util/string_builder.cpp new file mode 100755 index 000000000..3b00d4bce --- /dev/null +++ b/tools/hdi-gen/util/string_builder.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "util/string_builder.h" +#include +#include +#include "securec.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +const char* StringBuilder::TAG = "StringBuilder"; +constexpr int LINE_MAX_SIZE = 1024; + +StringBuilder::~StringBuilder() +{ + if (buffer_ != nullptr) { + free(buffer_); + } +} + +StringBuilder& StringBuilder::Append(char c) +{ + if (position_ + 1 >= capacity_) { + if (!Grow(1)) { + return *this; + } + } + + buffer_[position_] = c; + position_ += 1; + return *this; +} + +StringBuilder& StringBuilder::Append(const char* string) +{ + if (string == nullptr || string[0] == '\0') { + return *this; + } + + size_t len = strlen(string); + if (position_ + len >= capacity_) { + if (!Grow(len)) { + return *this; + } + } + + (void)memcpy_s(buffer_ + position_, capacity_ - position_, string, len); + position_ += len; + return *this; +} + +StringBuilder& StringBuilder::Append(const String& string) +{ + if (string.IsEmpty()) { + return *this; + } + + size_t len = string.GetLength(); + if (position_ + len >= capacity_) { + if (!Grow(len)) { + return *this; + } + } + + (void)memcpy_s(buffer_ + position_, capacity_ - position_, string.string(), len); + position_ += len; + return *this; +} + +StringBuilder& StringBuilder::AppendFormat(const char* format, ...) +{ + va_list args, argsCopy; + + va_start(args, format); + va_copy(argsCopy, args); + + char buf[LINE_MAX_SIZE] = {0}; + int len = vsnprintf_s(buf, LINE_MAX_SIZE, LINE_MAX_SIZE - 1, format, args); + if (len <= 0) { + va_end(args); + va_end(argsCopy); + return *this; + } + + if (position_ + len >= capacity_) { + if (!Grow(len)) { + va_end(args); + va_end(argsCopy); + return *this; + } + } + + if (vsnprintf_s(buffer_ + position_, len + 1, len, format, argsCopy) < 0) { + va_end(args); + va_end(argsCopy); + return *this; + } + position_ += len; + + va_end(args); + va_end(argsCopy); + + return *this; +} + +bool StringBuilder::Grow(size_t size) +{ + if (capacity_ > String::MAX_SIZE) { + Logger::E(TAG, "The StringBuilder is full."); + return false; + } + // 256->the default capacity. + size_t newSize = (capacity_ == 0) ? 256 : (capacity_ * 2); + if (newSize < capacity_ + size) { + newSize = capacity_ + size; + } + if (newSize > String::MAX_SIZE) { + newSize = String::MAX_SIZE; + } + if (newSize <= capacity_) { + return false; + } + + char* newBuffer = reinterpret_cast(calloc(newSize, 1)); + if (newBuffer == nullptr) { + Logger::E(TAG, "Fail to malloc %lu bytes memory.", newSize); + return false; + } + + if (buffer_ != nullptr) { + (void)memcpy_s(newBuffer, newSize, buffer_, capacity_); + free(buffer_); + } + buffer_ = newBuffer; + capacity_ = newSize; + return true; +} + +String StringBuilder::ToString() const +{ + return String(buffer_, position_); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/string_builder.h b/tools/hdi-gen/util/string_builder.h new file mode 100755 index 000000000..21d5d954a --- /dev/null +++ b/tools/hdi-gen/util/string_builder.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_STRINGBUILDER_H +#define OHOS_HDI_STRINGBUILDER_H + +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class StringBuilder { +public: + ~StringBuilder(); + + StringBuilder& Append(char c); + + StringBuilder& Append(const char* string); + + StringBuilder& Append(const String& string); + + StringBuilder& AppendFormat(const char* format, ...); + + String ToString() const; + +private: + bool Grow(size_t size); + + static const char* TAG; + char* buffer_ = nullptr; + size_t position_ = 0; + size_t capacity_ = 0; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_STRINGBUILDER_H \ No newline at end of file -- Gitee From 77b7690480b85dba40a4fd29e8504130a3dd5f31 Mon Sep 17 00:00:00 2001 From: yue Date: Thu, 2 Sep 2021 18:07:21 +0800 Subject: [PATCH 2/2] add hdi-gen Signed-off-by: yue --- tools/hdi-gen/Makefile | 46 + tools/hdi-gen/ast/Makefile | 12 + tools/hdi-gen/ast/ast.cpp | 236 +++ tools/hdi-gen/ast/ast.h | 174 ++ tools/hdi-gen/ast/ast_array_type.cpp | 389 +++++ tools/hdi-gen/ast/ast_array_type.h | 74 + tools/hdi-gen/ast/ast_boolean_type.cpp | 177 ++ tools/hdi-gen/ast/ast_boolean_type.h | 62 + tools/hdi-gen/ast/ast_byte_type.cpp | 174 ++ tools/hdi-gen/ast/ast_byte_type.h | 62 + tools/hdi-gen/ast/ast_double_type.cpp | 173 ++ tools/hdi-gen/ast/ast_double_type.h | 62 + tools/hdi-gen/ast/ast_enum_type.cpp | 277 ++++ tools/hdi-gen/ast/ast_enum_type.h | 188 +++ tools/hdi-gen/ast/ast_fd_type.cpp | 183 +++ tools/hdi-gen/ast/ast_fd_type.h | 62 + tools/hdi-gen/ast/ast_float_type.cpp | 173 ++ tools/hdi-gen/ast/ast_float_type.h | 62 + tools/hdi-gen/ast/ast_integer_type.cpp | 173 ++ tools/hdi-gen/ast/ast_integer_type.h | 62 + tools/hdi-gen/ast/ast_interface_type.cpp | 184 +++ tools/hdi-gen/ast/ast_interface_type.h | 120 ++ tools/hdi-gen/ast/ast_list_type.cpp | 390 +++++ tools/hdi-gen/ast/ast_list_type.h | 75 + tools/hdi-gen/ast/ast_long_type.cpp | 173 ++ tools/hdi-gen/ast/ast_long_type.h | 62 + tools/hdi-gen/ast/ast_map_type.cpp | 133 ++ tools/hdi-gen/ast/ast_map_type.h | 69 + tools/hdi-gen/ast/ast_method.cpp | 68 + tools/hdi-gen/ast/ast_method.h | 85 + tools/hdi-gen/ast/ast_module.cpp | 27 + tools/hdi-gen/ast/ast_module.h | 36 + tools/hdi-gen/ast/ast_namespace.cpp | 100 ++ tools/hdi-gen/ast/ast_namespace.h | 78 + tools/hdi-gen/ast/ast_node.cpp | 26 + tools/hdi-gen/ast/ast_node.h | 28 + tools/hdi-gen/ast/ast_parameter.cpp | 209 +++ tools/hdi-gen/ast/ast_parameter.h | 78 + tools/hdi-gen/ast/ast_sequenceable_type.cpp | 129 ++ tools/hdi-gen/ast/ast_sequenceable_type.h | 51 + tools/hdi-gen/ast/ast_short_type.cpp | 174 ++ tools/hdi-gen/ast/ast_short_type.h | 62 + tools/hdi-gen/ast/ast_string_type.cpp | 179 ++ tools/hdi-gen/ast/ast_string_type.h | 62 + tools/hdi-gen/ast/ast_struct_type.cpp | 265 +++ tools/hdi-gen/ast/ast_struct_type.h | 131 ++ tools/hdi-gen/ast/ast_type.cpp | 242 +++ tools/hdi-gen/ast/ast_type.h | 164 ++ tools/hdi-gen/ast/ast_uchar_type.cpp | 174 ++ tools/hdi-gen/ast/ast_uchar_type.h | 62 + tools/hdi-gen/ast/ast_uint_type.cpp | 174 ++ tools/hdi-gen/ast/ast_uint_type.h | 62 + tools/hdi-gen/ast/ast_ulong_type.cpp | 174 ++ tools/hdi-gen/ast/ast_ulong_type.h | 62 + tools/hdi-gen/ast/ast_union_type.cpp | 276 ++++ tools/hdi-gen/ast/ast_union_type.h | 131 ++ tools/hdi-gen/ast/ast_ushort_type.cpp | 174 ++ tools/hdi-gen/ast/ast_ushort_type.h | 62 + tools/hdi-gen/ast/ast_void_type.cpp | 43 + tools/hdi-gen/ast/ast_void_type.h | 33 + tools/hdi-gen/codegen/Makefile | 12 + .../c_client_interface_code_emitter.cpp | 141 ++ .../codegen/c_client_interface_code_emitter.h | 42 + .../codegen/c_client_proxy_code_emitter.cpp | 524 ++++++ .../codegen/c_client_proxy_code_emitter.h | 69 + tools/hdi-gen/codegen/c_code_emitter.cpp | 175 ++ tools/hdi-gen/codegen/c_code_emitter.h | 93 ++ tools/hdi-gen/codegen/c_code_generator.cpp | 84 + tools/hdi-gen/codegen/c_code_generator.h | 35 + .../codegen/c_custom_types_code_emitter.cpp | 446 +++++ .../codegen/c_custom_types_code_emitter.h | 65 + .../codegen/c_service_driver_code_emitter.cpp | 166 ++ .../codegen/c_service_driver_code_emitter.h | 44 + .../codegen/c_service_impl_code_emitter.cpp | 194 +++ .../codegen/c_service_impl_code_emitter.h | 45 + .../c_service_interface_code_emitter.cpp | 149 ++ .../c_service_interface_code_emitter.h | 46 + .../codegen/c_service_stub_code_emitter.cpp | 449 +++++ .../codegen/c_service_stub_code_emitter.h | 68 + tools/hdi-gen/codegen/code_generator.h | 39 + .../cpp_client_interface_code_emitter.cpp | 219 +++ .../cpp_client_interface_code_emitter.h | 56 + .../codegen/cpp_client_proxy_code_emitter.cpp | 305 ++++ .../codegen/cpp_client_proxy_code_emitter.h | 57 + tools/hdi-gen/codegen/cpp_code_emitter.cpp | 253 +++ tools/hdi-gen/codegen/cpp_code_emitter.h | 107 ++ tools/hdi-gen/codegen/cpp_code_generator.cpp | 84 + tools/hdi-gen/codegen/cpp_code_generator.h | 35 + .../codegen/cpp_custom_types_code_emitter.cpp | 311 ++++ .../codegen/cpp_custom_types_code_emitter.h | 62 + .../cpp_service_driver_code_emitter.cpp | 172 ++ .../codegen/cpp_service_driver_code_emitter.h | 45 + .../codegen/cpp_service_impl_code_emitter.cpp | 206 +++ .../codegen/cpp_service_impl_code_emitter.h | 47 + .../cpp_service_interface_code_emitter.cpp | 207 +++ .../cpp_service_interface_code_emitter.h | 56 + .../codegen/cpp_service_stub_code_emitter.cpp | 449 +++++ .../codegen/cpp_service_stub_code_emitter.h | 82 + tools/hdi-gen/codegen/generator_factory.cpp | 29 + tools/hdi-gen/codegen/generator_factory.h | 23 + .../java_client_interface_code_emitter.cpp | 142 ++ .../java_client_interface_code_emitter.h | 47 + .../java_client_proxy_code_emitter.cpp | 668 ++++++++ .../codegen/java_client_proxy_code_emitter.h | 84 + tools/hdi-gen/codegen/java_code_emitter.cpp | 121 ++ tools/hdi-gen/codegen/java_code_emitter.h | 72 + tools/hdi-gen/codegen/java_code_generator.cpp | 68 + tools/hdi-gen/codegen/java_code_generator.h | 35 + tools/hdi-gen/main.cpp | 90 + tools/hdi-gen/parser/Makefile | 12 + tools/hdi-gen/parser/file_detail.cpp | 48 + tools/hdi-gen/parser/file_detail.h | 82 + tools/hdi-gen/parser/lexer.cpp | 337 ++++ tools/hdi-gen/parser/lexer.h | 124 ++ tools/hdi-gen/parser/module_parser.cpp | 128 ++ tools/hdi-gen/parser/module_parser.h | 67 + tools/hdi-gen/parser/parser.cpp | 1443 +++++++++++++++++ tools/hdi-gen/parser/parser.h | 142 ++ tools/hdi-gen/parser/token.h | 71 + .../c_test/array_test/v1_0/IArrayTest.idl | 46 + .../c_test/array_test/v1_0/c_array_test.cpp | 676 ++++++++ .../test/c_test/cb_test/v1_0/ICallback.idl | 16 + .../test/c_test/cb_test/v1_0/ICbTest.idl | 15 + .../test/c_test/cb_test/v1_0/c_cb_test.cpp | 61 + .../test/c_test/data_test/v1_0/IDataTest.idl | 46 + .../c_test/data_test/v1_0/c_data_test.cpp | 275 ++++ .../test/c_test/list_test/v1_0/IListTest.idl | 46 + .../c_test/list_test/v1_0/c_list_test.cpp | 676 ++++++++ .../c_test/struct_test/v1_0/IStructTest.idl | 20 + .../c_test/struct_test/v1_0/c_struct_test.cpp | 823 ++++++++++ .../hdi-gen/test/c_test/types/v1_0/Types.idl | 95 ++ .../cpp_test/array_test/v1_0/IArrayTest.idl | 50 + .../array_test/v1_0/cpp_array_test.cpp | 416 +++++ .../test/cpp_test/cb_test/v1_0/ICallback.idl | 14 + .../test/cpp_test/cb_test/v1_0/ICbTest.idl | 15 + .../cpp_test/cb_test/v1_0/cpp_cb_test.cpp | 63 + .../cpp_test/data_test/v1_0/IDataTest.idl | 50 + .../cpp_test/data_test/v1_0/cpp_data_test.cpp | 265 +++ .../cpp_test/list_test/v1_0/IListTest.idl | 50 + .../cpp_test/list_test/v1_0/cpp_list_test.cpp | 416 +++++ .../test/cpp_test/map_test/v1_0/IMapTest.idl | 39 + .../cpp_test/map_test/v1_0/cpp_map_test.cpp | 350 ++++ .../cpp_test/struct_test/v1_0/IStructTest.idl | 20 + .../struct_test/v1_0/cpp_struct_test.cpp | 719 ++++++++ .../test/cpp_test/types/v1_0/Types.idl | 99 ++ .../java_test/array_test/v1_0/IArrayTest.idl | 34 + .../test/java_test/cb_test/v1_0/ICallback.idl | 14 + .../test/java_test/cb_test/v1_0/ICbTest.idl | 15 + .../java_test/data_test/v1_0/IDataTest.idl | 34 + .../java_test/list_test/v1_0/IListTest.idl | 34 + .../test/java_test/map_test/v1_0/IMapTest.idl | 49 + tools/hdi-gen/util/Makefile | 14 + tools/hdi-gen/util/autoptr.h | 261 +++ tools/hdi-gen/util/file.cpp | 233 +++ tools/hdi-gen/util/file.h | 92 ++ tools/hdi-gen/util/light_refcount_base.cpp | 28 + tools/hdi-gen/util/light_refcount_base.h | 41 + tools/hdi-gen/util/logger.cpp | 60 + tools/hdi-gen/util/logger.h | 49 + tools/hdi-gen/util/options.cpp | 148 ++ tools/hdi-gen/util/options.h | 125 ++ tools/hdi-gen/util/string.cpp | 748 +++++++++ tools/hdi-gen/util/string.h | 147 ++ tools/hdi-gen/util/string_builder.cpp | 150 ++ tools/hdi-gen/util/string_builder.h | 41 + 165 files changed, 24798 insertions(+) create mode 100755 tools/hdi-gen/Makefile create mode 100755 tools/hdi-gen/ast/Makefile create mode 100755 tools/hdi-gen/ast/ast.cpp create mode 100755 tools/hdi-gen/ast/ast.h create mode 100755 tools/hdi-gen/ast/ast_array_type.cpp create mode 100755 tools/hdi-gen/ast/ast_array_type.h create mode 100755 tools/hdi-gen/ast/ast_boolean_type.cpp create mode 100755 tools/hdi-gen/ast/ast_boolean_type.h create mode 100755 tools/hdi-gen/ast/ast_byte_type.cpp create mode 100755 tools/hdi-gen/ast/ast_byte_type.h create mode 100755 tools/hdi-gen/ast/ast_double_type.cpp create mode 100755 tools/hdi-gen/ast/ast_double_type.h create mode 100755 tools/hdi-gen/ast/ast_enum_type.cpp create mode 100755 tools/hdi-gen/ast/ast_enum_type.h create mode 100755 tools/hdi-gen/ast/ast_fd_type.cpp create mode 100755 tools/hdi-gen/ast/ast_fd_type.h create mode 100755 tools/hdi-gen/ast/ast_float_type.cpp create mode 100755 tools/hdi-gen/ast/ast_float_type.h create mode 100755 tools/hdi-gen/ast/ast_integer_type.cpp create mode 100755 tools/hdi-gen/ast/ast_integer_type.h create mode 100755 tools/hdi-gen/ast/ast_interface_type.cpp create mode 100755 tools/hdi-gen/ast/ast_interface_type.h create mode 100755 tools/hdi-gen/ast/ast_list_type.cpp create mode 100755 tools/hdi-gen/ast/ast_list_type.h create mode 100755 tools/hdi-gen/ast/ast_long_type.cpp create mode 100755 tools/hdi-gen/ast/ast_long_type.h create mode 100755 tools/hdi-gen/ast/ast_map_type.cpp create mode 100755 tools/hdi-gen/ast/ast_map_type.h create mode 100755 tools/hdi-gen/ast/ast_method.cpp create mode 100755 tools/hdi-gen/ast/ast_method.h create mode 100755 tools/hdi-gen/ast/ast_module.cpp create mode 100755 tools/hdi-gen/ast/ast_module.h create mode 100755 tools/hdi-gen/ast/ast_namespace.cpp create mode 100755 tools/hdi-gen/ast/ast_namespace.h create mode 100755 tools/hdi-gen/ast/ast_node.cpp create mode 100755 tools/hdi-gen/ast/ast_node.h create mode 100755 tools/hdi-gen/ast/ast_parameter.cpp create mode 100755 tools/hdi-gen/ast/ast_parameter.h create mode 100755 tools/hdi-gen/ast/ast_sequenceable_type.cpp create mode 100755 tools/hdi-gen/ast/ast_sequenceable_type.h create mode 100755 tools/hdi-gen/ast/ast_short_type.cpp create mode 100755 tools/hdi-gen/ast/ast_short_type.h create mode 100755 tools/hdi-gen/ast/ast_string_type.cpp create mode 100755 tools/hdi-gen/ast/ast_string_type.h create mode 100755 tools/hdi-gen/ast/ast_struct_type.cpp create mode 100755 tools/hdi-gen/ast/ast_struct_type.h create mode 100755 tools/hdi-gen/ast/ast_type.cpp create mode 100755 tools/hdi-gen/ast/ast_type.h create mode 100755 tools/hdi-gen/ast/ast_uchar_type.cpp create mode 100755 tools/hdi-gen/ast/ast_uchar_type.h create mode 100755 tools/hdi-gen/ast/ast_uint_type.cpp create mode 100755 tools/hdi-gen/ast/ast_uint_type.h create mode 100755 tools/hdi-gen/ast/ast_ulong_type.cpp create mode 100755 tools/hdi-gen/ast/ast_ulong_type.h create mode 100755 tools/hdi-gen/ast/ast_union_type.cpp create mode 100755 tools/hdi-gen/ast/ast_union_type.h create mode 100755 tools/hdi-gen/ast/ast_ushort_type.cpp create mode 100755 tools/hdi-gen/ast/ast_ushort_type.h create mode 100755 tools/hdi-gen/ast/ast_void_type.cpp create mode 100755 tools/hdi-gen/ast/ast_void_type.h create mode 100755 tools/hdi-gen/codegen/Makefile create mode 100755 tools/hdi-gen/codegen/c_client_interface_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_client_interface_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_client_proxy_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_client_proxy_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_code_generator.cpp create mode 100755 tools/hdi-gen/codegen/c_code_generator.h create mode 100755 tools/hdi-gen/codegen/c_custom_types_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_custom_types_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_service_driver_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_service_driver_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_service_impl_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_service_impl_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_service_interface_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_service_interface_code_emitter.h create mode 100755 tools/hdi-gen/codegen/c_service_stub_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/c_service_stub_code_emitter.h create mode 100755 tools/hdi-gen/codegen/code_generator.h create mode 100755 tools/hdi-gen/codegen/cpp_client_interface_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_client_interface_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_code_generator.cpp create mode 100755 tools/hdi-gen/codegen/cpp_code_generator.h create mode 100755 tools/hdi-gen/codegen/cpp_custom_types_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_custom_types_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_service_driver_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_service_driver_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_service_impl_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_service_impl_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_service_interface_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_service_interface_code_emitter.h create mode 100755 tools/hdi-gen/codegen/cpp_service_stub_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/cpp_service_stub_code_emitter.h create mode 100755 tools/hdi-gen/codegen/generator_factory.cpp create mode 100755 tools/hdi-gen/codegen/generator_factory.h create mode 100755 tools/hdi-gen/codegen/java_client_interface_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/java_client_interface_code_emitter.h create mode 100755 tools/hdi-gen/codegen/java_client_proxy_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/java_client_proxy_code_emitter.h create mode 100755 tools/hdi-gen/codegen/java_code_emitter.cpp create mode 100755 tools/hdi-gen/codegen/java_code_emitter.h create mode 100755 tools/hdi-gen/codegen/java_code_generator.cpp create mode 100755 tools/hdi-gen/codegen/java_code_generator.h create mode 100755 tools/hdi-gen/main.cpp create mode 100755 tools/hdi-gen/parser/Makefile create mode 100755 tools/hdi-gen/parser/file_detail.cpp create mode 100755 tools/hdi-gen/parser/file_detail.h create mode 100755 tools/hdi-gen/parser/lexer.cpp create mode 100755 tools/hdi-gen/parser/lexer.h create mode 100755 tools/hdi-gen/parser/module_parser.cpp create mode 100755 tools/hdi-gen/parser/module_parser.h create mode 100755 tools/hdi-gen/parser/parser.cpp create mode 100755 tools/hdi-gen/parser/parser.h create mode 100755 tools/hdi-gen/parser/token.h create mode 100755 tools/hdi-gen/test/c_test/array_test/v1_0/IArrayTest.idl create mode 100755 tools/hdi-gen/test/c_test/array_test/v1_0/c_array_test.cpp create mode 100755 tools/hdi-gen/test/c_test/cb_test/v1_0/ICallback.idl create mode 100755 tools/hdi-gen/test/c_test/cb_test/v1_0/ICbTest.idl create mode 100755 tools/hdi-gen/test/c_test/cb_test/v1_0/c_cb_test.cpp create mode 100755 tools/hdi-gen/test/c_test/data_test/v1_0/IDataTest.idl create mode 100755 tools/hdi-gen/test/c_test/data_test/v1_0/c_data_test.cpp create mode 100755 tools/hdi-gen/test/c_test/list_test/v1_0/IListTest.idl create mode 100755 tools/hdi-gen/test/c_test/list_test/v1_0/c_list_test.cpp create mode 100755 tools/hdi-gen/test/c_test/struct_test/v1_0/IStructTest.idl create mode 100755 tools/hdi-gen/test/c_test/struct_test/v1_0/c_struct_test.cpp create mode 100755 tools/hdi-gen/test/c_test/types/v1_0/Types.idl create mode 100755 tools/hdi-gen/test/cpp_test/array_test/v1_0/IArrayTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/array_test/v1_0/cpp_array_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICallback.idl create mode 100755 tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICbTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/cb_test/v1_0/cpp_cb_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/data_test/v1_0/IDataTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/data_test/v1_0/cpp_data_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/list_test/v1_0/IListTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/list_test/v1_0/cpp_list_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/map_test/v1_0/IMapTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/map_test/v1_0/cpp_map_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/struct_test/v1_0/IStructTest.idl create mode 100755 tools/hdi-gen/test/cpp_test/struct_test/v1_0/cpp_struct_test.cpp create mode 100755 tools/hdi-gen/test/cpp_test/types/v1_0/Types.idl create mode 100755 tools/hdi-gen/test/java_test/array_test/v1_0/IArrayTest.idl create mode 100755 tools/hdi-gen/test/java_test/cb_test/v1_0/ICallback.idl create mode 100755 tools/hdi-gen/test/java_test/cb_test/v1_0/ICbTest.idl create mode 100755 tools/hdi-gen/test/java_test/data_test/v1_0/IDataTest.idl create mode 100755 tools/hdi-gen/test/java_test/list_test/v1_0/IListTest.idl create mode 100755 tools/hdi-gen/test/java_test/map_test/v1_0/IMapTest.idl create mode 100755 tools/hdi-gen/util/Makefile create mode 100755 tools/hdi-gen/util/autoptr.h create mode 100755 tools/hdi-gen/util/file.cpp create mode 100755 tools/hdi-gen/util/file.h create mode 100755 tools/hdi-gen/util/light_refcount_base.cpp create mode 100755 tools/hdi-gen/util/light_refcount_base.h create mode 100755 tools/hdi-gen/util/logger.cpp create mode 100755 tools/hdi-gen/util/logger.h create mode 100755 tools/hdi-gen/util/options.cpp create mode 100755 tools/hdi-gen/util/options.h create mode 100755 tools/hdi-gen/util/string.cpp create mode 100755 tools/hdi-gen/util/string.h create mode 100755 tools/hdi-gen/util/string_builder.cpp create mode 100755 tools/hdi-gen/util/string_builder.h diff --git a/tools/hdi-gen/Makefile b/tools/hdi-gen/Makefile new file mode 100755 index 000000000..223697901 --- /dev/null +++ b/tools/hdi-gen/Makefile @@ -0,0 +1,46 @@ +TARGET = hdi-gen + +PWD:=$(shell pwd) +export BUILD_DIR = $(PWD)/build +export BOUNDS_CHECK_LIB := $(abspath ../../../../third_party/bounds_checking_function) +export INCLUDES = -I$(PWD) -I$(BOUNDS_CHECK_LIB)/include +export CXXFLAGS = -std=c++14 -O2 +export Q := @ +export MAKEFLAGS += --no-print-directory + +BOUNDS_CHECK_SOURCE := $(wildcard $(BOUNDS_CHECK_LIB)/src/*.c) +BOUNDS_CHECK_BUILD := $(BUILD_DIR)/bounds_checking_function +BOUNDS_CHECK_OBJS := $(addprefix $(BOUNDS_CHECK_BUILD)/, $(patsubst %.c, %.o, $(notdir $(BOUNDS_CHECK_SOURCE)))) +BOUNDS_CHECK_TARGET := $(BOUNDS_CHECK_BUILD)/bounds_checking_function.a + +SOURCE := $(wildcard *.cpp) +OBJS := $(addprefix $(BUILD_DIR)/, $(patsubst %.cpp, %.o, $(SOURCE))) + +SUBDIRS = util ast parser codegen +LIBS = $(BUILD_DIR)/codegen/codegen.a $(BUILD_DIR)/parser/parser.a $(BUILD_DIR)/ast/ast.a $(BUILD_DIR)/util/util.a + +all:$(TARGET) + +$(TARGET): $(OBJS) | $(BOUNDS_CHECK_TARGET) + $(Q) for subdir in $(SUBDIRS); do \ + $(MAKE) -C $$subdir || exit 1; \ + done + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $@ $(LIBS) $(BOUNDS_CHECK_TARGET) + $(Q) echo $(TARGET):build successful. + +$(OBJS):$(SOURCE) + $(Q) mkdir -p $(BUILD_DIR) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ + +$(BOUNDS_CHECK_TARGET):$(BOUNDS_CHECK_OBJS) + $(Q) echo $(BOUNDS_CHECK_TARGET) + $(Q) ar -rc $@ $^ + +$(BOUNDS_CHECK_BUILD)/%.o : $(BOUNDS_CHECK_LIB)/src/%.c + $(Q) mkdir -p $(BOUNDS_CHECK_BUILD) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ + +clean: + $(Q) rm -rf $(BUILD_DIR) $(TARGET) + +.PHONY:all clean \ No newline at end of file diff --git a/tools/hdi-gen/ast/Makefile b/tools/hdi-gen/ast/Makefile new file mode 100755 index 000000000..04f71251b --- /dev/null +++ b/tools/hdi-gen/ast/Makefile @@ -0,0 +1,12 @@ +OBJS_DIR:=$(BUILD_DIR)/ast +TARGET = $(OBJS_DIR)/ast.a +SOURCE:=$(wildcard *.cpp) +OBJS:=$(patsubst %.cpp, $(OBJS_DIR)/%.o, $(SOURCE)) + +$(TARGET):$(OBJS) + $(Q) echo $(TARGET) + $(Q) ar -rc $@ $^ + +$(OBJS_DIR)/%.o:%.cpp + $(Q) mkdir -p $(dir $@) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast.cpp b/tools/hdi-gen/ast/ast.cpp new file mode 100755 index 000000000..251e659d8 --- /dev/null +++ b/tools/hdi-gen/ast/ast.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +AST::AST() +{ + types_["boolean"] = new ASTBooleanType(); + types_["byte"] = new ASTByteType(); + types_["short"] = new ASTShortType(); + types_["int"] = new ASTIntegerType(); + types_["long"] = new ASTLongType(); + types_["float"] = new ASTFloatType(); + types_["double"] = new ASTDoubleType(); + types_["String"] = new ASTStringType(); + types_["unsigned char"] = new ASTUcharType(); + types_["unsigned short"] = new ASTUshortType(); + types_["unsigned int"] = new ASTUintType(); + types_["unsigned long"] = new ASTUlongType(); + types_["void"] = new ASTVoidType(); + types_["FileDescriptor"] = new ASTFdType(); +} + +void AST::SetIdlFile(const String& idlFile) +{ + idlFilePath_ = idlFile; +#ifdef __MINGW32__ + int index = idlFilePath_.LastIndexOf('\\'); +#else + int index = idlFilePath_.LastIndexOf('/'); +#endif + int end = (idlFilePath_.LastIndexOf(".idl") == -1) ? + (idlFilePath_.LastIndexOf(".idl")) : (idlFilePath_.LastIndexOf(".idl")); + name_ = idlFilePath_.Substring((index == -1) ? 0 : (index + 1), end); +} + +void AST::SetFullName(const String& fullName) +{ + int index = fullName.LastIndexOf('.'); + if (index != -1) { + packageName_ = fullName.Substring(0, index); + name_ = fullName.Substring(index + 1); + } else { + packageName_ = ""; + name_ = fullName; + } +} + +void AST::SetPackageName(const String& packageName) +{ + packageName_ = packageName; +} + +String AST::GetPackageName() +{ + return packageName_; +} + +AutoPtr AST::ParseNamespace(const String& nspaceStr) +{ + AutoPtr currNspace; + int begin = 0; + int index = 0; + while ((index = nspaceStr.IndexOf('.', begin)) != -1) { + String ns = nspaceStr.Substring(begin, index); + AutoPtr nspace; + if (currNspace == nullptr) { + nspace = FindNamespace(ns); + } else { + nspace = currNspace->FindNamespace(ns); + } + if (nspace == nullptr) { + nspace = new ASTNamespace(ns); + if (currNspace == nullptr) { + AddNamespace(nspace); + } else { + currNspace->AddNamespace(nspace); + } + } + currNspace = nspace; + begin = index + 1; + } + return currNspace; +} + +void AST::AddNamespace(const AutoPtr& nspace) +{ + if (nspace == nullptr) { + return; + } + namespaces_.push_back(nspace); +} + +AutoPtr AST::FindNamespace(const String& nspaceStr) +{ + for (auto nspace : namespaces_) { + if (nspace->ToShortString().Equals(nspaceStr)) { + return nspace; + } + } + return nullptr; +} + +AutoPtr AST::GetNamespace(size_t index) +{ + if (index >= namespaces_.size()) { + return nullptr; + } + + return namespaces_[index]; +} + +void AST::AddInterfaceDef(const AutoPtr& interface) +{ + if (interface == nullptr) { + return; + } + + interfaceDef_ = interface; + AddType(interface.Get()); +} + +void AST::AddSequenceableDef(const AutoPtr& sequenceable) +{ + if (sequenceable == nullptr) { + return; + } + + sequenceableDef_ = sequenceable; + AddType(sequenceable.Get()); +} + +void AST::AddType(const AutoPtr& type) +{ + if (type == nullptr) { + return; + } + + types_[type->ToString()] = type; +} + +AutoPtr AST::FindType(const String& typeName) +{ + if (typeName.IsEmpty()) { + return nullptr; + } + + auto it = types_.find(typeName); + if (it != types_.end()) { + return it->second; + } + + AutoPtr type = nullptr; + for (const auto& importPair : imports_) { + type = importPair.second->FindType(typeName); + if (type != nullptr) { + break; + } + } + return type; +} + +void AST::AddTypeDefinition(const AutoPtr& type) +{ + if (type == nullptr) { + return; + } + + AddType(type); + typeDefinitions_.push_back(type); +} + +AutoPtr AST::GetTypeDefintion(size_t index) +{ + if (index >= typeDefinitions_.size()) { + return nullptr; + } + return typeDefinitions_[index]; +} + +String AST::Dump(const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + sb.Append("AST["); + sb.Append("name: ").Append(name_).Append(" "); + sb.Append("file: ").Append(idlFilePath_); + sb.Append("]\n"); + + sb.Append("pakage ").Append(packageName_).Append(";"); + sb.Append('\n'); + sb.Append('\n'); + + if (imports_.size() > 0) { + for (const auto& import : imports_) { + sb.AppendFormat("import %s;\n", import.first.string()); + } + sb.Append("\n"); + } + + if (typeDefinitions_.size() > 0) { + for (auto type : typeDefinitions_) { + String info = type->Dump(""); + sb.Append(info).Append("\n"); + } + } + + if (interfaceDef_ != nullptr) { + String info = interfaceDef_->Dump(""); + sb.Append(info).Append("\n"); + } + + return sb.ToString(); +} + +bool AST::AddImport(const AutoPtr& importAst) +{ + if (imports_.find(importAst->GetFullName()) != imports_.end()) { + return false; + } + + imports_[importAst->GetFullName()] = importAst; + + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast.h b/tools/hdi-gen/ast/ast.h new file mode 100755 index 000000000..5804b77e8 --- /dev/null +++ b/tools/hdi-gen/ast/ast.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_AST_H +#define OHOS_HDI_AST_H + +#include +#include +#include "ast/ast_boolean_type.h" +#include "ast/ast_byte_type.h" +#include "ast/ast_double_type.h" +#include "ast/ast_fd_type.h" +#include "ast/ast_float_type.h" +#include "ast/ast_integer_type.h" +#include "ast/ast_interface_type.h" +#include "ast/ast_long_type.h" +#include "ast/ast_namespace.h" +#include "ast/ast_node.h" +#include "ast/ast_sequenceable_type.h" +#include "ast/ast_short_type.h" +#include "ast/ast_string_type.h" +#include "ast/ast_uchar_type.h" +#include "ast/ast_ushort_type.h" +#include "ast/ast_uint_type.h" +#include "ast/ast_ulong_type.h" +#include "ast/ast_void_type.h" +#include "ast/ast_enum_type.h" +#include "ast/ast_struct_type.h" +#include "ast/ast_union_type.h" +#include "ast/ast_array_type.h" +#include "ast/ast_list_type.h" +#include "ast/ast_map_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace HDI { +enum class ASTFileType { + AST_IFACE, // this idl file contains class of normal interface + AST_ICALLBACK, // this idl file contains class of callback interface + AST_TYPES, // this idl file contains custom types + AST_SEQUENCEABLE, // this is not an idl file, but a c++/java file +}; + +class AST : public ASTNode { +public: + using StrASTMap = std::unordered_map, StringHashFunc, StringEqualFunc>; + + AST(); + + virtual ~AST() = default; + + void SetAStFileType(ASTFileType fileType) + { + astFileType_ = fileType; + } + + ASTFileType GetASTFileType() + { + return astFileType_; + } + + void SetIdlFile(const String& idlFile); + + inline String GetName() + { + return name_; + } + + void SetFullName(const String& fullName); + + inline String GetFullName() + { + return packageName_ + "." + name_; + } + + inline void SetLicense(const String& license) + { + license_ = license; + } + + inline String GetLicense() + { + return license_; + } + + void SetPackageName(const String& packageName); + + String GetPackageName(); + + AutoPtr ParseNamespace(const String& nspaceStr); + + void AddNamespace(const AutoPtr& nspace); + + AutoPtr FindNamespace(const String& nspaceStr); + + AutoPtr GetNamespace(size_t index); + + inline size_t GetNamespaceNumber() + { + return namespaces_.size(); + } + + void AddInterfaceDef(const AutoPtr& interface); + + inline AutoPtr GetInterfaceDef() + { + return interfaceDef_; + } + + void AddSequenceableDef(const AutoPtr& sequenceable); + + inline AutoPtr GetSequenceableDef() + { + return sequenceableDef_; + } + + void AddType(const AutoPtr& type); + + AutoPtr FindType(const String& typeName); + + using TypeStringMap = std::unordered_map, StringHashFunc, StringEqualFunc>; + + inline const TypeStringMap& GetTypes() const + { + return types_; + } + + inline size_t GetTypeNumber() const + { + return types_.size(); + } + + void AddTypeDefinition(const AutoPtr& type); + + inline size_t GetTypeDefinitionNumber() const + { + return typeDefinitions_.size(); + } + + AutoPtr GetTypeDefintion(size_t index); + + String Dump(const String& prefix) override; + + bool AddImport(const AutoPtr& importAst); + + inline const StrASTMap& GetImports() const + { + return imports_; + } + +private: + ASTFileType astFileType_ = ASTFileType::AST_IFACE; + String name_; + String license_; + String packageName_; + std::vector> namespaces_; + std::vector> typeDefinitions_; + AutoPtr sequenceableDef_ = nullptr; + AutoPtr interfaceDef_ = nullptr; + + StrASTMap imports_; + TypeStringMap types_; + + String idlFilePath_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_AST_H diff --git a/tools/hdi-gen/ast/ast_array_type.cpp b/tools/hdi-gen/ast/ast_array_type.cpp new file mode 100755 index 000000000..62e239d39 --- /dev/null +++ b/tools/hdi-gen/ast/ast_array_type.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_array_type.h" + +namespace OHOS { +namespace HDI { +bool ASTArrayType::IsArrayType() +{ + return true; +} + +String ASTArrayType::ToString() +{ + return String::Format("%s[]", elementType_->ToString().string()); +} + +TypeKind ASTArrayType::GetTypeKind() +{ + return TypeKind::TYPE_ARRAY; +} + +String ASTArrayType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s*", elementType_->EmitCType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_IN: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + return String::Format("%s*", elementType_->EmitCType(TypeMode::NO_MODE).string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return String::Format("%s", elementType_->EmitCType(TypeMode::PARAM_IN).string()); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::PARAM_IN).string()); + } + } + case TypeMode::PARAM_OUT: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return elementType_->EmitCType(TypeMode::PARAM_OUT); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::PARAM_OUT).string()); + } + } + case TypeMode::LOCAL_VAR: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return String::Format("%s", elementType_->EmitCType(TypeMode::LOCAL_VAR).string()); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::LOCAL_VAR).string()); + } + } + default: + return "unknow type"; + } +} + +String ASTArrayType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("std::vector<%s>", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_IN: + return String::Format("const std::vector<%s>&", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_OUT: + return String::Format("std::vector<%s>&", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::LOCAL_VAR: + return String::Format("std::vector<%s>", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + default: + return "unknow type"; + } +} + +String ASTArrayType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return String::Format("%s[]", elementType_->EmitJavaType(TypeMode::NO_MODE, false).string()); +} + +void ASTArrayType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + + String elementName; + String elementReadName; + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + elementName = String::Format("%s[i]", name.string()); + elementReadName = "&" + elementName; + } else { + elementName = String::Format("%s[i]", name.string()); + elementReadName = elementName; + } + + elementType_->EmitCProxyWriteVar(parcelName, elementReadName, gotoLabel, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %sLen)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string(), name.string()); + + String element; + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + element = String::Format("&%s[i]", name.string()); + } else { + element = String::Format("%s[i]", name.string()); + } + + elementType_->EmitCStubWriteVar(parcelName, element, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, %s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix).AppendFormat("*%s = (%s*)OsalMemAlloc(sizeof(%s) * (*%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).AppendFormat("}\n"); + } else { + sb.Append(prefix).AppendFormat("*%s = (%s*)OsalMemCalloc(sizeof(%s) * (*%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).AppendFormat("}\n"); + } + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < *%s; i++) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String cpName = String::Format("%sCp", name.string()); + elementType_->EmitCProxyReadVar(parcelName, cpName, true, gotoLabel, sb, prefix + TAB); + sb.Append(prefix).Append(TAB).AppendFormat("(*%s)[i] = strdup(%sCp);\n", + name.string(), name.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("&(*%s)[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCProxyReadVar(parcelName, elementCp, true, gotoLabel, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("(void)memcpy_s(%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR) { + String element = String::Format("(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } else { + String element = String::Format("&(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, &%s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + + sb.Append(prefix).AppendFormat("if (%s > 0) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB).AppendFormat("%s = (%s*)OsalMemAlloc(sizeof(%s) * (%s));\n", name.string(), + elementType_->EmitCType().string(), elementType_->EmitCType().string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("goto errors;\n"); + sb.Append(prefix + TAB).AppendFormat("}\n"); + } else { + sb.Append(prefix + TAB).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s) * (%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("goto errors;\n"); + sb.Append(prefix + TAB).AppendFormat("}\n"); + } + + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String element = String::Format("%sCp", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + sb.Append(prefix + TAB + TAB).AppendFormat("%s[i] = strdup(%sCp);\n", name.string(), name.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("%s[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCStubReadVar(parcelName, elementCp, sb, prefix + TAB + TAB); + sb.Append(prefix + TAB + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR) { + String element = String::Format("%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } else { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s.size() failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + elementType_->EmitCppWriteVar(parcelName, elementName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i%d = 0; i%d < %sSize; ++i%d) {\n", + innerLevel, innerLevel, name.string(), innerLevel); + + String valueName = String::Format("value%d", innerLevel++); + elementType_->EmitCppReadVar(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(data, %sLen)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %sLen failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + + String elementName = String::Format("(%s)[i]", name.string()); + elementType_->EmitCMarshalling(elementName, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(data, &%s)) {\n", lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", lenName.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("if (%s > 0) {\n", lenName.string()); + String newPrefix = prefix + TAB; + + sb.Append(newPrefix).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s) * %s);\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), lenName.string()); + sb.Append(newPrefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(newPrefix + TAB).AppendFormat("goto errors;\n"); + sb.Append(newPrefix).Append("}\n"); + freeObjStatements.push_back(String::Format("OsalMemFree(%s);\n", name.string())); + sb.Append(newPrefix).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String element = String::Format("%sElement", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + sb.Append(newPrefix).Append(TAB).AppendFormat("%s[i] = strdup(%s);\n", + name.string(), element.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("%s[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCUnMarshalling(elementCp, sb, newPrefix + TAB, freeObjStatements); + sb.Append(newPrefix + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else { + String element = String::Format("%s[i]", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + } + sb.Append(newPrefix).Append("}\n"); + sb.Append(prefix).Append("}\n"); + freeObjStatements.pop_back(); +} + +void ASTArrayType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s.size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + elementType_->EmitCppMarshalling(parcelName, elementName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTArrayType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + int index = name.IndexOf('.', 0); + String memberName = name.Substring(index + 1); + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), memberName.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", + memberName.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i%d = 0; i%d < %sSize; ++i%d) {\n", + innerLevel, innerLevel, memberName.string(), innerLevel); + + String valueName = String::Format("value%d", innerLevel++); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("%s %s;\n", + elementType_->EmitCppType().string(), valueName.string()); + elementType_->EmitCppUnMarshalling(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append(prefix + TAB).AppendFormat("%s %s;\n", + elementType_->EmitCppType().string(), valueName.string()); + String cpName = String::Format("%sCp", valueName.string()); + elementType_->EmitCppUnMarshalling(parcelName, cpName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + valueName.string(), elementType_->EmitCppType().string(), cpName.string(), + elementType_->EmitCppType().string()); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } else { + elementType_->EmitCppUnMarshalling(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_array_type.h b/tools/hdi-gen/ast/ast_array_type.h new file mode 100755 index 000000000..bd1c50f1d --- /dev/null +++ b/tools/hdi-gen/ast/ast_array_type.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTARRAYTYPE_H +#define OHOS_HDI_ASTARRAYTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTArrayType : public ASTType { +public: + inline void SetElementType(const AutoPtr& elementType) + { + elementType_ = elementType; + } + + inline AutoPtr GetElementType() + { + return elementType_; + } + + bool IsArrayType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + AutoPtr elementType_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTARRAYTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_boolean_type.cpp b/tools/hdi-gen/ast/ast_boolean_type.cpp new file mode 100755 index 000000000..924944852 --- /dev/null +++ b/tools/hdi-gen/ast/ast_boolean_type.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_boolean_type.h" + +namespace OHOS { +namespace HDI { +bool ASTBooleanType::IsBooleanType() +{ + return true; +} + +String ASTBooleanType::ToString() +{ + return "boolean"; +} + +TypeKind ASTBooleanType::GetTypeKind() +{ + return TypeKind::TYPE_BOOLEAN; +} + +String ASTBooleanType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "bool"; + case TypeMode::PARAM_IN: + return "bool"; + case TypeMode::PARAM_OUT: + return "bool*"; + case TypeMode::LOCAL_VAR: + return "bool"; + default: + return "unknow type"; + } +} + +String ASTBooleanType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "bool"; + case TypeMode::PARAM_IN: + return "bool"; + case TypeMode::PARAM_OUT: + return "bool&"; + case TypeMode::LOCAL_VAR: + return "bool"; + default: + return "unknow type"; + } +} + +String ASTBooleanType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Boolean" : "boolean"; +} + +void ASTBooleanType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(%s, %s ? 1 : 0)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(%s, %s ? 1 : 0)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(%s, (int8_t *)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(%s, (int8_t *)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteBool(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadBool();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadBool();\n", + name.string(), parcelName.string()); + } +} + +void ASTBooleanType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(data, %s ? 1 : 0)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(data, (int8_t *)&%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteBool(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTBooleanType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadBool();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadBool();\n", + name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_boolean_type.h b/tools/hdi-gen/ast/ast_boolean_type.h new file mode 100755 index 000000000..1b42378fb --- /dev/null +++ b/tools/hdi-gen/ast/ast_boolean_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTBOOLEANTYPE_H +#define OHOS_HDI_ASTBOOLEANTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTBooleanType : public ASTType { +public: + bool IsBooleanType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTBOOLEANTYPE_H diff --git a/tools/hdi-gen/ast/ast_byte_type.cpp b/tools/hdi-gen/ast/ast_byte_type.cpp new file mode 100755 index 000000000..a5e59a65a --- /dev/null +++ b/tools/hdi-gen/ast/ast_byte_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_byte_type.h" + +namespace OHOS { +namespace HDI { +bool ASTByteType::IsByteType() +{ + return true; +} + +String ASTByteType::ToString() +{ + return "byte"; +} + +TypeKind ASTByteType::GetTypeKind() +{ + return TypeKind::TYPE_BYTE; +} + +String ASTByteType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int8_t"; + case TypeMode::PARAM_IN: + return "int8_t"; + case TypeMode::PARAM_OUT: + return "int8_t*"; + case TypeMode::LOCAL_VAR: + return "int8_t"; + default: + return "unknow type"; + } +} + +String ASTByteType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int8_t"; + case TypeMode::PARAM_IN: + return "int8_t"; + case TypeMode::PARAM_OUT: + return "int8_t&"; + case TypeMode::LOCAL_VAR: + return "int8_t"; + default: + return "unknow type"; + } +} + +String ASTByteType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Byte" : "byte"; +} + +void ASTByteType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt8(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadInt8();\n", EmitCppType().string(), + name.string(), EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = (%s)%s.ReadInt8();\n", name.string(), + EmitCppType().string(), parcelName.string()); + } +} + +void ASTByteType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt8(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt8(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt8(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTByteType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadInt8();\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt8();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_byte_type.h b/tools/hdi-gen/ast/ast_byte_type.h new file mode 100755 index 000000000..7b93a6b46 --- /dev/null +++ b/tools/hdi-gen/ast/ast_byte_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTBYTETYPE_H +#define OHOS_HDI_ASTBYTETYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTByteType : public ASTType { +public: + bool IsByteType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTBYTETYPE_H diff --git a/tools/hdi-gen/ast/ast_double_type.cpp b/tools/hdi-gen/ast/ast_double_type.cpp new file mode 100755 index 000000000..2812b655a --- /dev/null +++ b/tools/hdi-gen/ast/ast_double_type.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_double_type.h" + +namespace OHOS { +namespace HDI { +bool ASTDoubleType::IsDoubleType() +{ + return true; +} + +String ASTDoubleType::ToString() +{ + return "double"; +} + +TypeKind ASTDoubleType::GetTypeKind() +{ + return TypeKind::TYPE_DOUBLE; +} + +String ASTDoubleType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "double"; + case TypeMode::PARAM_IN: + return "double"; + case TypeMode::PARAM_OUT: + return "double*"; + case TypeMode::LOCAL_VAR: + return "double"; + default: + return "unknow type"; + } +} + +String ASTDoubleType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "double"; + case TypeMode::PARAM_IN: + return "double"; + case TypeMode::PARAM_OUT: + return "double&"; + case TypeMode::LOCAL_VAR: + return "double"; + default: + return "unknow type"; + } +} + +String ASTDoubleType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Double" : "double"; +} + +void ASTDoubleType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteDouble(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteDouble(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadDouble(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadDouble(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteDouble(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadDouble();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadDouble();\n", name.string(), parcelName.string()); + } +} + +void ASTDoubleType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteDouble(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadDouble(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteDouble(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTDoubleType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadDouble();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadDouble();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_double_type.h b/tools/hdi-gen/ast/ast_double_type.h new file mode 100755 index 000000000..266082c17 --- /dev/null +++ b/tools/hdi-gen/ast/ast_double_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTDOUBLETYPE_H +#define OHOS_HDI_ASTDOUBLETYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTDoubleType : public ASTType { +public: + bool IsDoubleType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + virtual void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTDOUBLETYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_enum_type.cpp b/tools/hdi-gen/ast/ast_enum_type.cpp new file mode 100755 index 000000000..829437078 --- /dev/null +++ b/tools/hdi-gen/ast/ast_enum_type.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_enum_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTEnumType::SetBaseType(const AutoPtr& baseType) +{ + if (baseType == nullptr) { + return; + } + baseType_ = baseType; +} + +void ASTEnumType::AddMember(const AutoPtr& member) +{ + members_.push_back(member); +} + +bool ASTEnumType::IsEnumType() +{ + return true; +} + +String ASTEnumType::ToString() +{ + return "enum " + name_; +} + +String ASTEnumType::Dump(const String& prefix) +{ + StringBuilder sb; + + std::vector attributes; + if (isFull_) attributes.push_back("full"); + if (isLite_) attributes.push_back("lite"); + if (attributes.size() > 0) { + sb.Append("["); + for (size_t i = 0; i < attributes.size(); i++) { + sb.Append(attributes[i]); + if (i < attributes.size() - 1) { + sb.Append(','); + } + } + sb.Append("] "); + } + + if (isDisplayBase_ && baseType_ != nullptr) { + sb.AppendFormat("enum %s : %s {\n", name_.string(), baseType_->ToString().string()); + } else { + sb.AppendFormat("enum %s {\n", name_.string()); + } + + if (members_.size() > 0) { + for (auto it : members_) { + if (it->isDefaultValue()) { + sb.Append(" ").AppendFormat("%s,\n", it->GetName().string()); + } else { + sb.Append(" ").AppendFormat("%s = %lu,\n", it->GetName().string(), it->GetValue()); + } + } + } + + sb.Append(prefix).Append("};\n"); + + return sb.ToString(); +} + +TypeKind ASTEnumType::GetTypeKind() +{ + return TypeKind::TYPE_ENUM; +} + +String ASTEnumType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("enum %s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("enum %s", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("enum %s*", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("enum %s", name_.string()); + default: + return "unknow type"; + } +} + +String ASTEnumType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("%s", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("%s&", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("%s", name_.string()); + default: + return "unknow type"; + } +} + +String ASTEnumType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // currently, Java does not support the enum type. + return "/"; +} + +String ASTEnumType::EmitCTypeDecl() const +{ + StringBuilder sb; + sb.AppendFormat("enum %s {\n", name_.string()); + + for (auto it : members_) { + if (it->isDefaultValue()) { + sb.Append(" ").AppendFormat("%s,\n", it->GetName().string()); + } else { + sb.Append(" ").AppendFormat("%s = %lu,\n", it->GetName().string(), it->GetValue()); + } + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTEnumType::EmitCppTypeDecl() const +{ + StringBuilder sb; + if (isDisplayBase_ && baseType_ != nullptr) { + sb.AppendFormat("enum %s : %s {\n", name_.string(), baseType_->EmitCppType().string()); + } else { + sb.AppendFormat("enum %s {\n", name_.string()); + } + + for (auto it : members_) { + if (it->isDefaultValue()) { + sb.Append(" ").AppendFormat("%s,\n", it->GetName().string()); + } else { + sb.Append(" ").AppendFormat("%s = %lu,\n", it->GetName().string(), it->GetValue()); + } + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTEnumType::EmitJavaTypeDecl() const +{ + StringBuilder sb; + + return sb.ToString(); +} + +void ASTEnumType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, (uint32_t)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, (uint32_t)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, (uint32_t*)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, (uint32_t*)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32((uint32_t)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadUint32();\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = (%s)%s.ReadUint32();\n", + name.string(), EmitCppType().string(), parcelName.string()); + } +} + +void ASTEnumType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt32(data, (int32_t)%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt32(data, (int32_t*)&%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32((uint32_t)%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTEnumType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadUint32();\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = (%s)%s.ReadUint32();\n", + name.string(), EmitCppType().string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_enum_type.h b/tools/hdi-gen/ast/ast_enum_type.h new file mode 100755 index 000000000..9d1c3dd75 --- /dev/null +++ b/tools/hdi-gen/ast/ast_enum_type.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTENUMTYPE_H +#define OHOS_HDI_ASTENUMTYPE_H + +#include +#include "ast/ast_type.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class ASTEnumValue : public LightRefCountBase { +public: + ASTEnumValue(const String& name) + :mName_(name), isDefault_(true), mValue_(0) + {} + + inline virtual ~ASTEnumValue() {} + + inline String GetName() + { + return mName_; + } + + inline void SetType(const AutoPtr& type) + { + mType_ = type; + } + + inline AutoPtr GetType() + { + return mType_; + } + + inline void SetValue(unsigned long value) + { + isDefault_ = false; + mValue_ = value; + } + + inline unsigned long GetValue() + { + return mValue_; + } + + inline bool isDefaultValue() + { + return isDefault_; + } + +private: + String mName_; + AutoPtr mType_; + bool isDefault_; + unsigned long mValue_; +}; + +class ASTEnumType : public ASTType { +public: + inline void SetName(const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetFull(bool full) + { + isFull_ = full; + } + + inline bool IsFull() + { + return isFull_; + } + + inline void SetLite(bool lite) + { + isLite_ = lite; + } + + inline bool IsLite() + { + return isLite_; + } + + inline void SetDisplayBase(bool display) + { + isDisplayBase_ = display; + } + + inline bool IsDisplayBase() + { + return isDisplayBase_; + } + + void SetBaseType(const AutoPtr& baseType); + + inline AutoPtr GetBaseType() + { + return baseType_; + } + + void AddMember(const AutoPtr& member); + + inline size_t GetMemberNumber() + { + return members_.size(); + } + + inline AutoPtr GetMember(size_t index) + { + if (index >= members_.size()) { + return nullptr; + } + return members_[index]; + } + + bool IsEnumType() override; + + String ToString() override; + + String Dump(const String& prefix) override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + String EmitCTypeDecl() const; + + String EmitCppTypeDecl() const; + + String EmitJavaTypeDecl() const; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + bool isFull_ = false; + bool isLite_ = false; + bool isDisplayBase_ = false; + AutoPtr baseType_ = nullptr; + + std::vector> members_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTENUMTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_fd_type.cpp b/tools/hdi-gen/ast/ast_fd_type.cpp new file mode 100755 index 000000000..7e36c9d11 --- /dev/null +++ b/tools/hdi-gen/ast/ast_fd_type.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_fd_type.h" + +namespace OHOS { +namespace HDI { +bool ASTFdType::IsFdType() +{ + return true; +} + +String ASTFdType::ToString() +{ + return "FileDescriptor"; +} + +TypeKind ASTFdType::GetTypeKind() +{ + return TypeKind::TYPE_FILEDESCRIPTOR; +} + +String ASTFdType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int"; + case TypeMode::PARAM_IN: + return "int"; + case TypeMode::PARAM_OUT: + return "int*"; + case TypeMode::LOCAL_VAR: + return "int"; + default: + return "unknow type"; + } +} + +String ASTFdType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int"; + case TypeMode::PARAM_IN: + return "int"; + case TypeMode::PARAM_OUT: + return "int&"; + case TypeMode::LOCAL_VAR: + return "int"; + default: + return "unknow type"; + } +} + +String ASTFdType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Integer" : "int"; +} + +void ASTFdType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFileDescriptor(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFileDescriptor(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + if (isInnerType) { + sb.Append(prefix).AppendFormat("%s = HdfSbufReadFileDescriptor(%s);\n", + name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("if (%s < 0) {\n", name.string()); + } else { + sb.Append(prefix).AppendFormat("*%s = HdfSbufReadFileDescriptor(%s);\n", + name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("if (*%s < 0) {\n", name.string()); + } + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("%s = HdfSbufReadFileDescriptor(%s);\n", + name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("if (%s < 0) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteFileDescriptor(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadFileDescriptor();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadFileDescriptor();\n", name.string(), parcelName.string()); + } +} + +void ASTFdType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFileDescriptor(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("%s = HdfSbufReadFileDescriptor(data);\n", name.string()); + sb.Append(prefix).AppendFormat("if (%s < 0) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteFileDescriptor(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFdType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadFileDescriptor();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadFileDescriptor();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_fd_type.h b/tools/hdi-gen/ast/ast_fd_type.h new file mode 100755 index 000000000..c73d8911a --- /dev/null +++ b/tools/hdi-gen/ast/ast_fd_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_FDTYPE_H +#define OHOS_HDI_FDTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTFdType : public ASTType { +public: + bool IsFdType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_FDTYPE_H diff --git a/tools/hdi-gen/ast/ast_float_type.cpp b/tools/hdi-gen/ast/ast_float_type.cpp new file mode 100755 index 000000000..701c794a9 --- /dev/null +++ b/tools/hdi-gen/ast/ast_float_type.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_float_type.h" + +namespace OHOS { +namespace HDI { +bool ASTFloatType::IsFloatType() +{ + return true; +} + +String ASTFloatType::ToString() +{ + return "float"; +} + +TypeKind ASTFloatType::GetTypeKind() +{ + return TypeKind::TYPE_FLOAT; +} + +String ASTFloatType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "float"; + case TypeMode::PARAM_IN: + return "float"; + case TypeMode::PARAM_OUT: + return "float*"; + case TypeMode::LOCAL_VAR: + return "float"; + default: + return "unknow type"; + } +} + +String ASTFloatType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "float"; + case TypeMode::PARAM_IN: + return "float"; + case TypeMode::PARAM_OUT: + return "float&"; + case TypeMode::LOCAL_VAR: + return "float"; + default: + return "unknow type"; + } +} + +String ASTFloatType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Float" : "float"; +} + +void ASTFloatType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFloat(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFloat(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadFloat(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadFloat(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteFloat(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadFloat();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadFloat();\n", name.string(), parcelName.string()); + } +} + +void ASTFloatType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteFloat(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadFloat(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteFloat(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTFloatType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadFloat();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadFloat();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_float_type.h b/tools/hdi-gen/ast/ast_float_type.h new file mode 100755 index 000000000..f48e5a92e --- /dev/null +++ b/tools/hdi-gen/ast/ast_float_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTFLOATTYPE_H +#define OHOS_HDI_ASTFLOATTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTFloatType : public ASTType { +public: + bool IsFloatType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTFLOATTYPE_H diff --git a/tools/hdi-gen/ast/ast_integer_type.cpp b/tools/hdi-gen/ast/ast_integer_type.cpp new file mode 100755 index 000000000..6bf7e14a5 --- /dev/null +++ b/tools/hdi-gen/ast/ast_integer_type.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_integer_type.h" + +namespace OHOS { +namespace HDI { +bool ASTIntegerType::IsIntegerType() +{ + return true; +} + +String ASTIntegerType::ToString() +{ + return "int"; +} + +TypeKind ASTIntegerType::GetTypeKind() +{ + return TypeKind::TYPE_INT; +} + +String ASTIntegerType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int32_t"; + case TypeMode::PARAM_IN: + return "int32_t"; + case TypeMode::PARAM_OUT: + return "int32_t*"; + case TypeMode::LOCAL_VAR: + return "int32_t"; + default: + return "unknow type"; + } +} + +String ASTIntegerType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int32_t"; + case TypeMode::PARAM_IN: + return "int32_t"; + case TypeMode::PARAM_OUT: + return "int32_t&"; + case TypeMode::LOCAL_VAR: + return "int32_t"; + default: + return "unknow type"; + } +} + +String ASTIntegerType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Integer" : "int"; +} + +void ASTIntegerType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt32(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt32(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt32(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt32(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt32(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadInt32();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt32();\n", name.string(), parcelName.string()); + } +} + +void ASTIntegerType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt32(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt32(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt32(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTIntegerType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadInt32();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt32();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_integer_type.h b/tools/hdi-gen/ast/ast_integer_type.h new file mode 100755 index 000000000..fb7724a0d --- /dev/null +++ b/tools/hdi-gen/ast/ast_integer_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTINTEGERTYPE_H +#define OHOS_HDI_ASTINTEGERTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTIntegerType : public ASTType { +public: + bool IsIntegerType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTINTEGERTYPE_H diff --git a/tools/hdi-gen/ast/ast_interface_type.cpp b/tools/hdi-gen/ast/ast_interface_type.cpp new file mode 100755 index 000000000..1a7c64f6e --- /dev/null +++ b/tools/hdi-gen/ast/ast_interface_type.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_interface_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTInterfaceType::SetNamespace(const AutoPtr& nspace) +{ + ASTType::SetNamespace(nspace); + if (namespace_ != nullptr) { + namespace_->AddInterface(this); + } +} + +void ASTInterfaceType::AddMethod(const AutoPtr& method) +{ + if (method == nullptr) { + return; + } + methods_.push_back(method); +} + +AutoPtr ASTInterfaceType::GetMethod(size_t index) +{ + if (index >= methods_.size()) { + return nullptr; + } + + return methods_[index]; +} + +bool ASTInterfaceType::IsInterfaceType() +{ + return true; +} + +String ASTInterfaceType::ToString() +{ + return name_; +} + +String ASTInterfaceType::Dump(const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + + std::vector attributes; + if (isOneWay_) attributes.push_back("oneway"); + if (isCallback_) attributes.push_back("callback"); + if (isFull_) attributes.push_back("full"); + if (isLite_) attributes.push_back("lite"); + if (attributes.size() > 0) { + sb.Append("["); + for (size_t i = 0; i < attributes.size(); i++) { + sb.Append(attributes[i]); + if (i < attributes.size() - 1) { + sb.Append(','); + } + } + sb.Append("] "); + } + + sb.AppendFormat("interface %s {\n", name_.string()); + + for (auto method : methods_) { + String info = method->Dump(prefix + " "); + sb.Append(info); + if (method != methods_[methods_.size() - 1]) { + sb.Append('\n'); + } + } + sb.Append(prefix).Append("}\n"); + + return sb.ToString(); +} + +TypeKind ASTInterfaceType::GetTypeKind() +{ + return TypeKind::TYPE_INTERFACE; +} + +String ASTInterfaceType::GetFullName() const +{ + return namespace_->ToString() + name_; +} + +String ASTInterfaceType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("struct %s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("struct %s*", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("struct %s**", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("struct %s*", name_.string()); + default: + return "unknow type"; + } +} + +String ASTInterfaceType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const sptr<%s>&", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("sptr<%s>&", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("sptr<%s>", name_.string()); + default: + return "unknow type"; + } +} + +String ASTInterfaceType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return name_; +} + +void ASTInterfaceType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (HdfSBufWriteRemoteService(data, %s->remote) != 0) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTInterfaceType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + String remoteName = String::Format("%sRemote", name.string()); + String miName = name_.StartsWith("I") ? name_.Substring(1) : name_; + + sb.Append(prefix).AppendFormat("struct HdfRemoteService *%s = HdfSBufReadRemoteService(data);\n", + remoteName.string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", remoteName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", remoteName.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("%s = %sProxyObtain(%s);\n", + name.string(), miName.string(), remoteName.string()); +} + +void ASTInterfaceType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteRemoteObject(%s->AsObject())) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTInterfaceType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("sptr<%s> %s = iface_cast<%s>(%s.ReadRemoteObject());\n", + name_.string(), name.string(), name_.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = iface_cast<%s>(%s.ReadRemoteObject());\n", + name.string(), name_.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_interface_type.h b/tools/hdi-gen/ast/ast_interface_type.h new file mode 100755 index 000000000..9c38d69a6 --- /dev/null +++ b/tools/hdi-gen/ast/ast_interface_type.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTINTERFACETYPE_H +#define OHOS_HDI_ASTINTERFACETYPE_H + +#include +#include "ast/ast_method.h" +#include "ast/ast_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace HDI { +class ASTInterfaceType : public ASTType { +public: + void SetNamespace(const AutoPtr& nspace) override; + + inline void SetLicense(const String& license) + { + license_ = license; + } + + inline String GetLicense() const + { + return license_; + } + + inline void SetOneWay(bool oneway) + { + isOneWay_ = oneway; + } + + inline bool IsOneWay() + { + return isOneWay_; + } + + inline void SetCallback(bool callback) + { + isCallback_ = callback; + } + + inline bool IsCallback() + { + return isCallback_; + } + + inline void SetFull(bool full) + { + isFull_ = full; + } + + inline bool IsFull() + { + return isFull_; + } + + inline void SetLite(bool lite) + { + isLite_ = lite; + } + + inline bool IsLite() + { + return isLite_; + } + + void AddMethod(const AutoPtr& method); + + AutoPtr GetMethod(size_t index); + + inline size_t GetMethodNumber() + { + return methods_.size(); + } + + bool IsInterfaceType() override; + + String ToString() override; + + String Dump(const String& prefix) override; + + TypeKind GetTypeKind() override; + + String GetFullName() const; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; +private: + String license_; + bool isOneWay_ = false; + bool isCallback_ = false; + bool isFull_ = false; + bool isLite_ = false; + std::vector> methods_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTINTERFACETYPE_H diff --git a/tools/hdi-gen/ast/ast_list_type.cpp b/tools/hdi-gen/ast/ast_list_type.cpp new file mode 100755 index 000000000..8b62d1509 --- /dev/null +++ b/tools/hdi-gen/ast/ast_list_type.cpp @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_list_type.h" + +namespace OHOS { +namespace HDI { +bool ASTListType::IsListType() +{ + return true; +} + +String ASTListType::ToString() +{ + return String::Format("List<%s>", elementType_->ToString().string()); +} + +TypeKind ASTListType::GetTypeKind() +{ + return TypeKind::TYPE_LIST; +} + +String ASTListType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s*", elementType_->EmitCType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_IN: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + return String::Format("%s*", elementType_->EmitCType(TypeMode::NO_MODE).string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return String::Format("%s", elementType_->EmitCType(TypeMode::PARAM_IN).string()); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::PARAM_IN).string()); + } + } + case TypeMode::PARAM_OUT: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return elementType_->EmitCType(TypeMode::PARAM_OUT); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::PARAM_OUT).string()); + } + } + case TypeMode::LOCAL_VAR: { + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + return String::Format("%s", elementType_->EmitCType(TypeMode::LOCAL_VAR).string()); + } else { + return String::Format("%s*", elementType_->EmitCType(TypeMode::LOCAL_VAR).string()); + } + } + default: + return "unknow type"; + } +} + +String ASTListType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("std::vector<%s>", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_IN: + return String::Format("const std::vector<%s>&", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::PARAM_OUT: + return String::Format("std::vector<%s>&", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + case TypeMode::LOCAL_VAR: + return String::Format("std::vector<%s>", elementType_->EmitCppType(TypeMode::NO_MODE).string()); + default: + return "unknow type"; + } +} + +String ASTListType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return String::Format("List<%s>", elementType_->EmitJavaType(mode, true).string()); +} + +void ASTListType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + + String elementName; + String elementReadName; + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + elementName = String::Format("%s[i]", name.string()); + elementReadName = "&" + elementName; + } else { + elementName = String::Format("%s[i]", name.string()); + elementReadName = elementName; + } + + elementType_->EmitCProxyWriteVar(parcelName, elementReadName, gotoLabel, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %sLen)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string(), name.string()); + + String element; + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT + || elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + element = String::Format("&%s[i]", name.string()); + } else { + element = String::Format("%s[i]", name.string()); + } + elementType_->EmitCStubWriteVar(parcelName, element, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ +String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, %s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix).AppendFormat("*%s = (%s*)OsalMemAlloc(sizeof(%s) * (*%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).AppendFormat("}\n"); + } else { + sb.Append(prefix).AppendFormat("*%s = (%s*)OsalMemCalloc(sizeof(%s) * (*%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).AppendFormat("}\n"); + } + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < *%s; i++) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String cpName = String::Format("%sCp", name.string()); + elementType_->EmitCProxyReadVar(parcelName, cpName, true, gotoLabel, sb, prefix + TAB); + sb.Append(prefix).Append(TAB).AppendFormat("(*%s)[i] = strdup(%sCp);\n", + name.string(), name.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("&(*%s)[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCProxyReadVar(parcelName, elementCp, true, gotoLabel, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("(void)memcpy_s(%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR) { + String element = String::Format("(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } else { + String element = String::Format("&(*%s)[i]", name.string()); + elementType_->EmitCProxyReadVar(parcelName, element, true, gotoLabel, sb, prefix + TAB); + } + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, &%s)) {\n", + parcelName.string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + + sb.Append(prefix).AppendFormat("if (%s > 0) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB).AppendFormat("%s = (%s*)OsalMemAlloc(sizeof(%s) * (%s));\n", name.string(), + elementType_->EmitCType().string(), elementType_->EmitCType().string(), lenName.string()); + sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("goto errors;\n"); + sb.Append(prefix + TAB).AppendFormat("}\n"); + } else { + sb.Append(prefix + TAB).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s) * (%s));\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), + lenName.string()); + sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("goto errors;\n"); + sb.Append(prefix + TAB).AppendFormat("}\n"); + } + + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String element = String::Format("%sCp", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + sb.Append(prefix + TAB + TAB).AppendFormat("%s[i] = strdup(%sCp);\n", name.string(), name.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("%s[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCStubReadVar(parcelName, elementCp, sb, prefix + TAB + TAB); + sb.Append(prefix + TAB + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR) { + String element = String::Format("%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } else { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCStubReadVar(parcelName, element, sb, prefix + TAB + TAB); + } + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s.size() failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + elementType_->EmitCppWriteVar(parcelName, elementName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i%d = 0; i%d < %sSize; ++i%d) {\n", + innerLevel, innerLevel, name.string(), innerLevel); + + String valueName = String::Format("value%d", innerLevel++); + elementType_->EmitCppReadVar(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(data, %sLen)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %sLen failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + + String elementName = String::Format("(%s)[i]", name.string()); + elementType_->EmitCMarshalling(elementName, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(data, &%s)) {\n", lenName.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", lenName.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + + sb.Append(prefix).AppendFormat("if (%s > 0) {\n", lenName.string()); + String newPrefix = prefix + TAB; + + sb.Append(newPrefix).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s) * %s);\n", + name.string(), elementType_->EmitCType().string(), elementType_->EmitCType().string(), lenName.string()); + sb.Append(newPrefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(newPrefix + TAB).AppendFormat("goto errors;\n"); + sb.Append(newPrefix).Append("}\n"); + + freeObjStatements.push_back(String::Format("OsalMemFree(%s);\n", name.string())); + sb.Append(newPrefix).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRING) { + String element = String::Format("%sElement", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + sb.Append(newPrefix).Append(TAB).AppendFormat("%s[i] = strdup(%s);\n", + name.string(), element.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String element = String::Format("&%s[i]", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + String element = String::Format("%s[i]", name.string()); + String elementCp = String::Format("%sElementCp", name.string()); + elementType_->EmitCUnMarshalling(elementCp, sb, newPrefix + TAB, freeObjStatements); + sb.Append(newPrefix + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + element.string(), elementType_->EmitCType().string(), elementCp.string(), + elementType_->EmitCType().string()); + } else { + String element = String::Format("%s[i]", name.string()); + elementType_->EmitCUnMarshalling(element, sb, newPrefix + TAB, freeObjStatements); + } + sb.Append(newPrefix).Append("}\n"); + sb.Append(prefix).Append("}\n"); + freeObjStatements.pop_back(); +} + +void ASTListType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s.size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + elementType_->EmitCppMarshalling(parcelName, elementName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTListType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + int index = name.IndexOf('.', 0); + String memberName = name.Substring(index + 1); + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), memberName.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", + memberName.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i%d = 0; i%d < %sSize; ++i%d) {\n", + innerLevel, innerLevel, memberName.string(), innerLevel); + + String valueName = String::Format("value%d", innerLevel++); + if (elementType_->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("%s %s;\n", + elementType_->EmitCppType().string(), valueName.string()); + elementType_->EmitCppUnMarshalling(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } else if (elementType_->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append(prefix + TAB).AppendFormat("%s %s;\n", + elementType_->EmitCppType().string(), valueName.string()); + String cpName = String::Format("%sCp", valueName.string()); + elementType_->EmitCppUnMarshalling(parcelName, cpName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + valueName.string(), elementType_->EmitCppType().string(), cpName.string(), + elementType_->EmitCppType().string()); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } else { + elementType_->EmitCppUnMarshalling(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(%s);\n", name.string(), valueName.string()); + } + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_list_type.h b/tools/hdi-gen/ast/ast_list_type.h new file mode 100755 index 000000000..c58233d51 --- /dev/null +++ b/tools/hdi-gen/ast/ast_list_type.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTLISTTYPE_H +#define OHOS_HDI_ASTLISTTYPE_H + +#include "ast/ast_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace HDI { +class ASTListType : public ASTType { +public: + inline void SetElementType(const AutoPtr& elementType) + { + elementType_ = elementType; + } + + inline AutoPtr GetElementType() + { + return elementType_; + } + + bool IsListType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + AutoPtr elementType_ = nullptr; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTLISTTYPE_H diff --git a/tools/hdi-gen/ast/ast_long_type.cpp b/tools/hdi-gen/ast/ast_long_type.cpp new file mode 100755 index 000000000..55264732b --- /dev/null +++ b/tools/hdi-gen/ast/ast_long_type.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_long_type.h" + +namespace OHOS { +namespace HDI { +bool ASTLongType::IsLongType() +{ + return true; +} + +String ASTLongType::ToString() +{ + return "long"; +} + +TypeKind ASTLongType::GetTypeKind() +{ + return TypeKind::TYPE_LONG; +} + +String ASTLongType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int64_t"; + case TypeMode::PARAM_IN: + return "int64_t"; + case TypeMode::PARAM_OUT: + return "int64_t*"; + case TypeMode::LOCAL_VAR: + return "int64_t"; + default: + return "unknow type"; + } +} + +String ASTLongType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int64_t"; + case TypeMode::PARAM_IN: + return "int64_t"; + case TypeMode::PARAM_OUT: + return "int64_t&"; + case TypeMode::LOCAL_VAR: + return "int64_t"; + default: + return "unknow type"; + } +} + +String ASTLongType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Long" : "long"; +} + +void ASTLongType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt64(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt64(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt64(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt64(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt64(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadInt64();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt64();\n", name.string(), parcelName.string()); + } +} + +void ASTLongType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt64(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt64(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt64(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTLongType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadInt64();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt64();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_long_type.h b/tools/hdi-gen/ast/ast_long_type.h new file mode 100755 index 000000000..dde4c8d01 --- /dev/null +++ b/tools/hdi-gen/ast/ast_long_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTLONGTYPE_H +#define OHOS_HDI_ASTLONGTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTLongType : public ASTType { +public: + bool IsLongType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTLONGTYPE_H diff --git a/tools/hdi-gen/ast/ast_map_type.cpp b/tools/hdi-gen/ast/ast_map_type.cpp new file mode 100755 index 000000000..f51f0eba4 --- /dev/null +++ b/tools/hdi-gen/ast/ast_map_type.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_map_type.h" + +namespace OHOS { +namespace HDI { +bool ASTMapType::IsMapType() +{ + return true; +} + +String ASTMapType::ToString() +{ + return String::Format("Map<%s, %s>", keyType_->ToString().string(), valueType_->ToString().string()); +} + +TypeKind ASTMapType::GetTypeKind() +{ + return TypeKind::TYPE_MAP; +} + +String ASTMapType::EmitCType(TypeMode mode) const +{ + // c language has no map type + return "/"; +} + +String ASTMapType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("std::map<%s, %s>", + keyType_->EmitCppType().string(), valueType_->EmitCppType().string()); + case TypeMode::PARAM_IN: + return String::Format("const std::map<%s, %s>&", + keyType_->EmitCppType().string(), valueType_->EmitCppType().string()); + case TypeMode::PARAM_OUT: + return String::Format("std::map<%s, %s>&", + keyType_->EmitCppType().string(), valueType_->EmitCppType().string()); + case TypeMode::LOCAL_VAR: + return String::Format("std::map<%s, %s>", + keyType_->EmitCppType().string(), valueType_->EmitCppType().string()); + default: + return "unknow type"; + } +} + +String ASTMapType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return String::Format("HashMap<%s, %s>", keyType_->EmitJavaType(mode, true).string(), + valueType_->EmitJavaType(mode, true).string()); +} + +void ASTMapType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + String keyName = String::Format("(%s.first)", elementName.string()); + String valueName = String::Format("(%s.second)", elementName.string()); + keyType_->EmitCppWriteVar(parcelName, keyName, sb, prefix + TAB, innerLevel); + valueType_->EmitCppWriteVar(parcelName, valueName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTMapType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sSize; ++i) {\n", name.string()); + + String KeyName = String::Format("key%d", innerLevel); + String valueName = String::Format("value%d", innerLevel); + innerLevel++; + keyType_->EmitCppReadVar(parcelName, KeyName, sb, prefix + TAB, true, innerLevel); + valueType_->EmitCppReadVar(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s[%s] = %s;\n", name.string(), KeyName.string(), valueName.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTMapType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s.size())) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s.size failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); + String elementName = String::Format("it%d", innerLevel++); + sb.Append(prefix).AppendFormat("for (auto %s : %s) {\n", elementName.string(), name.string()); + + String keyName = String::Format("(%s.first)", elementName.string()); + String valName = String::Format("(%s.second)", elementName.string()); + keyType_->EmitCppMarshalling(parcelName, keyName, sb, prefix + TAB, innerLevel); + valueType_->EmitCppMarshalling(parcelName, valName, sb, prefix + TAB, innerLevel); + sb.Append(prefix).Append("}\n"); +} + +void ASTMapType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat("uint32_t %sSize = %s.ReadUint32();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (uint32_t i = 0; i < %sSize; ++i) {\n", name.string()); + + String KeyName = String::Format("key%d", innerLevel); + String valueName = String::Format("value%d", innerLevel); + innerLevel++; + keyType_->EmitCppUnMarshalling(parcelName, KeyName, sb, prefix + TAB, true, innerLevel); + valueType_->EmitCppUnMarshalling(parcelName, valueName, sb, prefix + TAB, true, innerLevel); + sb.Append(prefix + TAB).AppendFormat("%s[%s] = %s;\n", + name.string(), KeyName.string(), valueName.string()); + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_map_type.h b/tools/hdi-gen/ast/ast_map_type.h new file mode 100755 index 000000000..44c011a1e --- /dev/null +++ b/tools/hdi-gen/ast/ast_map_type.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTMAPTYPE_H +#define OHOS_HDI_ASTMAPTYPE_H + +#include "ast/ast_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace HDI { +class ASTMapType : public ASTType { +public: + inline void SetKeyType(const AutoPtr& keyType) + { + keyType_ = keyType; + } + + inline AutoPtr GetKeyType() + { + return keyType_; + } + + inline void SetValueType(const AutoPtr& valueType) + { + valueType_ = valueType; + } + + inline AutoPtr GetValueType() + { + return valueType_; + } + + bool IsMapType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + AutoPtr keyType_; + AutoPtr valueType_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTMAPTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_method.cpp b/tools/hdi-gen/ast/ast_method.cpp new file mode 100755 index 000000000..05db4aad1 --- /dev/null +++ b/tools/hdi-gen/ast/ast_method.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_method.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTMethod::AddParameter(const AutoPtr& parameter) +{ + if (parameter == nullptr) { + return; + } + parameters_.push_back(parameter); +} + +AutoPtr ASTMethod::GetParameter(size_t index) +{ + if (index >= parameters_.size()) { + return nullptr; + } + + return parameters_[index]; +} + +String ASTMethod::Dump(const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + + std::vector attributes; + if (isOneWay_) attributes.push_back("oneway"); + if (isFull_) attributes.push_back("full"); + if (isLite_) attributes.push_back("lite"); + if (attributes.size() > 0) { + sb.Append("["); + for (size_t i = 0; i < attributes.size(); i++) { + sb.Append(attributes[i]); + if (i < attributes.size() - 1) { + sb.Append(','); + } + } + sb.Append("] "); + } + + sb.Append(name_).Append('('); + if (parameters_.size() != 0) { + sb.Append('\n'); + for (auto parameter : parameters_) { + String info = parameter->Dump(prefix + " "); + sb.Append(info); + if (parameter != parameters_[parameters_.size() - 1]) { + sb.Append(",\n"); + } + } + } + sb.Append(");\n"); + + return sb.ToString(); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_method.h b/tools/hdi-gen/ast/ast_method.h new file mode 100755 index 000000000..fd157b22d --- /dev/null +++ b/tools/hdi-gen/ast/ast_method.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTMETHOD_H +#define OHOS_HDI_ASTMETHOD_H + +#include +#include "ast/ast_node.h" +#include "ast/ast_parameter.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class ASTMethod : public ASTNode { +public: + + inline void SetName(const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetOneWay(bool oneway) + { + isOneWay_ = oneway; + } + + inline bool IsOneWay() + { + return isOneWay_; + } + + inline void SetFull(bool full) + { + isFull_ = full; + } + + inline bool IsFull() + { + return isFull_; + } + + inline void SetLite(bool lite) + { + isLite_ = lite; + } + + inline bool IsLite() + { + return isLite_; + } + + void AddParameter(const AutoPtr& parameter); + + AutoPtr GetParameter(size_t index); + + inline size_t GetParameterNumber() + { + return parameters_.size(); + } + + String Dump(const String& prefix) override; + +private: + String name_; + bool isOneWay_ = false; + bool isFull_ = false; + bool isLite_ = false; + + std::vector> parameters_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTMETHOD_H diff --git a/tools/hdi-gen/ast/ast_module.cpp b/tools/hdi-gen/ast/ast_module.cpp new file mode 100755 index 000000000..f07c1c57b --- /dev/null +++ b/tools/hdi-gen/ast/ast_module.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_module.h" + +namespace OHOS { +namespace HDI { +void ASTModule::AddAST(const String& astName, const AutoPtr ast) +{ + asts_[astName] = ast; +} + +AutoPtr ASTModule::GetAst(const String& astName) +{ + auto astIter = asts_.find(astName); + if (astIter == asts_.end()) { + return nullptr; + } + return astIter->second; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_module.h b/tools/hdi-gen/ast/ast_module.h new file mode 100755 index 000000000..328f6cd10 --- /dev/null +++ b/tools/hdi-gen/ast/ast_module.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_AST_MODULE_H +#define OHOS_HDI_AST_MODULE_H + +#include +#include "ast/ast.h" + +namespace OHOS { +namespace HDI { +class ASTModule : public LightRefCountBase { +public: + using ASTMap = std::unordered_map, StringHashFunc, StringEqualFunc>; + + void AddAST(const String& astName, const AutoPtr ast); + + AutoPtr GetAst(const String& astName); + + inline const ASTMap& GetAllAsts() const + { + return asts_; + } +private: + // all ast data + ASTMap asts_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_AST_MODULE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_namespace.cpp b/tools/hdi-gen/ast/ast_namespace.cpp new file mode 100755 index 000000000..02355c377 --- /dev/null +++ b/tools/hdi-gen/ast/ast_namespace.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_namespace.h" +#include "ast/ast_interface_type.h" +#include "ast/ast_sequenceable_type.h" + +namespace OHOS { +namespace HDI { +ASTNamespace::ASTNamespace(const String& nspaceStr) + : name_(nspaceStr), + outerNamespace_(nullptr) +{} + +void ASTNamespace::AddNamespace(const AutoPtr& innerNspace) +{ + if (innerNspace == nullptr) { + return; + } + + innerNamespaces_.push_back(innerNspace); + innerNspace->outerNamespace_ = this; +} + +AutoPtr ASTNamespace::FindNamespace(const String& nspaceStr) +{ + if (nspaceStr.IsEmpty()) { + return nullptr; + } + + for (auto nspace : innerNamespaces_) { + if (nspace->name_.Equals(nspaceStr)) { + return nspace; + } + } + return nullptr; +} + +AutoPtr ASTNamespace::GetNamespace(size_t index) +{ + if (index >= innerNamespaces_.size()) { + return nullptr; + } + + return innerNamespaces_[index]; +} + +void ASTNamespace::AddInterface(const AutoPtr& interface) +{ + if (interface == nullptr) { + return; + } + + interfaces_.push_back(interface); +} + +AutoPtr ASTNamespace::GetInterface(size_t index) +{ + if (index >= interfaces_.size()) { + return nullptr; + } + + return interfaces_[index]; +} + +void ASTNamespace::AddSequenceable(const AutoPtr& sequenceable) +{ + if (sequenceable == nullptr) { + return; + } + + sequenceables_.push_back(sequenceable); +} + +AutoPtr ASTNamespace::GetSequenceable(size_t index) +{ + if (index >= sequenceables_.size()) { + return nullptr; + } + + return sequenceables_[index]; +} + +String ASTNamespace::ToString() +{ + String nspaceStr; + ASTNamespace* nspace = this; + while (nspace != nullptr) { + nspaceStr = nspace->name_ + "." + nspaceStr; + nspace = nspace->outerNamespace_; + } + return nspaceStr; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_namespace.h b/tools/hdi-gen/ast/ast_namespace.h new file mode 100755 index 000000000..26944c594 --- /dev/null +++ b/tools/hdi-gen/ast/ast_namespace.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTNAMESPACE_H +#define OHOS_HDI_ASTNAMESPACE_H + +#include +#include "ast/ast_node.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace HDI { +class ASTInterfaceType; +class ASTSequenceableType; + +class ASTNamespace : public ASTNode { +public: + ASTNamespace(const String& nspaceStr); + + virtual ~ASTNamespace() = default; + + inline String GetName() + { + return name_; + } + + void AddNamespace(const AutoPtr& innerNspace); + + AutoPtr FindNamespace(const String& nspaceStr); + + AutoPtr GetNamespace(size_t index); + + inline size_t GetNamespaceNumber() + { + return innerNamespaces_.size(); + } + + void AddInterface(const AutoPtr& interface); + + AutoPtr GetInterface(size_t index); + + inline size_t GetInterfaceNumber() + { + return interfaces_.size(); + } + + void AddSequenceable(const AutoPtr& sequenceable); + + AutoPtr GetSequenceable(size_t index); + + inline size_t GetSequenceableNumber() + { + return sequenceables_.size(); + } + + inline String ToShortString() + { + return name_; + } + + String ToString() override; + +private: + String name_; + ASTNamespace* outerNamespace_; + std::vector> innerNamespaces_; + std::vector> sequenceables_; + std::vector> interfaces_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTNAMESPACE_H diff --git a/tools/hdi-gen/ast/ast_node.cpp b/tools/hdi-gen/ast/ast_node.cpp new file mode 100755 index 000000000..b1cb909d8 --- /dev/null +++ b/tools/hdi-gen/ast/ast_node.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_node.h" + +namespace OHOS { +namespace HDI { +ASTNode::~ASTNode() +{} + +String ASTNode::ToString() +{ + return "ASTNode"; +} + +String ASTNode::Dump(const String& prefix) +{ + return prefix + "ASTNode"; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_node.h b/tools/hdi-gen/ast/ast_node.h new file mode 100755 index 000000000..0aebbaafb --- /dev/null +++ b/tools/hdi-gen/ast/ast_node.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTNODE_H +#define OHOS_HDI_ASTNODE_H + +#include "util/light_refcount_base.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class ASTNode : public LightRefCountBase { +public: + virtual ~ASTNode(); + + virtual String ToString(); + + virtual String Dump(const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTNODE_H diff --git a/tools/hdi-gen/ast/ast_parameter.cpp b/tools/hdi-gen/ast/ast_parameter.cpp new file mode 100755 index 000000000..6247f981d --- /dev/null +++ b/tools/hdi-gen/ast/ast_parameter.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_parameter.h" +#include "ast/ast_array_type.h" +#include "ast/ast_list_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +String ASTParameter::Dump(const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + sb.Append('['); + + if (attribute_ == ParamAttr::PARAM_IN) { + sb.Append("in"); + } else { + sb.Append("out"); + } + + sb.Append("] "); + sb.Append(type_->ToString()).Append(' '); + sb.Append(name_); + + return sb.ToString(); +} + +String ASTParameter::EmitCParameter() +{ + StringBuilder sb; + + switch (type_->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + case TypeKind::TYPE_BYTE: + case TypeKind::TYPE_SHORT: + case TypeKind::TYPE_INT: + case TypeKind::TYPE_LONG: + case TypeKind::TYPE_UCHAR: + case TypeKind::TYPE_USHORT: + case TypeKind::TYPE_UINT: + case TypeKind::TYPE_ULONG: + case TypeKind::TYPE_FLOAT: + case TypeKind::TYPE_DOUBLE: + case TypeKind::TYPE_ENUM: + case TypeKind::TYPE_FILEDESCRIPTOR: + case TypeKind::TYPE_STRING: + case TypeKind::TYPE_INTERFACE: + case TypeKind::TYPE_STRUCT: + case TypeKind::TYPE_UNION: + case TypeKind::TYPE_VOID: { + if (attribute_ == ParamAttr::PARAM_IN) { + return String::Format("%s %s", type_->EmitCType(TypeMode::PARAM_IN).string(), name_.string()); + } else { + return String::Format("%s %s", type_->EmitCType(TypeMode::PARAM_OUT).string(), name_.string()); + } + } + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: { + StringBuilder paramStr; + if (attribute_ == ParamAttr::PARAM_IN) { + paramStr.AppendFormat("%s %s", type_->EmitCType(TypeMode::PARAM_IN).string(), name_.string()); + } else { + paramStr.AppendFormat("%s %s", type_->EmitCType(TypeMode::PARAM_OUT).string(), name_.string()); + } + + if (attribute_ == ParamAttr::PARAM_IN) { + paramStr.AppendFormat(", uint32_t %sLen", name_.string()); + } else { + paramStr.AppendFormat(", uint32_t* %sLen", name_.string()); + } + + return paramStr.ToString(); + } + default: + return String::Format("unknow type %s", name_.string()); + } + + return sb.ToString(); +} + +String ASTParameter::EmitCppParameter() +{ + if (attribute_ == ParamAttr::PARAM_IN) { + return String::Format("%s %s", type_->EmitCppType(TypeMode::PARAM_IN).string(), name_.string()); + } else { + return String::Format("%s %s", type_->EmitCppType(TypeMode::PARAM_OUT).string(), name_.string()); + } +} + +String ASTParameter::EmitJavaParameter() +{ + StringBuilder sb; + switch (type_->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + case TypeKind::TYPE_BYTE: + case TypeKind::TYPE_SHORT: + case TypeKind::TYPE_INT: + case TypeKind::TYPE_LONG: + case TypeKind::TYPE_UCHAR: + case TypeKind::TYPE_USHORT: + case TypeKind::TYPE_UINT: + case TypeKind::TYPE_ULONG: + case TypeKind::TYPE_FLOAT: + case TypeKind::TYPE_DOUBLE: + case TypeKind::TYPE_ENUM: + case TypeKind::TYPE_FILEDESCRIPTOR: + case TypeKind::TYPE_STRING: + case TypeKind::TYPE_SEQUENCEABLE: + case TypeKind::TYPE_INTERFACE: + case TypeKind::TYPE_STRUCT: + case TypeKind::TYPE_UNION: + case TypeKind::TYPE_VOID: + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: + case TypeKind::TYPE_MAP: { + return String::Format("%s %s", type_->EmitJavaType(TypeMode::NO_MODE, false).string(), name_.string()); + } + default: + return String::Format("unknow type %s", name_.string()); + } + + return sb.ToString(); +} + +String ASTParameter::EmitCLocalVar() +{ + StringBuilder sb; + sb.AppendFormat("%s %s", type_->EmitCType(TypeMode::LOCAL_VAR).string(), name_.string()); + switch (type_->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(" = false"); + break; + case TypeKind::TYPE_BYTE: + case TypeKind::TYPE_SHORT: + case TypeKind::TYPE_INT: + case TypeKind::TYPE_LONG: + case TypeKind::TYPE_UCHAR: + case TypeKind::TYPE_USHORT: + case TypeKind::TYPE_UINT: + case TypeKind::TYPE_ULONG: + case TypeKind::TYPE_FLOAT: + case TypeKind::TYPE_DOUBLE: + sb.Append(" = 0"); + break; + case TypeKind::TYPE_STRING: + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: + case TypeKind::TYPE_STRUCT: + case TypeKind::TYPE_UNION: + case TypeKind::TYPE_INTERFACE: + sb.Append(" = NULL"); + break; + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(" = -1"); + break; + default: + break; + } + sb.Append(";"); + return sb.ToString(); +} + +String ASTParameter::EmitCppLocalVar() +{ + StringBuilder sb; + sb.AppendFormat("%s %s", type_->EmitCppType(TypeMode::LOCAL_VAR).string(), name_.string()); + switch (type_->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(" = false"); + break; + case TypeKind::TYPE_BYTE: + case TypeKind::TYPE_SHORT: + case TypeKind::TYPE_INT: + case TypeKind::TYPE_LONG: + case TypeKind::TYPE_UCHAR: + case TypeKind::TYPE_USHORT: + case TypeKind::TYPE_UINT: + case TypeKind::TYPE_ULONG: + case TypeKind::TYPE_FLOAT: + case TypeKind::TYPE_DOUBLE: + sb.Append(" = 0"); + break; + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(" = -1"); + break; + case TypeKind::TYPE_SEQUENCEABLE: + sb.Append(" = nullptr"); + break; + default: + break; + } + sb.Append(";"); + return sb.ToString(); +} + +String ASTParameter::EmitJavaLocalVar() +{ + return ""; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_parameter.h b/tools/hdi-gen/ast/ast_parameter.h new file mode 100755 index 000000000..d2c905198 --- /dev/null +++ b/tools/hdi-gen/ast/ast_parameter.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTPARAMETER_H +#define OHOS_HDI_ASTPARAMETER_H + +#include "ast/ast_node.h" +#include "ast/ast_type.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +// parameter attribute +enum class ParamAttr { + PARAM_IN, + PARAM_OUT, +}; + +class ASTParameter : public ASTNode { +public: + inline void SetName(const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetType(const AutoPtr& type) + { + type_ = type; + } + + inline AutoPtr GetType() + { + return type_; + } + + inline void SetAttribute(ParamAttr attribute) + { + attribute_ = attribute; + } + + inline ParamAttr GetAttribute() + { + return attribute_; + } + + String Dump(const String& prefix) override; + + String EmitCParameter(); + + String EmitCppParameter(); + + String EmitJavaParameter(); + + String EmitCLocalVar(); + + String EmitCppLocalVar(); + + String EmitJavaLocalVar(); +private: + String name_; + AutoPtr type_ = nullptr; + ParamAttr attribute_ = ParamAttr::PARAM_IN; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTPARAMETER_H diff --git a/tools/hdi-gen/ast/ast_sequenceable_type.cpp b/tools/hdi-gen/ast/ast_sequenceable_type.cpp new file mode 100755 index 000000000..da20f21ab --- /dev/null +++ b/tools/hdi-gen/ast/ast_sequenceable_type.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_sequenceable_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTSequenceableType::SetNamespace(const AutoPtr& nspace) +{ + ASTType::SetNamespace(nspace); + if (namespace_ != nullptr) { + namespace_->AddSequenceable(this); + } +} + +bool ASTSequenceableType::IsSequenceableType() +{ + return true; +} + +String ASTSequenceableType::ToString() +{ + return name_; +} + +TypeKind ASTSequenceableType::GetTypeKind() +{ + return TypeKind::TYPE_SEQUENCEABLE; +} + +String ASTSequenceableType::Dump(const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix).Append("sequenceable "); + if (namespace_ != nullptr) { + sb.Append(namespace_->ToString()); + } + sb.Append(name_); + sb.Append(";\n"); + + return sb.ToString(); +} + +String ASTSequenceableType::GetFullName() const +{ + return namespace_->ToString() + name_; +} + +String ASTSequenceableType::EmitCType(TypeMode mode) const +{ + // c language has no Sequenceable type + return "/"; +} + +String ASTSequenceableType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("sptr<%s>", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const sptr<%s>&", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("sptr<%s>&", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("sptr<%s>", name_.string()); + default: + return "unknow type"; + } +} + +String ASTSequenceableType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return name_; +} + +void ASTSequenceableType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteStrongParcelable(%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTSequenceableType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("sptr<%s> %s = %s.ReadStrongParcelable<%s>();\n", + name_.string(), name.string(), parcelName.string(), name_.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadStrongParcelable<%s>();\n", + name.string(), parcelName.string(), name_.string()); + } +} + +void ASTSequenceableType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteStrongParcelable(%s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTSequenceableType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadStrongParcelable<%s>();\n", + EmitCppType().string(), name.string(), parcelName.string(), name_.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadStrongParcelable<%s>();\n", + name.string(), parcelName.string(), name_.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_sequenceable_type.h b/tools/hdi-gen/ast/ast_sequenceable_type.h new file mode 100755 index 000000000..92539424b --- /dev/null +++ b/tools/hdi-gen/ast/ast_sequenceable_type.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTSEQUENCEABLETYPE_H +#define OHOS_HDI_ASTSEQUENCEABLETYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTSequenceableType : public ASTType { +public: + void SetNamespace(const AutoPtr& nspace) override; + + bool IsSequenceableType() override; + + String ToString() override; + + String Dump(const String& prefix) override; + + TypeKind GetTypeKind() override; + + String GetFullName() const; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTSEQUENCEABLETYPE_H diff --git a/tools/hdi-gen/ast/ast_short_type.cpp b/tools/hdi-gen/ast/ast_short_type.cpp new file mode 100755 index 000000000..a30e7a101 --- /dev/null +++ b/tools/hdi-gen/ast/ast_short_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_short_type.h" + +namespace OHOS { +namespace HDI { +bool ASTShortType::IsShortType() +{ + return true; +} + +String ASTShortType::ToString() +{ + return "short"; +} + +TypeKind ASTShortType::GetTypeKind() +{ + return TypeKind::TYPE_SHORT; +} + +String ASTShortType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int16_t"; + case TypeMode::PARAM_IN: + return "int16_t"; + case TypeMode::PARAM_OUT: + return "int16_t*"; + case TypeMode::LOCAL_VAR: + return "int16_t"; + default: + return "unknow type"; + } +} + +String ASTShortType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "int16_t"; + case TypeMode::PARAM_IN: + return "int16_t"; + case TypeMode::PARAM_OUT: + return "int16_t&"; + case TypeMode::LOCAL_VAR: + return "int16_t"; + default: + return "unknow type"; + } +} + +String ASTShortType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return isInnerType ? "Short" : "short"; +} + +void ASTShortType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt16(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt16(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt16(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt16(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt16(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadInt16();\n", EmitCppType().string(), name.string(), + EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = (%s)%s.ReadInt16();\n", name.string(), EmitCppType().string(), + parcelName.string()); + } +} + +void ASTShortType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteInt16(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadInt16(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteInt16(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTShortType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.ReadInt16();\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadInt16();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_short_type.h b/tools/hdi-gen/ast/ast_short_type.h new file mode 100755 index 000000000..b85ff3715 --- /dev/null +++ b/tools/hdi-gen/ast/ast_short_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTSHORTTYPE_H +#define OHOS_HDI_ASTSHORTTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTShortType : public ASTType { +public: + bool IsShortType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTSHORTTYPE_H diff --git a/tools/hdi-gen/ast/ast_string_type.cpp b/tools/hdi-gen/ast/ast_string_type.cpp new file mode 100755 index 000000000..d658766fd --- /dev/null +++ b/tools/hdi-gen/ast/ast_string_type.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_string_type.h" + +namespace OHOS { +namespace HDI { +bool ASTStringType::IsStringType() +{ + return true; +} + +String ASTStringType::ToString() +{ + return "String"; +} + +TypeKind ASTStringType::GetTypeKind() +{ + return TypeKind::TYPE_STRING; +} + +String ASTStringType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "char*"; + case TypeMode::PARAM_IN: + return "const char*"; + case TypeMode::PARAM_OUT: + return "char**"; + case TypeMode::LOCAL_VAR: + return "char*"; + default: + return "unknow type"; + } +} + +String ASTStringType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "std::string"; + case TypeMode::PARAM_IN: + return "const std::string&"; + case TypeMode::PARAM_OUT: + return "std::string&"; + case TypeMode::LOCAL_VAR: + return "std::string"; + default: + return "unknow type"; + } +} + +String ASTStringType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return "String"; +} + +void ASTStringType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteString(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteString(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("const char *%s = HdfSbufReadString(%s);\n", + name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("const char *%s = HdfSbufReadString(%s);\n", + name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteString(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadString();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadString();\n", name.string(), parcelName.string()); + } +} + +void ASTStringType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteString(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("const char *%s = HdfSbufReadString(data);\n", name.string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteString(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStringType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadString();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadString();\n", + name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_string_type.h b/tools/hdi-gen/ast/ast_string_type.h new file mode 100755 index 000000000..84f4ff7b0 --- /dev/null +++ b/tools/hdi-gen/ast/ast_string_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTSTRINGTYPE_H +#define OHOS_HDI_ASTSTRINGTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTStringType : public ASTType { +public: + bool IsStringType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTSTRINGTYPE_H diff --git a/tools/hdi-gen/ast/ast_struct_type.cpp b/tools/hdi-gen/ast/ast_struct_type.cpp new file mode 100755 index 000000000..9ce8920aa --- /dev/null +++ b/tools/hdi-gen/ast/ast_struct_type.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_struct_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTStructType::AddMember(const AutoPtr& typeName, String name) +{ + for (auto it : members_) { + if (std::get<0>(it).Equals(name)) { + return; + } + } + members_.push_back(std::make_tuple(name, typeName)); +} + +bool ASTStructType::IsStructType() +{ + return true; +} + +String ASTStructType::ToString() +{ + return "struct " + name_; +} + +String ASTStructType::Dump(const String& prefix) +{ + StringBuilder sb; + sb.Append(prefix); + + std::vector attributes; + if (isFull_) attributes.push_back("full"); + if (isLite_) attributes.push_back("lite"); + if (attributes.size() > 0) { + sb.Append("["); + for (size_t i = 0; i < attributes.size(); i++) { + sb.Append(attributes[i]); + if (i < attributes.size() - 1) { + sb.Append(','); + } + } + sb.Append("] "); + } + + sb.AppendFormat("struct %s {\n", name_.string()); + + if (members_.size() > 0) { + for (auto it : members_) { + sb.Append(prefix + " "); + sb.AppendFormat("%s %s;\n", std::get<1>(it)->ToString().string(), std::get<0>(it).string()); + } + } + + sb.Append(prefix).Append("};\n"); + + return sb.ToString(); +} + +TypeKind ASTStructType::GetTypeKind() +{ + return TypeKind::TYPE_STRUCT; +} + +String ASTStructType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("struct %s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const struct %s*", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("struct %s**", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("struct %s*", name_.string()); + default: + return "unknow type"; + } +} + +String ASTStructType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const %s&", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("%s&", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("%s", name_.string()); + default: + return "unknow type"; + } +} + +String ASTStructType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // currently, Java does not support the struct type. + return "/"; +} + +String ASTStructType::EmitCTypeDecl() const +{ + StringBuilder sb; + sb.AppendFormat("struct %s {\n", name_.string()); + + for (auto it : members_) { + AutoPtr member = std::get<1>(it); + String memberName = std::get<0>(it); + sb.Append(" ").AppendFormat("%s %s;\n", member->EmitCType().string(), memberName.string()); + if (member->GetTypeKind() == TypeKind::TYPE_ARRAY || member->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.Append(" ").AppendFormat("uint32_t %sLen;\n", memberName.string()); + } + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTStructType::EmitCppTypeDecl() const +{ + StringBuilder sb; + sb.AppendFormat("struct %s {\n", name_.string()); + + for (auto it : members_) { + AutoPtr member = std::get<1>(it); + String memberName = std::get<0>(it); + sb.Append(" ").AppendFormat("%s %s;\n", member->EmitCppType().string(), memberName.string()); + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTStructType::EmitJavaTypeDecl() const +{ + StringBuilder sb; + + return sb.ToString(); +} + +void ASTStructType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockMarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockMarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockUnmarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockUnmarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).AppendFormat("}\n"); +} + +void ASTStructType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockMarshalling(%s, %s)) {\n", + EmitCppType().string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat("if (!%sBlockUnmarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockMarshalling(data, &%s)) {\n", + name_.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockUnmarshalling(data, %s)) {\n", + name_.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockMarshalling(%s, %s)) {\n", + name_.string(), parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTStructType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%sBlockUnmarshalling(data, %s)) {\n", + EmitCppType().string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_struct_type.h b/tools/hdi-gen/ast/ast_struct_type.h new file mode 100755 index 000000000..fb69c3207 --- /dev/null +++ b/tools/hdi-gen/ast/ast_struct_type.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTSTRUCTTYPE_H +#define OHOS_HDI_ASTSTRUCTTYPE_H + +#include +#include +#include "ast/ast_type.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class ASTStructType : public ASTType { +public: + inline void SetName(const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetFull(bool full) + { + isFull_ = full; + } + + inline bool IsFull() + { + return isFull_; + } + + inline void SetLite(bool lite) + { + isLite_ = lite; + } + + inline bool IsLite() + { + return isLite_; + } + + void AddMember(const AutoPtr& typeName, String name); + + inline size_t GetMemberNumber() + { + return members_.size(); + } + + inline String GetMemberName(size_t index) + { + if (index >= members_.size()) { + return String(""); + } + return std::get<0>(members_[index]); + } + + inline AutoPtr GetMemberType(size_t index) + { + if (index >= members_.size()) { + return nullptr; + } + return std::get<1>(members_[index]); + } + + bool IsStructType() override; + + String ToString() override; + + String Dump(const String& prefix) override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + String EmitCTypeDecl() const; + + String EmitCppTypeDecl() const; + + String EmitJavaTypeDecl() const; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + bool isFull_ = false; + bool isLite_ = false; + std::vector>> members_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTSTRUCTTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_type.cpp b/tools/hdi-gen/ast/ast_type.cpp new file mode 100755 index 000000000..6e18d8e08 --- /dev/null +++ b/tools/hdi-gen/ast/ast_type.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +const char* ASTType::TAB = " "; + +void ASTType::SetName(const String& name) +{ + name_ = name; +} + +String ASTType::GetName() +{ + return name_; +} + +void ASTType::SetNamespace(const AutoPtr& nspace) +{ + namespace_ = nspace; +} + +AutoPtr ASTType::GetNamespace() +{ + return namespace_; +} + +bool ASTType::IsBooleanType() +{ + return false; +} + +bool ASTType::IsByteType() +{ + return false; +} + +bool ASTType::IsShortType() +{ + return false; +} + +bool ASTType::IsIntegerType() +{ + return false; +} + +bool ASTType::IsLongType() +{ + return false; +} + +bool ASTType::IsUcharType() +{ + return false; +} + +bool ASTType::IsUshortType() +{ + return false; +} + +bool ASTType::IsUintType() +{ + return false; +} + +bool ASTType::IsUlongType() +{ + return false; +} + +bool ASTType::IsFloatType() +{ + return false; +} + +bool ASTType::IsDoubleType() +{ + return false; +} + +bool ASTType::IsStringType() +{ + return false; +} + +bool ASTType::IsListType() +{ + return false; +} + +bool ASTType::IsMapType() +{ + return false; +} + +bool ASTType::IsEnumType() +{ + return false; +} + +bool ASTType::IsStructType() +{ + return false; +} + +bool ASTType::IsUnionType() +{ + return false; +} + +bool ASTType::IsInterfaceType() +{ + return false; +} + +bool ASTType::IsSequenceableType() +{ + return false; +} + +bool ASTType::IsVoidType() +{ + return false; +} + +bool ASTType::IsArrayType() +{ + return false; +} + +bool ASTType::IsFdType() +{ + return false; +} + +String ASTType::ToShortString() +{ + return name_; +} + +String ASTType::ToString() +{ + return (namespace_ == nullptr) ? name_ : (namespace_->ToString() + name_); +} + +TypeKind ASTType::GetTypeKind() +{ + return TypeKind::TYPE_UNKNOWN; +} + +String ASTType::EmitCType(TypeMode mode) const +{ + return "unknow"; +} + +String ASTType::EmitCppType(TypeMode mode) const +{ + return "unknow"; +} + +String ASTType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return "unknow"; +} + +void ASTType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("//Writeing \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitFreeStatements(const std::vector& freeObjStatements, StringBuilder& sb, + const String& prefix) const +{ + for (auto it = freeObjStatements.rbegin(); it != freeObjStatements.rend(); it++) { + sb.Append(prefix).Append(*it); + } +} + +void ASTType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.string()); +} + +void ASTType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.string()); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_type.h b/tools/hdi-gen/ast/ast_type.h new file mode 100755 index 000000000..d2fee8085 --- /dev/null +++ b/tools/hdi-gen/ast/ast_type.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTTYPE_H +#define OHOS_HDI_ASTTYPE_H + +#include "ast/ast_namespace.h" +#include "ast/ast_node.h" +#include "util/autoptr.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +enum class TypeKind { + TYPE_UNKNOWN = 0, + TYPE_BOOLEAN, + TYPE_BYTE, + TYPE_SHORT, + TYPE_INT, + TYPE_LONG, + TYPE_FLOAT, + TYPE_DOUBLE, + TYPE_UCHAR, + TYPE_USHORT, + TYPE_UINT, + TYPE_ULONG, + TYPE_STRING, + TYPE_FILEDESCRIPTOR, + TYPE_VOID, + TYPE_SEQUENCEABLE, + TYPE_INTERFACE, + TYPE_LIST, + TYPE_MAP, + TYPE_ARRAY, + TYPE_ENUM, + TYPE_STRUCT, + TYPE_UNION, +}; + +enum class TypeMode { + NO_MODE, // only type + PARAM_IN, // type of the in attribute parameter + PARAM_OUT, // type of the out attribute parameter + LOCAL_VAR, // type of the local variable +}; + +enum class LanguageType { + LANG_C, + LANG_CPP, + LANG_JAVA, +}; + +class ASTType : public ASTNode { +public: + virtual void SetName(const String& name); + + virtual String GetName(); + + virtual void SetNamespace(const AutoPtr& nspace); + + virtual AutoPtr GetNamespace(); + + virtual bool IsBooleanType(); + + virtual bool IsByteType(); + + virtual bool IsShortType(); + + virtual bool IsIntegerType(); + + virtual bool IsLongType(); + + virtual bool IsUcharType(); + + virtual bool IsUshortType(); + + virtual bool IsUintType(); + + virtual bool IsUlongType(); + + virtual bool IsFloatType(); + + virtual bool IsDoubleType(); + + virtual bool IsStringType(); + + virtual bool IsListType(); + + virtual bool IsMapType(); + + virtual bool IsEnumType(); + + virtual bool IsStructType(); + + virtual bool IsUnionType(); + + virtual bool IsInterfaceType(); + + virtual bool IsSequenceableType(); + + virtual bool IsVoidType(); + + virtual bool IsArrayType(); + + virtual bool IsFdType(); + + virtual String ToShortString(); + + String ToString() override; + + virtual TypeKind GetTypeKind(); + + virtual String EmitCType(TypeMode mode = TypeMode::NO_MODE) const; + + virtual String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const; + + virtual String EmitJavaType(TypeMode mode, bool isInnerType = false) const; + + virtual void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const; + + virtual void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const; + + virtual void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const; + + virtual void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const; + + virtual void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const; + + virtual void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const; + + virtual void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const; + + virtual void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const; + + void EmitFreeStatements(const std::vector& freeObjStatements, StringBuilder& sb, + const String& prefix) const; + + virtual void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const; + + virtual void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const; +protected: + static const char* TAB; + String name_; + AutoPtr namespace_; + TypeKind typeKind_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTTYPE_H diff --git a/tools/hdi-gen/ast/ast_uchar_type.cpp b/tools/hdi-gen/ast/ast_uchar_type.cpp new file mode 100755 index 000000000..50e70e516 --- /dev/null +++ b/tools/hdi-gen/ast/ast_uchar_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_uchar_type.h" + +namespace OHOS { +namespace HDI { +bool ASTUcharType::IsUcharType() +{ + return true; +} + +String ASTUcharType::ToString() +{ + return "unsigned char"; +} + +TypeKind ASTUcharType::GetTypeKind() +{ + return TypeKind::TYPE_UCHAR; +} + +String ASTUcharType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint8_t"; + case TypeMode::PARAM_IN: + return "uint8_t"; + case TypeMode::PARAM_OUT: + return "uint8_t*"; + case TypeMode::LOCAL_VAR: + return "uint8_t"; + default: + return "unknow type"; + } +} + +String ASTUcharType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint8_t"; + case TypeMode::PARAM_IN: + return "uint8_t"; + case TypeMode::PARAM_OUT: + return "uint8_t&"; + case TypeMode::LOCAL_VAR: + return "uint8_t"; + default: + return "unknow type"; + } +} + +String ASTUcharType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // unsupported type + return "/"; +} + +void ASTUcharType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint8(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint8(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint8(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint8(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint8(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint8();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint8();\n", name.string(), parcelName.string()); + } +} + +void ASTUcharType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint8(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint8(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint8(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUcharType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint8();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint8();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_uchar_type.h b/tools/hdi-gen/ast/ast_uchar_type.h new file mode 100755 index 000000000..825b503c6 --- /dev/null +++ b/tools/hdi-gen/ast/ast_uchar_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTUCHARTYPE_H +#define OHOS_HDI_ASTUCHARTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTUcharType : public ASTType { +public: + bool IsUcharType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTUCHARTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_uint_type.cpp b/tools/hdi-gen/ast/ast_uint_type.cpp new file mode 100755 index 000000000..6d27b5499 --- /dev/null +++ b/tools/hdi-gen/ast/ast_uint_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_uint_type.h" + +namespace OHOS { +namespace HDI { +bool ASTUintType::IsUintType() +{ + return true; +} + +String ASTUintType::ToString() +{ + return "unsigned int"; +} + +TypeKind ASTUintType::GetTypeKind() +{ + return TypeKind::TYPE_UINT; +} + +String ASTUintType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint32_t"; + case TypeMode::PARAM_IN: + return "uint32_t"; + case TypeMode::PARAM_OUT: + return "uint32_t*"; + case TypeMode::LOCAL_VAR: + return "uint32_t"; + default: + return "unknow type"; + } +} + +String ASTUintType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint32_t"; + case TypeMode::PARAM_IN: + return "uint32_t"; + case TypeMode::PARAM_OUT: + return "uint32_t&"; + case TypeMode::LOCAL_VAR: + return "uint32_t"; + default: + return "unknow type"; + } +} + +String ASTUintType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // unsupported type + return "/"; +} + +void ASTUintType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint32();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint32();\n", name.string(), parcelName.string()); + } +} + +void ASTUintType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint32(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint32(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint32(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUintType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint32();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint32();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_uint_type.h b/tools/hdi-gen/ast/ast_uint_type.h new file mode 100755 index 000000000..97458c444 --- /dev/null +++ b/tools/hdi-gen/ast/ast_uint_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTUINTTYPE_H +#define OHOS_HDI_ASTUINTTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTUintType : public ASTType { +public: + bool IsUintType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTUINTTYPE_H diff --git a/tools/hdi-gen/ast/ast_ulong_type.cpp b/tools/hdi-gen/ast/ast_ulong_type.cpp new file mode 100755 index 000000000..d42fe90b8 --- /dev/null +++ b/tools/hdi-gen/ast/ast_ulong_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_ulong_type.h" + +namespace OHOS { +namespace HDI { +bool ASTUlongType::IsUlongType() +{ + return true; +} + +String ASTUlongType::ToString() +{ + return "unsigned long"; +} + +TypeKind ASTUlongType::GetTypeKind() +{ + return TypeKind::TYPE_ULONG; +} + +String ASTUlongType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint64_t"; + case TypeMode::PARAM_IN: + return "uint64_t"; + case TypeMode::PARAM_OUT: + return "uint64_t*"; + case TypeMode::LOCAL_VAR: + return "uint64_t"; + default: + return "unknow type"; + } +} + +String ASTUlongType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint64_t"; + case TypeMode::PARAM_IN: + return "uint64_t"; + case TypeMode::PARAM_OUT: + return "uint64_t&"; + case TypeMode::LOCAL_VAR: + return "uint64_t"; + default: + return "unknow type"; + } +} + +String ASTUlongType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // unsupported type + return "/"; +} + +void ASTUlongType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint64(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint64(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint64(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint64(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint64(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint64();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint64();\n", name.string(), parcelName.string()); + } +} + +void ASTUlongType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint64(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint64(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint64(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUlongType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint64();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint64();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_ulong_type.h b/tools/hdi-gen/ast/ast_ulong_type.h new file mode 100755 index 000000000..599ccd294 --- /dev/null +++ b/tools/hdi-gen/ast/ast_ulong_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTULONGTYPE_H +#define OHOS_HDI_ASTULONGTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTUlongType : public ASTType { +public: + bool IsUlongType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTULONGTYPE_H diff --git a/tools/hdi-gen/ast/ast_union_type.cpp b/tools/hdi-gen/ast/ast_union_type.cpp new file mode 100755 index 000000000..dfdf7bd9e --- /dev/null +++ b/tools/hdi-gen/ast/ast_union_type.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_union_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +void ASTUnionType::AddMember(const AutoPtr& typeName, String name) +{ + for (auto it : members_) { + if (std::get<0>(it).Equals(name)) { + return; + } + } + members_.push_back(std::make_tuple(name, typeName)); +} + +bool ASTUnionType::IsUnionType() +{ + return true; +} + +String ASTUnionType::ToString() +{ + return "union " + name_; +} + +String ASTUnionType::Dump(const String& prefix) +{ + StringBuilder sb; + sb.Append(prefix); + + std::vector attributes; + if (isFull_) attributes.push_back("full"); + if (isLite_) attributes.push_back("lite"); + if (attributes.size() > 0) { + sb.Append("["); + for (size_t i = 0; i < attributes.size(); i++) { + sb.Append(attributes[i]); + if (i < attributes.size() - 1) { + sb.Append(','); + } + } + sb.Append("] "); + } + + sb.AppendFormat("union %s {\n", name_.string()); + + if (members_.size() > 0) { + for (auto it : members_) { + sb.Append(prefix + " "); + sb.AppendFormat("%s %s;\n", std::get<1>(it)->ToString().string(), std::get<0>(it).string()); + } + } + + sb.Append(prefix).Append("};\n"); + + return sb.ToString(); +} + +TypeKind ASTUnionType::GetTypeKind() +{ + return TypeKind::TYPE_UNION; +} + +String ASTUnionType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("union %s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const union %s*", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("union %s**", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("union %s*", name_.string()); + default: + return "unknow type"; + } +} + +String ASTUnionType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return String::Format("%s", name_.string()); + case TypeMode::PARAM_IN: + return String::Format("const %s&", name_.string()); + case TypeMode::PARAM_OUT: + return String::Format("%s&", name_.string()); + case TypeMode::LOCAL_VAR: + return String::Format("%s", name_.string()); + default: + return "unknow type"; + } +} + +String ASTUnionType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // unsupported type + return "/"; +} + +String ASTUnionType::EmitCTypeDecl() const +{ + StringBuilder sb; + sb.AppendFormat("union %s {\n", name_.string()); + + for (auto it : members_) { + AutoPtr member = std::get<1>(it); + String memberName = std::get<0>(it); + sb.Append(" ").AppendFormat("%s %s;\n", member->EmitCType().string(), memberName.string()); + if (member->GetTypeKind() == TypeKind::TYPE_ARRAY || member->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.Append(" ").AppendFormat("uint32_t %sLen;\n", memberName.string()); + } + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTUnionType::EmitCppTypeDecl() const +{ + StringBuilder sb; + sb.AppendFormat("union %s {\n", name_.string()); + + for (auto it : members_) { + AutoPtr member = std::get<1>(it); + String memberName = std::get<0>(it); + sb.Append(" ").AppendFormat("%s %s;\n", member->EmitCppType().string(), memberName.string()); + } + + sb.Append("};"); + return sb.ToString(); +} + +String ASTUnionType::EmitJavaTypeDecl() const +{ + StringBuilder sb; + + return sb.ToString(); +} + +void ASTUnionType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUnpadBuffer(%s, (const uint8_t *)%s, sizeof(%s))) {\n", + parcelName.string(), name.string(), EmitCType().string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUnpadBuffer(%s, (const uint8_t *)%s, sizeof(%s))) {\n", + parcelName.string(), name.string(), EmitCType().string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("const %s *%s = (%s *)HdfSbufReadUnpadBuffer(%s, sizeof(%s));\n", + EmitCType().string(), name.string(), EmitCType().string(), parcelName.string(), + EmitCType().string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("const %s *%s = (%s *)HdfSbufReadUnpadBuffer(%s, sizeof(%s));\n", + EmitCType().string(), name.string(), EmitCType().string(), parcelName.string(), + EmitCType().string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUnpadBuffer((const uint8_t *)&%s, sizeof(%s))) {\n", + parcelName.string(), name.string(), EmitCppType().string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitCppType().string(), name.string()); + } + sb.Append(prefix).AppendFormat( + "const %s *%sCp = reinterpret_cast(%s.ReadUnpadBuffer(sizeof(%s)));\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string(), + EmitCppType().string()); + sb.Append(prefix).AppendFormat("if (%sCp == nullptr) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %sCp, sizeof(%s));\n", + name.string(), EmitCppType().string(), name.string(), EmitCppType().string()); +} + +void ASTUnionType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUnpadBuffer(data, (const uint8_t *)&%s, sizeof(%s))) {\n", + name.string(), EmitCType().string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("const %s *%s = (const %s *)HdfSbufReadUnpadBuffer(data, sizeof(%s));\n", + EmitCType().string(), name.string(), EmitCType().string(), EmitCType().string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUnpadBuffer((const void*)&%s, sizeof(%s))) {\n", + parcelName.string(), name.string(), EmitCppType().string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUnionType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat( + "const %s *%s = reinterpret_cast(%s.ReadUnpadBuffer(sizeof(%s)));\n", + EmitCppType().string(), name.string(), EmitCppType().string(), parcelName.string(), + EmitCppType().string()); + sb.Append(prefix).AppendFormat("if (%s == nullptr) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_union_type.h b/tools/hdi-gen/ast/ast_union_type.h new file mode 100755 index 000000000..4d494896a --- /dev/null +++ b/tools/hdi-gen/ast/ast_union_type.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTUNIONTYPE_H +#define OHOS_HDI_ASTUNIONTYPE_H + +#include +#include +#include "ast/ast_type.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class ASTUnionType : public ASTType { +public: + inline void SetName(const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetFull(bool full) + { + isFull_ = full; + } + + inline bool IsFull() + { + return isFull_; + } + + inline void SetLite(bool lite) + { + isLite_ = lite; + } + + inline bool IsLite() + { + return isLite_; + } + + void AddMember(const AutoPtr& typeName, String name); + + inline size_t GetMemberNumber() + { + return members_.size(); + } + + inline String GetMemberName(size_t index) + { + if (index >= members_.size()) { + return String(""); + } + return std::get<0>(members_[index]); + } + + inline AutoPtr GetMemberType(size_t index) + { + if (index >= members_.size()) { + return nullptr; + } + return std::get<1>(members_[index]); + } + + bool IsUnionType() override; + + String ToString() override; + + String Dump(const String& prefix) override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + String EmitCTypeDecl() const; + + String EmitCppTypeDecl() const; + + String EmitJavaTypeDecl() const; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +private: + bool isFull_ = false; + bool isLite_ = false; + std::vector>> members_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTUNIONTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_ushort_type.cpp b/tools/hdi-gen/ast/ast_ushort_type.cpp new file mode 100755 index 000000000..5e81653c6 --- /dev/null +++ b/tools/hdi-gen/ast/ast_ushort_type.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_ushort_type.h" + +namespace OHOS { +namespace HDI { +bool ASTUshortType::IsUshortType() +{ + return true; +} + +String ASTUshortType::ToString() +{ + return "unsigned short"; +} + +TypeKind ASTUshortType::GetTypeKind() +{ + return TypeKind::TYPE_USHORT; +} + +String ASTUshortType::EmitCType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint16_t"; + case TypeMode::PARAM_IN: + return "uint16_t"; + case TypeMode::PARAM_OUT: + return "uint16_t*"; + case TypeMode::LOCAL_VAR: + return "uint16_t"; + default: + return "unknow type"; + } +} + +String ASTUshortType::EmitCppType(TypeMode mode) const +{ + switch (mode) { + case TypeMode::NO_MODE: + return "uint16_t"; + case TypeMode::PARAM_IN: + return "uint16_t"; + case TypeMode::PARAM_OUT: + return "uint16_t&"; + case TypeMode::LOCAL_VAR: + return "uint16_t"; + default: + return "unknow type"; + } +} + +String ASTUshortType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + // unsupported type + return "/"; +} + +void ASTUshortType::EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint16(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint16(%s, %s)) {\n", + parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint16(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint16(%s, %s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint16(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel) const +{ + if (initVariable) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint16();\n", EmitCppType().string(), + name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint16();\n", name.string(), parcelName.string()); + } +} + +void ASTUshortType::EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint16(data, %s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const +{ + sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint16(data, &%s)) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.string()); + EmitFreeStatements(freeObjStatements, sb, prefix + TAB); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel) const +{ + sb.Append(prefix).AppendFormat("if (!%s.WriteUint16(%s)) {\n", parcelName.string(), name.string()); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: write %s failed!\", __func__);\n", name.string()); + sb.Append(prefix + TAB).Append("return false;\n"); + sb.Append(prefix).Append("}\n"); +} + +void ASTUshortType::EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel) const +{ + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %s.ReadUint16();\n", + EmitCppType().string(), name.string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %s.ReadUint16();\n", name.string(), parcelName.string()); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_ushort_type.h b/tools/hdi-gen/ast/ast_ushort_type.h new file mode 100755 index 000000000..08489189f --- /dev/null +++ b/tools/hdi-gen/ast/ast_ushort_type.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTUSHORTTYPE_H +#define OHOS_HDI_ASTUSHORTTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTUshortType : public ASTType { +public: + bool IsUshortType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; + + void EmitCProxyWriteVar(const String& parcelName, const String& name, const String& gotoLabel, + StringBuilder& sb, const String& prefix) const override; + + void EmitCStubWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCProxyReadVar(const String& parcelName, const String& name, bool isInnerType, + const String& gotoLabel, StringBuilder& sb, const String& prefix) const override; + + void EmitCStubReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix) const override; + + void EmitCppWriteVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppReadVar(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool initVariable, unsigned int innerLevel = 0) const override; + + void EmitCMarshalling(const String& name, StringBuilder& sb, const String& prefix) const override; + + void EmitCUnMarshalling(const String& name, StringBuilder& sb, const String& prefix, + std::vector& freeObjStatements) const override; + + void EmitCppMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, unsigned int innerLevel = 0) const override; + + void EmitCppUnMarshalling(const String& parcelName, const String& name, StringBuilder& sb, + const String& prefix, bool emitType, unsigned int innerLevel = 0) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTUSHORTTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_void_type.cpp b/tools/hdi-gen/ast/ast_void_type.cpp new file mode 100755 index 000000000..6c89ee3b4 --- /dev/null +++ b/tools/hdi-gen/ast/ast_void_type.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "ast/ast_void_type.h" + +namespace OHOS { +namespace HDI { +bool ASTVoidType::IsVoidType() +{ + return true; +} + +String ASTVoidType::ToString() +{ + return "void"; +} + +TypeKind ASTVoidType::GetTypeKind() +{ + return TypeKind::TYPE_VOID; +} + +String ASTVoidType::EmitCType(TypeMode mode) const +{ + return "void"; +} + +String ASTVoidType::EmitCppType(TypeMode mode) const +{ + return "void"; +} + +String ASTVoidType::EmitJavaType(TypeMode mode, bool isInnerType) const +{ + return "void"; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/ast/ast_void_type.h b/tools/hdi-gen/ast/ast_void_type.h new file mode 100755 index 000000000..44a3966ed --- /dev/null +++ b/tools/hdi-gen/ast/ast_void_type.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_ASTVOIDTYPE_H +#define OHOS_HDI_ASTVOIDTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace HDI { +class ASTVoidType : public ASTType { +public: + bool IsVoidType() override; + + String ToString() override; + + TypeKind GetTypeKind() override; + + String EmitCType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitCppType(TypeMode mode = TypeMode::NO_MODE) const override; + + String EmitJavaType(TypeMode mode, bool isInnerType = false) const override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_ASTBOOLEANTYPE_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/Makefile b/tools/hdi-gen/codegen/Makefile new file mode 100755 index 000000000..64ac5af8d --- /dev/null +++ b/tools/hdi-gen/codegen/Makefile @@ -0,0 +1,12 @@ +OBJS_DIR:=$(BUILD_DIR)/codegen +TARGET = $(OBJS_DIR)/codegen.a +SOURCE:=$(wildcard *.cpp) +OBJS:=$(patsubst %.cpp, $(OBJS_DIR)/%.o, $(SOURCE)) + +$(TARGET):$(OBJS) + $(Q) echo $(TARGET) + $(Q) ar -rc $@ $^ + +$(OBJS_DIR)/%.o:%.cpp + $(Q) mkdir -p $(dir $@) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_client_interface_code_emitter.cpp b/tools/hdi-gen/codegen/c_client_interface_code_emitter.cpp new file mode 100755 index 000000000..75aec71e4 --- /dev/null +++ b/tools/hdi-gen/codegen/c_client_interface_code_emitter.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_client_interface_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void CClientInterfaceCodeEmitter::EmitCode() +{ + EmitInterfaceHeaderFile(); +} + +void CClientInterfaceCodeEmitter::EmitInterfaceHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sclient/%s.h", directory_.string(), FileName(interfaceName_).string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(interfaceName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CClientInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, interfaceFullName_); + sb.Append("\n"); + EmitImportInclusions(sb); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitForwardDecls(sb); + sb.Append("\n"); + EmitInterfaceMethodCommands(sb); + sb.Append("\n"); + EmitInterfaceDecl(sb); + sb.Append("\n"); + EmitTailExternC(sb); + sb.Append("\n"); + EmitTailMacro(sb, interfaceFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CClientInterfaceCodeEmitter::EmitImportInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + for (const auto& importPair : ast_->GetImports()) { + AutoPtr importAst = importPair.second; + + String fileName; + if (importAst->GetASTFileType() == ASTFileType::AST_ICALLBACK && importAst->GetInterfaceDef() != nullptr) { + String ifaceName = importAst->GetInterfaceDef()->GetName(); + String name = ifaceName.StartsWith("I") ? ifaceName.Substring(1) : ifaceName; + String stubName = name + "Stub"; + fileName = FileName(importAst->GetInterfaceDef()->GetNamespace()->ToString() + stubName); + } else { + fileName = FileName(importAst->GetFullName()); + } + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } +} + +void CClientInterfaceCodeEmitter::EmitForwardDecls(StringBuilder& sb) +{ + sb.Append("struct HdfRemoteService;\n"); +} + +void CClientInterfaceCodeEmitter::EmitInterfaceDecl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s {\n", interfaceName_.string()); + sb.Append(TAB).Append("struct HdfRemoteService *remote;\n"); + sb.Append("\n"); + EmitInterfaceMethodsDecl(sb, TAB); + sb.Append("};\n"); + if (!isCallbackInterface()) { + sb.Append("\n"); + EmitInterfaceInstanceMethod(sb); + } +} + +void CClientInterfaceCodeEmitter::EmitInterfaceMethodsDecl(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitInterfaceMethodDecl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CClientInterfaceCodeEmitter::EmitInterfaceMethodDecl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t (*%s)(struct %s *self);\n", + method->GetName().string(), interfaceName_.string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t (*%s)(", method->GetName().string()); + paramStr.AppendFormat("struct %s *self, ", interfaceName_.string()); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(");"); + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void CClientInterfaceCodeEmitter::EmitInterfaceInstanceMethod(StringBuilder& sb) +{ + sb.AppendFormat("struct %s *Hdi%sGet();\n", interfaceName_.string(), infName_.string()); + sb.Append("\n"); + sb.AppendFormat("void Hdi%sRelease(struct %s *instance);\n", infName_.string(), interfaceName_.string()); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_client_interface_code_emitter.h b/tools/hdi-gen/codegen/c_client_interface_code_emitter.h new file mode 100755 index 000000000..edf0b2068 --- /dev/null +++ b/tools/hdi-gen/codegen/c_client_interface_code_emitter.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_CLIENT_INTERFACE_CODE_EMITTER_H +#define OHOS_HDI_C_CLIENT_INTERFACE_CODE_EMITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CClientInterfaceCodeEmitter : public CCodeEmitter { +public: + CClientInterfaceCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CCodeEmitter(ast, targetDirectory) {} + + virtual ~CClientInterfaceCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitInterfaceHeaderFile(); + + void EmitImportInclusions(StringBuilder& sb); + + void EmitForwardDecls(StringBuilder& sb); + + void EmitInterfaceDecl(StringBuilder& sb); + + void EmitInterfaceMethodsDecl(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodDecl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitInterfaceInstanceMethod(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_CLIENT_INTERFACE_CODE_EMITTER_H diff --git a/tools/hdi-gen/codegen/c_client_proxy_code_emitter.cpp b/tools/hdi-gen/codegen/c_client_proxy_code_emitter.cpp new file mode 100755 index 000000000..4b9ff996c --- /dev/null +++ b/tools/hdi-gen/codegen/c_client_proxy_code_emitter.cpp @@ -0,0 +1,524 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_client_proxy_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CClientProxyCodeEmitter::CClientProxyCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CCodeEmitter(ast, targetDirectory) +{ + String infFullName = String::Format("%sclient.%s", + interface_->GetNamespace()->ToString().string(), infName_.string()); + sourceFileName_ = String::Format("%s_proxy.c", FileName(infFullName).string()); +} + +void CClientProxyCodeEmitter::EmitCode() +{ + if (isCallbackInterface()) { + EmitCbProxyHeaderFile(); + } + EmitProxySourceFile(); +} + +void CClientProxyCodeEmitter::EmitCbProxyHeaderFile() +{ + String filePath = String::Format("%s%s.h", directory_.string(), FileName(proxyName_).string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("CClientProxyCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, proxyFullName_); + sb.Append("\n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitCbProxyMethodsDcl(sb); + sb.Append("\n"); + EmitTailExternC(sb); + sb.Append("\n"); + EmitTailMacro(sb, proxyFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CClientProxyCodeEmitter::EmitCbProxyMethodsDcl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s *%sProxyObtain(struct HdfRemoteService *remote);\n", + interfaceName_.string(), infName_.string()); + sb.Append("\n"); + sb.AppendFormat("void %sProxyRelease(struct %s *callback);\n", infName_.string(), interfaceName_.string()); +} + +void CClientProxyCodeEmitter::EmitProxySourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sclient/%s.c", directory_.string(), FileName(proxyName_).string()); + } else { + filePath = String::Format("%s%s.c", directory_.string(), FileName(proxyName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CClientProxyCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitProxyInclusions(sb); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitProxyCallMethodImpl(sb); + sb.Append("\n"); + EmitProxyMethodImpls(sb); + sb.Append("\n"); + EmitProxyConstruction(sb); + if (!isCallbackInterface()) { + sb.Append("\n"); + EmitProxyGetMethodImpl(sb); + sb.Append("\n"); + EmitProxyReleaseMethodImpl(sb); + } else { + sb.Append("\n"); + EmitCbProxyObtainMethodImpl(sb); + sb.Append("\n"); + EmitCbProxyReleaseMethodImpl(sb); + } + + sb.Append("\n"); + EmitTailExternC(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CClientProxyCodeEmitter::EmitProxyInclusions(StringBuilder& sb) +{ + if (!isCallbackInterface()) { + EmitProxyStdlibInclusions(sb); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + } else { + sb.AppendFormat("#include \"%s.h\"\n", FileName(proxyName_).string()); + EmitProxyStdlibInclusions(sb); + } +} + +void CClientProxyCodeEmitter::EmitProxyStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CClientProxyCodeEmitter::EmitProxyCallMethodImpl(StringBuilder& sb) +{ + sb.AppendFormat("static int32_t %sProxyCall(struct %s *self, int32_t id, struct HdfSBuf *data,\n", + infName_.string(), interfaceName_.string()); + sb.Append(TAB).Append("struct HdfSBuf *reply)\n"); + sb.Append("{\n"); + sb.Append(TAB).Append("if (self->remote == NULL\n"); + sb.Append(TAB).Append(TAB).Append("|| self->remote->dispatcher == NULL\n"); + sb.Append(TAB).Append(TAB).Append("|| self->remote->dispatcher->Dispatch == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: obj is null\", __func__);\n"); + sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_OBJECT;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append(TAB).Append("return self->remote->dispatcher->Dispatch(self->remote, id, data, reply);\n"); + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder& sb) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitProxyMethodImpl(method, sb); + if (i + 1 != interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb) +{ + if (method->GetParameterNumber() == 0) { + sb.AppendFormat("static int32_t %sProxy%s(struct %s *self)\n", + infName_.string(), method->GetName().string(), interfaceName_.string()); + } else { + StringBuilder paramStr; + paramStr.AppendFormat("static int32_t %sProxy%s(", infName_.string(), method->GetName().string()); + paramStr.AppendFormat("struct %s *self, ", interfaceName_.string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(")"); + sb.Append(SpecificationParam(paramStr, TAB)); + sb.Append("\n"); + } + EmitProxyMethodBody(method, sb, ""); +} + +void CClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("int32_t ec = HDF_FAILURE;\n"); + sb.Append("\n"); + + sb.Append(prefix + TAB).Append("struct HdfSBuf *data = HdfSBufTypedObtain(SBUF_IPC);\n"); + sb.Append(prefix + TAB).Append("struct HdfSBuf *reply = HdfSBufTypedObtain(SBUF_IPC);\n"); + sb.Append("\n"); + + sb.Append(prefix + TAB).Append("if (data == NULL || reply == NULL) {\n"); + sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: HdfSubf malloc failed!\", __func__);\n"); + sb.Append(prefix + TAB + TAB).Append("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB + TAB).Append("goto finished;\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("\n"); + + String gotoName = GetGotLabel(method); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_IN) { + EmitWriteProxyMethodParameter(param, "data", gotoName, sb, prefix + TAB); + sb.Append("\n"); + } + } + + sb.Append(prefix + TAB).AppendFormat("ec = %sCall(self, CMD_%s, data, reply);\n", + proxyName_.string(), ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB).Append("if (ec != HDF_SUCCESS) {\n"); + sb.Append(prefix + TAB + TAB).Append( + "HDF_LOGE(\"%{public}s: call failed! error code is %{public}d\", __func__, ec);\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", gotoName.string()); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("\n"); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_OUT) { + EmitReadProxyMethodParameter(param, "reply", gotoName, sb, prefix + TAB); + sb.Append("\n"); + } + } + + EmitErrorHandle(method, sb, prefix); + + sb.Append(prefix).Append("finished:\n"); + sb.Append(prefix + TAB).Append("if (data != NULL) {\n"); + sb.Append(prefix + TAB + TAB).Append("HdfSBufRecycle(data);\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("if (reply != NULL) {\n"); + sb.Append(prefix + TAB + TAB).Append("HdfSBufRecycle(reply);\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("return ec;\n"); + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitWriteProxyMethodParameter(const AutoPtr& param, + const String& parcelName, const String& gotoLabel, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + type->EmitCProxyWriteVar(parcelName, param->GetName(), gotoLabel, sb, prefix); +} + +void CClientProxyCodeEmitter::EmitReadProxyMethodParameter(const AutoPtr& param, + const String& parcelName, const String& gotoLabel, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + if (type->GetTypeKind() == TypeKind::TYPE_STRING) { + String cloneName = String::Format("%sCopy", param->GetName().string()); + type->EmitCProxyReadVar(parcelName, cloneName, false, gotoLabel, sb, prefix); + String leftVar = String::Format("*%s", param->GetName().string()); + sb.Append(prefix).AppendFormat("%s = strdup(%s);\n", leftVar.string(), cloneName.string()); + } else if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String name = String::Format("*%s", param->GetName().string()); + sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemAlloc(sizeof(%s));\n", + name.string(), type->EmitCType().string(), type->EmitCType().string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + type->EmitCProxyReadVar(parcelName, name, false, gotoLabel, sb, prefix); + } else if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + String cpName = String::Format("%sCp", param->GetName().string()); + type->EmitCProxyReadVar(parcelName, cpName, false, gotoLabel, sb, prefix); + sb.Append(prefix).AppendFormat("*%s = (%s*)OsalMemAlloc(sizeof(%s));\n", + param->GetName().string(), type->EmitCType().string(), type->EmitCType().string()); + sb.Append(prefix).AppendFormat("if (*%s == NULL) {\n", param->GetName().string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.string()); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("(void)memcpy_s(*%s, sizeof(%s), %s, sizeof(%s));\n", + param->GetName().string(), type->EmitCType().string(), cpName.string(), type->EmitCType().string()); + } else { + type->EmitCProxyReadVar(parcelName, param->GetName(), false, gotoLabel, sb, prefix); + } +} + +String CClientProxyCodeEmitter::GetGotLabel(const AutoPtr& method) +{ + String labelName = "finished"; + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + AutoPtr paramType = param->GetType(); + if (param->GetAttribute() == ParamAttr::PARAM_OUT && + (paramType->GetTypeKind() == TypeKind::TYPE_STRING + || paramType->GetTypeKind() == TypeKind::TYPE_ARRAY + || paramType->GetTypeKind() == TypeKind::TYPE_LIST + || paramType->GetTypeKind() == TypeKind::TYPE_STRUCT + || paramType->GetTypeKind() == TypeKind::TYPE_UNION)) { + labelName = "errors"; + break; + } + } + + return labelName; +} + +void CClientProxyCodeEmitter::EmitErrorHandle(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + bool errorLabel = false; + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + AutoPtr paramType = param->GetType(); + if (param->GetAttribute() == ParamAttr::PARAM_OUT && + (paramType->GetTypeKind() == TypeKind::TYPE_STRING + || paramType->GetTypeKind() == TypeKind::TYPE_ARRAY + || paramType->GetTypeKind() == TypeKind::TYPE_LIST + || paramType->GetTypeKind() == TypeKind::TYPE_STRUCT + || paramType->GetTypeKind() == TypeKind::TYPE_UNION)) { + if (!errorLabel) { + sb.Append(prefix + TAB).Append("goto finished;\n"); + sb.Append("\n"); + sb.Append(prefix).Append("errors:\n"); + errorLabel = true; + } + + EmitError(paramType, param->GetName(), sb, prefix + TAB); + sb.Append("\n"); + } + } +} + +void CClientProxyCodeEmitter::EmitError(const AutoPtr& type, const String& name, StringBuilder& sb, + const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: + case TypeKind::TYPE_UNION: { + sb.Append(prefix).AppendFormat("if (*%s != NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(*%s);\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("*%s = NULL;\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (*%s > 0 && *%s != NULL) {\n", lenName.string(), name.string()); + + AutoPtr arrayType = dynamic_cast(type.Get()); + AutoPtr elementType = arrayType->GetElementType(); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < *%s; i++) {\n", lenName.string()); + String elementName = String::Format("(*%s)[i]", name.string()); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else { + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(&%s, false);\n", + elementType->GetName().string(), elementName.string()); + } + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(*%s);\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("*%s = NULL;\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_LIST: { + String lenName = String::Format("%sLen", name.string()); + sb.Append(prefix).AppendFormat("if (*%s > 0 && *%s != NULL) {\n", lenName.string(), name.string()); + + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < *%s; i++) {\n", lenName.string()); + String elementName = String::Format("(*%s)[i]", name.string()); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else { + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(&%s, false);\n", + elementType->GetName().string(), elementName.string()); + } + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(*%s);\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("*%s = NULL;\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + sb.Append(prefix).AppendFormat("if (*%s != NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("%sFree(*%s, true);\n", type->GetName().string(), name.string()); + sb.Append(prefix + TAB).AppendFormat("*%s = NULL;\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + default: + break; + } +} + + +void CClientProxyCodeEmitter::EmitProxyConstruction(StringBuilder& sb) +{ + String objName; + if (!isCallbackInterface()) { + objName = "inst"; + sb.AppendFormat("static void %sConstruct(struct %s *%s)\n", + infName_.string(), interfaceName_.string(), objName.string()); + } else { + objName = "callback"; + sb.AppendFormat("static void %sProxyConstruct(struct %s *%s)\n", + infName_.string(), interfaceName_.string(), objName.string()); + } + sb.Append("{\n"); + + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + ASTMethod* method = interface_->GetMethod(i); + sb.Append(TAB).AppendFormat("%s->%s = %sProxy%s;\n", + objName.string(), method->GetName().string(), infName_.string(), method->GetName().string()); + } + + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitProxyGetMethodImpl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s *Hdi%sGet()\n", interfaceName_.string(), infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).Append("struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();\n"); + sb.Append(TAB).Append("if (serviceMgr == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: HDIServiceManager not found!\", __func__);\n"); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + + sb.Append(TAB).Append("struct HdfRemoteService *remote = "); + sb.AppendFormat("serviceMgr->GetService(serviceMgr, \"%sService\");\n", infName_.string()); + sb.Append(TAB).Append("HDIServiceManagerRelease(serviceMgr);\n"); + sb.Append(TAB).Append("if (remote == NULL) {\n"); + sb.Append(TAB).Append(TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: %sService not found!\", __func__);\n", infName_.string()); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + + sb.Append(TAB).AppendFormat("struct %s *%sClient = (struct %s *)OsalMemAlloc(sizeof(struct %s));\n", + interfaceName_.string(), infName_.string(), interfaceName_.string(), interfaceName_.string()); + sb.Append(TAB).AppendFormat("if (%sClient == NULL) {\n", infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: malloc %s instance failed!\", __func__);\n", interfaceName_.string()); + sb.Append(TAB).Append(TAB).Append("HdfRemoteServiceRecycle(remote);\n"); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + + sb.Append(TAB).AppendFormat("%sClient->remote = remote;\n", infName_.string()); + sb.Append(TAB).AppendFormat("%sConstruct(%sClient);\n", infName_.string(), infName_.string()); + sb.Append(TAB).AppendFormat("return %sClient;\n", infName_.string()); + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitProxyReleaseMethodImpl(StringBuilder& sb) +{ + sb.AppendFormat("void Hdi%sRelease(struct %s *instance)\n", infName_.string(), interfaceName_.string()); + sb.Append("{\n"); + sb.Append(TAB).Append("if (instance == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("return;\n"); + sb.Append(TAB).Append("}\n"); + + sb.Append(TAB).Append("HdfRemoteServiceRecycle(instance->remote);\n"); + sb.Append(TAB).Append("OsalMemFree(instance);\n"); + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitCbProxyObtainMethodImpl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s *%sProxyObtain(struct HdfRemoteService *remote)\n", + interfaceName_.string(), infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct %s *callback = (struct %s*)OsalMemAlloc(sizeof(struct %s));\n", + interfaceName_.string(), interfaceName_.string(), interfaceName_.string()); + sb.Append(TAB).Append("if (callback == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: OsalMemAlloc failed!\", __func__);\n"); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n\n"); + sb.Append(TAB).Append("callback->remote = remote;\n"); + sb.Append(TAB).AppendFormat("%sProxyConstruct(callback);\n", infName_.string()); + sb.Append(TAB).Append("return callback;\n"); + sb.Append("}\n"); +} + +void CClientProxyCodeEmitter::EmitCbProxyReleaseMethodImpl(StringBuilder& sb) +{ + sb.AppendFormat("void %sProxyRelease(struct %s *callback)\n", infName_.string(), interfaceName_.string()); + sb.Append("{\n"); + sb.Append(TAB).Append("if (callback == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("return;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append(TAB).Append("OsalMemFree(callback);\n"); + sb.Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_client_proxy_code_emitter.h b/tools/hdi-gen/codegen/c_client_proxy_code_emitter.h new file mode 100755 index 000000000..8594cfc20 --- /dev/null +++ b/tools/hdi-gen/codegen/c_client_proxy_code_emitter.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_CLIENT_PROXY_CODE_EMITTER_H +#define OHOS_HDI_C_CLIENT_PROXY_CODE_EMITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CClientProxyCodeEmitter : public CCodeEmitter { +public: + CClientProxyCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CClientProxyCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitCbProxyHeaderFile(); + + void EmitProxySourceFile(); + + void EmitCbProxyMethodsDcl(StringBuilder& sb); + + void EmitProxyInclusions(StringBuilder& sb); + + void EmitProxyStdlibInclusions(StringBuilder& sb); + + void EmitProxyCallMethodImpl(StringBuilder& sb); + + void EmitProxyMethodImpls(StringBuilder& sb); + + void EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb); + + void EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitWriteProxyMethodParameter(const AutoPtr& param, const String& parcelName, + const String& gotoLabel, StringBuilder& sb, const String& prefix); + + void EmitReadProxyMethodParameter(const AutoPtr& param, const String& parcelName, + const String& gotoLabel, StringBuilder& sb, const String& prefix); + + String GetGotLabel(const AutoPtr& method); + + void EmitErrorHandle(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitError(const AutoPtr& type, const String& name, StringBuilder& sb, const String& prefix); + + void EmitProxyConstruction(StringBuilder&); + + void EmitProxyGetMethodImpl(StringBuilder& sb); + + void EmitProxyReleaseMethodImpl(StringBuilder& sb); + + void EmitCbProxyObtainMethodImpl(StringBuilder& sb); + + void EmitCbProxyReleaseMethodImpl(StringBuilder& sb); + + std::vector freeObjStatements_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_CLIENT_PROXY_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_code_emitter.cpp b/tools/hdi-gen/codegen/c_code_emitter.cpp new file mode 100755 index 000000000..03c5edcd3 --- /dev/null +++ b/tools/hdi-gen/codegen/c_code_emitter.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_code_emitter.h" +#include +#include +#include + +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +const char* CCodeEmitter::TAB = " "; + +CCodeEmitter::CCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :LightRefCountBase(), ast_(ast), directory_(targetDirectory) +{ + if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) { + interface_ = ast_->GetInterfaceDef(); + } + + if (interface_ != nullptr) { + interfaceName_ = interface_->GetName(); + interfaceFullName_ = interface_->GetNamespace()->ToString() + interfaceName_; + infName_ = interfaceName_.StartsWith("I") ? interfaceName_.Substring(1) : interfaceName_; + proxyName_ = infName_ + "Proxy"; + proxyFullName_ = interface_->GetNamespace()->ToString() + proxyName_; + + stubName_ = infName_ + "Stub"; + stubFullName_ = interface_->GetNamespace()->ToString() + stubName_; + + ImplName_ = infName_ + "Service"; + ImplFullName_ = interface_->GetNamespace()->ToString() + ImplName_; + } else { + infName_ = ast_->GetName(); + } +} + +String CCodeEmitter::FileName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + StringBuilder sb; + + for (int i = 0; i < name.GetLength(); i++) { + char c = name[i]; + if (isupper(c) != 0) { + // 2->Index of the last char array. + if (i > 1 && name[i - 1] != '.' && name[i - 2] != '.') { + sb.Append('_'); + } + sb.Append(tolower(c)); + } else { + sb.Append(c); + } + } + + return sb.ToString().Replace('.', '/'); +} + +void CCodeEmitter::EmitInterfaceMethodCommands(StringBuilder& sb) +{ + sb.Append("enum {\n"); + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(TAB).AppendFormat("CMD_%s,\n", ConstantName(method->GetName()).string()); + } + sb.Append("};\n"); +} + +void CCodeEmitter::EmitInterfaceMethodParameter(const AutoPtr& parameter, StringBuilder& sb, + const String& prefix) +{ + AutoPtr type = parameter->GetType(); + sb.Append(prefix).Append(parameter->EmitCParameter()); +} + +void CCodeEmitter::EmitLicense(StringBuilder& sb) +{ + if (ast_->GetLicense().IsEmpty()) { + return; + } + sb.Append(ast_->GetLicense()).Append("\n\n"); +} + +void CCodeEmitter::EmitHeadMacro(StringBuilder& sb, const String& fullName) +{ + String macroName = MacroName(fullName); + sb.Append("#ifndef ").Append(macroName).Append("\n"); + sb.Append("#define ").Append(macroName).Append("\n"); +} + +void CCodeEmitter::EmitTailMacro(StringBuilder& sb, const String& fullName) +{ + String macroName = MacroName(fullName); + sb.Append("#endif // ").Append(macroName); +} + +void CCodeEmitter::EmitHeadExternC(StringBuilder& sb) +{ + sb.Append("#ifdef __cplusplus\n"); + sb.Append("extern \"C\" {\n"); + sb.Append("#endif /* __cplusplus */\n"); +} + +void CCodeEmitter::EmitTailExternC(StringBuilder& sb) +{ + sb.Append("#ifdef __cplusplus\n"); + sb.Append("}\n"); + sb.Append("#endif /* __cplusplus */\n"); +} + +String CCodeEmitter::MacroName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + String macro = name.Replace('.', '_').ToUpperCase() + "_H"; + return macro; +} + +String CCodeEmitter::ConstantName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + StringBuilder sb; + + for (int i = 0; i < name.GetLength(); i++) { + char c = name[i]; + if (isupper(c) != 0) { + if (i > 1) { + sb.Append('_'); + } + sb.Append(c); + } else { + sb.Append(toupper(c)); + } + } + + return sb.ToString(); +} + +String CCodeEmitter::SpecificationParam(StringBuilder& paramSb, const String& prefix) +{ + int maxLineLen = 120; + int replaceLen = 2; + String paramStr = paramSb.ToString(); + int preIndex = 0; + int curIndex = 0; + + String insertStr = String::Format("\n%s", prefix.string()); + for (; curIndex < paramStr.GetLength(); curIndex++) { + if (curIndex == maxLineLen && preIndex > 0) { + paramStr.Replace(preIndex, replaceLen, ","); + paramStr.insert(preIndex + 1, insertStr); + } else { + if (paramStr[curIndex] == ',') { + preIndex = curIndex; + } + } + } + return paramStr; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_code_emitter.h b/tools/hdi-gen/codegen/c_code_emitter.h new file mode 100755 index 000000000..a067ff799 --- /dev/null +++ b/tools/hdi-gen/codegen/c_code_emitter.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_CODE_EMITTER_H +#define OHOS_HDI_C_CODE_EMITTER_H + +#include +#include "ast/ast.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/string.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +class CCodeEmitter : public LightRefCountBase { +public: + CCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CCodeEmitter() = default; + + virtual void EmitCode() = 0; + + inline String GetSourceFile() + { + return sourceFileName_; + } + + inline bool isInvaildDir() + { + return directory_.Equals(""); + } + + static String FileName(const String& name); + +protected: + + void EmitInterfaceMethodCommands(StringBuilder& sb); + + void EmitInterfaceMethodParameter(const AutoPtr& parameter, StringBuilder& sb, const String& prefix); + + void EmitLicense(StringBuilder& sb); + + void EmitHeadMacro(StringBuilder& sb, const String& fullName); + + void EmitTailMacro(StringBuilder& sb, const String& fullName); + + void EmitHeadExternC(StringBuilder& sb); + + void EmitTailExternC(StringBuilder& sb); + + String MacroName(const String& name); + + String ConstantName(const String& name); + + bool isCallbackInterface() + { + if (interface_ == nullptr) { + return false; + } + + return interface_->IsCallback(); + } + + String SpecificationParam(StringBuilder& sb, const String& prefix); + + static const char* TAB; + + AutoPtr ast_; + AutoPtr interface_; + + String directory_; + String sourceFileName_; + + String interfaceName_; + String interfaceFullName_; + String infName_; + String proxyName_; + String proxyFullName_; + String stubName_; + String stubFullName_; + String ImplName_; + String ImplFullName_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_CODE_EMITTER_H diff --git a/tools/hdi-gen/codegen/c_code_generator.cpp b/tools/hdi-gen/codegen/c_code_generator.cpp new file mode 100755 index 000000000..2fadd06aa --- /dev/null +++ b/tools/hdi-gen/codegen/c_code_generator.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "c_code_generator.h" +#include +#include +#include +#include "codegen/c_client_interface_code_emitter.h" +#include "codegen/c_client_proxy_code_emitter.h" +#include "codegen/c_custom_types_code_emitter.h" +#include "codegen/c_service_driver_code_emitter.h" +#include "codegen/c_service_impl_code_emitter.h" +#include "codegen/c_service_interface_code_emitter.h" +#include "codegen/c_service_stub_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +const char* CCodeGenerator::TAG = "CCodeGenerator"; + +bool CCodeGenerator::Initializate(const AutoPtr& ast, const String& targetDirectory) +{ + ast_ = ast; + targetDirectory_ = targetDirectory; + + if (!ResolveDirectory()) { + return false; + } + + if (ast_->GetASTFileType() == ASTFileType::AST_TYPES) { + AutoPtr customTypesCodeEmitter = new CCustomTypesCodeEmitter(ast_, targetDirectory_); + emitters_.push_back(customTypesCodeEmitter); + return true; + } + + AutoPtr clientInterfaceCodeEmitter = new CClientInterfaceCodeEmitter(ast_, targetDirectory_); + AutoPtr clientProxyCodeEmitter = new CClientProxyCodeEmitter(ast_, targetDirectory_); + + AutoPtr serviceInterfaceCodeEmitter = new CServiceInterfaceCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceDriverCodeEmitter = new CServiceDriverCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceStubCodeEmitter = new CServiceStubCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceImplCodeEmitter = new CServiceImplCodeEmitter(ast_, targetDirectory_); + + emitters_.push_back(clientInterfaceCodeEmitter); + emitters_.push_back(clientProxyCodeEmitter); + emitters_.push_back(serviceInterfaceCodeEmitter); + emitters_.push_back(serviceDriverCodeEmitter); + emitters_.push_back(serviceStubCodeEmitter); + emitters_.push_back(serviceImplCodeEmitter); + + return true; +} + +bool CCodeGenerator::Generate() const +{ + for (auto emitter : emitters_) { + if (!emitter->isInvaildDir()) { + emitter->EmitCode(); + } + } + + return true; +} + +bool CCodeGenerator::ResolveDirectory() +{ + String packageFilePath = String::Format("%s/%s/", + targetDirectory_.string(), CCodeEmitter::FileName(ast_->GetPackageName()).string()); + targetDirectory_ = packageFilePath; + + if (!File::CreateParentDir(targetDirectory_)) { + Logger::E(TAG, "create '%s' directory failed!", targetDirectory_); + return false; + } + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_code_generator.h b/tools/hdi-gen/codegen/c_code_generator.h new file mode 100755 index 000000000..bfdd046de --- /dev/null +++ b/tools/hdi-gen/codegen/c_code_generator.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_CODE_GENERATOR_H +#define OHOS_HDI_C_CODE_GENERATOR_H + +#include "codegen/c_code_emitter.h" +#include "codegen/code_generator.h" + +namespace OHOS { +namespace HDI { +class CCodeGenerator : public CodeGenerator { +public: + CCodeGenerator() : CodeGenerator(), + emitters_() {} + + virtual ~CCodeGenerator() = default; + + bool Initializate(const AutoPtr& ast, const String& targetDirectory) override; + bool Generate() const override; +private: + bool ResolveDirectory() override; + + static const char* TAG; + std::vector> emitters_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_CODE_GENERATOR_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_custom_types_code_emitter.cpp b/tools/hdi-gen/codegen/c_custom_types_code_emitter.cpp new file mode 100755 index 000000000..4cecdd681 --- /dev/null +++ b/tools/hdi-gen/codegen/c_custom_types_code_emitter.cpp @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_custom_types_code_emitter.h" +#include "util/file.h" + +namespace OHOS { +namespace HDI { +void CCustomTypesCodeEmitter::EmitCode() +{ + EmitCustomTypesHeaderFile(); + EmitCustomTypesSourceFile(); +} + +void CCustomTypesCodeEmitter::EmitCustomTypesHeaderFile() +{ + String filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, infName_); + sb.Append("\n"); + EmitHeaderInclusions(sb); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitCustomTypeDecls(sb); + sb.Append("\n"); + EmitCustomTypeFuncDecl(sb); + sb.Append("\n"); + EmitTailExternC(sb); + sb.Append("\n"); + EmitTailMacro(sb, infName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CCustomTypesCodeEmitter::EmitHeaderInclusions(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append("#include \n"); + break; + } + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + EmitCustomTypeDecl(sb, type); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeDecl(StringBuilder& sb, const AutoPtr& type) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_ENUM: { + AutoPtr enumType = dynamic_cast(type.Get()); + sb.Append(enumType->EmitCTypeDecl()).Append("\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + AutoPtr structType = dynamic_cast(type.Get()); + sb.Append(structType->EmitCTypeDecl()).Append("\n"); + break; + } + case TypeKind::TYPE_UNION: { + AutoPtr unionType = dynamic_cast(type.Get()); + sb.Append(unionType->EmitCTypeDecl()).Append("\n"); + break; + } + default: + break; + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + AutoPtr structType = dynamic_cast(type.Get()); + EmitCustomTypeMarshallingDecl(sb, structType); + sb.Append("\n"); + EmitCustomTypeUnmarshallingDecl(sb, structType); + sb.Append("\n"); + EmitCustomTypeFreeDecl(sb, structType); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeMarshallingDecl(StringBuilder& sb, + const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("bool %sBlockMarshalling(struct HdfSBuf *data, const %s *%s);\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); +} + +void CCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingDecl(StringBuilder& sb, + const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("bool %sBlockUnmarshalling(struct HdfSBuf *data, %s *%s);\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); +} + +void CCustomTypesCodeEmitter::EmitCustomTypeFreeDecl(StringBuilder& sb, + const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("void %sFree(%s *%s, bool freeSelf);\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); +} + +void CCustomTypesCodeEmitter::EmitCustomTypesSourceFile() +{ + String filePath = String::Format("%s%s.c", directory_.string(), FileName(infName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitSoucreIncludsions(sb); + sb.Append("\n"); + EmitCustomTypeDataProcess(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CCustomTypesCodeEmitter::EmitSoucreIncludsions(StringBuilder& sb) +{ + sb.AppendFormat("#include \"%s.h\"\n", FileName(infName_).string()); + EmitSourceStdlibInclusions(sb); +} + +void CCustomTypesCodeEmitter::EmitSourceStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT + || type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + AutoPtr structType = dynamic_cast(type.Get()); + EmitCustomTypeMarshallingImpl(sb, structType); + sb.Append("\n"); + EmitCustomTypeUnmarshallingImpl(sb, structType); + sb.Append("\n"); + EmitCustomTypeFreeImpl(sb, structType); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("bool %sBlockMarshalling(struct HdfSBuf *data, const %s *%s)\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); + sb.Append("{\n"); + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + String memberName = type->GetMemberName(i); + AutoPtr memberType = type->GetMemberType(i); + String name = String::Format("%s->%s", objName.string(), memberName.string()); + memberType->EmitCMarshalling(name, sb, TAB); + sb.Append("\n"); + } + + sb.Append(TAB).Append("return true;\n"); + sb.Append("}\n"); +} + +void CCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + freeObjStatements_.clear(); + + sb.AppendFormat("bool %sBlockUnmarshalling(struct HdfSBuf *data, %s *%s)\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); + sb.Append("{\n"); + + sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.string()); + sb.Append(TAB).Append(TAB).Append("return false;\n"); + sb.Append(TAB).Append("}\n"); + + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + AutoPtr memberType = type->GetMemberType(i); + String memberName = type->GetMemberName(i); + String name = String::Format("%s->%s", objName.string(), memberName.string()); + + if (memberType->GetTypeKind() == TypeKind::TYPE_STRING) { + String tmpName = String::Format("%sCp", memberName.string()); + memberType->EmitCUnMarshalling(tmpName, sb, TAB, freeObjStatements_); + sb.Append(TAB).AppendFormat("%s = strdup(%s);\n", name.string(), tmpName.string()); + sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", name.string()); + sb.Append(TAB).Append(TAB).Append("goto errors;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + } else if (memberType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + String paramName = String::Format("&%s", name.string()); + memberType->EmitCUnMarshalling(paramName, sb, TAB, freeObjStatements_); + sb.Append("\n"); + } else if (memberType->GetTypeKind() == TypeKind::TYPE_UNION) { + String tmpName = String::Format("%sCp", memberName.string()); + memberType->EmitCUnMarshalling(tmpName, sb, TAB, freeObjStatements_); + sb.Append(TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", + name.string(), memberType->EmitCType().string(), + tmpName.string(), memberType->EmitCType().string()); + sb.Append("\n"); + } else if (memberType->GetTypeKind() == TypeKind::TYPE_ARRAY) { + String tmpName = String::Format("%sCp", memberName.string()); + AutoPtr arrayType = dynamic_cast(memberType.Get()); + AutoPtr elementType = arrayType->GetElementType(); + sb.Append(TAB).AppendFormat("%s* %s = NULL;\n", elementType->EmitCType().string(), tmpName.string()); + sb.Append(TAB).AppendFormat("uint32_t %sLen = 0;\n", tmpName.string()); + memberType->EmitCUnMarshalling(tmpName, sb, TAB, freeObjStatements_); + sb.Append(TAB).AppendFormat("%s = %s;\n", name.string(), tmpName.string()); + sb.Append(TAB).AppendFormat("%sLen = %sLen;\n", name.string(), tmpName.string()); + sb.Append("\n"); + } else if (memberType->GetTypeKind() == TypeKind::TYPE_LIST) { + String tmpName = String::Format("%sCp", memberName.string()); + AutoPtr listType = dynamic_cast(memberType.Get()); + AutoPtr elementType = listType->GetElementType(); + sb.Append(TAB).AppendFormat("%s* %s = NULL;\n", elementType->EmitCType().string(), tmpName.string()); + sb.Append(TAB).AppendFormat("uint32_t %sLen = 0;\n", tmpName.string()); + memberType->EmitCUnMarshalling(tmpName, sb, TAB, freeObjStatements_); + sb.Append(TAB).AppendFormat("%s = %s;\n", name.string(), tmpName.string()); + sb.Append(TAB).AppendFormat("%sLen = %sLen;\n", name.string(), tmpName.string()); + sb.Append("\n"); + } else { + memberType->EmitCUnMarshalling(name, sb, TAB, freeObjStatements_); + sb.Append("\n"); + } + } + + sb.Append(TAB).AppendFormat("return true;\n"); + sb.Append("errors:\n"); + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + AutoPtr memberType = type->GetMemberType(i); + String memberName = type->GetMemberName(i); + String name = String::Format("%s->%s", objName.string(), memberName.string()); + EmitError(name, memberType, sb, TAB); + } + + sb.Append(TAB).Append("return false;\n"); + sb.Append("}\n"); +} + + +void CCustomTypesCodeEmitter::EmitError(const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: { + sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + AutoPtr arrayType = dynamic_cast(type.Get()); + AutoPtr elementType = arrayType->GetElementType(); + String lenName = String::Format("%sLen", name.string()); + + sb.Append(prefix).AppendFormat("if (%s > 0 && %s != NULL) {\n", lenName.string(), name.string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + String elementName = String::Format("(%s)[i]", name.string()); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(&(%s), false);\n", + elementType->GetName().string(), elementName.string()); + } + + sb.Append(prefix + TAB).Append("}\n"); + } + + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + break; + } + case TypeKind::TYPE_LIST: { + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + String lenName = String::Format("%sLen", name.string()); + + sb.Append(prefix).AppendFormat("if (%s > 0 && %s != NULL) {\n", lenName.string(), name.string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + String elementName = String::Format("(%s)[i]", name.string()); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(&(%s), false);\n", + elementType->GetName().string(), elementName.string()); + } + + sb.Append(prefix + TAB).Append("}\n"); + } + + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + sb.Append(prefix).AppendFormat("%sFree(&%s, false);\n", type->GetName().string(), name.string()); + sb.Append(prefix).Append("\n"); + break; + } + default: + break; + } +} + +void CCustomTypesCodeEmitter::EmitCustomTypeFreeImpl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("void %sFree(%s *%s, bool freeSelf)\n", + type->GetName().string(), type->EmitCType().string(), objName.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.string()); + sb.Append(TAB).Append(TAB).Append("return;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + AutoPtr memberType = type->GetMemberType(i); + String memberName = type->GetMemberName(i); + String name = String::Format("%s->%s", objName.string(), memberName.string()); + EmitCustomTypeMemberFree(sb, name, memberType, TAB); + } + + sb.Append(TAB).Append("if (freeSelf) {\n"); + sb.Append(TAB).Append(TAB).Append("OsalMemFree(dataBlock);\n"); + sb.Append(TAB).Append("}\n"); + + sb.Append("}\n"); +} + +void CCustomTypesCodeEmitter::EmitCustomTypeMemberFree(StringBuilder& sb, const String& name, + const AutoPtr& type, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: { + sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", name.string()); + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + AutoPtr arrayType = dynamic_cast(type.Get()); + AutoPtr elementType = arrayType->GetElementType(); + + sb.Append(prefix).AppendFormat("if (%sLen > 0 && %s != NULL) {\n", name.string(), name.string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("OsalMemFree(%s[i]);\n", name.string()); + sb.Append(prefix + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(%s, false);\n", + elementType->GetName().string(), name.string()); + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + case TypeKind::TYPE_LIST: { + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + + sb.Append(prefix).AppendFormat("if (%sLen > 0 && %s != NULL) {\n", name.string(), name.string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("OsalMemFree(%s[i]);\n", name.string()); + sb.Append(prefix + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %sLen; i++) {\n", name.string()); + sb.Append(prefix + TAB + TAB).AppendFormat("%sFree(%s, false);\n", + elementType->GetName().string(), name.string()); + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", name.string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + sb.Append(prefix).AppendFormat("%sFree(&%s, false);\n\n", type->GetName().string(), name.string()); + break; + } + default: + break; + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_custom_types_code_emitter.h b/tools/hdi-gen/codegen/c_custom_types_code_emitter.h new file mode 100755 index 000000000..2473df8a1 --- /dev/null +++ b/tools/hdi-gen/codegen/c_custom_types_code_emitter.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_CUSTOM_TYPES_CODE_EMITTER_H +#define OHOS_HDI_C_CUSTOM_TYPES_CODE_EMITTER_H +#include +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CCustomTypesCodeEmitter : public CCodeEmitter { +public: + CCustomTypesCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CCodeEmitter(ast, targetDirectory) {} + + virtual ~CCustomTypesCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitCustomTypesHeaderFile(); + + void EmitHeaderInclusions(StringBuilder& sb); + + void EmitCustomTypeDecls(StringBuilder& sb); + + void EmitCustomTypeDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeFuncDecl(StringBuilder& sb); + + void EmitCustomTypeMarshallingDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeUnmarshallingDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeFreeDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypesSourceFile(); + + void EmitSoucreIncludsions(StringBuilder& sb); + + void EmitSourceStdlibInclusions(StringBuilder& sb); + + void EmitCustomTypeDataProcess(StringBuilder& sb); + + void EmitCustomTypeMarshallingImpl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeUnmarshallingImpl(StringBuilder& sb, const AutoPtr& type); + + void EmitError(const String& name, const AutoPtr& type, StringBuilder& sb, const String& prefix); + + void EmitCustomTypeFreeImpl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeMemberFree(StringBuilder& sb, const String& name, const AutoPtr& type, + const String& prefix); + + std::vector freeObjStatements_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_CUSTOM_TYPES_CODE_EMITTER_H diff --git a/tools/hdi-gen/codegen/c_service_driver_code_emitter.cpp b/tools/hdi-gen/codegen/c_service_driver_code_emitter.cpp new file mode 100755 index 000000000..d67c84584 --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_driver_code_emitter.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_service_driver_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CServiceDriverCodeEmitter::CServiceDriverCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CCodeEmitter(ast, targetDirectory) +{ + String infFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), infName_.string()); + sourceFileName_ = String::Format("%s_driver.c", FileName(infFullName).string()); +} + +void CServiceDriverCodeEmitter::EmitCode() +{ + // the callback interface have no driver file. + if (!isCallbackInterface()) { + EmitDriverSourceFile(); + } +} + +void CServiceDriverCodeEmitter::EmitDriverSourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.c", directory_.string(), FileName(infName_ + "Driver").string()); + } else { + filePath = String::Format("%s%s.c", directory_.string(), FileName(infName_ + "Driver").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceDriverCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitDriverIncluions(sb); + sb.Append("\n"); + EmitDriverServiceDecl(sb); + sb.Append("\n"); + EmitDriverDispatch(sb); + sb.Append("\n"); + EmitDriverInit(sb); + sb.Append("\n"); + EmitDriverBind(sb); + sb.Append("\n"); + EmitDriverRelease(sb); + sb.Append("\n"); + EmitDriverEntryDefinition(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceDriverCodeEmitter::EmitDriverIncluions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); +} + +void CServiceDriverCodeEmitter::EmitDriverServiceDecl(StringBuilder& sb) +{ + sb.AppendFormat("struct Hdf%sService {\n", infName_.string()); + sb.Append(TAB).AppendFormat("struct IDeviceIoService ioservice;\n"); + sb.Append(TAB).Append("void *instance;\n"); + sb.Append("};\n"); +} + +void CServiceDriverCodeEmitter::EmitDriverDispatch(StringBuilder& sb) +{ + sb.AppendFormat("static int32_t %sServiceDispatch(struct HdfDeviceIoClient *client, int cmdId,\n", + infName_.string()); + sb.Append(TAB).Append("struct HdfSBuf *data, struct HdfSBuf *reply)\n"); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct Hdf%sService *hdf%sService = CONTAINER_OF(\n", + infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("client->device->service, struct Hdf%sService, ioservice);\n", + infName_.string()); + sb.Append(TAB).AppendFormat("return %sServiceOnRemoteRequest(hdf%sService->instance, cmdId, data, reply);\n", + infName_.string(), infName_.string()); + sb.Append("}\n"); +} + +void CServiceDriverCodeEmitter::EmitDriverInit(StringBuilder& sb) +{ + sb.AppendFormat("int Hdf%sDriverInit(struct HdfDeviceObject *deviceObject)\n", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverInit enter, new hdi impl.\");\n", infName_.string()); + sb.Append(TAB).Append("return HDF_SUCCESS;\n"); + sb.Append("}\n"); +} + +void CServiceDriverCodeEmitter::EmitDriverBind(StringBuilder& sb) +{ + sb.AppendFormat("int Hdf%sDriverBind(struct HdfDeviceObject *deviceObject)\n", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverBind enter.\");\n", infName_.string()); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("struct Hdf%sService *hdf%sService = (struct Hdf%sService *)OsalMemAlloc(\n", + infName_.string(), infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("sizeof(struct Hdf%sService));\n", infName_.string()); + sb.Append(TAB).AppendFormat("if (hdf%sService == NULL) {\n", infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat( + "HDF_LOGE(\"Hdf%sDriverBind OsalMemAlloc Hdf%sService failed!\");\n", infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Dispatch = %sServiceDispatch;\n", + infName_.string(), infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Open = NULL;\n", infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Release = NULL;\n", infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->instance = Hdi%sInstance();\n", infName_.string(), infName_.string()); + sb.Append(TAB).AppendFormat("if (hdf%sService->instance == NULL) {\n", infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(hdf%sService);\n", infName_.string()); + sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("deviceObject->service = &hdf%sService->ioservice;\n", infName_.string()); + sb.Append(TAB).Append("return HDF_SUCCESS;\n"); + sb.Append("}\n"); +} + +void CServiceDriverCodeEmitter::EmitDriverRelease(StringBuilder& sb) +{ + sb.AppendFormat("void Hdf%sDriverRelease(struct HdfDeviceObject *deviceObject)\n", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct Hdf%sService *hdf%sService = CONTAINER_OF(\n", + infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("deviceObject->service, struct Hdf%sService, ioservice);\n", + infName_.string()); + sb.Append(TAB).AppendFormat("Hdi%sRelease(hdf%sService->instance);\n", infName_.string(), infName_.string()); + sb.Append(TAB).AppendFormat("OsalMemFree(hdf%sService);\n", infName_.string()); + sb.Append("}\n"); +} + +void CServiceDriverCodeEmitter::EmitDriverEntryDefinition(StringBuilder& sb) +{ + sb.AppendFormat("struct HdfDriverEntry g_%sDriverEntry = {\n", infName_.ToLowerCase().string()); + sb.Append(TAB).Append(".moduleVersion = 1,\n"); + sb.Append(TAB).Append(".moduleName = \"sample\", /* please change the moduleName */\n"); + sb.Append(TAB).AppendFormat(".Bind = Hdf%sDriverBind,\n", infName_.string()); + sb.Append(TAB).AppendFormat(".Init = Hdf%sDriverInit,\n", infName_.string()); + sb.Append(TAB).AppendFormat(".Release = Hdf%sDriverRelease,\n", infName_.string()); + sb.Append("};\n\n"); + sb.AppendFormat("HDF_INIT(g_%sDriverEntry);", infName_.ToLowerCase().string()); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_driver_code_emitter.h b/tools/hdi-gen/codegen/c_service_driver_code_emitter.h new file mode 100755 index 000000000..02a0aab74 --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_driver_code_emitter.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_SERVICE_DRIVER_CODE_EMITTER_H +#define OHOS_HDI_C_SERVICE_DRIVER_CODE_EMITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CServiceDriverCodeEmitter : public CCodeEmitter { +public: + + CServiceDriverCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CServiceDriverCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitDriverSourceFile(); + + void EmitDriverIncluions(StringBuilder& sb); + + void EmitDriverServiceDecl(StringBuilder& sb); + + void EmitDriverDispatch(StringBuilder& sb); + + void EmitDriverInit(StringBuilder& sb); + + void EmitDriverBind(StringBuilder& sb); + + void EmitDriverRelease(StringBuilder& sb); + + void EmitDriverEntryDefinition(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_SERVICE_DRIVER_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_impl_code_emitter.cpp b/tools/hdi-gen/codegen/c_service_impl_code_emitter.cpp new file mode 100755 index 000000000..ae876957a --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_impl_code_emitter.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_service_impl_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CServiceImplCodeEmitter::CServiceImplCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CCodeEmitter(ast, targetDirectory) +{ + String infFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), infName_.string()); + sourceFileName_ = String::Format("%s_service.c", FileName(infFullName).string()); +} + +void CServiceImplCodeEmitter::EmitCode() +{ + if (isCallbackInterface()) { + EmitServiceImplHeaderFile(); + } + EmitServiceImplSourceFile(); +} + +void CServiceImplCodeEmitter::EmitServiceImplHeaderFile() +{ + String filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_ + "Service").string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceDriverCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, ImplFullName_); + sb.Append("\n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitServiceImplConstructDecl(sb); + sb.Append("\n"); + EmitTailExternC(sb); + sb.Append("\n"); + EmitTailMacro(sb, ImplFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceImplCodeEmitter::EmitServiceImplConstructDecl(StringBuilder& sb) +{ + sb.AppendFormat("void %sServiceConstruct(struct %s* service);\n", infName_.string(), interfaceName_.string()); +} + +void CServiceImplCodeEmitter::EmitServiceImplSourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.c", directory_.string(), FileName(infName_ + "Service").string()); + } else { + filePath = String::Format("%s%s.c", directory_.string(), FileName(infName_ + "Service").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceDriverCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitServiceImplInclusions(sb); + sb.Append("\n"); + EmitServiceImplMethodImpls(sb, ""); + sb.Append("\n"); + EmitServiceImplConstruct(sb); + if (!isCallbackInterface()) { + sb.Append("\n"); + EmitServiceImplInstance(sb); + sb.Append("\n"); + EmitServiceImplRelease(sb); + } + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceImplCodeEmitter::EmitServiceImplInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); +} + +void CServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitServiceImplMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CServiceImplCodeEmitter::EmitServiceImplMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t %s%s(struct %s *self)\n", + infName_.string(), method->GetName().string(), interfaceName_.string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t %s%s(struct %s *self, ", + infName_.string(), method->GetName().string(), interfaceName_.string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(")"); + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } + + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n"); + sb.Append(prefix).Append("}\n"); +} + +void CServiceImplCodeEmitter::EmitServiceImplConstruct(StringBuilder& sb) +{ + String objName("instance"); + sb.AppendFormat("void %sServiceConstruct(struct %s *%s)\n", + infName_.string(), interfaceName_.string(), objName.string()); + sb.Append("{\n"); + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(TAB).AppendFormat("%s->%s = %s%s;\n", + objName.string(), method->GetName().string(), infName_.string(), method->GetName().string()); + } + sb.Append("}\n"); +} + +void CServiceImplCodeEmitter::EmitServiceImplInstance(StringBuilder& sb) +{ + String objName("instance"); + sb.AppendFormat("struct %s *Hdi%sInstance()\n", interfaceName_.string(), infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s*)OsalMemAlloc(sizeof(struct %s));\n", + interfaceName_.string(), objName.string(), interfaceName_.string(), interfaceName_.string()); + sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.string()); + sb.Append(TAB).Append(TAB).AppendFormat("HDF_LOGE(\"%%{public}s: OsalMemAlloc struct %s %s failed!\", __func__);\n", + interfaceName_.string(), objName.string()); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append(TAB).AppendFormat("%sServiceConstruct(%s);\n", infName_.string(), objName.string()); + sb.Append(TAB).AppendFormat("return %s;\n", objName.string()); + sb.Append("}\n"); +} + +void CServiceImplCodeEmitter::EmitServiceImplRelease(StringBuilder& sb) +{ + sb.AppendFormat("void Hdi%sRelease(struct %s *instance)\n", infName_.string(), interfaceName_.string()); + sb.Append("{\n"); + sb.Append(TAB).Append("if (instance == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("return;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append(TAB).Append("OsalMemFree(instance);\n"); + sb.Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_impl_code_emitter.h b/tools/hdi-gen/codegen/c_service_impl_code_emitter.h new file mode 100755 index 000000000..99cc5ca1a --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_impl_code_emitter.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_SERVICE_IMPL_CODE_EMITTER_H +#define OHOS_HDI_C_SERVICE_IMPL_CODE_EMITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CServiceImplCodeEmitter : public CCodeEmitter { +public: + CServiceImplCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CServiceImplCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitServiceImplHeaderFile(); + + void EmitServiceImplConstructDecl(StringBuilder& sb); + + void EmitServiceImplSourceFile(); + + void EmitServiceImplInclusions(StringBuilder& sb); + + void EmitServiceImplMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitServiceImplMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitServiceImplConstruct(StringBuilder& sb); + + void EmitServiceImplInstance(StringBuilder& sb); + + void EmitServiceImplRelease(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_SERVICE_IMPL_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_interface_code_emitter.cpp b/tools/hdi-gen/codegen/c_service_interface_code_emitter.cpp new file mode 100755 index 000000000..a38821b7d --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_interface_code_emitter.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_service_interface_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void CServiceInterfaceCodeEmitter::EmitCode() +{ + if (!isCallbackInterface()) { + EmitInterfaceHeadrFile(); + } +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceHeadrFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.h", directory_.string(), FileName(interfaceName_).string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(interfaceName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, interfaceFullName_); + sb.Append("\n"); + EmitImportInclusions(sb); + sb.Append("\n"); + EmitInterfaceDataDecls(sb); + sb.Append("\n"); + EmitInterfaceMethodCommands(sb); + sb.Append("\n"); + EmitInterfaceDefinition(sb); + sb.Append("\n"); + EmitTailMacro(sb, interfaceFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceInterfaceCodeEmitter::EmitImportInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + for (const auto& importPair : ast_->GetImports()) { + AutoPtr importAst = importPair.second; + + String fileName; + if (importAst->GetASTFileType() == ASTFileType::AST_ICALLBACK && importAst->GetInterfaceDef() != nullptr) { + String ifaceName = importAst->GetInterfaceDef()->GetName(); + String name = ifaceName.StartsWith("I") ? ifaceName.Substring(1) : ifaceName; + String stubName = name + "Proxy"; + fileName = FileName(importAst->GetInterfaceDef()->GetNamespace()->ToString() + stubName); + } else { + fileName = FileName(importAst->GetFullName()); + } + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceDataDecls(StringBuilder& sb) +{ + sb.Append("struct HdfSBuf;\n"); + sb.Append("struct HdfDeviceObject;\n"); + sb.Append("struct HdfDeviceIoClient;\n"); +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder& sb) +{ + sb.AppendFormat("struct %s {\n", interfaceName_.string()); + EmitInterfaceMethods(sb, TAB); + sb.Append("};\n\n"); + EmitInterfaceInstanceMethodDecl(sb); + sb.Append("\n"); + EmitInterfaceReleaseMethodDecl(sb); + sb.Append("\n"); + EmitInterfaceRequestMethodDecl(sb); +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceMethods(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitInterfaceMethod(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t (*%s)(struct %s *self);\n", + method->GetName().string(), interfaceName_.string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t (*%s)(struct %s *self, ", + method->GetName().string(), interfaceName_.string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(");"); + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceInstanceMethodDecl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s *Hdi%sInstance();\n", interfaceName_.string(), infName_.string()); +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceReleaseMethodDecl(StringBuilder& sb) +{ + sb.AppendFormat("void Hdi%sRelease(struct %s *instance);\n", + infName_.string(), interfaceName_.string()); +} + +void CServiceInterfaceCodeEmitter::EmitInterfaceRequestMethodDecl(StringBuilder& sb) +{ + sb.AppendFormat("int32_t %sServiceOnRemoteRequest(void *service, int cmdId,\n", infName_.string()); + sb.Append(TAB).Append("struct HdfSBuf *data, struct HdfSBuf *reply);\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_interface_code_emitter.h b/tools/hdi-gen/codegen/c_service_interface_code_emitter.h new file mode 100755 index 000000000..b1b6f7a95 --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_interface_code_emitter.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_SERVICE_INTERFACE_CODEE_MITTER_H +#define OHOS_HDI_C_SERVICE_INTERFACE_CODEE_MITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CServiceInterfaceCodeEmitter : public CCodeEmitter { +public: + CServiceInterfaceCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CCodeEmitter(ast, targetDirectory) {} + + virtual ~CServiceInterfaceCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitInterfaceHeadrFile(); + + void EmitImportInclusions(StringBuilder& sb); + + void EmitInterfaceDataDecls(StringBuilder& sb); + + void EmitInterfaceDefinition(StringBuilder& sb); + + void EmitInterfaceMethods(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitInterfaceInstanceMethodDecl(StringBuilder& sb); + + void EmitInterfaceReleaseMethodDecl(StringBuilder& sb); + + void EmitInterfaceRequestMethodDecl(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_SERVICE_INTERFACE_CODEE_MITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_stub_code_emitter.cpp b/tools/hdi-gen/codegen/c_service_stub_code_emitter.cpp new file mode 100755 index 000000000..e4d7794aa --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_stub_code_emitter.cpp @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/c_service_stub_code_emitter.h" + +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CServiceStubCodeEmitter::CServiceStubCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CCodeEmitter(ast, targetDirectory) +{ + String infFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), infName_.string()); + sourceFileName_ = String::Format("%s_stub.c", FileName(infFullName).string()); +} + +void CServiceStubCodeEmitter::EmitCode() +{ + if (isCallbackInterface()) { + EmitCbServiceStubHeaderFile(); + } + EmitServiceStubSourceFile(); +} + +void CServiceStubCodeEmitter::EmitCbServiceStubHeaderFile() +{ + String filePath = String::Format("%s%s.h", directory_.string(), FileName(stubName_).string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceStubCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, stubFullName_); + sb.Append("\n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + sb.Append("\n"); + EmitHeadExternC(sb); + sb.Append("\n"); + EmitCbServiceStubMethodsDcl(sb); + sb.Append("\n"); + EmitTailExternC(sb); + sb.Append("\n"); + EmitTailMacro(sb, stubFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceStubCodeEmitter::EmitCbServiceStubMethodsDcl(StringBuilder& sb) +{ + sb.AppendFormat("struct %s* %sStubObtain();\n", interfaceName_.string(), infName_.string()); + sb.Append("\n"); + sb.AppendFormat("void %sStubRelease(struct %s *callback);\n", infName_.string(), interfaceName_.string()); +} + +void CServiceStubCodeEmitter::EmitServiceStubSourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.c", directory_.string(), FileName(stubName_).string()); + } else { + filePath = String::Format("%s%s.c", directory_.string(), FileName(stubName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CServiceStubCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitServiceStubInclusions(sb); + sb.Append("\n"); + EmitServiceStubMethodImpls(sb, ""); + sb.Append("\n"); + EmitServiceStubOnRequestMethodImpl(sb, ""); + if (isCallbackInterface()) { + sb.Append("\n"); + EmitCbStubDefinitions(sb); + sb.Append("\n"); + EmitCbStubObtainImpl(sb); + sb.Append("\n"); + EmitCbStubReleaseImpl(sb); + } + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CServiceStubCodeEmitter::EmitServiceStubInclusions(StringBuilder& sb) +{ + if (!isCallbackInterface()) { + EmitServiceStubStdlibInclusions(sb); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + } else { + sb.AppendFormat("#include \"%s.h\"\n", FileName(stubFullName_).string()); + EmitServiceStubStdlibInclusions(sb); + sb.Append("#include \n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(ImplName_).string()); + } +} + +void CServiceStubCodeEmitter::EmitServiceStubStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + + const AST::TypeStringMap& types = ast_->GetTypes(); + int i = 0; + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CServiceStubCodeEmitter::EmitServiceStubMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitServiceStubMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CServiceStubCodeEmitter::EmitServiceStubMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).AppendFormat( + "static int32_t SerStub%s(struct %s *serviceImpl, struct HdfSBuf *data, struct HdfSBuf *reply)\n", + method->GetName().string(), interfaceName_.string()); + sb.Append(prefix).Append("{\n"); + + sb.Append(prefix + TAB).Append("int32_t ec = HDF_FAILURE;\n"); + + if (method->GetParameterNumber() > 0) { + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitStubLocalVariable(param, sb, prefix + TAB); + } + + sb.Append("\n"); + for (int i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_IN) { + EmitReadStubMethodParameter(param, "data", sb, prefix + TAB); + sb.Append("\n"); + } + } + } + + if (method->GetParameterNumber() == 0) { + sb.Append(prefix + TAB).AppendFormat("ec = serviceImpl->%s(serviceImpl);\n", method->GetName().string()); + } else { + sb.Append(prefix + TAB).AppendFormat("ec = serviceImpl->%s(serviceImpl, ", method->GetName().string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitCallParameter(sb, param->GetType(), param->GetAttribute(), param->GetName()); + if (i + 1 < method->GetParameterNumber()) { + sb.Append(", "); + } + } + sb.AppendFormat(");\n", method->GetName().string()); + } + + sb.Append(prefix + TAB).Append("if (ec != HDF_SUCCESS) {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: call %s function failed!\", __func__);\n", method->GetName().string()); + sb.Append(prefix + TAB + TAB).Append("goto errors;\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("\n"); + + for (int i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_OUT) { + EmitWriteStubMethodParameter(param, "reply", sb, prefix + TAB); + sb.Append("\n"); + } + } + + sb.Append(prefix).Append("errors:\n"); + for (int i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitError(param, sb, prefix + TAB); + } + + sb.Append(prefix + TAB).Append("return ec;\n"); + sb.Append(prefix).Append("}\n"); +} + +void CServiceStubCodeEmitter::EmitStubLocalVariable(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + AutoPtr type = param->GetType(); + sb.Append(prefix).Append(param->EmitCLocalVar()).Append("\n"); + if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.Append(prefix).AppendFormat("uint32_t %sLen = 0;\n", param->GetName().string()); + } +} + +void CServiceStubCodeEmitter::EmitReadStubMethodParameter(const AutoPtr& param, + const String& parcelName, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + + if (type->GetTypeKind() == TypeKind::TYPE_STRING) { + String cloneName = String::Format("%sCp", param->GetName().string()); + type->EmitCStubReadVar(parcelName, cloneName, sb, prefix); + sb.Append(prefix).AppendFormat("%s = strdup(%s);\n", param->GetName().string(), cloneName.string()); + } else if (type->GetTypeKind() == TypeKind::TYPE_INTERFACE) { + type->EmitCStubReadVar(parcelName, param->GetName(), sb, prefix); + } else if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemAlloc(sizeof(%s));\n", param->GetName().string(), + type->EmitCType(TypeMode::NO_MODE).string(), type->EmitCType(TypeMode::NO_MODE).string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + type->EmitCStubReadVar(parcelName, param->GetName(), sb, prefix); + } else if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + String cpName = String::Format("%sCp", param->GetName().string()); + type->EmitCStubReadVar(parcelName, cpName, sb, prefix); + sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemAlloc(sizeof(%s));\n", param->GetName().string(), + type->EmitCType(TypeMode::NO_MODE).string(), type->EmitCType(TypeMode::NO_MODE).string()); + sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().string()); + sb.Append(prefix + TAB).Append("ec = HDF_ERR_MALLOC_FAIL;\n"); + sb.Append(prefix + TAB).Append("goto errors;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append(prefix).AppendFormat("(void)memcpy_s(%s, sizeof(%s), %s, sizeof(%s));\n", param->GetName().string(), + type->EmitCType(TypeMode::NO_MODE).string(), cpName.string(), type->EmitCType(TypeMode::NO_MODE).string()); + } else if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) { + type->EmitCStubReadVar(parcelName, param->GetName(), sb, prefix); + } else if (type->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR) { + type->EmitCStubReadVar(parcelName, param->GetName(), sb, prefix); + } else { + String name = String::Format("&%s", param->GetName().string()); + type->EmitCStubReadVar(parcelName, name, sb, prefix); + } +} + +void CServiceStubCodeEmitter::EmitWriteStubMethodParameter(const AutoPtr& param, + const String& parcelName, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + type->EmitCStubWriteVar(parcelName, param->GetName(), sb, prefix); +} + +void CServiceStubCodeEmitter::EmitCallParameter(StringBuilder& sb, const AutoPtr& type, ParamAttr attribute, + const String& name) +{ + if (attribute == ParamAttr::PARAM_OUT) { + sb.AppendFormat("&%s", name.string()); + if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.AppendFormat(", &%sLen", name.string()); + } + } else { + sb.AppendFormat("%s", name.string()); + if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.AppendFormat(", %sLen", name.string()); + } + } +} + + +void CServiceStubCodeEmitter::EmitError(const AutoPtr& param, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: + case TypeKind::TYPE_UNION: { + sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", param->GetName().string()); + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", param->GetName().string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + String lenName = String::Format("%sLen", param->GetName().string()); + sb.Append(prefix).AppendFormat("if (%s > 0 && %s != NULL) {\n", + lenName.string(), param->GetName().string()); + + AutoPtr arrayType = dynamic_cast(type.Get()); + AutoPtr elementType = arrayType->GetElementType(); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + String elementName = String::Format("%s[i]", param->GetName().string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("%sFree(&%s, false);\n", + elementType->GetName().string(), elementName.string()); + } + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", param->GetName().string()); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + break; + } + case TypeKind::TYPE_LIST: { + String lenName = String::Format("%sLen", param->GetName().string()); + sb.Append(prefix).AppendFormat("if (%s > 0 && %s != NULL) {\n", + lenName.string(), param->GetName().string()); + + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING + || elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB).AppendFormat("for (uint32_t i = 0; i < %s; i++) {\n", lenName.string()); + String elementName = String::Format("%s[i]", param->GetName().string()); + if (elementType->GetTypeKind() == TypeKind::TYPE_STRING) { + sb.Append(prefix + TAB + TAB).AppendFormat("if (%s != NULL) {\n", elementName.string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("OsalMemFree(%s);\n", elementName.string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + } else if (elementType->GetTypeKind() == TypeKind::TYPE_STRUCT) { + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("%sFree(&%s, false);\n", + elementType->GetName().string(), elementName.string()); + } + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).AppendFormat("OsalMemFree(%s);\n", param->GetName().string()); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", param->GetName().string()); + sb.Append(prefix + TAB).AppendFormat("%sFree(%s, true);\n", + type->GetName().string(), param->GetName().string()); + sb.Append(prefix).Append("}\n\n"); + break; + } + default: + break; + } +} + +void CServiceStubCodeEmitter::EmitServiceStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix) +{ + String codeName; + if (!isCallbackInterface()) { + codeName = "cmdId"; + sb.Append(prefix).AppendFormat("int32_t %sServiceOnRemoteRequest(void *service, int %s,\n", + infName_.string(), codeName.string()); + } else { + codeName = "code"; + sb.Append(prefix).AppendFormat("int32_t %sServiceOnRemoteRequest(struct HdfRemoteService *service, int %s,\n", + infName_.string(), codeName.string()); + } + sb.Append(prefix + TAB).Append("struct HdfSBuf *data, struct HdfSBuf *reply)\n"); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("struct %s *serviceImpl = (struct %s*)service;\n", + interfaceName_.string(), interfaceName_.string()); + sb.Append(prefix + TAB).AppendFormat("switch (%s) {\n", codeName.string()); + + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(prefix + TAB + TAB).AppendFormat("case CMD_%s:\n", ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("return SerStub%s(serviceImpl, data, reply);\n", + method->GetName().string()); + } + + sb.Append(prefix + TAB + TAB).Append("default: {\n"); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: not support cmd %%{public}d\", __func__, %s);\n", codeName.string()); + sb.Append(prefix + TAB + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("}\n"); +} + +void CServiceStubCodeEmitter::EmitCbStubDefinitions(StringBuilder& sb) +{ + sb.AppendFormat("struct %sStub {\n", infName_.string()); + sb.Append(TAB).AppendFormat("struct %s service;\n", interfaceName_.string()); + sb.Append(TAB).Append("struct HdfRemoteDispatcher dispatcher;\n"); + sb.Append("};\n"); +} + +void CServiceStubCodeEmitter::EmitCbStubObtainImpl(StringBuilder& sb) +{ + String stubTypeName = String::Format("%sStub", infName_.string()); + String objName = "stub"; + sb.AppendFormat("struct %s* %sStubObtain()\n", interfaceName_.string(), infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct %s* %s = (struct %s*)OsalMemAlloc(sizeof(struct %s));\n", + stubTypeName.string(), objName.string(), stubTypeName.string(), stubTypeName.string()); + sb.Append(TAB).AppendFormat("if (stub == NULL) {\n", objName.string()); + sb.Append(TAB).Append(TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: OsalMemAlloc %s obj failed!\", __func__);\n", stubTypeName.string()); + sb.Append(TAB).Append(TAB).AppendFormat("return NULL;\n"); + sb.Append(TAB).Append("}\n\n"); + sb.Append(TAB).AppendFormat("%s->dispatcher.Dispatch = %sServiceOnRemoteRequest;\n", + objName.string(), infName_.string()); + sb.Append(TAB).AppendFormat( + "%s->service.remote = HdfRemoteServiceObtain((struct HdfObject*)%s, &(%s->dispatcher));\n", + objName.string(), objName.string(), objName.string()); + sb.Append(TAB).AppendFormat("if (%s->service.remote == NULL) {\n", objName.string()); + sb.Append(TAB).Append(TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: %s->service.remote is null\", __func__);\n", objName.string()); + sb.Append(TAB).Append(TAB).Append("return NULL;\n"); + sb.Append(TAB).Append("}\n\n"); + sb.Append(TAB).AppendFormat("%sServiceConstruct(&%s->service);\n", infName_.string(), objName.string()); + sb.Append(TAB).AppendFormat("return &%s->service;\n", objName.string()); + sb.Append("}\n"); +} + +void CServiceStubCodeEmitter::EmitCbStubReleaseImpl(StringBuilder& sb) +{ + sb.AppendFormat("void %sStubRelease(struct %s *stub)\n", infName_.string(), interfaceName_.string()); + sb.Append("{\n"); + sb.Append(TAB).Append("if (stub == NULL) {\n"); + sb.Append(TAB).Append(TAB).Append("return;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append(TAB).Append("OsalMemFree(stub);\n"); + sb.Append("}"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/c_service_stub_code_emitter.h b/tools/hdi-gen/codegen/c_service_stub_code_emitter.h new file mode 100755 index 000000000..38bad234a --- /dev/null +++ b/tools/hdi-gen/codegen/c_service_stub_code_emitter.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_C_SERVICE_STUB_CODEE_MITTER_H +#define OHOS_HDI_C_SERVICE_STUB_CODEE_MITTER_H + +#include "codegen/c_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CServiceStubCodeEmitter : public CCodeEmitter { +public: + CServiceStubCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CServiceStubCodeEmitter() = default; + + void EmitCode() override; +private: + + void EmitCbServiceStubHeaderFile(); + + void EmitCbServiceStubMethodsDcl(StringBuilder& sb); + + void EmitServiceStubSourceFile(); + + void EmitServiceStubInclusions(StringBuilder& sb); + + void EmitServiceStubStdlibInclusions(StringBuilder& sb); + + void EmitServiceStubMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitServiceStubMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitStubLocalVariable(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + void EmitReadStubMethodParameter(const AutoPtr& param, const String& parcelName, StringBuilder& sb, + const String& prefix); + + void EmitReadStubVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitWriteStubMethodParameter(const AutoPtr& param, const String& parcelName, StringBuilder& sb, + const String& prefix); + + void EmitWriteStubVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitCallParameter(StringBuilder& sb, const AutoPtr& type, ParamAttr attribute, const String& name); + + void EmitError(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + void EmitServiceStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitCbStubDefinitions(StringBuilder& sb); + + void EmitCbStubObtainImpl(StringBuilder& sb); + + void EmitCbStubReleaseImpl(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_C_SERVICE_STUB_CODEE_MITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/code_generator.h b/tools/hdi-gen/codegen/code_generator.h new file mode 100755 index 000000000..da57088f2 --- /dev/null +++ b/tools/hdi-gen/codegen/code_generator.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CODEGENERATOR_H +#define OHOS_HDI_CODEGENERATOR_H + +#include "ast/ast.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class CodeGenerator : public LightRefCountBase { +public: + CodeGenerator() : LightRefCountBase(), + targetDirectory_(), + ast_(nullptr) {} + + virtual ~CodeGenerator() = default; + + virtual bool Initializate(const AutoPtr& ast, const String& targetDirectory) = 0; + + virtual bool Generate() const = 0; +protected: + virtual bool ResolveDirectory() = 0; + + String targetDirectory_; + AutoPtr ast_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CODEGENERATOR_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.cpp new file mode 100755 index 000000000..82f75824b --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_client_interface_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void CppClientInterfaceCodeEmitter::EmitCode() +{ + EmitInterfaceHeaderFile(); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sclient/%s.h", directory_.string(), FileName(interfaceName_).string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(interfaceName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppClientInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitClientInfHeadMacro(sb); + sb.Append("\n"); + EmitInterfaceInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitUsingNamespace(sb); + sb.Append("\n"); + EmitInterfaceMethodCommands(sb, ""); + sb.Append("\n"); + EmitInterfaceDecl(sb); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); + EmitClientInfTailMacro(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppClientInterfaceCodeEmitter::EmitClientInfHeadMacro(StringBuilder& sb) +{ + String clientMacroName(interfaceFullName_); + if (!isCallbackInterface()) { + clientMacroName += ".client"; + } + EmitHeadMacro(sb, clientMacroName); +} + +void CppClientInterfaceCodeEmitter::EmitClientInfTailMacro(StringBuilder& sb) +{ + String clientMacroName(interfaceFullName_); + if (!isCallbackInterface()) { + clientMacroName += ".client"; + } + EmitTailMacro(sb, clientMacroName); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceInclusions(StringBuilder& sb) +{ + EmitInterfaceStdlibInclusions(sb); + EmitInterfaceDBinderInclusions(sb); + EmitInterfaceSelfDefinedTypeInclusions(sb); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceStdlibInclusions(StringBuilder& sb) +{ + bool includeString = false; + bool includeList = false; + bool includeMap = false; + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: { + if (!includeString) { + sb.Append("#include \n"); + includeString = true; + } + break; + } + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: { + if (!includeList) { + sb.Append("#include \n"); + includeList = true; + } + break; + } + case TypeKind::TYPE_MAP: { + if (!includeMap) { + sb.Append("#include \n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceDBinderInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceSelfDefinedTypeInclusions(StringBuilder& sb) +{ + for (const auto& importPair : ast_->GetImports()) { + AutoPtr importAst = importPair.second; + + String fileName; + if (importAst->GetASTFileType() == ASTFileType::AST_ICALLBACK && importAst->GetInterfaceDef() != nullptr) { + String ifaceName = importAst->GetInterfaceDef()->GetName(); + String name = ifaceName.StartsWith("I") ? ifaceName.Substring(1) : ifaceName; + String stubName = name + "Service"; + fileName = FileName(importAst->GetInterfaceDef()->GetNamespace()->ToString() + stubName); + } else { + fileName = FileName(importAst->GetFullName()); + } + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceDecl(StringBuilder& sb) +{ + sb.AppendFormat("class %s : public IRemoteBroker {\n", interface_->GetName().string()); + sb.Append("public:\n"); + EmitInterfaceBody(sb, TAB); + sb.Append("};\n\n"); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceBody(StringBuilder& sb, const String& prefix) +{ + sb.Append(TAB).AppendFormat("DECLARE_INTERFACE_DESCRIPTOR(u\"%s\");\n", interfaceFullName_.string()); + sb.Append("\n"); + EmitInterfaceDestruction(sb, TAB); + sb.Append("\n"); + if (!isCallbackInterface()) { + EmitInterfaceGetMethodDecl(sb, TAB); + sb.Append("\n"); + } + EmitInterfaceMethodsDecl(sb, TAB); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceDestruction(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", interface_->GetName().string()); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceGetMethodDecl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("static sptr<%s> Get();\n", interface_->GetName().string()); +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceMethodsDecl(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitInterfaceMethodDecl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceMethodDecl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("virtual int32_t %s() = 0;\n", method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("virtual int32_t %s(", method->GetName().string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(") = 0;"); + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void CppClientInterfaceCodeEmitter::EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append(param->EmitCppParameter()); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.h b/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.h new file mode 100755 index 000000000..27e5662de --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_client_interface_code_emitter.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_CLIENT_INTERFACE_CODE_EMITTER_H +#define OHOS_HDI_CPP_CLIENT_INTERFACE_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppClientInterfaceCodeEmitter : public CppCodeEmitter { +public: + CppClientInterfaceCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CppCodeEmitter(ast, targetDirectory) {} + + virtual ~CppClientInterfaceCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitInterfaceHeaderFile(); + + void EmitClientInfHeadMacro(StringBuilder& sb); + + void EmitClientInfTailMacro(StringBuilder& sb); + + void EmitInterfaceInclusions(StringBuilder& sb); + + void EmitInterfaceStdlibInclusions(StringBuilder& sb); + + void EmitInterfaceDBinderInclusions(StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeInclusions(StringBuilder& sb); + + void EmitInterfaceDecl(StringBuilder& sb); + + void EmitInterfaceBody(StringBuilder& sb, const String& prefix); + + void EmitInterfaceDestruction(StringBuilder& sb, const String& prefix); + + void EmitInterfaceGetMethodDecl(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodsDecl(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodDecl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_CLIENT_INTERFACE_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.cpp new file mode 100755 index 000000000..5905a3510 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_client_proxy_code_emitter.h" +#include "util/file.h" + +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CppClientProxyCodeEmitter::CppClientProxyCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CppCodeEmitter(ast, targetDirectory) +{ + String proxyName = String::Format("%sclient.%s", + interface_->GetNamespace()->ToString().string(), proxyName_.string()); + sourceFileName_ = String::Format("%s.cpp", FileName(proxyName).string()); +} + +void CppClientProxyCodeEmitter::EmitCode() +{ + EmitProxyHeaderFile(); + EmitProxySourceFile(); +} + +void CppClientProxyCodeEmitter::EmitProxyHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sclient/%s.h", directory_.string(), FileName(infName_ + "Proxy").string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_ + "Proxy").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppClientProxyCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, proxyFullName_); + sb.Append("\n"); + EmitProxyHeadrInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitProxyDecl(sb, ""); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); + EmitTailMacro(sb, proxyFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppClientProxyCodeEmitter::EmitProxyHeadrInclusions(StringBuilder& sb) +{ + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + sb.Append("#include \n"); +} + +void CppClientProxyCodeEmitter::EmitProxyDecl(StringBuilder& sb, const String& prefix) +{ + sb.AppendFormat("class %s : public IRemoteProxy<%s> {\n", + proxyName_.string(), interfaceName_.string()); + sb.Append("public:\n"); + EmitProxyConstructor(sb, TAB); + sb.Append("\n"); + EmitProxyMethodDecls(sb, TAB); + sb.Append("\n"); + sb.Append("private:\n"); + EmitProxyConstants(sb, TAB); + sb.Append("};\n"); +} + +void CppClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("explicit %s(\n", proxyName_.string()); + sb.Append(prefix + TAB).Append("const sptr& remote)\n"); + sb.Append(prefix + TAB).AppendFormat(": IRemoteProxy<%s>(remote)\n", interfaceName_.string()); + sb.Append(prefix).Append("{}\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat("virtual ~%s() {}\n", proxyName_.string()); +} + +void CppClientProxyCodeEmitter::EmitProxyMethodDecls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitProxyMethodDecl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppClientProxyCodeEmitter::EmitProxyMethodDecl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().string()); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitProxyMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(") override;"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void CppClientProxyCodeEmitter::EmitProxyConstants(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("static inline BrokerDelegator<%s> delegator_;\n", proxyName_.string()); +} + +void CppClientProxyCodeEmitter::EmitProxyMethodParameter(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append(param->EmitCppParameter()); +} + +void CppClientProxyCodeEmitter::EmitProxySourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sclient/%s.cpp", directory_.string(), FileName(infName_ + "Proxy").string()); + } else { + filePath = String::Format("%s%s.cpp", directory_.string(), FileName(infName_ + "Proxy").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppClientProxyCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitProxySourceInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + if (!isCallbackInterface()) { + EmitGetMethodImpl(sb, ""); + sb.Append("\n"); + } + EmitProxyMethodImpls(sb, ""); + sb.Append("\n"); + EmitEndNamespace(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppClientProxyCodeEmitter::EmitProxySourceInclusions(StringBuilder& sb) +{ + sb.AppendFormat("#include \"%s.h\"\n", FileName(proxyName_).string()); + EmitProxySourceStdlibInclusions(sb); +} + +void CppClientProxyCodeEmitter::EmitProxySourceStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CppClientProxyCodeEmitter::EmitGetMethodImpl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("sptr<%s> %s::Get()\n", + interface_->GetName().string(), interface_->GetName().string()); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("do {\n"); + sb.Append(prefix + TAB + TAB).Append("using namespace OHOS::HDI::ServiceManager::V1_0;\n"); + sb.Append(prefix + TAB + TAB).Append("auto servMgr = IServiceManager::Get();\n"); + sb.Append(prefix + TAB + TAB).Append("if (servMgr == nullptr) {\n"); + sb.Append(prefix + TAB + TAB + TAB).Append("HDF_LOGE(\"%{public}s:get IServiceManager failed!\", __func__);\n"); + sb.Append(prefix + TAB + TAB + TAB).Append("break;\n"); + sb.Append(prefix + TAB + TAB).Append("}\n\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("sptr remote = servMgr->GetService(\"%sService\");\n", + infName_.string()); + sb.Append(prefix + TAB + TAB).Append("if (remote != nullptr) {\n"); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("return iface_cast<%s>(remote);\n", + interface_->GetName().string()); + sb.Append(prefix + TAB + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("} while(false);\n"); + sb.Append(prefix + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s: get %sService failed!\", __func__);\n", infName_.string()); + sb.Append(prefix + TAB).Append("return nullptr;\n"); + sb.Append(prefix).Append("}\n"); +} + + +void CppClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitProxyMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t %s::%s()\n", proxyName_.string(), method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t %s::%s(", proxyName_.string(), method->GetName().string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitProxyMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(")"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } + EmitProxyMethodBody(method, sb, prefix); +} + +void CppClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("MessageParcel data;\n"); + sb.Append(prefix + TAB).Append("MessageParcel reply;\n"); + sb.Append(prefix + TAB).Append("MessageOption option(MessageOption::TF_SYNC);\n"); + sb.Append("\n"); + + if (method->GetParameterNumber() > 0) { + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_IN) { + EmitWriteMethodParameter(param, "data", sb, prefix + TAB); + } + } + sb.Append("\n"); + } + + sb.Append(prefix + TAB).AppendFormat("int32_t ec = Remote()->SendRequest(CMD_%s, data, reply, option);\n", + ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB).Append("if (ec != HDF_SUCCESS) {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s failed, error code is %%d\", ec);\n", method->GetName().string()); + sb.Append(prefix + TAB + TAB).Append("return ec;\n"); + sb.Append(prefix + TAB).Append("}\n"); + + if (!method->IsOneWay()) { + sb.Append("\n"); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_OUT) { + EmitReadMethodParameter(param, "reply", false, sb, prefix + TAB); + sb.Append("\n"); + } + } + } + + sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n"); + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.h b/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.h new file mode 100755 index 000000000..9e97982e7 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_client_proxy_code_emitter.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_CLIENT_PROXY_CODE_EMITTER_H +#define OHOS_HDI_CPP_CLIENT_PROXY_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppClientProxyCodeEmitter : public CppCodeEmitter { +public: + CppClientProxyCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CppClientProxyCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitProxyHeaderFile(); + + void EmitProxyHeadrInclusions(StringBuilder& sb); + + void EmitProxyDecl(StringBuilder& sb, const String& prefix); + + void EmitProxyConstructor(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodDecls(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodDecl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitProxyConstants(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodParameter(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + void EmitProxySourceFile(); + + void EmitProxySourceInclusions(StringBuilder& sb); + + void EmitProxySourceStdlibInclusions(StringBuilder& sb); + + void EmitGetMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_CLIENT_PROXY_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_code_emitter.cpp new file mode 100755 index 000000000..9b79a26ca --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_code_emitter.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_code_emitter.h" +#include +#include +#include +#include + +namespace OHOS { +namespace HDI { +const char* CppCodeEmitter::TAB = " "; + +CppCodeEmitter::CppCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : LightRefCountBase(), ast_(ast), directory_(targetDirectory) +{ + if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) { + interface_ = ast_->GetInterfaceDef(); + } + + if (interface_ != nullptr) { + interfaceName_ = interface_->GetName(); + interfaceFullName_ = interface_->GetNamespace()->ToString() + interfaceName_; + infName_ = interfaceName_.StartsWith("I") ? interfaceName_.Substring(1) : interfaceName_; + proxyName_ = infName_ + "Proxy"; + proxyFullName_ = interface_->GetNamespace()->ToString() + proxyName_; + + stubName_ = infName_ + "Stub"; + stubFullName_ = interface_->GetNamespace()->ToString() + stubName_; + + ImplName_ = infName_ + "Service"; + ImplFullName_ = interface_->GetNamespace()->ToString() + ImplName_; + } else { + infName_ = ast_->GetName(); + } +} + +String CppCodeEmitter::FileName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + StringBuilder sb; + + for (int i = 0; i < name.GetLength(); i++) { + char c = name[i]; + if (isupper(c) != 0) { + // 2->Index of the last char array. + if (i > 1 && name[i - 1] != '.' && name[i - 2] != '.') { + sb.Append('_'); + } + sb.Append(tolower(c)); + } else { + sb.Append(c); + } + } + + return sb.ToString().Replace('.', '/'); +} + +void CppCodeEmitter::EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).Append("enum {\n"); + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(TAB).AppendFormat("CMD_%s,\n", ConstantName(method->GetName()).string()); + } + sb.Append(prefix).Append("};\n"); +} + +void CppCodeEmitter::EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).AppendFormat(param->EmitCppParameter()); +} + +void CppCodeEmitter::EmitLicense(StringBuilder& sb) +{ + if (ast_->GetLicense().IsEmpty()) { + return; + } + sb.Append(ast_->GetLicense()).Append("\n\n"); +} + +void CppCodeEmitter::EmitHeadMacro(StringBuilder& sb, const String& fullName) +{ + String macroName = MacroName(fullName); + sb.Append("#ifndef ").Append(macroName).Append("\n"); + sb.Append("#define ").Append(macroName).Append("\n"); +} + +void CppCodeEmitter::EmitTailMacro(StringBuilder& sb, const String& fullName) +{ + String macroName = MacroName(fullName); + sb.Append("#endif // ").Append(macroName).Append("\n\n"); +} + +void CppCodeEmitter::EmitBeginNamespace(StringBuilder& sb) +{ + String nspace = interface_->GetNamespace()->ToString(); + int index = nspace.IndexOf('.'); + while (index != -1) { + sb.AppendFormat("namespace %s {\n", nspace.Substring(0, index).string()); + nspace = nspace.Substring(index + 1); + index = nspace.IndexOf('.'); + } +} + +void CppCodeEmitter::EmitEndNamespace(StringBuilder& sb) +{ + String nspace = interface_->GetNamespace()->ToString(); + nspace = nspace.Substring(0, nspace.GetLength() - 1); + while (!nspace.IsEmpty()) { + int index = nspace.LastIndexOf('.'); + sb.AppendFormat("} // %s\n", + (index != -1) ? nspace.Substring(index + 1, nspace.GetLength()).string() : nspace.string()); + nspace = nspace.Substring(0, index); + } +} + +void CppCodeEmitter::EmitUsingNamespace(StringBuilder& sb) +{ + sb.Append("using namespace OHOS;\n"); + EmitImportUsingNamespace(sb); +} + +void CppCodeEmitter::EmitImportUsingNamespace(StringBuilder& sb) +{ + using StringSet = std::unordered_set; + StringSet namespaceSet; + String selfNameSpace = CppNameSpace(ast_->GetFullName()); + + for (const auto& importPair : ast_->GetImports()) { + AutoPtr import = importPair.second; + String nameSpace = CppNameSpace(import->GetFullName()); + if (nameSpace.Equals(selfNameSpace)) { + continue; + } + namespaceSet.emplace(nameSpace); + } + + for (const auto& nspace : namespaceSet) { + sb.Append("using namespace ").AppendFormat("%s;\n", nspace.string()); + } +} + +void CppCodeEmitter::EmitWriteMethodParameter(const AutoPtr& param, const String& parcelName, + StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + type->EmitCppWriteVar(parcelName, param->GetName(), sb, prefix); +} + +void CppCodeEmitter::EmitReadMethodParameter(const AutoPtr& param, const String& parcelName, + bool initVariable, StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + type->EmitCppReadVar(parcelName, param->GetName(), sb, prefix, initVariable); +} + +void CppCodeEmitter::EmitLocalVariable(const AutoPtr& param, StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).Append(param->EmitCppLocalVar()).Append("\n"); +} + +String CppCodeEmitter::MacroName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + String macro = name.Replace('.', '_').ToUpperCase() + "_H"; + return macro; +} + +String CppCodeEmitter::CppFullName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + return name.Replace(".", "::"); +} + +String CppCodeEmitter::ConstantName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + StringBuilder sb; + + for (int i = 0; i < name.GetLength(); i++) { + char c = name[i]; + if (isupper(c) != 0) { + if (i > 1) { + sb.Append('_'); + } + sb.Append(c); + } else { + sb.Append(toupper(c)); + } + } + + return sb.ToString(); +} + +String CppCodeEmitter::CppNameSpace(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + String space; + int lastIndex = name.LastIndexOf('.'); + if (lastIndex != -1) { + space = name.Substring(0, lastIndex); + } else { + space = name; + } + + return CppFullName(space); +} + +String CppCodeEmitter::SpecificationParam(StringBuilder& paramSb, const String& prefix) +{ + int maxLineLen = 120; + int replaceLen = 2; + String paramStr = paramSb.ToString(); + int preIndex = 0; + int curIndex = 0; + + String insertStr = String::Format("\n%s", prefix.string()); + for (; curIndex < paramStr.GetLength(); curIndex++) { + if (curIndex == maxLineLen && preIndex > 0) { + paramStr.Replace(preIndex, replaceLen, ","); + paramStr.insert(preIndex + 1, insertStr); + } else { + if (paramStr[curIndex] == ',') { + preIndex = curIndex; + } + } + } + return paramStr; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_code_emitter.h b/tools/hdi-gen/codegen/cpp_code_emitter.h new file mode 100755 index 000000000..a519a6def --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_code_emitter.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_CODE_EMITTER_H +#define OHOS_HDI_CPP_CODE_EMITTER_H + +#include "ast/ast.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/string.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +class CppCodeEmitter : public LightRefCountBase { +public: + CppCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CppCodeEmitter() = default; + + virtual void EmitCode() = 0; + + inline String GetSourceFile() + { + return sourceFileName_; + } + + inline bool isInvaildDir() + { + return directory_.Equals(""); + } + + static String FileName(const String& name); +protected: + + void EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + void EmitLicense(StringBuilder& sb); + + void EmitHeadMacro(StringBuilder& sb, const String& fullName); + + void EmitTailMacro(StringBuilder& sb, const String& fullName); + + virtual void EmitBeginNamespace(StringBuilder& sb); + + virtual void EmitEndNamespace(StringBuilder& sb); + + void EmitUsingNamespace(StringBuilder& sb); + + void EmitImportUsingNamespace(StringBuilder& sb); + + void EmitWriteMethodParameter(const AutoPtr& param, const String& parcelName, StringBuilder& sb, + const String& prefix); + + void EmitReadMethodParameter(const AutoPtr& param, const String& parcelName, bool initVariable, + StringBuilder& sb, const String& prefix); + + void EmitLocalVariable(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + String MacroName(const String& name); + + String CppFullName(const String& name); + + String ConstantName(const String& name); + + String CppNameSpace(const String& name); + + bool isCallbackInterface() + { + if (interface_ == nullptr) { + return false; + } + + return interface_->IsCallback(); + } + + String SpecificationParam(StringBuilder& sb, const String& prefix); + + static const char* TAB; + + AutoPtr ast_; + AutoPtr interface_; + + String directory_; + String sourceFileName_; + + String interfaceName_; + String interfaceFullName_; + String infName_; + String proxyName_; + String proxyFullName_; + String stubName_; + String stubFullName_; + String ImplName_; + String ImplFullName_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_code_generator.cpp b/tools/hdi-gen/codegen/cpp_code_generator.cpp new file mode 100755 index 000000000..01452799b --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_code_generator.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "cpp_code_generator.h" +#include +#include +#include +#include "codegen/cpp_client_interface_code_emitter.h" +#include "codegen/cpp_client_proxy_code_emitter.h" +#include "codegen/cpp_custom_types_code_emitter.h" +#include "codegen/cpp_service_driver_code_emitter.h" +#include "codegen/cpp_service_impl_code_emitter.h" +#include "codegen/cpp_service_interface_code_emitter.h" +#include "codegen/cpp_service_stub_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +const char* CppCodeGenerator::TAG = "CppCodeGenerator"; + +bool CppCodeGenerator::Initializate(const AutoPtr& ast, const String& targetDirectory) +{ + ast_ = ast; + targetDirectory_ = targetDirectory; + + if (!ResolveDirectory()) { + return false; + } + + if (ast_->GetASTFileType() == ASTFileType::AST_TYPES) { + AutoPtr customTypesCodeEmitter = new CppCustomTypesCodeEmitter(ast_, targetDirectory_); + emitters_.push_back(customTypesCodeEmitter); + return true; + } + + AutoPtr clientInterfaceCodeEmitter = new CppClientInterfaceCodeEmitter(ast_, targetDirectory_); + AutoPtr clientProxyCodeEmitter = new CppClientProxyCodeEmitter(ast_, targetDirectory_); + + AutoPtr serviceInterfaceCodeEmitter = new CppServiceInterfaceCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceDriverCodeEmitter = new CppServiceDriverCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceStubCodeEmitter = new CppServiceStubCodeEmitter(ast_, targetDirectory_); + AutoPtr serviceImplCodeEmitter = new CppServiceImplCodeEmitter(ast_, targetDirectory_); + + emitters_.push_back(clientInterfaceCodeEmitter); + emitters_.push_back(clientProxyCodeEmitter); + emitters_.push_back(serviceInterfaceCodeEmitter); + emitters_.push_back(serviceDriverCodeEmitter); + emitters_.push_back(serviceStubCodeEmitter); + emitters_.push_back(serviceImplCodeEmitter); + + return true; +} + +bool CppCodeGenerator::Generate() const +{ + for (auto emitter : emitters_) { + if (!emitter->isInvaildDir()) { + emitter->EmitCode(); + } + } + + return true; +} + +bool CppCodeGenerator::ResolveDirectory() +{ + String packageFilePath = String::Format("%s/%s/", + targetDirectory_.string(), CppCodeEmitter::FileName(ast_->GetPackageName()).string()); + targetDirectory_ = packageFilePath; + + if (!File::CreateParentDir(targetDirectory_)) { + Logger::E(TAG, "create '%s' directory failed!", targetDirectory_); + return false; + } + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_code_generator.h b/tools/hdi-gen/codegen/cpp_code_generator.h new file mode 100755 index 000000000..3a36abf3b --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_code_generator.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_CODE_GENERATOR_H +#define OHOS_HDI_CPP_CODE_GENERATOR_H + +#include "codegen/code_generator.h" +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppCodeGenerator : public CodeGenerator { +public: + CppCodeGenerator() : CodeGenerator(), + emitters_() {} + + ~CppCodeGenerator() override {}; + + bool Initializate(const AutoPtr& ast, const String& targetDirectory) override; + bool Generate() const override; +private: + bool ResolveDirectory() override; + + static const char* TAG; + std::vector> emitters_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_CODE_GENERATOR_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.cpp new file mode 100755 index 000000000..0ed77382b --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.cpp @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_custom_types_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void CppCustomTypesCodeEmitter::EmitCode() +{ + EmitCustomTypesHeaderFile(); + EmitCustomTypesSourceFile(); +} + +void CppCustomTypesCodeEmitter::EmitCustomTypesHeaderFile() +{ + String filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_).string()); + File file(filePath, File::WRITE); + String marcoName = String::Format("%s.%s", ast_->GetPackageName().string(), infName_.string()); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, marcoName); + sb.Append("\n"); + EmitHeaderFileInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitUsingNamespace(sb); + sb.Append("\n"); + EmitCustomTypeDecls(sb); + sb.Append("\n"); + EmitCustomTypeFuncDecl(sb); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); + EmitTailMacro(sb, marcoName); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppCustomTypesCodeEmitter::EmitHeaderFileInclusions(StringBuilder& sb) +{ + EmitCustomTypesStdlibInclusions(sb); + sb.Append("#include \n"); + EmitImportInclusions(sb); +} + +void CppCustomTypesCodeEmitter::EmitCustomTypesStdlibInclusions(StringBuilder& sb) +{ + bool includeString = false; + bool includeList = false; + bool includeMap = false; + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: { + if (!includeString) { + sb.Append("#include \n"); + includeString = true; + } + break; + } + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: { + if (!includeList) { + sb.Append("#include \n"); + includeList = true; + } + break; + } + case TypeKind::TYPE_MAP: { + if (!includeMap) { + sb.Append("#include \n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void CppCustomTypesCodeEmitter::EmitImportInclusions(StringBuilder& sb) +{ + for (const auto& importPair : ast_->GetImports()) { + AutoPtr importAst = importPair.second; + String fileName = FileName(importAst->GetFullName()); + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + EmitCustomTypeDecl(sb, type); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeDecl(StringBuilder& sb, const AutoPtr& type) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_ENUM: { + AutoPtr enumType = dynamic_cast(type.Get()); + sb.Append(enumType->EmitCppTypeDecl()).Append("\n"); + break; + } + case TypeKind::TYPE_STRUCT: { + AutoPtr structType = dynamic_cast(type.Get()); + sb.Append(structType->EmitCppTypeDecl()).Append("\n"); + break; + } + case TypeKind::TYPE_UNION: { + AutoPtr unionType = dynamic_cast(type.Get()); + sb.Append(unionType->EmitCppTypeDecl()).Append("\n"); + break; + } + default: + break; + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + AutoPtr structType = dynamic_cast(type.Get()); + EmitCustomTypeMarshallingDecl(sb, structType); + sb.Append("\n"); + EmitCustomTypeUnmarshallingDecl(sb, structType); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingDecl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel &data, const %s& %s);\n", + type->GetName().string(), type->EmitCppType().string(), objName.string()); +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingDecl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel &data, %s& %s);\n", + type->GetName().string(), type->EmitCppType().string(), objName.string()); +} + +void CppCustomTypesCodeEmitter::EmitCustomTypesSourceFile() +{ + String filePath = String::Format("%s%s.cpp", directory_.string(), FileName(infName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitSourceFileInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitCustomTypeDataProcess(sb); + sb.Append("\n"); + EmitEndNamespace(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppCustomTypesCodeEmitter::EmitSourceFileInclusions(StringBuilder& sb) +{ + sb.AppendFormat("#include \"%s.h\"\n", FileName(infName_).string()); + EmitSourceStdlibInclusions(sb); +} + +void CppCustomTypesCodeEmitter::EmitSourceStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT || type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder& sb) +{ + for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) { + AutoPtr type = ast_->GetTypeDefintion(i); + if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) { + AutoPtr structType = dynamic_cast(type.Get()); + EmitCustomTypeMarshallingImpl(sb, structType); + sb.Append("\n"); + EmitCustomTypeUnmarshallingImpl(sb, structType); + if (i + 1 < ast_->GetTypeDefinitionNumber()) { + sb.Append("\n"); + } + } + } +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + + sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel& data, const %s& %s)\n", + type->EmitCppType().string(), type->EmitCppType().string(), objName.string()); + sb.Append("{\n"); + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + AutoPtr memberType = type->GetMemberType(i); + String memberName = type->GetMemberName(i); + + String name = String::Format("%s.%s", objName.string(), memberName.string()); + memberType->EmitCppMarshalling("data", name, sb, TAB); + if (i + 1 < type->GetMemberNumber()) { + sb.Append("\n"); + } + } + + sb.Append(TAB).Append("return true;\n"); + sb.Append("}\n"); +} + +void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(StringBuilder& sb, const AutoPtr& type) +{ + String objName("dataBlock"); + + sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel& data, %s& %s)\n", + type->GetName().string(), type->EmitCppType().string(), objName.string()); + sb.Append("{\n"); + + for (size_t i = 0; i < type->GetMemberNumber(); i++) { + AutoPtr memberType = type->GetMemberType(i); + String memberName = type->GetMemberName(i); + String name = String::Format("%s.%s", objName.string(), memberName.string()); + + if (i > 0 && + (memberType->GetTypeKind() == TypeKind::TYPE_STRUCT + || memberType->GetTypeKind() == TypeKind::TYPE_UNION + || memberType->GetTypeKind() == TypeKind::TYPE_ARRAY + || memberType->GetTypeKind() == TypeKind::TYPE_LIST)) { + sb.Append("\n"); + } + + if (memberType->GetTypeKind() == TypeKind::TYPE_UNION) { + String cpName = String::Format("%sCp", memberName.string()); + memberType->EmitCppUnMarshalling("data", cpName, sb, TAB, false); + sb.Append(TAB).AppendFormat("(void)memcpy_s(&%s, sizeof(%s), %s, sizeof(%s));\n", name.string(), + memberType->EmitCppType().string(), cpName.string(), memberType->EmitCppType().string()); + } else { + memberType->EmitCppUnMarshalling("data", name, sb, TAB, false); + } + } + + sb.Append(TAB).AppendFormat("return true;\n", objName.string()); + sb.Append("}\n"); +} + +void CppCustomTypesCodeEmitter::EmitBeginNamespace(StringBuilder& sb) +{ + String nspace = ast_->GetPackageName(); + int index = nspace.IndexOf('.'); + while (index != -1) { + sb.AppendFormat("namespace %s {\n", nspace.Substring(0, index).string()); + nspace = nspace.Substring(index + 1); + index = nspace.IndexOf('.'); + } + + if (!nspace.IsEmpty()) { + sb.AppendFormat("namespace %s {\n", nspace.string()); + } +} + +void CppCustomTypesCodeEmitter::EmitEndNamespace(StringBuilder& sb) +{ + String nspace = ast_->GetPackageName(); + nspace = nspace.Substring(0, nspace.GetLength() - 1); + while (!nspace.IsEmpty()) { + int index = nspace.LastIndexOf('.'); + sb.AppendFormat("} // %s\n", + (index != -1) ? nspace.Substring(index + 1, nspace.GetLength()).string() : nspace.string()); + nspace = nspace.Substring(0, index); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.h b/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.h new file mode 100755 index 000000000..d8e3be78f --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_custom_types_code_emitter.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_CUSTOM_TYPES_CODE_EMITTER_H +#define OHOS_HDI_CPP_CUSTOM_TYPES_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppCustomTypesCodeEmitter : public CppCodeEmitter { +public: + CppCustomTypesCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CppCodeEmitter(ast, targetDirectory) {} + + virtual ~CppCustomTypesCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitCustomTypesHeaderFile(); + + void EmitHeaderFileInclusions(StringBuilder& sb); + + void EmitCustomTypesStdlibInclusions(StringBuilder& sb); + + void EmitImportInclusions(StringBuilder& sb); + + void EmitCustomTypeDecls(StringBuilder& sb); + + void EmitCustomTypeDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeFuncDecl(StringBuilder& sb); + + void EmitCustomTypeMarshallingDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeUnmarshallingDecl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypesSourceFile(); + + void EmitSourceFileInclusions(StringBuilder& sb); + + void EmitSourceStdlibInclusions(StringBuilder& sb); + + void EmitCustomTypeDataProcess(StringBuilder& sb); + + void EmitCustomTypeMarshallingImpl(StringBuilder& sb, const AutoPtr& type); + + void EmitCustomTypeUnmarshallingImpl(StringBuilder& sb, const AutoPtr& type); + + void EmitBeginNamespace(StringBuilder& sb) override; + + void EmitEndNamespace(StringBuilder& sb) override; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_CUSTOM_TYPES_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.cpp new file mode 100755 index 000000000..244255264 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_service_driver_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CppServiceDriverCodeEmitter::CppServiceDriverCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CppCodeEmitter(ast, targetDirectory) +{ + String infFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), infName_.string()); + sourceFileName_ = String::Format("%s_driver.cpp", FileName(infFullName).string()); +} + +void CppServiceDriverCodeEmitter::EmitCode() +{ + // the callback interface have no driver file. + if (!isCallbackInterface()) { + EmitDriverSourceFile(); + } +} + +void CppServiceDriverCodeEmitter::EmitDriverSourceFile() +{ + String filePath = String::Format("%sserver/%s.cpp", directory_.string(), FileName(infName_ + "Driver").string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceDriverCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitDriverIncluions(sb); + sb.Append("\n"); + EmitDriverUsings(sb); + sb.Append("\n"); + EmitDriverServiceDecl(sb); + sb.Append("\n"); + EmitDriverDispatch(sb); + sb.Append("\n"); + EmitDriverInit(sb); + sb.Append("\n"); + EmitDriverBind(sb); + sb.Append("\n"); + EmitDriverRelease(sb); + sb.Append("\n"); + EmitDriverEntryDefinition(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceDriverCodeEmitter::EmitDriverIncluions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(stubName_).string()); +} + +void CppServiceDriverCodeEmitter::EmitDriverUsings(StringBuilder& sb) +{ + String nspace(interface_->GetNamespace()->ToString()); + int index = nspace.LastIndexOf('.'); + if (index > 0) { + nspace = nspace.Substring(0, index); + } + + String fullName = CppFullName(nspace); + sb.AppendFormat("using namespace %s;\n", fullName.string()); +} + +void CppServiceDriverCodeEmitter::EmitDriverServiceDecl(StringBuilder& sb) +{ + sb.AppendFormat("struct Hdf%s%s {\n", infName_.string(), "Service"); + sb.Append(TAB).Append("struct IDeviceIoService ioservice;\n"); + sb.Append(TAB).Append("void *instance;\n"); + sb.Append("};\n"); +} + +void CppServiceDriverCodeEmitter::EmitDriverDispatch(StringBuilder& sb) +{ + sb.AppendFormat("static int32_t %sServiceDispatch(struct HdfDeviceIoClient *client, int cmdId,\n", + infName_.string()); + sb.Append(TAB).Append("struct HdfSBuf *data, struct HdfSBuf *reply)\n"); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("struct Hdf%sService *hdf%sService = CONTAINER_OF(\n", + infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("client->device->service, struct Hdf%sService, ioservice);\n", + infName_.string()); + sb.Append(TAB).AppendFormat("return %sServiceOnRemoteRequest(hdf%sService->instance, cmdId, data, reply);\n", + infName_.string(), infName_.string()); + sb.Append("}\n"); +} + +void CppServiceDriverCodeEmitter::EmitDriverInit(StringBuilder& sb) +{ + sb.AppendFormat("int Hdf%sDriverInit(struct HdfDeviceObject *deviceObject)\n", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverInit enter, new hdi impl.\");\n", infName_.string()); + sb.Append(TAB).Append("return HDF_SUCCESS;\n"); + sb.Append("}\n"); +} + +void CppServiceDriverCodeEmitter::EmitDriverBind(StringBuilder& sb) +{ + sb.AppendFormat("int Hdf%sDriverBind(struct HdfDeviceObject *deviceObject)\n", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverBind enter.\");\n", infName_.string()); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("struct Hdf%sService *hdf%sService = (struct Hdf%sService *)OsalMemAlloc(\n", + infName_.string(), infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("sizeof(struct Hdf%sService));\n", infName_.string()); + sb.Append(TAB).AppendFormat("if (hdf%sService == nullptr) {\n", infName_.string()); + sb.Append(TAB).Append(TAB).AppendFormat("HDF_LOGE(\"Hdf%sDriverBind OsalMemAlloc Hdf%sService failed!\");\n", + infName_.string(), infName_.string()); + sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n"); + sb.Append(TAB).Append("}\n"); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Dispatch = %sServiceDispatch;\n", + infName_.string(), infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Open = NULL;\n", infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->ioservice.Release = NULL;\n", infName_.string()); + sb.Append(TAB).AppendFormat("hdf%sService->instance = %sStubInstance();\n", infName_.string(), infName_.string()); + sb.Append("\n"); + sb.Append(TAB).AppendFormat("deviceObject->service = &hdf%sService->ioservice;\n", infName_.string()); + sb.Append(TAB).Append("return HDF_SUCCESS;\n"); + sb.Append("}\n"); +} + +void CppServiceDriverCodeEmitter::EmitDriverRelease(StringBuilder& sb) +{ + sb.AppendFormat("void Hdf%sDriverRelease(struct HdfDeviceObject *deviceObject)", infName_.string()); + sb.Append("{\n"); + sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverRelease enter.\");\n", interfaceName_.string()); + sb.Append("}\n"); +} + +void CppServiceDriverCodeEmitter::EmitDriverEntryDefinition(StringBuilder& sb) +{ + sb.AppendFormat("struct HdfDriverEntry g_%sDriverEntry = {\n", infName_.ToLowerCase().string()); + sb.Append(TAB).Append(".moduleVersion = 1,\n"); + sb.Append(TAB).AppendFormat(".moduleName = \"%s\",\n", infName_.ToLowerCase().string()); + sb.Append(TAB).AppendFormat(".Bind = Hdf%sDriverBind,\n", infName_.string()); + sb.Append(TAB).AppendFormat(".Init = Hdf%sDriverInit,\n", infName_.string()); + sb.Append(TAB).AppendFormat(".Release = Hdf%sDriverRelease,\n", infName_.string()); + sb.Append("};\n"); + sb.Append("\n"); + sb.Append("#ifndef __cplusplus\n"); + sb.Append("extern \"C\" {\n"); + sb.Append("#endif\n"); + sb.AppendFormat("HDF_INIT(g_%sDriverEntry);\n", infName_.ToLowerCase().string()); + sb.Append("#ifndef __cplusplus\n"); + sb.Append("}\n"); + sb.Append("#endif\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.h b/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.h new file mode 100755 index 000000000..2d67cbf27 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_driver_code_emitter.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_SERVICE_DRIVER_CODE_EMITTER_H +#define OHOS_HDI_CPP_SERVICE_DRIVER_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppServiceDriverCodeEmitter : public CppCodeEmitter { +public: + CppServiceDriverCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CppServiceDriverCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitDriverSourceFile(); + + void EmitDriverIncluions(StringBuilder& sb); + + void EmitDriverUsings(StringBuilder& sb); + + void EmitDriverServiceDecl(StringBuilder& sb); + + void EmitDriverDispatch(StringBuilder& sb); + + void EmitDriverInit(StringBuilder& sb); + + void EmitDriverBind(StringBuilder& sb); + + void EmitDriverRelease(StringBuilder& sb); + + void EmitDriverEntryDefinition(StringBuilder& sb); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_SERVICE_DRIVER_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.cpp new file mode 100755 index 000000000..486c5fe09 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_service_impl_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CppServiceImplCodeEmitter::CppServiceImplCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CppCodeEmitter(ast, targetDirectory) +{ + String ImplFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), ImplName_.string()); + sourceFileName_ = String::Format("%s.cpp", FileName(ImplFullName).string()); +} + +void CppServiceImplCodeEmitter::EmitCode() +{ + EmitImplHeaderFile(); + EmitImplSourceFile(); +} + +void CppServiceImplCodeEmitter::EmitImplHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.h", directory_.string(), FileName(infName_ + "Service").string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_ + "Service").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceImplCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, ImplFullName_); + sb.Append("\n"); + EmitServiceImplInclusions(sb); + sb.Append("\n"); + EmitServiceImplDecl(sb); + sb.Append("\n"); + EmitTailMacro(sb, ImplFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceImplCodeEmitter::EmitServiceImplInclusions(StringBuilder& sb) +{ + if (!isCallbackInterface()) { + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + } else { + sb.AppendFormat("#include \"%s.h\"\n", FileName(stubName_).string()); + } + sb.Append("#include \n"); +} + +void CppServiceImplCodeEmitter::EmitServiceImplDecl(StringBuilder& sb) +{ + EmitBeginNamespace(sb); + sb.Append("\n"); + if (!isCallbackInterface()) { + sb.AppendFormat("class %sService : public %s {\n", infName_.string(), interfaceName_.string()); + } else { + sb.AppendFormat("class %sService : public %s {\n", infName_.string(), stubName_.string()); + } + sb.Append("public:\n"); + EmitServiceImplBody(sb, TAB); + sb.Append("};\n"); + + sb.Append("\n"); + EmitEndNamespace(sb); +} + +void CppServiceImplCodeEmitter::EmitServiceImplBody(StringBuilder& sb, const String& prefix) +{ + EmitServiceImplDestruction(sb, TAB); + sb.Append("\n"); + EmitServiceImplMethodDecls(sb, TAB); +} + +void CppServiceImplCodeEmitter::EmitServiceImplDestruction(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("virtual ~%sService() {}\n", infName_.string()); +} + +void CppServiceImplCodeEmitter::EmitServiceImplMethodDecls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitServiceImplMethodDecl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppServiceImplCodeEmitter::EmitServiceImplMethodDecl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(") override;"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void CppServiceImplCodeEmitter::EmitImplSourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.cpp", directory_.string(), FileName(infName_ + "Service").string()); + } else { + filePath = String::Format("%s%s.cpp", directory_.string(), FileName(infName_ + "Service").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceImplCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + sb.AppendFormat("#include \"%s_service.h\"\n", FileName(infName_).string()); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitServiceImplMethodImpls(sb, ""); + sb.Append("\n"); + EmitEndNamespace(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitServiceImplMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppServiceImplCodeEmitter::EmitServiceImplMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int32_t %sService::%s()\n", infName_.string(), method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int32_t %sService::%s(", infName_.string(), method->GetName().string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.AppendFormat(")"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } + + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n"); + sb.Append(prefix).Append("}\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.h b/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.h new file mode 100755 index 000000000..e93c7b899 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_impl_code_emitter.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_SERVICE_IMPL_CODE_EMITTER_H +#define OHOS_HDI_CPP_SERVICE_IMPL_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppServiceImplCodeEmitter : public CppCodeEmitter { +public: + CppServiceImplCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CppServiceImplCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitImplHeaderFile(); + + void EmitServiceImplInclusions(StringBuilder& sb); + + void EmitServiceImplDecl(StringBuilder& sb); + + void EmitServiceImplBody(StringBuilder& sb, const String& prefix); + + void EmitServiceImplDestruction(StringBuilder& sb, const String& prefix); + + void EmitServiceImplMethodDecls(StringBuilder& sb, const String& prefix); + + void EmitServiceImplMethodDecl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitImplSourceFile(); + + void EmitServiceImplMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitServiceImplMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_SERVICE_IMPL_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.cpp new file mode 100755 index 000000000..289d0e782 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_service_interface_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void CppServiceInterfaceCodeEmitter::EmitCode() +{ + if (!isCallbackInterface()) { + EmitInterfaceHeaderFile(); + } +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.h", directory_.string(), FileName(interfaceName_).string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(interfaceName_).string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitServiceInfHeadMacro(sb); + sb.Append("\n"); + EmitInterfaceInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitUsingNamespace(sb); + sb.Append("\n"); + EmitInterfaceDecl(sb); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); + EmitServiceInfTailMacro(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceInterfaceCodeEmitter::EmitServiceInfHeadMacro(StringBuilder& sb) +{ + String serviceMacroName(interfaceFullName_); + if (!isCallbackInterface()) { + serviceMacroName += ".service"; + } + EmitHeadMacro(sb, serviceMacroName); +} + +void CppServiceInterfaceCodeEmitter::EmitServiceInfTailMacro(StringBuilder& sb) +{ + String serviceMacroName(interfaceFullName_); + if (!isCallbackInterface()) { + serviceMacroName += ".service"; + } + EmitTailMacro(sb, serviceMacroName); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceInclusions(StringBuilder& sb) +{ + EmitInterfaceStdlibInclusions(sb); + EmitInterfaceDBinderInclusions(sb); + EmitInterfaceSelfDefinedTypeInclusions(sb); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceStdlibInclusions(StringBuilder& sb) +{ + bool includeString = false; + bool includeList = false; + bool includeMap = false; + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + switch (type->GetTypeKind()) { + case TypeKind::TYPE_STRING: { + if (!includeString) { + sb.Append("#include \n"); + includeString = true; + } + break; + } + case TypeKind::TYPE_ARRAY: + case TypeKind::TYPE_LIST: { + if (!includeList) { + sb.Append("#include \n"); + includeList = true; + } + break; + } + case TypeKind::TYPE_MAP: { + if (!includeMap) { + sb.Append("#include \n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceDBinderInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceSelfDefinedTypeInclusions(StringBuilder& sb) +{ + for (const auto& importPair : ast_->GetImports()) { + AutoPtr importAst = importPair.second; + + String fileName; + if (importAst->GetASTFileType() == ASTFileType::AST_ICALLBACK && importAst->GetInterfaceDef() != nullptr) { + String ifaceName = importAst->GetInterfaceDef()->GetName(); + String name = ifaceName.StartsWith("I") ? ifaceName.Substring(1) : ifaceName; + String stubName = name + "Proxy"; + fileName = FileName(importAst->GetInterfaceDef()->GetNamespace()->ToString() + stubName); + } else { + fileName = FileName(importAst->GetFullName()); + } + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceDecl(StringBuilder& sb) +{ + EmitInterfaceMethodCommands(sb, ""); + sb.Append("\n"); + + sb.AppendFormat("class %s {\n", interface_->GetName().string()); + sb.Append("public:\n"); + EmitInterfaceBody(sb, TAB); + sb.Append("};\n"); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceBody(StringBuilder& sb, const String& prefix) +{ + EmitInterfaceDestruction(sb, TAB); + sb.Append("\n"); + EmitInterfaceMethods(sb, TAB); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceDestruction(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("virtual ~%s() {}\n", interface_->GetName().string()); +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceMethods(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitInterfaceMethod(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppServiceInterfaceCodeEmitter::EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("virtual int32_t %s() = 0;\n", method->GetName().string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("virtual int32_t %s(", method->GetName().string()); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(") = 0;"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.h b/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.h new file mode 100755 index 000000000..7e648887e --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_interface_code_emitter.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_SERVICE_INTERFACE_CODE_EMITTER_H +#define OHOS_HDI_CPP_SERVICE_INTERFACE_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppServiceInterfaceCodeEmitter : public CppCodeEmitter { +public: + CppServiceInterfaceCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : CppCodeEmitter(ast, targetDirectory) {} + + virtual ~CppServiceInterfaceCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitInterfaceHeaderFile(); + + void EmitServiceInfHeadMacro(StringBuilder& sb); + + void EmitServiceInfTailMacro(StringBuilder& sb); + + void EmitInterfaceInclusions(StringBuilder& sb); + + void EmitInterfaceStdlibInclusions(StringBuilder& sb); + + void EmitInterfaceDBinderInclusions(StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeInclusions(StringBuilder& sb); + + void EmitInterfaceUsings(StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeUsings(StringBuilder& sb); + + void EmitInterfaceDecl(StringBuilder& sb); + + void EmitInterfaceBody(StringBuilder& sb, const String& prefix); + + void EmitInterfaceDestruction(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethods(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_SERVICE_INTERFACE_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.cpp b/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.cpp new file mode 100755 index 000000000..572189656 --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.cpp @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/cpp_service_stub_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +CppServiceStubCodeEmitter::CppServiceStubCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :CppCodeEmitter(ast, targetDirectory) +{ + String stubFullName = String::Format("%sserver.%s", + interface_->GetNamespace()->ToString().string(), stubName_.string()); + sourceFileName_ = String::Format("%s.cpp", FileName(stubFullName).string()); +} + +void CppServiceStubCodeEmitter::EmitCode() +{ + EmitStubHeaderFile(); + EmitStubSourceFile(); +} + +void CppServiceStubCodeEmitter::EmitStubHeaderFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.h", directory_.string(), FileName(infName_ + "Stub").string()); + } else { + filePath = String::Format("%s%s.h", directory_.string(), FileName(infName_ + "Stub").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceStubCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitHeadMacro(sb, stubFullName_); + sb.Append("\n"); + EmitStubHeaderInclusions(sb); + sb.Append("\n"); + + if (!isCallbackInterface()) { + EmitStubDecl(sb); + } else { + EmitCbStubDecl(sb); + } + sb.Append("\n"); + EmitTailMacro(sb, stubFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceStubCodeEmitter::EmitStubHeaderInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + if (!isCallbackInterface()) { + sb.AppendFormat("#include \"%s_service.h\"\n", FileName(infName_).string()); + } else { + sb.Append("#include \n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + } +} + +void CppServiceStubCodeEmitter::EmitStubDecl(StringBuilder& sb) +{ + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitStubUsingNamespace(sb); + sb.Append("\n"); + sb.AppendFormat("class %s {\n", stubName_.string()); + sb.Append("public:\n"); + EmitStubBody(sb, TAB); + sb.Append("};\n"); + + sb.Append("\n"); + EmitEndNamespace(sb); + + sb.Append("\n"); + EmitStubExternalsMethodsDel(sb); +} + +void CppServiceStubCodeEmitter::EmitCbStubDecl(StringBuilder& sb) +{ + EmitBeginNamespace(sb); + sb.Append("\n"); + EmitStubUsingNamespace(sb); + sb.Append("\n"); + sb.AppendFormat("class %s : public IRemoteStub<%s> {\n", stubName_.string(), interfaceName_.string()); + EmitCbStubBody(sb, TAB); + sb.Append("};\n"); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); +} + +void CppServiceStubCodeEmitter::EmitStubUsingNamespace(StringBuilder& sb) +{ + sb.Append("using namespace OHOS;\n"); +} + +void CppServiceStubCodeEmitter::EmitStubBody(StringBuilder& sb, const String& prefix) +{ + sb.Append("public:\n"); + EmitStubDestruction(sb, prefix); + sb.Append("\n"); + EmitStubMethodDecls(sb, prefix); + sb.Append("\n"); + EmitStubOnRequestMethodDecl(sb, prefix); + sb.Append("\n"); + EmitStubMembers(sb, prefix); +} + +void CppServiceStubCodeEmitter::EmitCbStubBody(StringBuilder& sb, const String& prefix) +{ + sb.Append("public:\n"); + EmitStubDestruction(sb, prefix); + sb.Append("\n"); + EmitCbStubOnRequestDecl(sb, prefix); + EmitStubMethodDecls(sb, prefix); +} + +void CppServiceStubCodeEmitter::EmitStubDestruction(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("virtual ~%s() {}\n", stubName_.string()); +} + +void CppServiceStubCodeEmitter::EmitCbStubOnRequestDecl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).Append("int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,\n"); + sb.Append(prefix + TAB).Append("MessageOption &option) override;\n"); +} + +void CppServiceStubCodeEmitter::EmitStubMethodDecls(StringBuilder& sb, const String& prefix) +{ + if (interface_->GetMethodNumber() > 0) { + if (isCallbackInterface()) { + sb.Append("private:\n"); + } + + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitStubMethodDecl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } + } +} + +void CppServiceStubCodeEmitter::EmitStubMethodDecl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).AppendFormat("int32_t %s%s(MessageParcel& data, MessageParcel& reply, MessageOption& option);\n", + stubName_.string(), method->GetName().string()); +} + +void CppServiceStubCodeEmitter::EmitStubOnRequestMethodDecl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("int32_t %sOnRemoteRequest(int cmdId, MessageParcel& data, MessageParcel& reply,\n", + stubName_.string()); + sb.Append(prefix).Append(TAB).Append("MessageOption& option);\n"); +} + +void CppServiceStubCodeEmitter::EmitStubMembers(StringBuilder& sb, const String& prefix) +{ + sb.Append("private:\n"); + sb.Append(prefix).AppendFormat("%sService service;\n", infName_.string()); +} + +void CppServiceStubCodeEmitter::EmitStubExternalsMethodsDel(StringBuilder& sb) +{ + sb.AppendFormat("void *%sInstance();\n", stubName_.string()); + sb.Append("\n"); + sb.AppendFormat("void %sRelease(void *obj);\n", stubName_.string()); + sb.Append("\n"); + sb.AppendFormat( + "int32_t %sServiceOnRemoteRequest(void *stub, int cmdId, struct HdfSBuf* data, struct HdfSBuf* reply);\n", + infName_.string()); +} + +void CppServiceStubCodeEmitter::EmitStubSourceFile() +{ + String filePath; + if (!isCallbackInterface()) { + filePath = String::Format("%sserver/%s.cpp", directory_.string(), FileName(infName_ + "Stub").string()); + } else { + filePath = String::Format("%s%s.cpp", directory_.string(), FileName(infName_ + "Stub").string()); + } + + if (!File::CreateParentDir(filePath)) { + Logger::E("CppServiceStubCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitStubSourceInclusions(sb); + sb.Append("\n"); + EmitBeginNamespace(sb); + sb.Append("\n"); + if (!isCallbackInterface()) { + EmitStubOnRequestMethodImpl(sb, ""); + } else { + EmitCbStubOnRequestMethodImpl(sb, ""); + } + sb.Append("\n"); + EmitStubMethodImpls(sb, ""); + sb.Append("\n"); + EmitEndNamespace(sb); + sb.Append("\n"); + + if (!isCallbackInterface()) { + EmitStubExternalsMethodsImpl(sb, ""); + } + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppServiceStubCodeEmitter::EmitStubSourceInclusions(StringBuilder& sb) +{ + sb.AppendFormat("#include \"%s.h\"\n", FileName(stubName_).string()); + EmitStubSourceStdlibInclusions(sb); +} + +void CppServiceStubCodeEmitter::EmitStubSourceStdlibInclusions(StringBuilder& sb) +{ + sb.Append("#include \n"); + sb.Append("#include \n"); + sb.Append("#include \n"); + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + if (type->GetTypeKind() == TypeKind::TYPE_UNION) { + sb.Append("#include \n"); + break; + } + } +} + +void CppServiceStubCodeEmitter::EmitStubMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitStubMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void CppServiceStubCodeEmitter::EmitStubMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).AppendFormat( + "int32_t %s::%s%s(MessageParcel& data, MessageParcel& reply, MessageOption& option)\n", + stubName_.string(), stubName_.string(), method->GetName().string()); + sb.Append(prefix).Append("{\n"); + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_IN) { + EmitReadMethodParameter(param, "data", true, sb, prefix + TAB); + sb.Append("\n"); + } else { + EmitLocalVariable(param, sb, prefix + TAB); + sb.Append("\n"); + } + } + + if (method->GetParameterNumber() == 0) { + if (!isCallbackInterface()) { + sb.Append(prefix + TAB).AppendFormat("int32_t ec = service.%s();\n", method->GetName().string()); + } else { + sb.Append(prefix + TAB).AppendFormat("int32_t ec = %s();\n", method->GetName().string()); + } + } else { + if (!isCallbackInterface()) { + sb.Append(prefix + TAB).AppendFormat("int32_t ec = service.%s(", method->GetName().string()); + } else { + sb.Append(prefix + TAB).AppendFormat("int32_t ec = %s(", method->GetName().string()); + } + + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + sb.Append(param->GetName()); + if (i + 1 < method->GetParameterNumber()) { + sb.Append(", "); + } + } + sb.Append(");\n"); + } + + sb.Append(prefix + TAB).Append("if (ec != HDF_SUCCESS) {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat( + "HDF_LOGE(\"%%{public}s failed, error code is %%d\", ec);\n", method->GetName().string()); + sb.Append(prefix + TAB + TAB).Append("return ec;\n"); + sb.Append(prefix + TAB).Append("}\n\n"); + + if (!method->IsOneWay()) { + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_OUT) { + EmitWriteMethodParameter(param, "reply", sb, prefix + TAB); + sb.Append("\n"); + } + } + } + + sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n"); + sb.Append("}\n"); +} + +void CppServiceStubCodeEmitter::EmitStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("int32_t %s::%sOnRemoteRequest(int cmdId,\n", + stubName_.string(), stubName_.string()); + sb.Append(prefix + TAB).Append("MessageParcel& data, MessageParcel& reply, MessageOption& option)\n"); + sb.Append(prefix).Append("{\n"); + + sb.Append(prefix + TAB).Append("switch (cmdId) {\n"); + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(prefix + TAB + TAB).AppendFormat("case CMD_%s:\n", ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("return %sStub%s(data, reply, option);\n", + infName_.string(), method->GetName().string()); + } + + sb.Append(prefix + TAB + TAB).Append("default: {\n"); + sb.Append(prefix + TAB + TAB + TAB).Append( + "HDF_LOGE(\"%{public}s: not support cmd %{public}d\", __func__, cmdId);\n"); + sb.Append(prefix + TAB + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("}\n"); +} + +void CppServiceStubCodeEmitter::EmitCbStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("int32_t %s::OnRemoteRequest(uint32_t code,\n", stubName_.string()); + sb.Append(prefix + TAB).Append("MessageParcel& data, MessageParcel& reply, MessageOption& option)\n"); + sb.Append(prefix).Append("{\n"); + + sb.Append(prefix + TAB).Append("switch (code) {\n"); + + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(prefix + TAB + TAB).AppendFormat("case CMD_%s:\n", ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB + TAB + TAB).AppendFormat("return %sStub%s(data, reply, option);\n", + infName_.string(), method->GetName().string()); + } + + sb.Append(prefix + TAB + TAB).Append("default: {\n"); + sb.Append(prefix + TAB + TAB + TAB).Append( + "HDF_LOGE(\"%{public}s: not support cmd %{public}d\", __func__, code);\n"); + sb.Append(prefix + TAB + TAB + TAB).Append("return IPCObjectStub::OnRemoteRequest(code, data, reply, option);\n"); + sb.Append(prefix + TAB + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("}\n"); +} + +void CppServiceStubCodeEmitter::EmitStubExternalsMethodsImpl(StringBuilder& sb, const String& prefix) +{ + EmitStubInstanceMethodImpl(sb, prefix); + sb.Append("\n"); + EmitStubReleaseMethodImpl(sb, prefix); + sb.Append("\n"); + EmitServiceOnRemoteRequest(sb, prefix); +} + +void CppServiceStubCodeEmitter::EmitStubInstanceMethodImpl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("void *%sInstance()\n", stubName_.string()); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("using namespace %s;\n", + EmitStubServiceUsings(interface_->GetNamespace()->ToString()).string()); + sb.Append(prefix + TAB).AppendFormat("return reinterpret_cast(new %s());\n", stubName_.string()); + sb.Append(prefix).Append("}\n"); +} + +void CppServiceStubCodeEmitter::EmitStubReleaseMethodImpl(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("void %sRelease(void *obj)\n", stubName_.string()); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("using namespace %s;\n", + EmitStubServiceUsings(interface_->GetNamespace()->ToString()).string()); + sb.Append(prefix + TAB).AppendFormat("delete reinterpret_cast<%s *>(obj);\n", stubName_.string()); + sb.Append(prefix).Append("}\n"); +} + +void CppServiceStubCodeEmitter::EmitServiceOnRemoteRequest(StringBuilder& sb, const String& prefix) +{ + String stubObjName = String::Format("%sStub", infName_.ToLowerCase().string()); + sb.Append(prefix).AppendFormat( + "int32_t %sServiceOnRemoteRequest(void *stub, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)\n", + infName_.string()); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("using namespace %s;\n", + EmitStubServiceUsings(interface_->GetNamespace()->ToString()).string()); + sb.Append(prefix + TAB).AppendFormat("%s *%s = reinterpret_cast<%s *>(stub);\n", + stubName_.string(), stubObjName.string(), stubName_.string()); + sb.Append(prefix + TAB).Append("OHOS::MessageParcel *dataParcel = nullptr;\n"); + sb.Append(prefix + TAB).Append("OHOS::MessageParcel *replyParcel = nullptr;\n"); + sb.Append("\n"); + + sb.Append(prefix + TAB).Append("(void)SbufToParcel(reply, &replyParcel);\n"); + sb.Append(prefix + TAB).Append("if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {\n"); + sb.Append(prefix + TAB + TAB).Append( + "HDF_LOGE(\"%{public}s:invalid data sbuf object to dispatch\", __func__);\n"); + sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n"); + sb.Append(prefix + TAB).Append("}\n\n"); + sb.Append(prefix + TAB).Append("OHOS::MessageOption option;\n"); + sb.Append(prefix + TAB).AppendFormat("return %s->%sOnRemoteRequest(cmdId, *dataParcel, *replyParcel, option);\n", + stubObjName.string(), stubName_.string()); + sb.Append(prefix).Append("}\n"); +} + +String CppServiceStubCodeEmitter::EmitStubServiceUsings(String nameSpace) +{ + int index = nameSpace.LastIndexOf('.'); + if (index > 0) { + nameSpace = nameSpace.Substring(0, index); + } + return CppFullName(nameSpace); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.h b/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.h new file mode 100755 index 000000000..12f7ce1af --- /dev/null +++ b/tools/hdi-gen/codegen/cpp_service_stub_code_emitter.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_CPP_SERVICE_STUB_CODE_EMITTER_H +#define OHOS_HDI_CPP_SERVICE_STUB_CODE_EMITTER_H + +#include "codegen/cpp_code_emitter.h" + +namespace OHOS { +namespace HDI { +class CppServiceStubCodeEmitter : public CppCodeEmitter { +public: + CppServiceStubCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~CppServiceStubCodeEmitter() = default; + + void EmitCode() override; +private: + + // ISample.idl -> sample_service_stub.h + void EmitStubHeaderFile(); + + void EmitStubHeaderInclusions(StringBuilder& sb); + + void EmitStubUsingNamespace(StringBuilder& sb); + + void EmitStubDecl(StringBuilder& sb); + + void EmitCbStubDecl(StringBuilder& sb); + + void EmitStubBody(StringBuilder& sb, const String& prefix); + + void EmitCbStubBody(StringBuilder& sb, const String& prefix); + + void EmitStubDestruction(StringBuilder& sb, const String& prefix); + + void EmitCbStubOnRequestDecl(StringBuilder& sb, const String& prefix); + + void EmitStubMethodDecls(StringBuilder& sb, const String& prefix); + + void EmitStubMethodDecl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitStubOnRequestMethodDecl(StringBuilder& sb, const String& prefix); + + void EmitStubMembers(StringBuilder& sb, const String& prefix); + + void EmitStubExternalsMethodsDel(StringBuilder& sb); + + // ISample.idl -> sample_service_stub.cpp + void EmitStubSourceFile(); + + void EmitStubSourceInclusions(StringBuilder& sb); + + void EmitStubSourceStdlibInclusions(StringBuilder& sb); + + void EmitStubMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitStubMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitCbStubOnRequestMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitStubExternalsMethodsImpl(StringBuilder& sb, const String& prefix); + + void EmitStubInstanceMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitStubReleaseMethodImpl(StringBuilder& sb, const String& prefix); + + void EmitServiceOnRemoteRequest(StringBuilder& sb, const String& prefix); + + String EmitStubServiceUsings(String nameSpace); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_CPP_SERVICE_STUB_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/generator_factory.cpp b/tools/hdi-gen/codegen/generator_factory.cpp new file mode 100755 index 000000000..73418e738 --- /dev/null +++ b/tools/hdi-gen/codegen/generator_factory.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/generator_factory.h" +#include "codegen/c_code_generator.h" +#include "codegen/cpp_code_generator.h" +#include "codegen/java_code_generator.h" + +namespace OHOS { +namespace HDI { +AutoPtr GeneratorFactory::GetCodeGenerator(const String& targetLanuage) +{ + if (targetLanuage.Equals("c")) { + return new CCodeGenerator(); + } else if (targetLanuage.Equals("cpp")) { + return new CppCodeGenerator(); + } else if (targetLanuage.Equals("java")) { + return new JavaCodeGenerator(); + } + + return nullptr; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/generator_factory.h b/tools/hdi-gen/codegen/generator_factory.h new file mode 100755 index 000000000..8b99621fb --- /dev/null +++ b/tools/hdi-gen/codegen/generator_factory.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_GENERATORFACTORY_H +#define OHOS_HDI_GENERATORFACTORY_H + +#include "codegen/code_generator.h" + +namespace OHOS { +namespace HDI { +class GeneratorFactory { +public: + AutoPtr GetCodeGenerator(const String& targetLanuage); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_GENERATORFACTORY_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_client_interface_code_emitter.cpp b/tools/hdi-gen/codegen/java_client_interface_code_emitter.cpp new file mode 100755 index 000000000..abbe81f12 --- /dev/null +++ b/tools/hdi-gen/codegen/java_client_interface_code_emitter.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/java_client_interface_code_emitter.h" +#include +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void JavaClientInterfaceCodeEmitter::EmitCode() +{ + EmitInterfaceFile(); +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceFile() +{ + String filePath = String::Format("%s/%s.java", directory_.string(), FileName(interfaceName_).string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("JavaClientInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitPackage(sb); + sb.Append("\n"); + EmitInterfaceImports(sb); + sb.Append("\n"); + EmitInterfaceDefinition(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceImports(StringBuilder& sb) +{ + EmitInterfaceCorelibImports(sb); + EmitInterfaceSelfDefinedTypeImports(sb); + EmitInterfaceDBinderImports(sb); +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceCorelibImports(StringBuilder& sb) +{ + bool includeList = false; + bool includeMap = false; + + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + switch (type->GetTypeKind()) { + case TypeKind::TYPE_LIST: { + if (!includeList) { + sb.Append("import java.util.List;\n"); + includeList = true; + } + break; + } + case TypeKind::TYPE_MAP: { + if (!includeMap) { + sb.Append("import java.util.Map;\n"); + sb.Append("import java.util.HashMap;\n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceDBinderImports(StringBuilder& sb) +{ + sb.Append("import ohos.rpc.IRemoteBroker;\n"); + sb.Append("import ohos.rpc.RemoteException;\n"); +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceSelfDefinedTypeImports(StringBuilder& sb) +{ + for (const auto& importPair : ast_->GetImports()) { + AutoPtr import = importPair.second; + sb.AppendFormat("import %s;\n", import->GetFullName().string()); + } +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder& sb) +{ + sb.AppendFormat("public interface %s extends IRemoteBroker {\n", interface_->GetName().string()); + EmitInterfaceMethods(sb, TAB); + sb.Append("}"); +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceMethods(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitInterfaceMethod(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("int %s() throws RemoteException;\n", MethodName(method->GetName()).string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("int %s(", MethodName(method->GetName()).string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + + paramStr.Append(") throws RemoteException;"); + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } +} + +void JavaClientInterfaceCodeEmitter::EmitInterfaceMethodParameter(const AutoPtr& param, + StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).Append(param->EmitJavaParameter()); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_client_interface_code_emitter.h b/tools/hdi-gen/codegen/java_client_interface_code_emitter.h new file mode 100755 index 000000000..9ffecd245 --- /dev/null +++ b/tools/hdi-gen/codegen/java_client_interface_code_emitter.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_JAVA_CLIENT_INTERFACE_CODE_EMITTER_H +#define OHOS_HDI_JAVA_CLIENT_INTERFACE_CODE_EMITTER_H + +#include "java_code_emitter.h" + +namespace OHOS { +namespace HDI { +class JavaClientInterfaceCodeEmitter : public JavaCodeEmitter { +public: + JavaClientInterfaceCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : JavaCodeEmitter(ast, targetDirectory) {} + + virtual ~JavaClientInterfaceCodeEmitter() = default; + + void EmitCode() override; +private: + + void EmitInterfaceFile(); + + void EmitInterfaceImports(StringBuilder& sb); + + void EmitInterfaceCorelibImports(StringBuilder& sb); + + void EmitInterfaceDBinderImports(StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeImports(StringBuilder& sb); + + void EmitInterfaceDefinition(StringBuilder& sb); + + void EmitInterfaceMethods(StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethod(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, const String& prefix); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_JAVA_CLIENT_INTERFACE_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_client_proxy_code_emitter.cpp b/tools/hdi-gen/codegen/java_client_proxy_code_emitter.cpp new file mode 100755 index 000000000..798be2741 --- /dev/null +++ b/tools/hdi-gen/codegen/java_client_proxy_code_emitter.cpp @@ -0,0 +1,668 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/java_client_proxy_code_emitter.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +void JavaClientProxyCodeEmitter::EmitCode() +{ + EmitProxyFile(); +} + +void JavaClientProxyCodeEmitter::EmitProxyFile() +{ + String filePath = String::Format("%s/%s.java", directory_.string(), FileName(proxyName_).string()); + if (!File::CreateParentDir(filePath)) { + Logger::E("CppClientInterfaceCodeEmitter", "Create '%s' failed!", filePath.string()); + return; + } + + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + EmitPackage(sb); + sb.Append("\n"); + EmitProxyImports(sb); + sb.Append("\n"); + EmitProxyImpl(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void JavaClientProxyCodeEmitter::EmitProxyImports(StringBuilder& sb) +{ + EmitProxyCorelibImports(sb); + EmitProxySelfDefinedTypeImports(sb); + EmitProxyDBinderImports(sb); +} + +void JavaClientProxyCodeEmitter::EmitProxyCorelibImports(StringBuilder& sb) +{ + bool includeList = false; + bool includeMap = false; + const AST::TypeStringMap& types = ast_->GetTypes(); + for (const auto& pair : types) { + AutoPtr type = pair.second; + switch (type->GetTypeKind()) { + case TypeKind::TYPE_LIST: { + if (!includeList) { + sb.Append("import java.util.List;\n"); + includeList = true; + } + break; + } + case TypeKind::TYPE_MAP: { + if (!includeMap) { + sb.Append("import java.util.Map;\n"); + sb.Append("import java.util.HashMap;\n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void JavaClientProxyCodeEmitter::EmitProxySelfDefinedTypeImports(StringBuilder& sb) +{ + for (const auto& importPair : ast_->GetImports()) { + AutoPtr import = importPair.second; + sb.AppendFormat("import %s;\n", import->GetFullName().string()); + } +} + +void JavaClientProxyCodeEmitter::EmitProxyDBinderImports(StringBuilder& sb) +{ + sb.Append("import ohos.hiviewdfx.HiLog;\n"); + sb.Append("import ohos.hiviewdfx.HiLogLabel;\n"); + sb.Append("import ohos.rpc.IRemoteObject;\n"); + sb.Append("import ohos.rpc.RemoteException;\n"); + sb.Append("import ohos.rpc.MessageParcel;\n"); + sb.Append("import ohos.rpc.MessageOption;\n"); +} + +void JavaClientProxyCodeEmitter::EmitProxyImpl(StringBuilder& sb) +{ + sb.AppendFormat("public class %s implements %s {\n", proxyName_.string(), interfaceName_.string()); + EmitProxyConstants(sb, TAB); + sb.Append("\n"); + sb.Append(TAB).AppendFormat( + "private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_CORE, 0xD001510, \"%s\");\n", + interfaceFullName_.string()); + sb.Append(TAB).Append("private final IRemoteObject remote;\n"); + sb.Append(TAB).Append("private static final int ERR_OK = 0;\n"); + sb.Append("\n"); + EmitProxyConstructor(sb, TAB); + sb.Append("\n"); + EmitProxyMethodImpls(sb, TAB); + sb.Append("};"); +} + +void JavaClientProxyCodeEmitter::EmitProxyConstants(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("private static final String DESCRIPTOR = \"%s\";\n\n", + interfaceFullName_.string()); + EmitInterfaceMethodCommands(sb, prefix); +} + +void JavaClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("public %s(IRemoteObject remote) {\n", proxyName_.string()); + sb.Append(prefix + TAB).Append("this.remote = remote;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat("@Override\n"); + sb.Append(prefix).Append("public IRemoteObject asObject() {\n"); + sb.Append(prefix + TAB).Append("return remote;\n"); + sb.Append(prefix).Append("}\n"); +} + +void JavaClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + EmitProxyMethodImpl(method, sb, prefix); + if (i + 1 < interface_->GetMethodNumber()) { + sb.Append("\n"); + } + } +} + +void JavaClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append("@Override\n"); + if (method->GetParameterNumber() == 0) { + sb.Append(prefix).AppendFormat("public int %s() throws RemoteException ", + MethodName(method->GetName()).string()); + } else { + StringBuilder paramStr; + paramStr.Append(prefix).AppendFormat("public int %s(", MethodName(method->GetName()).string()); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + EmitInterfaceMethodParameter(param, paramStr, ""); + if (i + 1 < method->GetParameterNumber()) { + paramStr.Append(", "); + } + } + paramStr.Append(") throws RemoteException"); + + sb.Append(SpecificationParam(paramStr, prefix + TAB)); + sb.Append("\n"); + } + EmitProxyMethodBody(method, sb, prefix); +} + +void JavaClientProxyCodeEmitter::EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append(param->EmitJavaParameter()); +} + +void JavaClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, + const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("MessageParcel data = MessageParcel.obtain();\n"); + sb.Append(prefix + TAB).Append("MessageParcel reply = MessageParcel.obtain();\n"); + sb.Append(prefix + TAB).AppendFormat("MessageOption option = new MessageOption(MessageOption.TF_SYNC);\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat(" data.writeInterfaceToken(DESCRIPTOR);\n"); + + bool needBlankLine = false; + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_IN) { + EmitWriteMethodParameter(param, "data", sb, prefix + TAB); + needBlankLine = true; + } else { + AutoPtr type = param->GetType(); + if (type->GetTypeKind() == TypeKind::TYPE_ARRAY) { + EmitWriteOutArrayVariable("data", param->GetName(), type, sb, prefix + TAB); + } + } + } + if (needBlankLine) { + sb.Append("\n"); + } + + sb.Append(prefix + TAB).Append("try {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("if (remote.sendRequest(COMMAND_%s, data, reply, option)) {\n", + ConstantName(method->GetName()).string()); + sb.Append(prefix + TAB + TAB + TAB).Append("return 1;\n"); + sb.Append(prefix + TAB + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append(" reply.readException();\n"); + for (size_t i = 0; i < method->GetParameterNumber(); i++) { + AutoPtr param = method->GetParameter(i); + if (param->GetAttribute() == ParamAttr::PARAM_OUT) { + EmitReadMethodParameter(param, "reply", sb, prefix + TAB + TAB); + } + } + + sb.Append(prefix + TAB).Append("} finally {\n"); + sb.Append(prefix + TAB + TAB).Append("data.reclaim();\n"); + sb.Append(prefix + TAB + TAB).Append("reply.reclaim();\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("return 0;\n"); + sb.Append(prefix).Append("}\n"); +} + +void JavaClientProxyCodeEmitter::EmitWriteMethodParameter(const AutoPtr& param, const String& parcelName, + StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + EmitWriteVariable(parcelName, param->GetName(), type, sb, prefix); +} + +void JavaClientProxyCodeEmitter::EmitReadMethodParameter(const AutoPtr& param, const String& parcelName, + StringBuilder& sb, const String& prefix) +{ + AutoPtr type = param->GetType(); + EmitReadOutVariable(parcelName, param->GetName(), type, sb, prefix); +} + +void JavaClientProxyCodeEmitter::EmitWriteVariable(const String& parcelName, const String& name, + const AutoPtr& type, StringBuilder& sb, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s.writeBoolean(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s.writeByte(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s.writeShort(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s.writeInt(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s.writeLong(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s.writeFloat(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s.writeDouble(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s.writeString(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + if (type->EmitJavaType(TypeMode::NO_MODE).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s);\n", parcelName.string(), name.string()); + break; + } + sb.Append(prefix).AppendFormat("%s.writeSequenceable(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_INTERFACE: + sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s.asObject());\n", parcelName.string(), + name.string()); + break; + case TypeKind::TYPE_LIST: { + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + + sb.Append(prefix).AppendFormat("%s.writeInt(%s.size());\n", parcelName.string(), name.string()); + sb.Append(prefix).AppendFormat("for (%s element : %s) {\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string()); + EmitWriteVariable(parcelName, "element", elementType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_MAP: { + AutoPtr mapType = dynamic_cast(type.Get()); + AutoPtr keyType = mapType->GetKeyType(); + AutoPtr valueType = mapType->GetValueType(); + + sb.Append(prefix).AppendFormat("%s.writeInt(%s.size());\n", parcelName.string(), name.string()); + sb.Append(prefix).AppendFormat("for (Map.Entry<%s, %s> entry : %s.entrySet()) {\n", + keyType->EmitJavaType(TypeMode::NO_MODE, true).string(), + valueType->EmitJavaType(TypeMode::NO_MODE, true).string(), name.string()); + EmitWriteVariable(parcelName, "entry.getKey()", keyType, sb, prefix + TAB); + EmitWriteVariable(parcelName, "entry.getValue()", valueType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + AutoPtr arrayType = dynamic_cast(type.Get()); + AutoPtr elementType = arrayType->GetElementType(); + + sb.Append(prefix).AppendFormat("if (%s == null) {\n", name.string()); + sb.Append(prefix).AppendFormat(" %s.writeInt(-1);\n", parcelName.string()); + sb.Append(prefix).Append("} else { \n"); + EmitWriteArrayVariable(parcelName, name, elementType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitWriteArrayVariable(const String& parcelName, const String& name, + const AutoPtr& type, StringBuilder& sb, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s.writeBooleanArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s.writeByteArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s.writeShortArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s.writeIntArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s.writeLongArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s.writeFloatArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s.writeDoubleArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s.writeStringArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + sb.Append(prefix).AppendFormat("%s.writeSequenceableArray(%s);\n", parcelName.string(), name.string()); + break; + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitWriteOutArrayVariable(const String& parcelName, const String& name, + const AutoPtr& type, StringBuilder& sb, const String& prefix) +{ + sb.Append(prefix).AppendFormat("if (%s == null) {\n", name.string()); + sb.Append(prefix).AppendFormat(" %s.writeInt(-1);\n", parcelName.string()); + sb.Append(prefix).Append("} else {\n"); + sb.Append(prefix).AppendFormat(" %s.writeInt(%s.length);\n", parcelName.string(), name.string()); + sb.Append(prefix).Append("}\n"); +} + +void JavaClientProxyCodeEmitter::EmitReadVariable(const String& parcelName, const String& name, + const AutoPtr& type, ParamAttr attribute, StringBuilder& sb, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s %s = %s.readBoolean();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s %s = %s.readByte();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s %s = %s.readShort();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s %s = %s.readInt();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s %s = %s.readLong();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s %s = %s.readFloat();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s %s = %s.readDouble();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s %s = %s.readString();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + if (attribute == ParamAttr::PARAM_OUT && type->EmitJavaType(TypeMode::NO_MODE).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("IRemoteObject %s = %s.readRemoteObject();\n", + name.string(), parcelName.string()); + break; + } + if (attribute == ParamAttr::PARAM_OUT) { + sb.Append(prefix).AppendFormat("%s %s = new %s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + } + sb.Append(prefix).AppendFormat("%s.readSequenceable(%s);\n", parcelName.string(), name.string()); + + break; + case TypeKind::TYPE_INTERFACE: + sb.Append(prefix).AppendFormat("%s %s = %s.asInterface(%s.readRemoteObject());\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), + StubName(type->EmitJavaType(TypeMode::NO_MODE)).string(), parcelName.string()); + break; + case TypeKind::TYPE_LIST: { + sb.Append(prefix).AppendFormat("%s %s = new Array%s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.string()); + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + EmitReadVariable(parcelName, "value", elementType, ParamAttr::PARAM_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.add(value);\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_MAP: { + sb.Append(prefix).AppendFormat("%s %s = new Hash%s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.string()); + + AutoPtr mapType = dynamic_cast(type.Get()); + AutoPtr keyType = mapType->GetKeyType(); + AutoPtr valueType = mapType->GetValueType(); + + EmitReadVariable(parcelName, "key", keyType, ParamAttr::PARAM_IN, sb, prefix + TAB); + EmitReadVariable(parcelName, "value", valueType, ParamAttr::PARAM_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.put(key, value);\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + AutoPtr arrayType = dynamic_cast(type.Get()); + if (attribute == ParamAttr::PARAM_OUT) { + EmitReadOutArrayVariable(parcelName, name, arrayType, sb, prefix); + } else { + EmitReadArrayVariable(parcelName, name, arrayType, attribute, sb, prefix); + } + break; + } + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitReadArrayVariable(const String& parcelName, const String& name, + const AutoPtr& arrayType, ParamAttr attribute, StringBuilder& sb, const String& prefix) +{ + AutoPtr elementType = arrayType->GetElementType(); + switch (elementType->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readBooleanArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readByteArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readShortArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readIntArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readLongArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readFloatArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readDoubleArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readStringArray();\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + sb.Append(prefix).AppendFormat("int size = %s.readInt();\n", parcelName.string()); + sb.Append(prefix).AppendFormat("%s %s = new %s[size];\n", + elementType->EmitJavaType(TypeMode::NO_MODE).string(), name.string(), + elementType->EmitJavaType(TypeMode::NO_MODE).string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < size; ++i) {\n"); + EmitReadVariable(parcelName, "value", elementType, ParamAttr::PARAM_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s[i] = value;\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitReadOutArrayVariable(const String& parcelName, const String& name, + const AutoPtr& arrayType, StringBuilder& sb, const String& prefix) +{ + AutoPtr elementType = arrayType->GetElementType(); + switch (elementType->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s.readBooleanArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s.readByteArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s.readShortArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s.readIntArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s.readLongArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s.readFloatArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s.readDoubleArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s.readStringArray(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + sb.Append(prefix).AppendFormat("%s.readSequenceableArray(%s);\n", parcelName.string(), name.string()); + break; + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitReadOutVariable(const String& parcelName, const String& name, + const AutoPtr& type, StringBuilder& sb, const String& prefix) +{ + switch (type->GetTypeKind()) { + case TypeKind::TYPE_BOOLEAN: + sb.Append(prefix).AppendFormat("%s = %s.readBoolean();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_BYTE: + sb.Append(prefix).AppendFormat("%s = %s.readByte();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SHORT: + sb.Append(prefix).AppendFormat("%s = %s.readShort();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_INT: + case TypeKind::TYPE_FILEDESCRIPTOR: + sb.Append(prefix).AppendFormat("%s = %s.readInt();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_LONG: + sb.Append(prefix).AppendFormat("%s = %s.readLong();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_FLOAT: + sb.Append(prefix).AppendFormat("%s = %s.readFloat();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_DOUBLE: + sb.Append(prefix).AppendFormat("%s = %s.readDouble();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_STRING: + sb.Append(prefix).AppendFormat("%s = %s.readString();\n", + name.string(), parcelName.string()); + break; + case TypeKind::TYPE_SEQUENCEABLE: + if (type->EmitJavaType(TypeMode::NO_MODE).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("%s = %s.readRemoteObject();\n", name.string(), parcelName.string()); + break; + } + sb.Append(prefix).AppendFormat("%s.readSequenceable(%s);\n", parcelName.string(), name.string()); + break; + case TypeKind::TYPE_INTERFACE: + sb.Append(prefix).AppendFormat("%s = %s.asInterface(%s.readRemoteObject());\n", name.string(), + StubName(type->EmitJavaType(TypeMode::NO_MODE)).string(), parcelName.string()); + break; + case TypeKind::TYPE_LIST: { + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.string()); + + AutoPtr listType = dynamic_cast(type.Get()); + AutoPtr elementType = listType->GetElementType(); + + EmitReadVariable(parcelName, "value", elementType, ParamAttr::PARAM_OUT, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.add(value);\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_MAP: { + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.string(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.string()); + + AutoPtr mapType = dynamic_cast(type.Get()); + AutoPtr keyType = mapType->GetKeyType(); + AutoPtr valueType = mapType->GetValueType(); + + EmitReadVariable(parcelName, "key", keyType, ParamAttr::PARAM_OUT, sb, prefix + TAB); + EmitReadVariable(parcelName, "value", valueType, ParamAttr::PARAM_OUT, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.put(key, value);\n", name.string()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::TYPE_ARRAY: { + AutoPtr arrayType = dynamic_cast(type.Get()); + EmitReadOutArrayVariable(parcelName, name, arrayType, sb, prefix); + break; + } + default: + break; + } +} + +void JavaClientProxyCodeEmitter::EmitLocalVariable(const AutoPtr& param, StringBuilder& sb, + const String& prefix) +{ + AutoPtr type = param->GetType(); + if (type->GetTypeKind() == TypeKind::TYPE_SEQUENCEABLE) { + sb.Append(prefix).AppendFormat("%s %s = new %s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), param->GetName().string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + } else if (type->GetTypeKind() == TypeKind::TYPE_LIST) { + sb.Append(prefix).AppendFormat("%s %s = new Array%s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), param->GetName().string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + } else if (type->GetTypeKind() == TypeKind::TYPE_MAP) { + sb.Append(prefix).AppendFormat("%s %s = new Hash%s();\n", + type->EmitJavaType(TypeMode::NO_MODE).string(), param->GetName().string(), + type->EmitJavaType(TypeMode::NO_MODE).string()); + } else { + sb.Append(prefix).AppendFormat("%s %s;\n", type->EmitJavaType(TypeMode::NO_MODE).string(), + param->GetName().string()); + } +} + +String JavaClientProxyCodeEmitter::StubName(const String& name) +{ + return name.StartsWith("I") ? (name.Substring(1) + "Stub") : (name + "Stub"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_client_proxy_code_emitter.h b/tools/hdi-gen/codegen/java_client_proxy_code_emitter.h new file mode 100755 index 000000000..bc077cb3b --- /dev/null +++ b/tools/hdi-gen/codegen/java_client_proxy_code_emitter.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_JAVA_CLIENT_PROXY_CODE_EMITTER_H +#define OHOS_HDI_JAVA_CLIENT_PROXY_CODE_EMITTER_H + +#include "java_code_emitter.h" +#include "util/file.h" + +namespace OHOS { +namespace HDI { +class JavaClientProxyCodeEmitter : public JavaCodeEmitter { +public: + JavaClientProxyCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + : JavaCodeEmitter(ast, targetDirectory) {} + + virtual ~JavaClientProxyCodeEmitter() = default; + + void EmitCode() override; +private: + void EmitProxyFile(); + + void EmitProxyImports(StringBuilder& sb); + + void EmitProxyCorelibImports(StringBuilder& sb); + + void EmitProxySelfDefinedTypeImports(StringBuilder& sb); + + void EmitProxyDBinderImports(StringBuilder& sb); + + void EmitProxyImpl(StringBuilder& sb); + + void EmitProxyConstants(StringBuilder& sb, const String& prefix); + + void EmitProxyConstructor(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodImpls(StringBuilder& sb, const String& prefix); + + void EmitProxyMethodImpl(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitInterfaceMethodParameter(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + void EmitProxyMethodBody(const AutoPtr& method, StringBuilder& sb, const String& prefix); + + void EmitWriteMethodParameter(const AutoPtr& param, const String& parcelName, StringBuilder& sb, + const String& prefix); + + void EmitReadMethodParameter(const AutoPtr& param, const String& parcelName, StringBuilder& sb, + const String& prefix); + + void EmitWriteVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitWriteArrayVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitWriteOutArrayVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitReadVariable(const String& parcelName, const String& name, const AutoPtr& type, + ParamAttr attribute, StringBuilder& sb, const String& prefix); + + void EmitReadArrayVariable(const String& parcelName, const String& name, const AutoPtr& arrayType, + ParamAttr attribute, StringBuilder& sb, const String& prefix); + + void EmitReadOutArrayVariable(const String& parcelName, const String& name, const AutoPtr& arrayType, + StringBuilder& sb, const String& prefix); + + void EmitReadOutVariable(const String& parcelName, const String& name, const AutoPtr& type, + StringBuilder& sb, const String& prefix); + + void EmitLocalVariable(const AutoPtr& param, StringBuilder& sb, const String& prefix); + + String StubName(const String& name); +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_JAVA_CLIENT_PROXY_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_code_emitter.cpp b/tools/hdi-gen/codegen/java_code_emitter.cpp new file mode 100755 index 000000000..cc9adc685 --- /dev/null +++ b/tools/hdi-gen/codegen/java_code_emitter.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/java_code_emitter.h" +#include +#include +#include + +namespace OHOS { +namespace HDI { +const char* JavaCodeEmitter::TAB = " "; + +JavaCodeEmitter::JavaCodeEmitter(const AutoPtr& ast, const String& targetDirectory) + :LightRefCountBase(), ast_(ast), directory_(targetDirectory) +{ + if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) { + interface_ = ast_->GetInterfaceDef(); + } + + if (interface_ != nullptr) { + interfaceName_ = interface_->GetName(); + interfaceFullName_ = interface_->GetNamespace()->ToString() + interfaceName_; + infName_ = interfaceName_.StartsWith("I") ? interfaceName_.Substring(1) : interfaceName_; + proxyName_ = infName_ + "Proxy"; + proxyFullName_ = interface_->GetNamespace()->ToString() + proxyName_; + } else { + infName_ = ast_->GetName(); + } +} + +String JavaCodeEmitter::FileName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + return name.Replace('.', '/'); +} + +void JavaCodeEmitter::EmitLicense(StringBuilder& sb) +{ + if (ast_->GetLicense().IsEmpty()) { + return; + } + sb.Append(ast_->GetLicense()).Append("\n\n"); +} + +void JavaCodeEmitter::EmitPackage(StringBuilder& sb) +{ + sb.AppendFormat("package %s;\n", ast_->GetPackageName().string()); +} + +void JavaCodeEmitter::EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix) +{ + for (size_t i = 0; i < interface_->GetMethodNumber(); i++) { + AutoPtr method = interface_->GetMethod(i); + sb.Append(prefix).AppendFormat( + "private static final int COMMAND_%s = IRemoteObject.MIN_TRANSACTION_ID + %d;\n", + ConstantName(method->GetName()).string(), i); + } +} + +String JavaCodeEmitter::MethodName(const String& name) +{ + if (name.IsEmpty() || islower(name[0])) { + return name; + } + return String::Format("%c%s", tolower(name[0]), name.Substring(1).string()); +} + +String JavaCodeEmitter::ConstantName(const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + StringBuilder sb; + + for (int i = 0; i < name.GetLength(); i++) { + char c = name[i]; + if (isupper(c) != 0) { + if (i > 1) { + sb.Append('_'); + } + sb.Append(c); + } else { + sb.Append(toupper(c)); + } + } + + return sb.ToString(); +} + +String JavaCodeEmitter::SpecificationParam(StringBuilder& paramSb, const String& prefix) +{ + int maxLineLen = 120; + int replaceLen = 2; + String paramStr = paramSb.ToString(); + int preIndex = 0; + int curIndex = 0; + + String insertStr = String::Format("\n%s", prefix.string()); + for (; curIndex < paramStr.GetLength(); curIndex++) { + if (curIndex == maxLineLen && preIndex > 0) { + paramStr.Replace(preIndex, replaceLen, ","); + paramStr.insert(preIndex + 1, insertStr); + } else { + if (paramStr[curIndex] == ',') { + preIndex = curIndex; + } + } + } + return paramStr; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_code_emitter.h b/tools/hdi-gen/codegen/java_code_emitter.h new file mode 100755 index 000000000..5dc400034 --- /dev/null +++ b/tools/hdi-gen/codegen/java_code_emitter.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_JAVA_CODE_EMITTER_H +#define OHOS_HDI_JAVA_CODE_EMITTER_H + +#include "ast/ast.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/string.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +class JavaCodeEmitter : public LightRefCountBase { +public: + JavaCodeEmitter(const AutoPtr& ast, const String& targetDirectory); + + virtual ~JavaCodeEmitter() = default; + + virtual void EmitCode() = 0; + + inline String GetSourceFile() + { + return sourceFileName_; + } + + inline bool isInvaildDir() + { + return directory_.Equals(""); + } + + static String FileName(const String& name); +protected: + + bool CreateDirectory(); + + void EmitLicense(StringBuilder& sb); + + void EmitPackage(StringBuilder& sb); + + void EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix); + + String MethodName(const String& name); + + String ConstantName(const String& name); + + String SpecificationParam(StringBuilder& paramSb, const String& prefix); + + static const char* TAB; + + AutoPtr ast_; + AutoPtr interface_; + + String directory_; + String sourceFileName_; + + String interfaceName_; + String interfaceFullName_; + String infName_; + String proxyName_; + String proxyFullName_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_JAVA_CODE_EMITTER_H \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_code_generator.cpp b/tools/hdi-gen/codegen/java_code_generator.cpp new file mode 100755 index 000000000..853aee68d --- /dev/null +++ b/tools/hdi-gen/codegen/java_code_generator.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "java_code_generator.h" +#include +#include +#include +#include "codegen/java_client_interface_code_emitter.h" +#include "codegen/java_client_proxy_code_emitter.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +const char* JavaCodeGenerator::TAG = "JavaCodeGenerator"; + +bool JavaCodeGenerator::Initializate(const AutoPtr& ast, const String& targetDirectory) +{ + if (ast->GetASTFileType() == ASTFileType::AST_TYPES) { + Logger::E(TAG, "java has no types idl."); + return false; + } + + ast_ = ast; + targetDirectory_ = targetDirectory; + + if (!ResolveDirectory()) { + return false; + } + + AutoPtr clientInterfaceCodeEmitter = new JavaClientInterfaceCodeEmitter(ast_, targetDirectory_); + AutoPtr clientProxyCodeEmitter = new JavaClientProxyCodeEmitter(ast_, targetDirectory_); + + emitters_.push_back(clientInterfaceCodeEmitter); + emitters_.push_back(clientProxyCodeEmitter); + return true; +} + +bool JavaCodeGenerator::Generate() const +{ + for (auto emitter : emitters_) { + if (!emitter->isInvaildDir()) { + emitter->EmitCode(); + } + } + + return true; +} + +bool JavaCodeGenerator::ResolveDirectory() +{ + String packageFilePath = String::Format("%s/%s/", + targetDirectory_.string(), JavaCodeEmitter::FileName(ast_->GetPackageName()).string()); + targetDirectory_ = packageFilePath; + + if (!File::CreateParentDir(targetDirectory_)) { + Logger::E(TAG, "create '%s' directory failed!", targetDirectory_); + return false; + } + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/codegen/java_code_generator.h b/tools/hdi-gen/codegen/java_code_generator.h new file mode 100755 index 000000000..0fea5d53b --- /dev/null +++ b/tools/hdi-gen/codegen/java_code_generator.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_JAVA_CODE_GENERATOR_H +#define OHOS_HDI_JAVA_CODE_GENERATOR_H + +#include "codegen/code_generator.h" +#include "codegen/java_code_emitter.h" + +namespace OHOS { +namespace HDI { +class JavaCodeGenerator : public CodeGenerator { +public: + JavaCodeGenerator() : CodeGenerator(), + emitters_() {} + + ~JavaCodeGenerator() override {}; + + bool Initializate(const AutoPtr& ast, const String& targetDirectory) override; + bool Generate() const override; +private: + bool ResolveDirectory() override; + + static const char* TAG; + std::vector> emitters_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_JAVA_CODE_GENERATOR_H \ No newline at end of file diff --git a/tools/hdi-gen/main.cpp b/tools/hdi-gen/main.cpp new file mode 100755 index 000000000..907efed68 --- /dev/null +++ b/tools/hdi-gen/main.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "codegen/code_generator.h" +#include "codegen/generator_factory.h" +#include "parser/module_parser.h" +#include "util/file.h" +#include "util/logger.h" +#include "util/options.h" + +using namespace OHOS::HDI; + +int main(int argc, char** argv) +{ + Options& options = Options::GetInstance().Parse(argc, argv); + + if (options.HasErrors()) { + options.ShowErrors(); + return 0; + } + + if (options.DoShowUsage()) { + options.ShowUsage(); + return 0; + } + + if (options.DoShowVersion()) { + options.ShowVersion(); + return 0; + } + + if (!options.DoCompile()) { + return 0; + } + + if (options.DoGetHashKey()) { + std::unique_ptr idlFile = std::make_unique(options.GetSourceFile(), int(File::READ)); + if (!idlFile->IsValid()) { + Logger::E("hdi-gen", "open idl file failed!"); + return -1; + } + + printf("%s:%lu\n", idlFile->GetPath().string(), idlFile->GetHashKey()); + return 0; + } + + ModuleParser moduleParser(options); + if (!moduleParser.ParserDependencies()) { + Logger::E("hdi-gen", "Parsing dependencies failed."); + return -1; + } + + if (!moduleParser.CompileFiles()) { + Logger::E("hdi-gen", "Parsing .idl failed."); + return -1; + } + + AutoPtr astModule = moduleParser.GetAStModule(); + + if (!options.DoGenerateCode()) { + return 0; + } + + for (auto& astPair : astModule->GetAllAsts()) { + AutoPtr ast = astPair.second; + GeneratorFactory factory; + AutoPtr codeGen = factory.GetCodeGenerator(options.GetTargetLanguage()); + if (codeGen == nullptr) { + Logger::E("hdi-gen", "new Generate failed."); + return -1; + } + + if (!codeGen->Initializate(ast, options.GetGenerationDirectory())) { + Logger::E("hdi-gen", "Generate initializate failed."); + return -1; + } + + if (!codeGen->Generate()) { + Logger::E("hdi-gen", "Generate \"%s\" codes failed.", options.GetTargetLanguage().string()); + return -1; + } + } + + return 0; +} \ No newline at end of file diff --git a/tools/hdi-gen/parser/Makefile b/tools/hdi-gen/parser/Makefile new file mode 100755 index 000000000..186125b56 --- /dev/null +++ b/tools/hdi-gen/parser/Makefile @@ -0,0 +1,12 @@ +OBJS_DIR:=$(BUILD_DIR)/parser +TARGET = $(OBJS_DIR)/parser.a +SOURCE:=$(wildcard *.cpp) +OBJS:=$(patsubst %.cpp, $(OBJS_DIR)/%.o, $(SOURCE)) + +$(TARGET):$(OBJS) + $(Q) echo $(TARGET) + $(Q) ar -rc $@ $^ + +$(OBJS_DIR)/%.o:%.cpp + $(Q) mkdir -p $(dir $@) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ \ No newline at end of file diff --git a/tools/hdi-gen/parser/file_detail.cpp b/tools/hdi-gen/parser/file_detail.cpp new file mode 100755 index 000000000..019f95438 --- /dev/null +++ b/tools/hdi-gen/parser/file_detail.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "parser/file_detail.h" + +namespace OHOS { +namespace HDI { +void FileDetail::SetFilePath(const String& filePath) +{ + idlFilePath_ = filePath; +#ifdef __MINGW32__ + int index = idlFilePath_.LastIndexOf('\\'); +#else + int index = idlFilePath_.LastIndexOf('/'); +#endif + int end = ((idlFilePath_.LastIndexOf(".idl") == -1) ? + idlFilePath_.LastIndexOf(".idl") : idlFilePath_.LastIndexOf(".idl")); + idlName_ = idlFilePath_.Substring((index == -1) ? 0 : (index + 1), end); +} + +bool FileDetail::AddImport(const String& packageName) +{ + if (imports_.find(packageName) != imports_.end()) { + return false; + } + + imports_.emplace(packageName); + return true; +} + +String FileDetail::Dump() +{ + StringBuilder sb; + sb.AppendFormat("filePath:%s\n", idlFilePath_.string()); + sb.AppendFormat("package:%s\n", packageName_.string()); + sb.AppendFormat("import number:%d\n", imports_.size()); + for (const auto& importName : imports_) { + sb.AppendFormat("import %s\n", importName.string()); + } + return sb.ToString(); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/parser/file_detail.h b/tools/hdi-gen/parser/file_detail.h new file mode 100755 index 000000000..7f78afdd4 --- /dev/null +++ b/tools/hdi-gen/parser/file_detail.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_FILE_DETAIL_H +#define OHOS_HDI_FILE_DETAIL_H + +#include +#include "util/string_builder.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +class FileDetail { +public: + using StringSet = std::unordered_set; + + void SetFilePath(const String& filePath); + + inline String GetFilePath() const + { + return idlFilePath_; + } + + void SetPackageName(const String& packageName) + { + packageName_ = packageName; + } + + inline String GetPackageName() const + { + return packageName_; + } + + inline String GetName() const + { + return idlName_; + } + + inline String GetFullName() const + { + return packageName_ + "." + idlName_; + } + + bool AddImport(const String& packageName); + + void DelImport(const String& packageName) + { + imports_.erase(packageName); + } + + inline size_t GetImportSize() const + { + return imports_.size(); + } + + inline const StringSet& GetImports() const + { + return imports_; + } + + inline static String ImportsToPath(const String& importPkgName) + { + return importPkgName.Replace('.', '/') + ".idl"; + } + + String Dump(); + +private: + String idlFilePath_; + String packageName_; + String idlName_; + StringSet imports_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_FILE_DETAIL_H \ No newline at end of file diff --git a/tools/hdi-gen/parser/lexer.cpp b/tools/hdi-gen/parser/lexer.cpp new file mode 100755 index 000000000..81677a968 --- /dev/null +++ b/tools/hdi-gen/parser/lexer.cpp @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "parser/lexer.h" +#include +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +Lexer::Lexer() +{ + InitializeKeywords(); +} + +Lexer::~Lexer() +{ + if (currentFile_ != nullptr) { + currentFile_->Close(); + } +} + +void Lexer::InitializeKeywords() +{ + keywords_ = { + { "boolean", Token::BOOLEAN }, { "byte", Token::BYTE }, { "callback", Token::CALLBACK }, + { "char", Token::CHAR}, { "double", Token::DOUBLE }, { "enum", Token::ENUM }, + { "extends", Token::EXTENDS }, { "float", Token::FLOAT }, { "full", Token::FULL }, + { "import", Token::IMPORT }, { "in", Token::IN }, { "int", Token::INTEGER }, { "interface", Token::INTERFACE }, + { "List", Token::LIST }, { "lite", Token::LITE }, { "long", Token::LONG }, + { "Map", Token::MAP }, { "oneway", Token::ONEWAY }, { "out", Token::OUT }, + { "package", Token::PACKAGE}, { "sequenceable", Token::SEQUENCEABLE }, { "short", Token::SHORT }, + { "String", Token::STRING }, { "struct", Token::STRUCT }, { "union", Token::UNION }, + { "unsigned", Token::UNSIGNED }, { "FileDescriptor", Token::FILEDESCRIPTOR } + }; + + delimiters_ = { + {'<', Token::ANGLE_BRACKETS_LEFT}, {'>', Token::ANGLE_BRACKETS_RIGHT}, + {'{', Token::BRACES_LEFT}, {'}', Token::BRACES_RIGHT}, + {'[', Token::BRACKETS_LEFT}, {']', Token::BRACKETS_RIGHT}, + {',', Token::COMMA}, {'(', Token::PARENTHESES_LEFT}, + {')', Token::PARENTHESES_RIGHT}, {'.', Token::DOT}, + {':', Token::COLON}, {';', Token::SEMICOLON}, + {'=', Token::ASSIGN} + }; + + tokenDumps_ = { + { Token::ANGLE_BRACKETS_LEFT, "<" }, { Token::ANGLE_BRACKETS_RIGHT, ">"}, { Token::BOOLEAN, "boolean"}, + { Token::BRACES_LEFT, "{"}, { Token::BRACES_RIGHT, "}"}, { Token::BRACKETS_LEFT, "["}, + { Token::BRACKETS_RIGHT, "]"}, { Token::BYTE, "byte"}, { Token::CALLBACK, "callback"}, + { Token::CHAR, "char"}, { Token::COLON, ":"}, { Token::COMMA, ","}, + { Token::DOT, "."}, { Token::DOUBLE, "double"}, { Token::END_OF_FILE, "eof"}, + { Token::ENUM, "enum"}, { Token::EXTENDS, "extends"}, { Token::FLOAT, "float"}, + { Token::FULL, "full"}, { Token::IMPORT, "import"}, { Token::IN, "in"}, + { Token::INTEGER, "int"}, { Token::INTERFACE, "interface"}, { Token::LITE, "lite"}, + { Token::LIST, "List"}, { Token::LONG, "long"}, { Token::MAP, "Map"}, + { Token::ONEWAY, "oneway"}, { Token::OUT, "out"}, { Token::PACKAGE, "package"}, + { Token::SEQUENCEABLE, "sequenceable"}, { Token::STRUCT, "struct"}, { Token::PARENTHESES_LEFT, "("}, + { Token::PARENTHESES_RIGHT, ")"}, { Token::SEMICOLON, ";"}, { Token::SHORT, "short"}, + { Token::STRING, "String"}, { Token::UNION, "union"}, { Token::UNSIGNED, "unsigned"}, + { Token::FILEDESCRIPTOR, "FileDescriptor"} + }; +} + +bool Lexer::OpenSourceFile(const String& filePath) +{ + currentFile_ = std::make_unique(filePath, int(File::READ)); + if (!currentFile_->IsValid()) { + return false; + } + + return true; +} + +Token Lexer::GetToken(bool skipComment) +{ + if (!havePeek_) { + currentToken_ = ReadToken(skipComment); + } + havePeek_ = false; + return currentToken_; +} + +Token Lexer::PeekToken(bool skipComment) +{ + if (!havePeek_) { + currentToken_ = ReadToken(skipComment); + havePeek_ = true; + } + return currentToken_; +} + +Token Lexer::ReadToken(bool skipComment) +{ + while (!currentFile_->IsEof()) { + char c = currentFile_->GetChar(); + tokenLineNo_ = currentFile_->GetCharLineNumber(); + tokenColumnNo_ = currentFile_->GetCharColumnNumber(); + if (IsSpace(c)) { + continue; + } else if (IsAlphabet(c) || c == '_') { + Token t = ReadIdentifier(c); + return t; + } else if (IsDecimalDigital(c)) { + Token t = ReadDecimalDigital(c); + return t; + } + + auto iter = delimiters_.find(c); + if (iter != delimiters_.end()) { + return iter->second; + } + + if (c == '/') { + if (currentFile_->PeekChar() == '/') { + ReadLineComment(c); + if (!skipComment) { + return currentToken_; + } + continue; + } else if (currentFile_->PeekChar() == '*') { + ReadBlockComment(c); + if (!skipComment) { + return currentToken_; + } + continue; + } + currentToken_ = Token::UNKNOWN; + return currentToken_; + } + + currentToken_ = Token::UNKNOWN; + return currentToken_; + } + currentToken_ = Token::END_OF_FILE; + return currentToken_; +} + +Token Lexer::ReadIdentifier(char c) +{ + StringBuilder sb; + + sb.Append(c); + while (!currentFile_->IsEof()) { + c = currentFile_->PeekChar(); + if (IsAlphabet(c) || c == '_' || IsDecimalDigital(c) || c == '.') { + c = currentFile_->GetChar(); + sb.Append(c); + continue; + } + if (IsSpace(c)) { + currentFile_->GetChar(); + } + break; + } + String key = sb.ToString(); + auto it = keywords_.find(key); + if (it == keywords_.end()) { + identifier_ = key; + currentToken_ = Token::IDENTIFIER; + } else { + currentToken_ = it->second; + } + + return currentToken_; +} + +Token Lexer::ReadDecimalDigital(char c) +{ + StringBuilder sb; + sb.Append(c); + while (!currentFile_->IsEof()) { + c = currentFile_->PeekChar(); + if (IsDecimalDigital(c)) { + c = currentFile_->GetChar(); + sb.Append(c); + continue; + } else { + break; + } + } + digit_ = sb.ToString(); + currentToken_ = Token::DIGIT; + return currentToken_; +} + +Token Lexer::ReadLineComment(char c) +{ + StringBuilder sb; + + sb.Append(c); + while (!currentFile_->IsEof()) { + c = currentFile_->GetChar(); + if (c == '\n') { + break; + } + sb.Append(c); + } + comment_ = sb.ToString(); + currentToken_ = Token::COMMENT_LINE; + return currentToken_; +} + +Token Lexer::ReadBlockComment(char c) +{ + StringBuilder sb; + + sb.Append(c); + while (!currentFile_->IsEof()) { + c = currentFile_->GetChar(); + sb.Append(c); + if (c == '*' && currentFile_->PeekChar() == '/') { + c = currentFile_->GetChar(); + sb.Append(c); + break; + } + } + comment_ = sb.ToString(); + currentToken_ = Token::COMMENT_BLOCK; + return currentToken_; +} + +void Lexer::SkipCurrentLine() +{ + while (!currentFile_->IsEof()) { + char c = currentFile_->GetChar(); + if (c == '\n') { + currentFile_->GetChar(); + return; + } + } +} + +bool Lexer::SkipCurrentLine(char untilChar) +{ + while (!currentFile_->IsEof()) { + int c = currentFile_->GetChar(); + if (c == untilChar) { + return true; + } + if (c == '\n') { + currentFile_->GetChar(); + return false; + } + } + return true; +} + +void Lexer::Skip(char untilChar) +{ + while (!currentFile_->IsEof()) { + int c = currentFile_->GetChar(); + if (c == untilChar) { + return; + } + } +} + +void Lexer::SkipEof() +{ + while (!currentFile_->IsEof()) {} +} + +int Lexer::TokenToChar(Token token) +{ + switch (token) { + case Token::ANGLE_BRACKETS_LEFT: + return '<'; + case Token::ANGLE_BRACKETS_RIGHT: + return '>'; + case Token::BRACES_LEFT: + return '{'; + case Token::BRACES_RIGHT: + return '}'; + case Token::BRACKETS_LEFT: + return '['; + case Token::BRACKETS_RIGHT: + return ']'; + case Token::COMMA: + return ','; + case Token::DOT: + return '.'; + case Token::PARENTHESES_LEFT: + return '('; + case Token::PARENTHESES_RIGHT: + return ')'; + case Token::COLON: + return ':'; + case Token::SEMICOLON: + return ';'; + case Token::BOOLEAN: + case Token::BYTE: + case Token::CHAR: + case Token::COMMENT_BLOCK: + case Token::COMMENT_LINE: + case Token::DOUBLE: + case Token::END_OF_FILE: + case Token::FLOAT: + case Token::IDENTIFIER: + case Token::IN: + case Token::INTEGER: + case Token::LIST: + case Token::LONG: + case Token::MAP: + case Token::ONEWAY: + case Token::OUT: + case Token::SEQUENCEABLE: + case Token::SHORT: + case Token::STRING: + default: + return -1; + } +} + +String Lexer::DumpToken() const +{ + auto iter = tokenDumps_.find(currentToken_); + if (iter != tokenDumps_.end()) { + return iter->second; + } + + if (currentToken_ == Token::COMMENT_BLOCK || currentToken_ == Token::COMMENT_LINE) { + return comment_; + } + + if (currentToken_ == Token::IDENTIFIER) { + return identifier_; + } + + return "unknown token"; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/parser/lexer.h b/tools/hdi-gen/parser/lexer.h new file mode 100755 index 000000000..dde09fda6 --- /dev/null +++ b/tools/hdi-gen/parser/lexer.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_LEXER_H +#define OHOS_HDI_LEXER_H + +#include +#include +#include +#include +#include "parser/token.h" +#include "util/file.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class Lexer { +public: + Lexer(); + + ~Lexer(); + + bool OpenSourceFile(const String& filePath); + + Token GetToken(bool skipComment = true); + + Token PeekToken(bool skipComment = true); + + inline String GetIdentifier() const + { + return identifier_; + } + + inline unsigned long GetDigit() const + { + return std::atoll(digit_.string()); + } + + inline String GetComment() const + { + return comment_; + } + + void SkipCurrentLine(); + + bool SkipCurrentLine(char untilChar); + + void Skip(char untilChar); + + void SkipEof(); + + inline String GetFilePath() const + { + if (currentFile_ == nullptr) { + return String(""); + } + + return currentFile_->GetPath(); + } + + String DumpToken() const; + + inline int GetTokenLineNumber() const + { + return tokenLineNo_; + } + + inline int GetTokenColumnNumber() const + { + return tokenColumnNo_; + } + + static int TokenToChar(Token token); + +private: + void InitializeKeywords(); + + Token ReadToken(bool skipComment); + + Token ReadIdentifier(char c); + + Token ReadDecimalDigital(char c); + + Token ReadLineComment(char c); + + Token ReadBlockComment(char c); + + inline static bool IsAlphabet(char c) + { + return isalpha(c); + } + + inline static bool IsDecimalDigital(char c) + { + return isdigit(c); + } + + inline static bool IsSpace(char c) + { + return isspace(c); + } + + static const char* TAG; + std::unordered_map keywords_; + std::unordered_map delimiters_; + std::unordered_map tokenDumps_; + Token currentToken_ = Token::UNKNOWN; + int tokenLineNo_ = 0; + int tokenColumnNo_ = 0; + String identifier_; + String digit_; + String comment_; + bool havePeek_ = false; + std::unique_ptr currentFile_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_LEXER_H \ No newline at end of file diff --git a/tools/hdi-gen/parser/module_parser.cpp b/tools/hdi-gen/parser/module_parser.cpp new file mode 100755 index 000000000..d2f3b2586 --- /dev/null +++ b/tools/hdi-gen/parser/module_parser.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "parser/module_parser.h" +#include + +namespace OHOS { +namespace HDI { +const char* ModuleParser::TAG = "ModuleParser"; + +bool ModuleParser::ParserDependencies() +{ + if (!ParserAllImports(option_.GetSourceFile())) { + Logger::E(TAG, "Parsing all idl file failed."); + return false; + } + + if (!CheckCircularReference()) { + Logger::E(TAG, "has circle reference."); + return false; + } + + return true; +} + +bool ModuleParser::CompileFiles() +{ + std::unique_ptr parserPtr = std::make_unique(option_, module_); + + for (const auto& filePath : compileFiles_) { + if (!parserPtr->Parse(filePath)) { + Logger::E(TAG, "parse %s failed", filePath.string()); + return false; + } + } + + return true; +} + +bool ModuleParser::ParserAllImports(const String& rootFilePath) +{ + std::unique_ptr parserPtr = std::make_unique(option_); + std::shared_ptr fileInfo = nullptr; + + if (!parserPtr->Parse(rootFilePath, fileInfo)) { + return false; + } + + if (fileInfo == nullptr) { + return false; + } + + sourceFiles_[fileInfo->GetFullName()] = fileInfo; + return ParserAllImportsRecursion(fileInfo); +} + +bool ModuleParser::ParserAllImportsRecursion(const std::shared_ptr& fileInfo) +{ + for (const auto& importName : fileInfo->GetImports()) { + if (sourceFiles_.find(importName) != sourceFiles_.end()) { + continue; + } + + String filePath = FileDetail::ImportsToPath(importName); + + std::unique_ptr parserPtr = std::make_unique(option_); + std::shared_ptr file = nullptr; + if (!parserPtr->Parse(filePath, file)) { + Logger::E(TAG, "Parsing %s failed.", filePath.string()); + return false; + } + + if (file == nullptr) { + Logger::E(TAG, "Parsing %s failed, generator filedetail is nullptr.", filePath.string()); + return false; + } + + sourceFiles_[file->GetFullName()] = file; + + if (!ParserAllImportsRecursion(file)) { + Logger::E(TAG, "Parsing %s file's import failed.", file->GetFilePath().string()); + return false; + } + } + + return true; +} + +bool ModuleParser::CheckCircularReference() +{ + std::queue> fileQueue; + for (const auto& filePair : sourceFiles_) { + std::shared_ptr fileNode = filePair.second; + if (fileNode->GetImportSize() == 0) { + fileQueue.push(fileNode); + } + } + + compileFiles_.clear(); + while (!fileQueue.empty()) { + std::shared_ptr importFile = fileQueue.front(); + fileQueue.pop(); + compileFiles_.push_back(importFile->GetFilePath()); + + for (const auto& filePair : sourceFiles_) { + std::shared_ptr fileNode = filePair.second; + if (fileNode->GetImportSize() > 0) { + fileNode->DelImport(importFile->GetFullName()); + if (fileNode->GetImportSize() == 0) { + fileQueue.push(fileNode); + } + } + } + } + + if (compileFiles_.size() < sourceFiles_.size()) { + return false; + } + + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/parser/module_parser.h b/tools/hdi-gen/parser/module_parser.h new file mode 100755 index 000000000..ba94b8f34 --- /dev/null +++ b/tools/hdi-gen/parser/module_parser.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_MODULE_PARSER_H +#define OHOS_HDI_MODULE_PARSER_H + +#include +#include "parser/file_detail.h" +#include "parser/parser.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +class ModuleParser { +public: + using FileDetailMap = std::unordered_map, StringHashFunc, StringEqualFunc>; + + explicit ModuleParser(const Options& option) : option_(option), + sourceFiles_(), + searchedFile_(), + traceFilePtr_(nullptr), + allCirclesFile_(), + compileFiles_(), + module_(new ASTModule()) {} + + ~ModuleParser() {} + + // parser file and circular reference + bool ParserDependencies(); + + bool CompileFiles(); + + inline AutoPtr GetAStModule() const + { + return module_; + } + +private: + // parse all idl file involved in compilation. + bool ParserAllImports(const String& rootFilePath); + + bool ParserAllImportsRecursion(const std::shared_ptr& fileInfo); + + // check circular reference and reverse topology sorting of all idl file + bool CheckCircularReference(); + + static const char* TAG; + const Options& option_; + FileDetailMap sourceFiles_; + + std::set searchedFile_; + std::shared_ptr> traceFilePtr_; + std::vector> allCirclesFile_; + + std::vector compileFiles_; + + AutoPtr module_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_MODULE_PARSER_H \ No newline at end of file diff --git a/tools/hdi-gen/parser/parser.cpp b/tools/hdi-gen/parser/parser.cpp new file mode 100755 index 000000000..73a1499db --- /dev/null +++ b/tools/hdi-gen/parser/parser.cpp @@ -0,0 +1,1443 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "parser/parser.h" +#include "ast/ast_array_type.h" +#include "ast/ast_enum_type.h" +#include "ast/ast_list_type.h" +#include "ast/ast_map_type.h" +#include "ast/ast_parameter.h" +#include "ast/ast_sequenceable_type.h" +#include "ast/ast_struct_type.h" +#include "ast/ast_union_type.h" +#include "util/logger.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +const char* Parser::TAG = "Parser"; + +Parser::Parser(const Options& options, const AutoPtr& module) + :options_(options), lexer_(nullptr), errors_(nullptr), ast_(nullptr), astModule_(module) +{} + +bool Parser::Parse(const String& sourceFile) +{ + lexer_ = std::make_shared(); + bool ret = lexer_->OpenSourceFile(sourceFile); + if (!ret) { + Logger::E(TAG, "Fail to open file '%s'.", sourceFile.string()); + return false; + } + + ret = ParseFile(); + ret = CheckIntegrity() && ret; + ret = AddAst() && ret; + if (!ret || errors_ != nullptr) { + ShowError(); + return false; + } + + if (options_.DoDumpAST()) { + String astStr = ast_->Dump(""); + printf("%s\n", astStr.string()); + } + + return ret; +} + +bool Parser::Parse(const String& sourceFile, std::shared_ptr& fileDetailPtr) +{ + lexer_ = std::make_shared(); + bool ret = lexer_->OpenSourceFile(sourceFile); + if (!ret) { + Logger::E(TAG, "Fail to open file '%s'.", sourceFile.string()); + return false; + } + + ret = ParseIdlDetail(fileDetailPtr); + if (!ret) { + ShowError(); + return false; + } + + return ret; +} + +bool Parser::ParseIdlDetail(std::shared_ptr& fileDetailPtr) +{ + bool ret = true; + fileDetailPtr = std::make_shared(); + fileDetailPtr->SetFilePath(lexer_->GetFilePath()); + + Token token; + while ((token = lexer_->PeekToken()) != Token::END_OF_FILE) { + switch (token) { + case Token::PACKAGE: + ret = ParseIdlPackage(fileDetailPtr) && ret; + break; + case Token::IMPORT: + ret = ParseIdlImport(fileDetailPtr) && ret; + break; + default: + lexer_->GetToken(); + break; + } + } + lexer_->GetToken(); + return ret; +} + +bool Parser::ParseIdlPackage(std::shared_ptr& fileDetailPtr) +{ + lexer_->GetToken(); + String packageName; + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + if (token == Token::SEMICOLON) { + LogError(String::Format("expected identifier before ';'.")); + lexer_->GetToken(); + } else { + LogError(String::Format("'%s' is an invalid package name.", lexer_->DumpToken().string())); + } + lexer_->SkipCurrentLine(); + return false; + } else { + lexer_->GetToken(); + packageName = lexer_->GetIdentifier(); + token = lexer_->PeekToken(); + } + + if (token != Token::SEMICOLON) { + LogError(String::Format("expected ';' before '%s'", lexer_->DumpToken().string())); + return false; + } + + // read ';' + lexer_->GetToken(); + + if (packageName.IsEmpty()) { + LogError(String("Package name is not expected.")); + return false; + } else if (!IsValidTypeName(packageName)) { + LogError(String::Format("Package name '%s' is illegal.", packageName.string())); + return false; + } else if (!CheckPackageName(lexer_->GetFilePath(), packageName)) { + LogError(String::Format("Package name '%s' does not match file apth '%s'.", + packageName.string(), lexer_->GetFilePath().string())); + return false; + } + + fileDetailPtr->SetPackageName(packageName); + + return true; +} + +bool Parser::ParseIdlImport(std::shared_ptr& fileDetailPtr) +{ + lexer_->GetToken(); + + String importPkgName; + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + if (token == Token::SEMICOLON) { + LogError(String::Format("expected identifier before ';'.")); + lexer_->GetToken(); + } else { + LogError(String::Format("'%s' is an invalid import package name.", lexer_->DumpToken().string())); + } + lexer_->SkipCurrentLine(); + return false; + } + lexer_->GetToken(); + importPkgName = lexer_->GetIdentifier(); + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("expected ';' before '%s'.", lexer_->DumpToken().string())); + return false; + } + + // read ';' + lexer_->GetToken(); + if (importPkgName.IsEmpty()) { + LogError(String("import package name is not expected.")); + return false; + } else if (!IsValidTypeName(importPkgName)) { + LogError(String::Format("import package name '%s' is illegal.", importPkgName.string())); + return false; + } + + if (!fileDetailPtr->AddImport(importPkgName)) { + LogError(String::Format("the package of '%s' has been imported.", importPkgName.string())); + return false; + } + + return true; +} + +bool Parser::ParseFile() +{ + bool ret = true; + + ast_ = new AST(); + ast_->SetIdlFile(lexer_->GetFilePath()); + + ParseLicense(); + + Token token; + while ((token = lexer_->PeekToken()) != Token::END_OF_FILE) { + switch (token) { + case Token::PACKAGE: + ret = ParsePackageName() && ret; + continue; + case Token::IMPORT: + ret = ParseImport() && ret; + continue; + case Token::SEQUENCEABLE: + ret = ParseSequenceable() && ret; + continue; + case Token::BRACKETS_LEFT: + ret = ParseAttribute() && ret; + continue; + case Token::INTERFACE: + ret = ParseInterface() && ret; + continue; + case Token::COMMENT_LINE: + lexer_->GetToken(); + continue; + case Token::ENUM: + ret = ParseEnumDefine() && ret; + continue; + case Token::STRUCT: + ret = ParseStructDefine() && ret; + continue; + case Token::UNION: + ret = ParseUnionDefine() && ret; + continue; + default: + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->GetToken(); + ret = false; + continue; + } + } + lexer_->GetToken(); + + // here, ast_ cannot be a sequenceable idl + if (ast_->GetInterfaceDef() != nullptr) { + if (ast_->GetInterfaceDef()->IsCallback()) { + ast_->SetAStFileType(ASTFileType::AST_ICALLBACK); + } else { + ast_->SetAStFileType(ASTFileType::AST_IFACE); + } + } else { + ast_->SetAStFileType(ASTFileType::AST_TYPES); + } + + return ret; +} + +bool Parser::ParseLicense() +{ + Token token = lexer_->PeekToken(false); + if (token != Token::COMMENT_BLOCK) { + return false; + } + + lexer_->GetToken(false); + + ast_->SetLicense(lexer_->GetComment()); + + return true; +} + +bool Parser::ParsePackageName() +{ + lexer_->GetToken(); + + String packageFullName; + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + if (token == Token::SEMICOLON) { + LogError(String::Format("expected identifier before ';'.")); + } else { + LogError(String::Format("'%s' is an invalid package name.", lexer_->DumpToken().string())); + } + lexer_->SkipCurrentLine(); + lexer_->GetToken(); + return false; + } else { + lexer_->GetToken(); + packageFullName = lexer_->GetIdentifier(); + token = lexer_->PeekToken(); + } + + if (token != Token::SEMICOLON) { + LogError(String::Format("expected ';' before '%s'", lexer_->DumpToken().string())); + return false; + } + + // read ';' + lexer_->GetToken(); + + if (packageFullName.IsEmpty()) { + LogError(String("Package name is not expected.")); + return false; + } else if (!IsValidTypeName(packageFullName)) { + LogError(String::Format("Package name '%s' is illegal.", packageFullName.string())); + return false; + } else if (!CheckPackageName(lexer_->GetFilePath(), packageFullName)) { + LogError(String::Format("Package name '%s' does not match file apth '%s'.", + packageFullName.string(), lexer_->GetFilePath().string())); + return false; + } + + ast_->SetPackageName(packageFullName); + + return true; +} + +bool Parser::ParseImport() +{ + lexer_->GetToken(); + + String packageFullName; + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + if (token == Token::SEMICOLON) { + LogError(String::Format("expected identifier before ';'.")); + } else { + LogError(String::Format("%s is an invalid import package name.", lexer_->DumpToken().string())); + } + lexer_->SkipCurrentLine(); + lexer_->GetToken(); + return false; + } + lexer_->GetToken(); + packageFullName = lexer_->GetIdentifier(); + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("expected ';' before '%s'.", lexer_->DumpToken().string())); + return false; + } + + // read ';' + lexer_->GetToken(); + if (packageFullName.IsEmpty()) { + LogError(String("import package name is not expected.")); + return false; + } else if (!IsValidTypeName(packageFullName)) { + LogError(String::Format("import package name '%s' is illegal.", packageFullName.string())); + return false; + } + + AutoPtr importAst = astModule_->GetAst(packageFullName); + if (importAst == nullptr) { + LogError(String("not find import ast.")); + return false; + } + + if (!ast_->AddImport(importAst)) { + LogError(String::Format("the package '%s' has been import", packageFullName.string())); + return false; + } + + return true; +} + +bool Parser::ParseSequenceable() +{ + lexer_->GetToken(); + String classFullName; + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + if (token == Token::SEMICOLON) { + LogError(String::Format("expected identifier before ';'.")); + } else { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + } + lexer_->SkipCurrentLine(); + lexer_->GetToken(); + return false; + } + lexer_->GetToken(); + classFullName = lexer_->GetIdentifier(); + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("expected ';' before '%s'.", lexer_->DumpToken().string())); + return false; + } + // read ';' + lexer_->GetToken(); + + if (classFullName.IsEmpty()) { + LogError(String("class name is not expected.")); + return false; + } else if (!IsValidTypeName(classFullName)) { + LogError(String::Format("class name '%s' is illegal.", classFullName.string())); + return false; + } + + AutoPtr sequenceable = new ASTSequenceableType(); + int index = classFullName.LastIndexOf('.'); + if (index != -1) { + sequenceable->SetName(classFullName.Substring(index + 1)); + sequenceable->SetNamespace(ast_->ParseNamespace(classFullName.Substring(0, index + 1))); + } else { + sequenceable->SetName(classFullName); + } + + AutoPtr sequenceableAst = new AST(); + sequenceableAst->SetFullName(classFullName); + sequenceableAst->AddSequenceableDef(sequenceable); + sequenceableAst->SetAStFileType(ASTFileType::AST_SEQUENCEABLE); + ast_->AddImport(sequenceableAst); + + return true; +} + +bool Parser::ParseAttribute() +{ + bool ret = true; + AutoPtr attributes = nullptr; + + // read '[' + Token token = lexer_->GetToken(); + if (token == Token::BRACKETS_LEFT) { + attributes = new Attribute(); + token = lexer_->PeekToken(); + while (token != Token::BRACKETS_RIGHT) { + switch (token) { + case Token::ONEWAY: + attributes->isOneWay = true; + break; + case Token::CALLBACK: + attributes->isCallback = true; + break; + case Token::FULL: + attributes->isFull = true; + break; + case Token::LITE: + attributes->isLite = true; + break; + default: { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(Lexer::TokenToChar(Token::BRACKETS_RIGHT)); + lexer_->GetToken(); + return false; + } + } + lexer_->GetToken(); + token = lexer_->PeekToken(); + if (token == Token::COMMA) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token == Token::BRACKETS_RIGHT) { + break; + } else { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + return false; + } + } + lexer_->GetToken(); + } + + token = lexer_->PeekToken(); + switch (token) { + case Token::ENUM: + ret = ParseEnumDefine(attributes) && ret; + break; + case Token::STRUCT: + ret = ParseStructDefine(attributes) && ret; + break; + case Token::UNION: + ret = ParseUnionDefine(attributes) && ret; + break; + case Token::INTERFACE: + ret = ParseInterface(attributes) && ret; + break; + default: { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + return false; + } + } + return ret; +} + +bool Parser::ParseInterface(const AutoPtr& attributes) +{ + lexer_->GetToken(); + bool ret = true; + bool isOneWay = false; + bool isCallback = false; + bool isFull = false; + bool isLite = false; + String interfaceName; + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->Skip('}'); + lexer_->GetToken(); + return false; + } + lexer_->GetToken(); + + interfaceName = lexer_->GetIdentifier(); + + token = lexer_->PeekToken(); + if (token != Token::BRACES_LEFT) { + LogError(String::Format("expected '{' after the '%s'.", lexer_->DumpToken().string())); + lexer_->Skip('}'); + lexer_->GetToken(); + return false; + } + + // read '{' + lexer_->GetToken(); + + if (interfaceName.IsEmpty()) { + LogError(String("interface name is expected.")); + return false; + } + + AutoPtr interface = new ASTInterfaceType(); + interface->SetName(interfaceName); + interface->SetNamespace(ast_->ParseNamespace(ast_->GetFullName())); + + if (!interface->GetName().Equals(ast_->GetName())) { + LogError(String::Format("Module name '%s' is not equal to interface name '%s'.", + ast_->GetName().string(), interface->GetName().string())); + } + + interface->SetLicense(ast_->GetLicense()); + if (attributes != nullptr) { + interface->SetOneWay(attributes->isOneWay); + interface->SetCallback(attributes->isCallback); + interface->SetFull(attributes->isFull); + interface->SetLite(attributes->isLite); + } + + while (token != Token::BRACES_RIGHT && token != Token::END_OF_FILE) { + ret = ParseMethod(interface) && ret; + token = lexer_->PeekToken(); + } + + if (token != Token::BRACES_RIGHT) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipEof(); + return false; + } + + lexer_->GetToken(); + + if (ast_->GetInterfaceDef() != nullptr) { + LogError(String::Format("an interface class already exists int idl file.")); + lexer_->SkipEof(); + return false; + } + + ast_->AddInterfaceDef(interface); + + return ret; +} + +bool Parser::ParseMethod(const AutoPtr& interface) +{ + bool ret = true; + AutoPtr attributes = new Attribute(); + ret = ParseMethodAttr(interface, attributes) && ret; + if (!ret) { + return false; + } + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("Method name is expected.")); + if (token == Token::BRACES_RIGHT) { + return false; + } + // jump over colon + lexer_->GetToken(); + while (token != Token::SEMICOLON && token != Token::END_OF_FILE) { + token = lexer_->PeekToken(); + if (token == Token::BRACES_RIGHT) { + break; + } + lexer_->GetToken(); + } + return false; + } + token = lexer_->GetToken(); + + AutoPtr method = new ASTMethod(); + method->SetName(lexer_->GetIdentifier()); + + if (attributes != nullptr) { + method->SetOneWay(attributes->isOneWay); + method->SetFull(attributes->isFull); + method->SetLite(attributes->isLite); + } + + token = lexer_->PeekToken(); + if (token != Token::PARENTHESES_LEFT) { + LogError(String("'(' is expected.")); + if (token == Token::BRACES_RIGHT) { + return false; + } + // jump over colon + lexer_->GetToken(); + while (token != Token::SEMICOLON && token != Token::END_OF_FILE) { + token = lexer_->PeekToken(); + if (token == Token::BRACES_RIGHT) { + break; + } + lexer_->GetToken(); + } + return false; + } + token = lexer_->GetToken(); + + token = lexer_->PeekToken(); + while (token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) { + ret = ParseParameter(method) && ret; + token = lexer_->PeekToken(); + if (token == Token::COMMA) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token != Token::PARENTHESES_RIGHT) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(';'); + lexer_->GetToken(); + return false; + } + } + + lexer_->GetToken(); + if (!ret) { + lexer_->SkipCurrentLine(); + return false; + } + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String("';' is expected.")); + return false; + } + lexer_->GetToken(); + interface->AddMethod(method); + return ret; +} + +bool Parser::ParseMethodAttr(const AutoPtr& interface, const AutoPtr& attributes) +{ + if (interface == nullptr || attributes == nullptr) { + return false; + } + + Token token = lexer_->PeekToken(); + if (token == Token::BRACES_RIGHT) { + LogError(String::Format("%s has no method.", interface->GetName().string())); + lexer_->SkipCurrentLine(Lexer::TokenToChar(Token::BRACES_RIGHT)); + lexer_->GetToken(); + return false; + } + + if (token == Token::BRACKETS_LEFT) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + while (token != Token::BRACKETS_RIGHT) { + switch (token) { + case Token::ONEWAY: + attributes->isOneWay = true; + break; + case Token::FULL: + attributes->isFull = true; + break; + case Token::LITE: + attributes->isLite = true; + break; + default: { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(Lexer::TokenToChar(Token::BRACKETS_RIGHT)); + lexer_->GetToken(); + return false; + } + } + lexer_->GetToken(); + token = lexer_->PeekToken(); + if (token == Token::COMMA) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token == Token::BRACKETS_RIGHT) { + } else { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(Lexer::TokenToChar(Token::BRACKETS_RIGHT)); + lexer_->GetToken(); + return false; + } + } + lexer_->GetToken(); + } + return true; +} + +bool Parser::ParseParameter(const AutoPtr& method) +{ + Token token = lexer_->PeekToken(); + if (token != Token::BRACKETS_LEFT) { + LogError(String("'[' is expected.")); + while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } + return false; + } + lexer_->GetToken(); + + AutoPtr parameter = new ASTParameter(); + if (!ParseParamAttr(parameter)) { + return false; + } + + token = lexer_->PeekToken(); + if (token != Token::BRACKETS_RIGHT) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + while (token != Token::SEMICOLON && token != Token::END_OF_FILE) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } + return false; + } + lexer_->GetToken(); + AutoPtr type = ParseType(); + if (type == nullptr) { + while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } + return false; + } + + token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("Parameter name is expected.")); + while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } + return false; + } + lexer_->GetToken(); + parameter->SetName(lexer_->GetIdentifier()); + parameter->SetType(type); + method->AddParameter(parameter); + return true; +} + +bool Parser::ParseParamAttr(const AutoPtr& parameter) +{ + if (parameter == nullptr) { + return false; + } + Token token = lexer_->PeekToken(); + if (token == Token::IN) { + lexer_->GetToken(); + parameter->SetAttribute(ParamAttr::PARAM_IN); + } else if (token == Token::OUT) { + lexer_->GetToken(); + parameter->SetAttribute(ParamAttr::PARAM_OUT); + } else { + LogError(String::Format("'%s' is not a parameter property, it must be 'in' or 'out'.", + lexer_->DumpToken().string())); + while (token != Token::SEMICOLON && token != Token::END_OF_FILE) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } + return false; + } + return true; +} + +AutoPtr Parser::ParseType() +{ + int typeLineNo = lexer_->GetTokenLineNumber(); + int typeColumnNo = lexer_->GetTokenColumnNumber(); + AutoPtr type; + + Token token = lexer_->PeekToken(); + if (IsPrimitiveType(token)) { + lexer_->GetToken(); + type = ast_->FindType(lexer_->DumpToken()); + } else if (token == Token::LIST) { + type = ParseList(); + } else if (token == Token::MAP) { + type = ParseMap(); + } else if (token == Token::ENUM || token == Token::STRUCT || token == Token::UNION) { + type = ParseCustomType(); + } else if (token == Token::IDENTIFIER) { + lexer_->GetToken(); + type = ast_->FindType(lexer_->GetIdentifier()); + } else if (token == Token::UNSIGNED) { + String unsignedStr = lexer_->DumpToken(); + lexer_->GetToken(); + token = lexer_->PeekToken(); + switch (token) { + case Token::CHAR: + case Token::SHORT: + case Token::INTEGER: + case Token::LONG: { + type = ast_->FindType(unsignedStr + " " + lexer_->DumpToken()); + lexer_->GetToken(); + break; + } + default: { + LogError(typeLineNo, typeColumnNo, + String::Format("'unsigned %s' type was not declared in the idl file.", + lexer_->DumpToken().string())); + return nullptr; + } + } + } else { + LogError(typeLineNo, typeColumnNo, String("Invalid type name.")); + return nullptr; + } + + if (type == nullptr) { + LogError(typeLineNo, typeColumnNo, String::Format("Type '%s' was not declared in any idl file.", + lexer_->DumpToken().string())); + } + + token = lexer_->PeekToken(); + if (token == Token::BRACKETS_LEFT) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + if (token != Token::BRACKETS_RIGHT) { + LogError(typeLineNo, typeColumnNo, String("']' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + if (type != nullptr) { + AutoPtr arrayType = new ASTArrayType(); + arrayType->SetElementType(type); + + type = ast_->FindType(arrayType->ToString()); + if (type == nullptr) { + ast_->AddType(arrayType.Get()); + type = static_cast(arrayType.Get()); + } + } + } + + if (!CheckType(typeLineNo, typeColumnNo, type)) { + return nullptr; + } + + return type; +} + +AutoPtr Parser::ParseList() +{ + lexer_->GetToken(); + + Token token = lexer_->PeekToken(); + if (token != Token::ANGLE_BRACKETS_LEFT) { + LogError(String("'<' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + AutoPtr type = ParseType(); + if (type == nullptr) { + lexer_->SkipCurrentLine('>'); + lexer_->GetToken(); + return nullptr; + } + + token = lexer_->PeekToken(); + if (token != Token::ANGLE_BRACKETS_RIGHT) { + LogError(String("'>' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + AutoPtr list = new ASTListType(); + list->SetElementType(type); + + AutoPtr ret = ast_->FindType(list->ToString()); + if (ret == nullptr) { + ast_->AddType(list.Get()); + ret = list.Get(); + } + + return ret; +} + +AutoPtr Parser::ParseMap() +{ + lexer_->GetToken(); + + Token token = lexer_->PeekToken(); + if (token != Token::ANGLE_BRACKETS_LEFT) { + LogError(String("'<' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + AutoPtr keyType = ParseType(); + if (keyType == nullptr) { + lexer_->SkipCurrentLine('>'); + return nullptr; + } + + token = lexer_->PeekToken(); + if (token != Token::COMMA) { + LogError(String("',' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + AutoPtr valueType = ParseType(); + if (valueType == nullptr) { + lexer_->SkipCurrentLine('>'); + return nullptr; + } + + token = lexer_->PeekToken(); + if (token != Token::ANGLE_BRACKETS_RIGHT) { + LogError(String("'>' is expected.")); + return nullptr; + } + lexer_->GetToken(); + + AutoPtr map = new ASTMapType(); + map->SetKeyType(keyType); + map->SetValueType(valueType); + + AutoPtr ret = ast_->FindType(map->ToString()); + if (ret == nullptr) { + ast_->AddType(map.Get()); + ret = map.Get(); + } + + return ret; +} + +AutoPtr Parser::ParseCustomType() +{ + Token token = lexer_->GetToken(); + String typePrefix; + if (token == Token::ENUM) { + typePrefix = "enum"; + } else if (token == Token::STRUCT) { + typePrefix = "struct"; + } else if (token == Token::UNION) { + typePrefix = "union"; + } + + token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("custom type name is expected.")); + return nullptr; + } + + String typeName = typePrefix + " " + lexer_->GetIdentifier(); + lexer_->GetToken(); + AutoPtr type = ast_->FindType(typeName); + if (type != nullptr) { + ast_->AddType(type); + } + + return type; +} + +bool Parser::ParseEnumDefine(const AutoPtr& attributes) +{ + lexer_->GetToken(); + AutoPtr type = new ASTEnumType(); + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("custom enum type name is expected.")); + return false; + } + type->SetName(lexer_->GetIdentifier()); + lexer_->GetToken(); + + if (!ParseEnumBaseType(type)) { + return false; + } + + token = lexer_->PeekToken(); + if (token != Token::BRACES_LEFT) { + lexer_->SkipCurrentLine(';'); + return false; + } + lexer_->GetToken(); + + if (!ParseEnumMember(type)) { + return false; + } + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(); + return false; + } + lexer_->GetToken(); + + if (attributes != nullptr) { + type->SetFull(attributes->isFull); + type->SetLite(attributes->isLite); + } + + ast_->AddTypeDefinition(type.Get()); + return true; +} + +bool Parser::ParseEnumBaseType(const AutoPtr& type) +{ + Token token = lexer_->PeekToken(); + if (token == Token::COLON) { + lexer_->GetToken(); + AutoPtr baseType = ParseType(); + if (baseType == nullptr) { + LogError("no base type of enum type"); + lexer_->SkipCurrentLine(';'); + return false; + } + if (baseType->IsByteType() || + baseType->IsShortType() || + baseType->IsIntegerType() || + baseType->IsLongType() || + baseType->IsUcharType() || + baseType->IsUshortType() || + baseType->IsUintType() || + baseType->IsUlongType()) { + ast_->AddType(baseType); + type->SetBaseType(baseType); + type->SetDisplayBase(true); + } else { + LogError("invaild base type of enum type"); + lexer_->SkipCurrentLine(';'); + return false; + } + } + + if (type->GetBaseType() == nullptr) { + AutoPtr baseType = ast_->FindType("int"); + if (baseType == nullptr) { + ast_->AddType(new ASTIntegerType()); + baseType = ast_->FindType("int"); + } + type->SetBaseType(baseType); + } + return true; +} + +bool Parser::ParseEnumMember(const AutoPtr& type) +{ + Token token = lexer_->PeekToken(); + while (token != Token::BRACES_RIGHT) { + if (token != Token::IDENTIFIER) { + lexer_->SkipCurrentLine(';'); + return false; + } + AutoPtr enumValue = new ASTEnumValue(lexer_->GetIdentifier()); + lexer_->GetToken(); + + token = lexer_->PeekToken(); + if (token == Token::ASSIGN) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + if (token == Token::DIGIT) { + enumValue->SetValue(lexer_->GetDigit()); + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else { + return false; + } + } + + if (token == Token::COMMA) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token == Token::BRACES_RIGHT) { + } else { + lexer_->SkipCurrentLine(';'); + return false; + } + enumValue->SetType(type->GetBaseType()); + type->AddMember(enumValue); + } + lexer_->GetToken(); + return true; +} + +bool Parser::ParseStructDefine(const AutoPtr& attributes) +{ + lexer_->GetToken(); + + AutoPtr type = new ASTStructType(); + if (type == nullptr) { + lexer_->SkipCurrentLine(';'); + return false; + } + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("custom struct type name is expected.")); + return false; + } + type->SetName(lexer_->GetIdentifier()); + lexer_->GetToken(); + + token = lexer_->PeekToken(); + if (token != Token::BRACES_LEFT) { + lexer_->SkipCurrentLine(';'); + return false; + } + lexer_->GetToken(); + + token = lexer_->PeekToken(); + while (token != Token::BRACES_RIGHT) { + AutoPtr member = ParseType(); + if (member == nullptr) { + lexer_->SkipCurrentLine(';'); + return false; + } + String typeName = member->ToString(); + + token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("member name is expected.")); + return false; + } + String memberName = lexer_->GetIdentifier(); + lexer_->GetToken(); + + type->AddMember(member, memberName); + + token = lexer_->PeekToken(); + if (token == Token::SEMICOLON) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token == Token::BRACES_RIGHT) { + break; + } else { + lexer_->SkipCurrentLine(';'); + return false; + } + } + lexer_->GetToken(); + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(); + return false; + } + lexer_->GetToken(); + + if (attributes != nullptr) { + type->SetFull(attributes->isFull); + type->SetLite(attributes->isLite); + } + + ast_->AddTypeDefinition(type.Get()); + return true; +} + +bool Parser::ParseUnionDefine(const AutoPtr& attributes) +{ + lexer_->GetToken(); + + AutoPtr type = new ASTUnionType(); + if (type == nullptr) { + lexer_->SkipCurrentLine(';'); + return false; + } + + Token token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("custom union type name is expected.")); + return false; + } + type->SetName(lexer_->GetIdentifier()); + lexer_->GetToken(); + + token = lexer_->PeekToken(); + if (token != Token::BRACES_LEFT) { + lexer_->SkipCurrentLine(';'); + return false; + } + lexer_->GetToken(); + + token = lexer_->PeekToken(); + while (token != Token::BRACES_RIGHT) { + AutoPtr member = ParseType(); + if (member == nullptr) { + lexer_->SkipCurrentLine(';'); + return false; + } + String typeName = member->ToString(); + + token = lexer_->PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(String("member name is expected.")); + return false; + } + String memberName = lexer_->GetIdentifier(); + lexer_->GetToken(); + + type->AddMember(member, memberName); + + token = lexer_->PeekToken(); + if (token == Token::SEMICOLON) { + lexer_->GetToken(); + token = lexer_->PeekToken(); + } else if (token == Token::BRACES_RIGHT) { + break; + } else { + lexer_->SkipCurrentLine(';'); + return false; + } + } + lexer_->GetToken(); + + token = lexer_->PeekToken(); + if (token != Token::SEMICOLON) { + LogError(String::Format("'%s' is not expected.", lexer_->DumpToken().string())); + lexer_->SkipCurrentLine(); + return false; + } + lexer_->GetToken(); + + if (attributes != nullptr) { + type->SetFull(attributes->isFull); + type->SetLite(attributes->isLite); + } + + ast_->AddTypeDefinition(type.Get()); + return true; +} + +bool Parser::CheckType(int lineNo, int columnNo, const AutoPtr& type) +{ + if (type == nullptr) { + return false; + } + + if (options_.GetTargetLanguage().Equals("c")) { + if (type->IsSequenceableType()) { + LogError(lineNo, columnNo, String::Format("The sequenceable type is not supported by c language.")); + return false; + } + } else if (options_.GetTargetLanguage().Equals("java")) { + switch (type->GetTypeKind()) { + case TypeKind::TYPE_UCHAR: + case TypeKind::TYPE_USHORT: + case TypeKind::TYPE_UINT: + case TypeKind::TYPE_ULONG: + case TypeKind::TYPE_ENUM: + case TypeKind::TYPE_STRUCT: + case TypeKind::TYPE_UNION: + case TypeKind::TYPE_UNKNOWN: + LogError(lineNo, columnNo, String::Format("The '%s' type is not supported by java language.", + lexer_->DumpToken().string())); + return false; + default: + break; + } + } + + return true; +} + +bool Parser::CheckIntegrity() +{ + if (ast_ == nullptr) { + LogError(String("ast is nullptr.")); + return false; + } + + if (ast_->GetName().IsEmpty()) { + LogError(String("ast's name is empty.")); + return false; + } + + if (ast_->GetPackageName().IsEmpty()) { + LogError(String("ast's package name is empty.")); + return false; + } + + switch (ast_->GetASTFileType()) { + case ASTFileType::AST_IFACE: { + AutoPtr interface = ast_->GetInterfaceDef(); + if (interface == nullptr) { + LogError(String("ast's interface is empty.")); + return false; + } + + if (ast_->GetTypeDefinitionNumber() > 0) { + LogError(String("interface ast cannot has custom types.")); + return false; + } + + if (interface->GetMethodNumber() == 0) { + LogError(String("interface ast has no method.")); + return false; + } + + break; + } + case ASTFileType::AST_ICALLBACK: { + AutoPtr interface = ast_->GetInterfaceDef(); + if (interface == nullptr) { + LogError(String("ast's interface is empty.")); + return false; + } + + if (!interface->IsCallback()) { + LogError(String("ast is callback, but ast's interface is not callback.")); + return false; + } + break; + } + case ASTFileType::AST_SEQUENCEABLE: { + LogError(String("it's impossible that ast is sequenceable.")); + return false; + } + case ASTFileType::AST_TYPES: { + if (ast_->GetInterfaceDef() != nullptr) { + LogError(String("custom ast cannot has interface.")); + return false; + } + break; + } + default: + break; + } + + return true; +} + +bool Parser::IsValidTypeName(const String& typeName) +{ + if (typeName[0] == '.') { + return false; + } + + if (typeName[typeName.GetLength() - 1] == '.') { + return false; + } + + return true; +} + +/* +* For example +* filePath: ./test/cpp_test/data_test/v1_0/IDataTest.idl +* package test.cpp_test.data_test.v1_0; +*/ +bool Parser::CheckPackageName(const String& filePath, const String& packageName) +{ + String pkgToPath = packageName.Replace('.', '/'); + int index = filePath.LastIndexOf('/'); + if (index == -1) { + return false; + } + + String parentDir = filePath.Substring(0, index); + if (parentDir.IndexOf(pkgToPath) == -1) { + return false; + } + + return true; +} + +bool Parser::AddAst() +{ + if (ast_ == nullptr) { + LogError(String("ast is nullptr.")); + return false; + } + astModule_->AddAST(ast_->GetFullName(), ast_); + return true; +} + +void Parser::LogError(const String& message) +{ + AutoPtr error = new ErrorInfo(); + + String sourceFile = lexer_->GetFilePath(); +#ifdef __MINGW32__ + error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('\\') + 1); +#else + error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('/') + 1); +#endif + error->lineNo_ = lexer_->GetTokenLineNumber(); + error->columnNo_ = lexer_->GetTokenColumnNumber(); + error->message_ = message; + + if (errors_ == nullptr) { + errors_ = error; + } else { + AutoPtr pos = errors_; + while (pos->next_ != nullptr) { + pos = pos->next_; + } + pos->next_ = error; + } +} + +void Parser::LogError(int lineNo, int columnNo, const String& message) +{ + AutoPtr error = new ErrorInfo(); + + String sourceFile = lexer_->GetFilePath(); +#ifdef __MINGW32__ + error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('\\') + 1); +#else + error->file_ = sourceFile.Substring(sourceFile.LastIndexOf('/') + 1); +#endif + error->lineNo_ = lineNo; + error->columnNo_ = columnNo; + error->message_ = message; + + if (errors_ == nullptr) { + errors_ = error; + } else { + AutoPtr pos = errors_; + while (pos->next_ != nullptr) { + pos = pos->next_; + } + pos->next_ = error; + } +} + +void Parser::ShowError() +{ + AutoPtr error = errors_; + while (error != nullptr) { + Logger::E(TAG, "%s[line %d, column %d] %s", error->file_.string(), + error->lineNo_, error->columnNo_, error->message_.string()); + error = error->next_; + } +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/parser/parser.h b/tools/hdi-gen/parser/parser.h new file mode 100755 index 000000000..578bb8364 --- /dev/null +++ b/tools/hdi-gen/parser/parser.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_PARSER_H +#define OHOS_HDI_PARSER_H + +#include +#include +#include "ast/ast_module.h" +#include "ast/ast_interface_type.h" +#include "ast/ast_method.h" +#include "ast/ast.h" +#include "ast/ast_type.h" +#include "parser/lexer.h" +#include "parser/token.h" +#include "parser/file_detail.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/options.h" +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class Parser { +public: + Parser(const Options& options, const AutoPtr& module = nullptr); + + ~Parser() = default; + + bool Parse(const String& sourceFile); + + bool Parse(const String& sourceFile, std::shared_ptr& fileDetailPtr); + + inline AutoPtr GetAst() const + { + return ast_; + } + +private: + + class Attribute : public LightRefCountBase { + public: + bool isOneWay = false; + bool isCallback = false; + bool isFull = false; + bool isLite = false; + }; + + class ErrorInfo : public LightRefCountBase { + public: + String file_; + Token token_; + int lineNo_; + int columnNo_; + String message_; + AutoPtr next_; + }; + + bool ParseIdlDetail(std::shared_ptr& fileDetailPtr); + + bool ParseIdlPackage(std::shared_ptr& fileDetailPtr); + + bool ParseIdlImport(std::shared_ptr& fileDetailPtr); + + bool ParseFile(); + + bool ParseLicense(); + + bool ParsePackageName(); + + bool ParseImport(); + + bool ParseSequenceable(); + + bool ParseAttribute(); + + bool ParseInterface(const AutoPtr& attributes = nullptr); + + bool ParseMethod(const AutoPtr& interface); + + bool ParseMethodAttr(const AutoPtr& interface, const AutoPtr& attributes); + + bool ParseParameter(const AutoPtr& method); + + bool ParseParamAttr(const AutoPtr& parameter); + + AutoPtr ParseType(); + + AutoPtr ParseList(); + + AutoPtr ParseMap(); + + AutoPtr ParseCustomType(); + + bool ParseEnumDefine(const AutoPtr& attributes = nullptr); + + bool ParseEnumBaseType(const AutoPtr& type); + + bool ParseEnumMember(const AutoPtr& type); + + bool ParseStructDefine(const AutoPtr& attributes = nullptr); + + bool ParseUnionDefine(const AutoPtr& attributes = nullptr); + + bool CheckType(int lineNo, int columnNo, const AutoPtr& type); + + bool CheckIntegrity(); + + bool IsValidTypeName(const String& typeName); + + bool CheckPackageName(const String& filePath, const String& packageName); + + inline static bool IsPrimitiveType(Token token) + { + return token >= Token::BOOLEAN && token <= Token::FILEDESCRIPTOR; + } + + bool AddAst(); + + void LogError(const String& message); + + void LogError(int lineNo, int columnNo, const String& message); + + void ShowError(); + + static const char* TAG; + + const Options& options_; + std::shared_ptr lexer_; + AutoPtr errors_; + AutoPtr ast_; + AutoPtr astModule_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_PARSER_H \ No newline at end of file diff --git a/tools/hdi-gen/parser/token.h b/tools/hdi-gen/parser/token.h new file mode 100755 index 000000000..108ca1a2b --- /dev/null +++ b/tools/hdi-gen/parser/token.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_TOKEN_H +#define OHOS_HDI_TOKEN_H + +namespace OHOS { +namespace HDI { +enum class Token { + UNKNOWN = 0, + // types + VOID, + BOOLEAN, + BYTE, + SHORT, + INTEGER, + LONG, + STRING, + FLOAT, + DOUBLE, + FILEDESCRIPTOR, + LIST, + MAP, + CHAR, + // qualifier + UNSIGNED, + // custom types + STRUCT, + ENUM, + UNION, + // keywords + PACKAGE, + SEQUENCEABLE, + IMPORT, + INTERFACE, + EXTENDS, + ONEWAY, + CALLBACK, + FULL, + LITE, + IN, + OUT, + DOT, // '.' + COMMA, // ',' + COLON, // ':' + ASSIGN, // '=' + SEMICOLON, // ';' + BRACES_LEFT, // '{' + BRACES_RIGHT, // '}' + BRACKETS_LEFT, // '[' + BRACKETS_RIGHT, // ']' + PARENTHESES_LEFT, // '(' + PARENTHESES_RIGHT, // ')' + ANGLE_BRACKETS_LEFT, // '<' + ANGLE_BRACKETS_RIGHT, // '>' + // others + IDENTIFIER, + DIGIT, + COMMENT_BLOCK, + COMMENT_LINE, + END_OF_FILE, +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_TOKEN_H \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/array_test/v1_0/IArrayTest.idl b/tools/hdi-gen/test/c_test/array_test/v1_0/IArrayTest.idl new file mode 100755 index 000000000..5e42ce2c8 --- /dev/null +++ b/tools/hdi-gen/test/c_test/array_test/v1_0/IArrayTest.idl @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.array_test.v1_0; + +import test.c_test.types.v1_0.Types; + +interface IArrayTest { + + BoolArrayTest([in] boolean[] param1, [out] boolean[] param2); + + ByteArrayTest([in] byte[] param1, [out] byte[] param2); + + ShortArrayTest([in] short[] param1, [out] short[] param2); + + IntArrayTest([in] int[] param1, [out] int[] param2); + + LongArrayTest([in] long[] param1, [out] long[] param2); + + UCharArrayTest([in] unsigned char[] param1, [out] unsigned char[] param2); + + UShortArrayTest([in] unsigned short[] param1, [out] unsigned short[] param2); + + UIntArrayTest([in] unsigned int[] param1, [out] unsigned int[] param2); + + ULongArrayTest([in] unsigned long[] param1, [out] unsigned long[] param2); + + FloatArrayTest([in] float[] param1, [out] float[] param2); + + DoubleArrayTest([in] double[] param1, [out] double[] param2); + + StringArrayTest([in] String[] param1, [out] String[] param2); + + FdArrayTest([in] FileDescriptor[] param1, [out] FileDescriptor[] param2); + + EnumArrayTest([in] enum ESample[] param1, [out] enum ESample[] param2); + + StructArrayTest([in] struct SSample[] param1, [out] struct SSample[] param2); + + UnionArrayTest([in] union USample[] param1, [out] union USample[] param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/array_test/v1_0/c_array_test.cpp b/tools/hdi-gen/test/c_test/array_test/v1_0/c_array_test.cpp new file mode 100755 index 000000000..653f2910e --- /dev/null +++ b/tools/hdi-gen/test/c_test/array_test/v1_0/c_array_test.cpp @@ -0,0 +1,676 @@ +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include +#include +#include +#include "c_test/array_test/v1_0/client/iarray_test.h" + +using namespace OHOS; +using namespace testing::ext; + +struct IArrayTest *g_testClient = nullptr; + +class ArrayTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(){} + void TearDown(){} +}; + +void ArrayTest::SetUpTestCase() +{ + g_testClient = HdiArrayTestGet(); + if (g_testClient == nullptr) { + printf("ArrayTest: get g_testClient failed.\n"); + } +} + +void ArrayTest::TearDownTestCase() +{ + if (g_testClient != nullptr) { + HdiArrayTestRelease(g_testClient); + g_testClient = nullptr; + } +} + +HWTEST_F(ArrayTest, ArratTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(ArrayTest, ArratTest_002, TestSize.Level0) +{ + uint32_t inParamLen = 4; + bool *inParam = (bool*)OsalMemAlloc(sizeof(bool) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = false; + } else { + inParam[i] = true; + } + } + + bool *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->BoolArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ((inParam[i] ? 1 : 0), (outParam[i]? 1 : 0)); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_003, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int8_t *inParam = (int8_t*)OsalMemAlloc(sizeof(int8_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int8_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ByteArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_004, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int16_t *inParam = (int16_t*)OsalMemAlloc(sizeof(int16_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int16_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ShortArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_005, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int32_t *inParam = (int32_t*)OsalMemAlloc(sizeof(int32_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int32_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->IntArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_006, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int64_t *inParam = (int64_t*)OsalMemAlloc(sizeof(int64_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int64_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->LongArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_007, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint8_t *inParam = (uint8_t*)OsalMemAlloc(sizeof(uint8_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint8_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UCharArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_008, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint16_t *inParam = (uint16_t*)OsalMemAlloc(sizeof(uint16_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint16_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UShortArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_009, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint32_t *inParam = (uint32_t*)OsalMemAlloc(sizeof(uint32_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint32_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UIntArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_010, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint64_t *inParam = (uint64_t*)OsalMemAlloc(sizeof(uint64_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint64_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ULongArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_011, TestSize.Level0) +{ + uint32_t inParamLen = 4; + float *inParam = (float*)OsalMemAlloc(sizeof(float) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0.5; + } else { + inParam[i] = 1.5; + } + } + + float *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->FloatArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_012, TestSize.Level0) +{ + uint32_t inParamLen = 4; + double *inParam = (double*)OsalMemAlloc(sizeof(double) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0.5; + } else { + inParam[i] = 1.5; + } + } + + double *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->DoubleArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_013, TestSize.Level0) +{ + uint32_t inParamLen = 2; + char **inParam = (char**)OsalMemAlloc(sizeof(char*) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i] = strdup("inParam string array"); + } + + char **outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->StringArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_STREQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + for (uint32_t i = 0; i < inParamLen; i++) { + if (inParam[i] != nullptr) { + OsalMemFree(inParam[i]); + } + } + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + for (uint32_t i = 0; i < outParamLen; i++) { + if (outParam[i] != nullptr) { + OsalMemFree(outParam[i]); + } + } + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_014, TestSize.Level0) +{ + uint32_t inParamLen = 2; + + int fd1 = open("/cpp_array_test_014_0.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + int fd2 = open("/cpp_array_test_014_1.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + ASSERT_NE(fd1, -1); + ASSERT_NE(fd2, -1); + + int *inParam = (int*)OsalMemAlloc(sizeof(int) * inParamLen); + ASSERT_NE(inParam, nullptr); + + inParam[0] = fd1; + inParam[1] = fd2; + + int *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->FdArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + + std::cout << "inParam[0]:"<< inParam[0] << ", inParam[1]" << inParam[1] << std::endl; + std::cout << "outParam[0]:"<< outParam[0] << ", outParam[1]" << outParam[1] << std::endl; + close(fd1); + close(fd2); + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_015, TestSize.Level0) +{ + uint32_t inParamLen = 4; + enum ESample *inParam = (enum ESample*)OsalMemAlloc(sizeof(enum ESample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = MEM_ONE; + } else { + inParam[i] = MEM_TWO; + } + } + + enum ESample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->EnumArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_016, TestSize.Level0) +{ + uint32_t inParamLen = 2; + struct SSample *inParam = (struct SSample *)OsalMemAlloc(sizeof(struct SSample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i].m1 = true; + inParam[i].m2 = 1; + inParam[i].m3 = 1.5; + inParam[i].m4 = strdup("inParam.m4"); + ASSERT_NE(inParam[i].m4, nullptr); + } + + struct SSample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->StructArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + if (outParamLen > 0) { + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + EXPECT_EQ(inParam[i].m1, outParam[i].m1); + EXPECT_EQ(inParam[i].m2, outParam[i].m2); + EXPECT_DOUBLE_EQ(inParam[i].m3, outParam[i].m3); + EXPECT_STREQ(inParam[i].m4, outParam[i].m4); + } + } + + if (inParam != nullptr && inParamLen > 0) { + for (uint32_t i = 0; i < inParamLen; i++) { + if (inParam[i].m4 != nullptr) { + SSampleFree(&inParam[i], false); + } + } + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + for (uint32_t i = 0; i < outParamLen; i++) { + SSampleFree(&outParam[i], false); + } + OsalMemFree(outParam); + } +} + +HWTEST_F(ArrayTest, ArratTest_017, TestSize.Level0) +{ + uint32_t inParamLen = 2; + union USample *inParam = (union USample *)OsalMemAlloc(sizeof(union USample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i].m1 = true; + inParam[i].m2 = 1; + } + + union USample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UnionArrayTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + EXPECT_EQ(inParam[i].m1, outParam[i].m1); + EXPECT_EQ(inParam[i].m2, outParam[i].m2); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/cb_test/v1_0/ICallback.idl b/tools/hdi-gen/test/c_test/cb_test/v1_0/ICallback.idl new file mode 100755 index 000000000..c00b4e425 --- /dev/null +++ b/tools/hdi-gen/test/c_test/cb_test/v1_0/ICallback.idl @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.cb_test.v1_0; + +import test.c_test.types.v1_0.Types; + +[callback] interface ICallback { + Ping([in] String message); + Plus([in] int num1, [in] int num2, [out] int result); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/cb_test/v1_0/ICbTest.idl b/tools/hdi-gen/test/c_test/cb_test/v1_0/ICbTest.idl new file mode 100755 index 000000000..e7b314747 --- /dev/null +++ b/tools/hdi-gen/test/c_test/cb_test/v1_0/ICbTest.idl @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.cb_test.v1_0; + +import test.c_test.cb_test.v1_0.ICallback; + +interface ICbTest { + CallbackTest([in] ICallback callbackObj); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/cb_test/v1_0/c_cb_test.cpp b/tools/hdi-gen/test/c_test/cb_test/v1_0/c_cb_test.cpp new file mode 100755 index 000000000..51ba485a7 --- /dev/null +++ b/tools/hdi-gen/test/c_test/cb_test/v1_0/c_cb_test.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "c_test/cb_test/v1_0/client/icb_test.h" +#include "c_test/cb_test/v1_0/callback_stub.h" + +using namespace OHOS; +using namespace testing::ext; + +struct ICbTest *g_testClient = nullptr; +struct ICallback *g_callback = nullptr; + +class CbTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(){} + void TearDown(){} +}; + +void CbTest::SetUpTestCase() +{ + g_testClient = HdiCbTestGet(); + if (g_testClient == nullptr) { + printf("CbTest: get g_testClient failed.\n"); + } + + g_callback = CallbackStubObtain(); + if (g_callback == nullptr) { + printf("CbTest: get g_callback failed.\n"); + } +} + +void CbTest::TearDownTestCase() +{ + if (g_testClient != nullptr) { + HdiCbTestRelease(g_testClient); + g_testClient = nullptr; + } + + if (g_callback != nullptr) { + CallbackStubRelease(g_callback); + g_callback = nullptr; + } +} + +HWTEST_F(CbTest, CbTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); + ASSERT_NE(nullptr, g_callback); +} + +HWTEST_F(CbTest, CbTest_002, TestSize.Level0) +{ + int32_t ec = g_testClient->CallbackTest(g_testClient, g_callback); + ASSERT_EQ(ec, HDF_SUCCESS); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/data_test/v1_0/IDataTest.idl b/tools/hdi-gen/test/c_test/data_test/v1_0/IDataTest.idl new file mode 100755 index 000000000..ac113c2c9 --- /dev/null +++ b/tools/hdi-gen/test/c_test/data_test/v1_0/IDataTest.idl @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.data_test.v1_0; + +import test.c_test.types.v1_0.Types; + +interface IDataTest { + + BoolTest([in] boolean param1, [out] boolean param2); + + ByteTest([in] byte param1, [out] byte param2); + + ShortTest([in] short param1, [out] short param2); + + IntTest([in] int param1, [out] int param2); + + LongTest([in] long param1, [out] long param2); + + UCharTest([in] unsigned char param1, [out] unsigned char param2); + + UShortTest([in] unsigned short param1, [out] unsigned short param2); + + UIntTest([in] unsigned int param1, [out] unsigned int param2); + + ULongTest([in] unsigned long param1, [out] unsigned long param2); + + FloatTest([in] float param1, [out] float param2); + + DoubleTest([in] double param1, [out] double param2); + + StringTest([in] String param1, [out] String param2); + + FdTest([in] FileDescriptor fd); + + EnumTest([in] enum ESample param1, [out] enum ESample param2); + + StructTest([in] struct SSample param1, [out] struct SSample param2); + + UnionTest([in] union USample param1, [out] union USample param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/data_test/v1_0/c_data_test.cpp b/tools/hdi-gen/test/c_test/data_test/v1_0/c_data_test.cpp new file mode 100755 index 000000000..3c8d844b4 --- /dev/null +++ b/tools/hdi-gen/test/c_test/data_test/v1_0/c_data_test.cpp @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include +#include +#include +#include "test/c_test/data_test/v1_0/client/idata_test.h" + +using namespace OHOS; +using namespace testing::ext; + +struct IDataTest *g_testClient = nullptr; +struct ICallback *g_callback = nullptr; + +class DataTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(){} + void TearDown(){} +}; + +void DataTest::SetUpTestCase() +{ + g_testClient = HdiDataTestGet(); + if (g_testClient == nullptr) { + printf("DataTest: get g_testClient failed.\n"); + } +} + +void DataTest::TearDownTestCase() +{ + if (g_testClient != nullptr) { + HdiDataTestRelease(g_testClient); + g_testClient = nullptr; + } +} + +HWTEST_F(DataTest, DataTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(DataTest, DataTest_002, TestSize.Level0) +{ + bool inParam = true; + bool outParam = false; + + int32_t ec = g_testClient->BoolTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_TRUE(inParam); + EXPECT_TRUE(outParam); +} + + +HWTEST_F(DataTest, DataTest_003, TestSize.Level0) +{ + int8_t inParam = 10; + int8_t outParam = 0; + + int32_t ec = g_testClient->ByteTest(g_testClient, inParam, &outParam); + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_004, TestSize.Level0) +{ + int16_t inParam = 10; + int16_t outParam = 0; + + int32_t ec = g_testClient->ShortTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_005, TestSize.Level0) +{ + int32_t inParam = 10; + int32_t outParam = 0; + + int32_t ec = g_testClient->IntTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_006, TestSize.Level0) +{ + int64_t inParam = 10; + int64_t outParam = 0; + + int32_t ec = g_testClient->LongTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_007, TestSize.Level0) +{ + uint8_t inParam = 10; + uint8_t outParam = 0; + + int32_t ec = g_testClient->UCharTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_008, TestSize.Level0) +{ + uint16_t inParam = 10; + uint16_t outParam = 0; + + int32_t ec = g_testClient->UShortTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_009, TestSize.Level0) +{ + uint32_t inParam = 10; + uint32_t outParam = 0; + + int32_t ec = g_testClient->UIntTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_010, TestSize.Level0) +{ + uint64_t inParam = 10; + uint64_t outParam = 0; + + int32_t ec = g_testClient->ULongTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_011, TestSize.Level0) +{ + float inParam = 10.5; + float outParam = 0; + + int32_t ec = g_testClient->FloatTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_FLOAT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_012, TestSize.Level0) +{ + double inParam = 10.5; + double outParam = 0; + + int32_t ec = g_testClient->DoubleTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_DOUBLE_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_013, TestSize.Level0) +{ + const char* inParam = "hello"; + char* outParam = nullptr; + + int32_t ec = g_testClient->StringTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_STREQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_014, TestSize.Level0) +{ + int fd = open("/c_data_test_014.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + printf("file open, fd = %d\n", fd); + + + const char* oldMsg = "client:message\n"; + int size = 0; + if ((size = write(fd, oldMsg, strlen(oldMsg))) > 0) { + printf("write oldMsg success, size:%d\n", size); + } + + lseek(fd, 0, SEEK_SET); + + int32_t ec = g_testClient->FdTest(g_testClient, fd); + + ASSERT_EQ(ec, HDF_SUCCESS); + + lseek(fd, 0, SEEK_SET); + + char recvMsg[1024] = {0}; + ssize_t readSize = read(fd, recvMsg, sizeof(recvMsg)); + if (readSize < 0) { + printf("read failed\n"); + goto finished; + } else { + printf("read size:%d\n", readSize); + } + printf("recvMsg:%s", recvMsg); + +finished: + close(fd); +} + +HWTEST_F(DataTest, DataTest_015, TestSize.Level0) +{ + enum ESample inParam = MEM_ONE; + enum ESample outParam = MEM_TWO; + + int32_t ec = g_testClient->EnumTest(g_testClient, inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_016, TestSize.Level0) +{ + struct SSample inParam; + inParam.m1 = true; + inParam.m2 = 1; + inParam.m3 = 1.5; + inParam.m4 = strdup("inParam string"); + ASSERT_NE(inParam.m4, nullptr); + + struct SSample *outParam = nullptr; + + int32_t ec = g_testClient->StructTest(g_testClient, &inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + EXPECT_EQ(inParam.m1? 1: 0, outParam->m1? 1:0); + EXPECT_EQ(inParam.m2, outParam->m2); + EXPECT_DOUBLE_EQ(inParam.m3, outParam->m3); + ASSERT_NE(outParam->m4, nullptr); + EXPECT_STREQ(inParam.m4, outParam->m4); + + + SSampleFree(&inParam, false); + + + if (outParam != nullptr) { + SSampleFree(outParam, true); + } +} + +HWTEST_F(DataTest, DataTest_017, TestSize.Level0) +{ + union USample inParam; + inParam.m2 = 10; + + union USample *outParam = nullptr; + + int32_t ec = g_testClient->UnionTest(g_testClient, &inParam, &outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + EXPECT_EQ(inParam.m1? 1:0, outParam->m1? 1:0); + EXPECT_EQ(inParam.m2, outParam->m2); + + if (outParam != nullptr) { + OsalMemFree(outParam); + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/list_test/v1_0/IListTest.idl b/tools/hdi-gen/test/c_test/list_test/v1_0/IListTest.idl new file mode 100755 index 000000000..92ea6c3dd --- /dev/null +++ b/tools/hdi-gen/test/c_test/list_test/v1_0/IListTest.idl @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.list_test.v1_0; + +import test.c_test.types.v1_0.Types; + +interface IListTest { + + BoolListTest([in] List param1, [out] List param2); + + ByteListTest([in] List param1, [out] List param2); + + ShortListTest([in] List param1, [out] List param2); + + IntListTest([in] List param1, [out] List param2); + + LongListTest([in] List param1, [out] List param2); + + UCharListTest([in] List param1, [out] List param2); + + UShortListTest([in] List param1, [out] List param2); + + UIntListTest([in] List param1, [out] List param2); + + ULongListTest([in] List param1, [out] List param2); + + FloatListTest([in] List param1, [out] List param2); + + DoubleListTest([in] List param1, [out] List param2); + + StringListTest([in] List param1, [out] List param2); + + FdListTest([in] List param1, [out] List param2); + + EnumListTest([in] List param1, [out] List param2); + + StructListTest([in] List param1, [out] List param2); + + UnionListTest([in] List param1, [out] List param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/list_test/v1_0/c_list_test.cpp b/tools/hdi-gen/test/c_test/list_test/v1_0/c_list_test.cpp new file mode 100755 index 000000000..33cb6048e --- /dev/null +++ b/tools/hdi-gen/test/c_test/list_test/v1_0/c_list_test.cpp @@ -0,0 +1,676 @@ +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include +#include +#include +#include "c_test/list_test/v1_0/client/ilist_test.h" + +using namespace OHOS; +using namespace testing::ext; + +struct IListTest *g_testClient = nullptr; + +class ListTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(){} + void TearDown(){} +}; + +void ListTest::SetUpTestCase() +{ + g_testClient = HdiListTestGet(); + if (g_testClient == nullptr) { + printf("ListTest: get g_testClient failed.\n"); + } +} + +void ListTest::TearDownTestCase() +{ + if (g_testClient != nullptr) { + HdiListTestRelease(g_testClient); + g_testClient = nullptr; + } +} + +HWTEST_F(ListTest, ArratTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(ListTest, ArratTest_002, TestSize.Level0) +{ + uint32_t inParamLen = 4; + bool *inParam = (bool*)OsalMemAlloc(sizeof(bool) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = false; + } else { + inParam[i] = true; + } + } + + bool *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->BoolListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ((inParam[i] ? 1 : 0), (outParam[i]? 1 : 0)); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_003, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int8_t *inParam = (int8_t*)OsalMemAlloc(sizeof(int8_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int8_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ByteListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_004, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int16_t *inParam = (int16_t*)OsalMemAlloc(sizeof(int16_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int16_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ShortListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_005, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int32_t *inParam = (int32_t*)OsalMemAlloc(sizeof(int32_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int32_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->IntListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_006, TestSize.Level0) +{ + uint32_t inParamLen = 4; + int64_t *inParam = (int64_t*)OsalMemAlloc(sizeof(int64_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + int64_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->LongListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_007, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint8_t *inParam = (uint8_t*)OsalMemAlloc(sizeof(uint8_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint8_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UCharListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_008, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint16_t *inParam = (uint16_t*)OsalMemAlloc(sizeof(uint16_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint16_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UShortListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_009, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint32_t *inParam = (uint32_t*)OsalMemAlloc(sizeof(uint32_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint32_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UIntListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_010, TestSize.Level0) +{ + uint32_t inParamLen = 4; + uint64_t *inParam = (uint64_t*)OsalMemAlloc(sizeof(uint64_t) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0; + } else { + inParam[i] = 1; + } + } + + uint64_t *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->ULongListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_011, TestSize.Level0) +{ + uint32_t inParamLen = 4; + float *inParam = (float*)OsalMemAlloc(sizeof(float) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0.5; + } else { + inParam[i] = 1.5; + } + } + + float *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->FloatListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_012, TestSize.Level0) +{ + uint32_t inParamLen = 4; + double *inParam = (double*)OsalMemAlloc(sizeof(double) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = 0.5; + } else { + inParam[i] = 1.5; + } + } + + double *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->DoubleListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_013, TestSize.Level0) +{ + uint32_t inParamLen = 2; + char **inParam = (char**)OsalMemAlloc(sizeof(char*) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i] = strdup("inParam string array"); + } + + char **outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->StringListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_STREQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + for (uint32_t i = 0; i < inParamLen; i++) { + if (inParam[i] != nullptr) { + OsalMemFree(inParam[i]); + } + } + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + for (uint32_t i = 0; i < outParamLen; i++) { + if (outParam[i] != nullptr) { + OsalMemFree(outParam[i]); + } + } + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_014, TestSize.Level0) +{ + uint32_t inParamLen = 2; + + int fd1 = open("/ListTest_014_0.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + int fd2 = open("/ListTest_014_1.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + ASSERT_NE(fd1, -1); + ASSERT_NE(fd2, -1); + + int *inParam = (int*)OsalMemAlloc(sizeof(int) * inParamLen); + ASSERT_NE(inParam, nullptr); + + inParam[0] = fd1; + inParam[1] = fd2; + + int *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->FdListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + + std::cout << "inParam[0]:"<< inParam[0] << ", inParam[1]" << inParam[1] << std::endl; + std::cout << "outParam[0]:"<< outParam[0] << ", outParam[1]" << outParam[1] << std::endl; + close(fd1); + close(fd2); + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_015, TestSize.Level0) +{ + uint32_t inParamLen = 4; + enum ESample *inParam = (enum ESample*)OsalMemAlloc(sizeof(enum ESample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + if ((i+1)/2 == 0) { + inParam[i] = MEM_ONE; + } else { + inParam[i] = MEM_TWO; + } + } + + enum ESample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->EnumListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_016, TestSize.Level0) +{ + uint32_t inParamLen = 2; + struct SSample *inParam = (struct SSample *)OsalMemAlloc(sizeof(struct SSample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i].m1 = true; + inParam[i].m2 = 1; + inParam[i].m3 = 1.5; + inParam[i].m4 = strdup("inParam.m4"); + ASSERT_NE(inParam[i].m4, nullptr); + } + + struct SSample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->StructListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + if (outParamLen > 0) { + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + EXPECT_EQ(inParam[i].m1, outParam[i].m1); + EXPECT_EQ(inParam[i].m2, outParam[i].m2); + EXPECT_DOUBLE_EQ(inParam[i].m3, outParam[i].m3); + EXPECT_STREQ(inParam[i].m4, outParam[i].m4); + } + } + + if (inParam != nullptr && inParamLen > 0) { + for (uint32_t i = 0; i < inParamLen; i++) { + if (inParam[i].m4 != nullptr) { + SSampleFree(&inParam[i], false); + } + } + OsalMemFree(inParam); + } + + if (outParam != nullptr && outParamLen > 0) { + for (uint32_t i = 0; i < outParamLen; i++) { + SSampleFree(&outParam[i], false); + } + OsalMemFree(outParam); + } +} + +HWTEST_F(ListTest, ArratTest_017, TestSize.Level0) +{ + uint32_t inParamLen = 2; + union USample *inParam = (union USample *)OsalMemAlloc(sizeof(union USample) * inParamLen); + ASSERT_NE(inParam, nullptr); + + for (uint32_t i = 0; i < inParamLen; i++) { + inParam[i].m1 = true; + inParam[i].m2 = 1; + } + + union USample *outParam = nullptr; + uint32_t outParamLen = 0; + + int32_t ec = g_testClient->UnionListTest(g_testClient, + inParam, inParamLen, + &outParam, &outParamLen); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_NE(outParam, nullptr); + ASSERT_EQ(inParamLen, outParamLen); + for (uint32_t i = 0; i < inParamLen; i++) { + EXPECT_EQ(inParam[i].m1, outParam[i].m1); + EXPECT_EQ(inParam[i].m2, outParam[i].m2); + } + + if (inParam != nullptr && inParamLen > 0) { + OsalMemFree(inParam); + } + + if (outParam != nullptr && inParamLen > 0) { + OsalMemFree(outParam); + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/struct_test/v1_0/IStructTest.idl b/tools/hdi-gen/test/c_test/struct_test/v1_0/IStructTest.idl new file mode 100755 index 000000000..70efe9d8f --- /dev/null +++ b/tools/hdi-gen/test/c_test/struct_test/v1_0/IStructTest.idl @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.struct_test.v1_0; + +import test.c_test.types.v1_0.Types; + +interface IStructTest { + SSampleTest([in] struct SSample param1, [out] struct SSample param2); + SSample2Test([in] struct SSample2 param1, [out] struct SSample2 param2); + SSample3Test([in] struct SSample3 param1, [out] struct SSample3 param2); + SSample4Test([in] struct SSample4 param1, [out] struct SSample4 param2); + SSample5Test([in] struct SSample5 param1, [out] struct SSample5 param2); + SSample6Test([in] struct SSample6 param1, [out] struct SSample6 param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/c_test/struct_test/v1_0/c_struct_test.cpp b/tools/hdi-gen/test/c_test/struct_test/v1_0/c_struct_test.cpp new file mode 100755 index 000000000..de94bc630 --- /dev/null +++ b/tools/hdi-gen/test/c_test/struct_test/v1_0/c_struct_test.cpp @@ -0,0 +1,823 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "c_test/struct_test/v1_0/client/istruct_test.h" + +using namespace OHOS; +using namespace testing::ext; + +struct IStructTest* g_testClient = nullptr; + +class StructTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void StructTest::SetUpTestCase() +{ + g_testClient = HdiStructTestGet(); + if (g_testClient == nullptr) { + printf("StructTest: get g_testClient failed.\n"); + } +} + +void TearDownTestCase() +{ + if (g_testClient != nullptr) { + HdiStructTestRelease(g_testClient); + g_testClient = nullptr; + } +} + +HWTEST_F(StructTest, StructTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + + +static std::string ESampleToStr(ESample obj) +{ + switch (obj) { + case MEM_ONE: + return "MEM_ONE"; + case MEM_TWO: + return "MEM_TWO"; + case MEM_THREE: + return "MEM_THREE"; + } +} + +static void PrintSSample(const struct SSample* obj) +{ + std::cout << "{"; + std::cout << (obj->m1?1:0) << ","; + std::cout << obj->m2 << ","; + std::cout << obj->m3 << ","; + std::cout << obj->m4; + std::cout << "}"; +} + +static void PrintUSample(const union USample* obj) +{ + std::cout << "{"; + std::cout << (obj->m1?1:0) << ","; + std::cout << obj->m2; + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_002, TestSize.Level0) +{ + struct SSample* srcObj = (struct SSample*)OsalMemCalloc(sizeof(struct SSample)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1 = true; + srcObj->m2 = 1; + srcObj->m3 = 10.125; + srcObj->m4 = strdup("hello world"); + + PrintSSample(srcObj); + std::cout << "\n"; + + struct SSample* destObj = nullptr; + int32_t ec = g_testClient->SSampleTest(g_testClient, srcObj, &destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + + EXPECT_EQ(srcObj->m1?1:0, destObj->m1?1:0); + EXPECT_EQ(srcObj->m2, destObj->m2); + EXPECT_DOUBLE_EQ(srcObj->m3, destObj->m3); + EXPECT_STREQ(srcObj->m4, destObj->m4); + + PrintSSample(destObj); + std::cout << "\n"; + + SSampleFree(srcObj, true); + SSampleFree(destObj, true); +} + +static void PrintSSample2(const struct SSample2* obj) +{ + std::cout << "{"; + std::cout << (obj->m1?1:0) << ","; + std::cout << obj->m2 << ","; + std::cout << obj->m3 << ","; + std::cout << obj->m4 << ","; + std::cout << obj->m5 << ","; + std::cout << obj->m6 << ","; + std::cout << obj->m7 << ","; + std::cout << obj->m8 << ","; + std::cout << obj->m9 << ","; + std::cout << obj->m10 << ","; + std::cout << obj->m11; + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_003, TestSize.Level0) +{ + + struct SSample2* srcObj = (struct SSample2*)OsalMemCalloc(sizeof(struct SSample2)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1 = true; + srcObj->m2 = 65; + srcObj->m3 = 10; + srcObj->m4 = 20; + srcObj->m5 = 30; + srcObj->m6 = 97; + srcObj->m7 = 100; + srcObj->m8 = 200; + srcObj->m9 = 300; + srcObj->m10 = 10.5; + srcObj->m11 = 20.125; + + PrintSSample2(srcObj); + std::cout << "\n"; + + struct SSample2* destObj = nullptr; + int32_t ec = g_testClient->SSample2Test(g_testClient, srcObj, &destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(srcObj->m1?1:0, destObj->m1?1:0); + EXPECT_EQ(srcObj->m2, destObj->m2); + EXPECT_EQ(srcObj->m3, destObj->m3); + EXPECT_EQ(srcObj->m4, destObj->m4); + EXPECT_EQ(srcObj->m5, destObj->m5); + EXPECT_EQ(srcObj->m6, destObj->m6); + EXPECT_EQ(srcObj->m7, destObj->m7); + EXPECT_EQ(srcObj->m8, destObj->m8); + EXPECT_EQ(srcObj->m9, destObj->m9); + EXPECT_FLOAT_EQ(srcObj->m10, destObj->m10); + EXPECT_DOUBLE_EQ(srcObj->m11, destObj->m11); + + PrintSSample2(destObj); + std::cout << "\n"; + + SSample2Free(srcObj, true); + SSample2Free(destObj, true); +} + +static void PrintSSample3(const struct SSample3* obj) +{ + std::cout << "{"; + + std::cout << obj->m1 << ", "; + std::cout << ESampleToStr(obj->m2) << ", "; + + PrintSSample2(&obj->m3); + std::cout << ", "; + + std::cout << obj->m4; + + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_004, TestSize.Level0) +{ + struct SSample3* srcObj = (struct SSample3*)OsalMemCalloc(sizeof(struct SSample3)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1 = strdup("hello world"); + srcObj->m2 = MEM_THREE; + + srcObj->m3.m1 = true; + srcObj->m3.m2 = 65; + srcObj->m3.m3 = 10; + srcObj->m3.m4 = 20; + srcObj->m3.m5 = 30; + srcObj->m3.m6 = 97; + srcObj->m3.m7 = 100; + srcObj->m3.m8 = 200; + srcObj->m3.m9 = 300; + srcObj->m3.m10 = 10.5; + srcObj->m3.m11 = 20.125; + + srcObj->m4 = open("/fdtest1.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + + PrintSSample3(srcObj); + std::cout << "\n"; + + struct SSample3* destObj = nullptr; + int32_t ec = g_testClient->SSample3Test(g_testClient, srcObj, &destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_STREQ(srcObj->m1, destObj->m1); + EXPECT_EQ(srcObj->m2, destObj->m2); + + EXPECT_EQ(srcObj->m3.m1?1:0, destObj->m3.m1?1:0); + EXPECT_EQ(srcObj->m3.m2, destObj->m3.m2); + EXPECT_EQ(srcObj->m3.m3, destObj->m3.m3); + EXPECT_EQ(srcObj->m3.m4, destObj->m3.m4); + EXPECT_EQ(srcObj->m3.m5, destObj->m3.m5); + EXPECT_EQ(srcObj->m3.m6, destObj->m3.m6); + EXPECT_EQ(srcObj->m3.m7, destObj->m3.m7); + EXPECT_EQ(srcObj->m3.m8, destObj->m3.m8); + EXPECT_EQ(srcObj->m3.m9, destObj->m3.m9); + EXPECT_FLOAT_EQ(srcObj->m3.m10, destObj->m3.m10); + EXPECT_DOUBLE_EQ(srcObj->m3.m11, destObj->m3.m11); + + PrintSSample3(destObj); + std::cout << "\n"; + + SSample3Free(srcObj, true); + SSample3Free(destObj, true); +} + +static void PrintSSample4(struct SSample4* obj) +{ + std::cout << "{"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m1Len; i++) { + std::cout << (obj->m1[i]? 1:0) << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m2Len; i++) { + std::cout << obj->m2[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m3Len; i++) { + std::cout << obj->m3[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m4Len; i++) { + std::cout << obj->m4[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m5Len; i++) { + std::cout << obj->m5[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m6Len; i++) { + std::cout << obj->m6[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m7Len; i++) { + std::cout << obj->m7[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m8Len; i++) { + std::cout << obj->m8[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m9Len; i++) { + std::cout << obj->m9[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m10Len; i++) { + std::cout << obj->m10[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m11Len; i++) { + std::cout << obj->m11[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m12Len; i++) { + std::cout << obj->m12[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m13Len; i++) { + std::cout << ESampleToStr(obj->m13[i]) << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m14Len; i++) { + PrintSSample(&(obj->m14[i])); + std::cout << ","; + } + std::cout << "}"; + + std::cout << "}\n"; +} + +HWTEST_F(StructTest, StructTest_005, TestSize.Level0) +{ + struct SSample4* srcObj = (struct SSample4*)OsalMemCalloc(sizeof(struct SSample4)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1Len = 2; + srcObj->m1 = (bool*)OsalMemCalloc(sizeof(bool) * srcObj->m1Len); + for (uint32_t i = 0; i < srcObj->m1Len; i++) { + srcObj->m1[i] = true; + } + + srcObj->m2Len = 2; + srcObj->m2 = (int8_t*)OsalMemCalloc(sizeof(int8_t) * srcObj->m2Len); + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + srcObj->m2[i] = 65; + } + + srcObj->m3Len = 2; + srcObj->m3 = (int16_t*)OsalMemCalloc(sizeof(int16_t) * srcObj->m3Len); + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + srcObj->m3[i] = 3; + } + + srcObj->m4Len = 2; + srcObj->m4 = (int32_t*)OsalMemCalloc(sizeof(int32_t) * srcObj->m4Len); + for (uint32_t i = 0; i < srcObj->m4Len; i++) { + srcObj->m4[i] = 4; + } + + srcObj->m5Len = 2; + srcObj->m5 = (int64_t*)OsalMemCalloc(sizeof(int64_t) * srcObj->m5Len); + for (uint32_t i = 0; i < srcObj->m5Len; i++) { + srcObj->m5[i] = 5; + } + + srcObj->m6Len = 2; + srcObj->m6 = (uint8_t*)OsalMemCalloc(sizeof(uint8_t) * srcObj->m6Len); + for (uint32_t i = 0; i < srcObj->m6Len; i++) { + srcObj->m6[i] = 97; + } + + srcObj->m7Len = 2; + srcObj->m7 = (uint16_t*)OsalMemCalloc(sizeof(uint16_t) * srcObj->m7Len); + for (uint32_t i = 0; i < srcObj->m7Len; i++) { + srcObj->m7[i] = 7; + } + + srcObj->m8Len = 2; + srcObj->m8 = (uint32_t*)OsalMemCalloc(sizeof(uint32_t) * srcObj->m8Len); + for (uint32_t i = 0; i < srcObj->m8Len; i++) { + srcObj->m8[i] = 8; + } + + srcObj->m9Len = 2; + srcObj->m9 = (uint64_t*)OsalMemCalloc(sizeof(uint64_t) * srcObj->m9Len); + for (uint32_t i = 0; i < srcObj->m9Len; i++) { + srcObj->m9[i] = 9; + } + + srcObj->m10Len = 2; + srcObj->m10 = (float*)OsalMemCalloc(sizeof(float) * srcObj->m10Len); + for (uint32_t i = 0; i < srcObj->m10Len; i++) { + srcObj->m10[i] = 10.5; + } + + srcObj->m11Len = 2; + srcObj->m11 = (double*)OsalMemCalloc(sizeof(double) * srcObj->m11Len); + for (uint32_t i = 0; i < srcObj->m11Len; i++) { + srcObj->m11[i] = 11.55; + } + + srcObj->m12Len = 2; + srcObj->m12 = (char**)OsalMemCalloc(sizeof(char*) * srcObj->m12Len); + for (uint32_t i = 0; i < srcObj->m12Len; i++) { + const char* str = "hello world"; + srcObj->m12[i] = strdup(str); + } + + srcObj->m13Len = 2; + srcObj->m13 = (enum ESample*)OsalMemCalloc(sizeof(enum ESample) * srcObj->m13Len); + for (uint32_t i = 0; i < srcObj->m13Len; i++) { + srcObj->m13[i] = MEM_ONE; + } + + srcObj->m14Len = 2; + srcObj->m14 = (struct SSample*)OsalMemCalloc(sizeof(struct SSample) * srcObj->m14Len); + for (uint32_t i = 0; i < srcObj->m14Len; i++) { + srcObj->m14[i].m1 = true; + srcObj->m14[i].m2 = 2; + srcObj->m14[i].m3 = 3.55; + srcObj->m14[i].m4 = strdup("hello"); + } + + PrintSSample4(srcObj); + std::cout << "\n"; + + struct SSample4* destObj = nullptr; + int32_t ec = g_testClient->SSample4Test(g_testClient, srcObj, &destObj); + + ASSERT_EQ(ec, HDF_SUCCESS); + + + for (uint32_t i = 0; i < srcObj->m1Len; i++) { + EXPECT_EQ(srcObj->m1[i]?1:0, destObj->m1[i]?1:0); + } + + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + EXPECT_EQ(srcObj->m2[i], destObj->m2[i]); + } + + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + EXPECT_EQ(srcObj->m3[i], destObj->m3[i]); + } + + for (uint32_t i = 0; i < srcObj->m4Len; i++) { + EXPECT_EQ(srcObj->m4[i], destObj->m4[i]); + } + + for (uint32_t i = 0; i < srcObj->m5Len; i++) { + EXPECT_EQ(srcObj->m5[i], destObj->m5[i]); + } + + for (uint32_t i = 0; i < srcObj->m6Len; i++) { + EXPECT_EQ(srcObj->m6[i], destObj->m6[i]); + } + + for (uint32_t i = 0; i < srcObj->m7Len; i++) { + EXPECT_EQ(srcObj->m7[i], destObj->m7[i]); + } + + for (uint32_t i = 0; i < srcObj->m8Len; i++) { + EXPECT_EQ(srcObj->m8[i], destObj->m8[i]); + } + + for (uint32_t i = 0; i < srcObj->m9Len; i++) { + EXPECT_EQ(srcObj->m9[i], destObj->m9[i]); + } + + for (uint32_t i = 0; i < srcObj->m10Len; i++) { + EXPECT_FLOAT_EQ(srcObj->m10[i], destObj->m10[i]); + } + + for (uint32_t i = 0; i < srcObj->m11Len; i++) { + EXPECT_DOUBLE_EQ(srcObj->m11[i], destObj->m11[i]); + } + + for (uint32_t i = 0; i < srcObj->m12Len; i++) { + EXPECT_STREQ(srcObj->m12[i], destObj->m12[i]); + } + + for (uint32_t i = 0; i < srcObj->m13Len; i++) { + EXPECT_EQ(srcObj->m13[i], destObj->m13[i]); + } + + for (uint32_t i = 0; i < srcObj->m14Len; i++) { + EXPECT_EQ((srcObj->m14[i]).m1?1:0, (destObj->m14[i]).m1?1:0); + EXPECT_EQ((srcObj->m14[i]).m2, (destObj->m14[i]).m2); + EXPECT_DOUBLE_EQ((srcObj->m14[i]).m3, (destObj->m14[i]).m3); + EXPECT_STREQ((srcObj->m14[i]).m4, (destObj->m14[i]).m4); + } + + PrintSSample4(destObj); + std::cout << "\n"; + + SSample4Free(srcObj, true); + SSample4Free(destObj, true); +} + +static void PrintSSample5(struct SSample5* obj) +{ + std::cout << "{"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m1Len; i++) { + std::cout << (obj->m1[i]? 1:0) << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m2Len; i++) { + std::cout << obj->m2[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m3Len; i++) { + std::cout << obj->m3[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m4Len; i++) { + std::cout << obj->m4[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m5Len; i++) { + std::cout << obj->m5[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m6Len; i++) { + std::cout << obj->m6[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m7Len; i++) { + std::cout << obj->m7[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m8Len; i++) { + std::cout << obj->m8[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m9Len; i++) { + std::cout << obj->m9[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m10Len; i++) { + std::cout << obj->m10[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m11Len; i++) { + std::cout << obj->m11[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m12Len; i++) { + std::cout << obj->m12[i] << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m13Len; i++) { + std::cout << ESampleToStr(obj->m13[i]) << ","; + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m14Len; i++) { + PrintSSample(&(obj->m14[i])); + std::cout << ","; + } + std::cout << "},"; + + std::cout << "}\n"; +} + +HWTEST_F(StructTest, StructTest_006, TestSize.Level0) +{ + struct SSample5* srcObj = (struct SSample5*)OsalMemCalloc(sizeof(struct SSample5)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1Len = 2; + srcObj->m1 = (bool*)OsalMemCalloc(sizeof(bool) * srcObj->m1Len); + for (uint32_t i = 0; i < srcObj->m1Len; i++) { + srcObj->m1[i] = true; + } + + srcObj->m2Len = 2; + srcObj->m2 = (int8_t*)OsalMemCalloc(sizeof(int8_t) * srcObj->m2Len); + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + srcObj->m2[i] = 65; + } + + srcObj->m3Len = 2; + srcObj->m3 = (int16_t*)OsalMemCalloc(sizeof(int16_t) * srcObj->m3Len); + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + srcObj->m3[i] = 3; + } + + srcObj->m4Len = 2; + srcObj->m4 = (int32_t*)OsalMemCalloc(sizeof(int32_t) * srcObj->m4Len); + for (uint32_t i = 0; i < srcObj->m4Len; i++) { + srcObj->m4[i] = 4; + } + + srcObj->m5Len = 2; + srcObj->m5 = (int64_t*)OsalMemCalloc(sizeof(int64_t) * srcObj->m5Len); + for (uint32_t i = 0; i < srcObj->m5Len; i++) { + srcObj->m5[i] = 5; + } + + srcObj->m6Len = 2; + srcObj->m6 = (uint8_t*)OsalMemCalloc(sizeof(uint8_t) * srcObj->m6Len); + for (uint32_t i = 0; i < srcObj->m6Len; i++) { + srcObj->m6[i] = 97; + } + + srcObj->m7Len = 2; + srcObj->m7 = (uint16_t*)OsalMemCalloc(sizeof(uint16_t) * srcObj->m7Len); + for (uint32_t i = 0; i < srcObj->m7Len; i++) { + srcObj->m7[i] = 7; + } + + srcObj->m8Len = 2; + srcObj->m8 = (uint32_t*)OsalMemCalloc(sizeof(uint32_t) * srcObj->m8Len); + for (uint32_t i = 0; i < srcObj->m8Len; i++) { + srcObj->m8[i] = 8; + } + + srcObj->m9Len = 2; + srcObj->m9 = (uint64_t*)OsalMemCalloc(sizeof(uint64_t) * srcObj->m9Len); + for (uint32_t i = 0; i < srcObj->m9Len; i++) { + srcObj->m9[i] = 9; + } + + srcObj->m10Len = 2; + srcObj->m10 = (float*)OsalMemCalloc(sizeof(float) * srcObj->m10Len); + for (uint32_t i = 0; i < srcObj->m10Len; i++) { + srcObj->m10[i] = 10.5; + } + + srcObj->m11Len = 2; + srcObj->m11 = (double*)OsalMemCalloc(sizeof(double) * srcObj->m11Len); + for (uint32_t i = 0; i < srcObj->m11Len; i++) { + srcObj->m11[i] = 11.55; + } + + srcObj->m12Len = 2; + srcObj->m12 = (char**)OsalMemCalloc(sizeof(char*) * srcObj->m12Len); + for (uint32_t i = 0; i < srcObj->m12Len; i++) { + const char* str = "hello world"; + srcObj->m12[i] = strdup(str); + } + + srcObj->m13Len = 2; + srcObj->m13 = (enum ESample*)OsalMemCalloc(sizeof(enum ESample) * srcObj->m13Len); + for (uint32_t i = 0; i < srcObj->m13Len; i++) { + srcObj->m13[i] = MEM_ONE; + } + + srcObj->m14Len = 2; + srcObj->m14 = (struct SSample*)OsalMemCalloc(sizeof(struct SSample) * srcObj->m14Len); + for (uint32_t i = 0; i < srcObj->m14Len; i++) { + srcObj->m14[i].m1 = true; + srcObj->m14[i].m2 = 2; + srcObj->m14[i].m3 = 3.55; + srcObj->m14[i].m4 = strdup("hello"); + } + + PrintSSample5(srcObj); + std::cout << "\n"; + + struct SSample5* destObj = nullptr; + int32_t ec = g_testClient->SSample5Test(g_testClient, srcObj, &destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + for (uint32_t i = 0; i < srcObj->m1Len; i++) { + EXPECT_EQ(srcObj->m1[i]?1:0, destObj->m1[i]?1:0); + } + + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + EXPECT_EQ(srcObj->m2[i], destObj->m2[i]); + } + + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + EXPECT_EQ(srcObj->m3[i], destObj->m3[i]); + } + + for (uint32_t i = 0; i < srcObj->m4Len; i++) { + EXPECT_EQ(srcObj->m4[i], destObj->m4[i]); + } + + for (uint32_t i = 0; i < srcObj->m5Len; i++) { + EXPECT_EQ(srcObj->m5[i], destObj->m5[i]); + } + + for (uint32_t i = 0; i < srcObj->m6Len; i++) { + EXPECT_EQ(srcObj->m6[i], destObj->m6[i]); + } + + for (uint32_t i = 0; i < srcObj->m7Len; i++) { + EXPECT_EQ(srcObj->m7[i], destObj->m7[i]); + } + + for (uint32_t i = 0; i < srcObj->m8Len; i++) { + EXPECT_EQ(srcObj->m8[i], destObj->m8[i]); + } + + for (uint32_t i = 0; i < srcObj->m9Len; i++) { + EXPECT_EQ(srcObj->m9[i], destObj->m9[i]); + } + + for (uint32_t i = 0; i < srcObj->m10Len; i++) { + EXPECT_FLOAT_EQ(srcObj->m10[i], destObj->m10[i]); + } + + for (uint32_t i = 0; i < srcObj->m11Len; i++) { + EXPECT_DOUBLE_EQ(srcObj->m11[i], destObj->m11[i]); + } + + for (uint32_t i = 0; i < srcObj->m12Len; i++) { + EXPECT_STREQ(srcObj->m12[i], destObj->m12[i]); + } + + for (uint32_t i = 0; i < srcObj->m13Len; i++) { + EXPECT_EQ(srcObj->m13[i], destObj->m13[i]); + } + + for (uint32_t i = 0; i < srcObj->m14Len; i++) { + EXPECT_EQ((srcObj->m14[i]).m1?1:0, (destObj->m14[i]).m1?1:0); + EXPECT_EQ((srcObj->m14[i]).m2, (destObj->m14[i]).m2); + EXPECT_DOUBLE_EQ((srcObj->m14[i]).m3, (destObj->m14[i]).m3); + EXPECT_STREQ((srcObj->m14[i]).m4, (destObj->m14[i]).m4); + } + + PrintSSample5(destObj); + std::cout << "\n"; + + SSample5Free(srcObj, true); + SSample5Free(destObj, true); +} + +static void PrintSSample6(struct SSample6* obj) +{ + std::cout << "{"; + + PrintUSample(&obj->m1); + std::cout << ",\n"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m2Len; i++) { + PrintUSample(&obj->m2[i]); + } + std::cout << "},"; + + std::cout << "{"; + for (uint32_t i = 0; i < obj->m3Len; i++) { + PrintUSample(&obj->m3[i]); + } + std::cout << "}"; + + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_007, TestSize.Level0) +{ + struct SSample6* srcObj = (struct SSample6*)OsalMemCalloc(sizeof(struct SSample6)); + ASSERT_NE(srcObj, nullptr); + + srcObj->m1.m1 = true; + srcObj->m1.m2 = 1; + + srcObj->m2Len = 2; + srcObj->m2 = (union USample*)OsalMemCalloc(sizeof(union USample) * srcObj->m2Len); + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + (srcObj->m2[i]).m1 = true; + (srcObj->m2[i]).m2 = 2; + } + + srcObj->m3Len = 2; + srcObj->m3 = (union USample*)OsalMemCalloc(sizeof(union USample) * srcObj->m3Len); + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + (srcObj->m3[i]).m1 = true; + (srcObj->m3[i]).m2 = 2; + } + + PrintSSample6(srcObj); + std::cout << "\n"; + + struct SSample6* destObj = nullptr; + int32_t ec = g_testClient->SSample6Test(g_testClient, srcObj, &destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(srcObj->m1.m1?1:0, destObj->m1.m1?1:0); + EXPECT_EQ(srcObj->m1.m2, destObj->m1.m2); + + for (uint32_t i = 0; i < srcObj->m2Len; i++) { + EXPECT_EQ((srcObj->m2[i]).m1?1:0, (destObj->m2[i]).m1?1:0); + EXPECT_EQ((srcObj->m2[i]).m2, (destObj->m2[i]).m2); + } + + for (uint32_t i = 0; i < srcObj->m3Len; i++) { + EXPECT_EQ((srcObj->m3[i]).m1?1:0, (destObj->m3[i]).m1?1:0); + EXPECT_EQ((srcObj->m3[i]).m2, (destObj->m3[i]).m2); + } + + PrintSSample6(destObj); + std::cout << "\n"; + + SSample6Free(srcObj, true); + SSample6Free(destObj, true); +} + diff --git a/tools/hdi-gen/test/c_test/types/v1_0/Types.idl b/tools/hdi-gen/test/c_test/types/v1_0/Types.idl new file mode 100755 index 000000000..5de08a556 --- /dev/null +++ b/tools/hdi-gen/test/c_test/types/v1_0/Types.idl @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.c_test.types.v1_0; + +enum ESample +{ + MEM_ONE, + MEM_TWO, + MEM_THREE, +}; + +struct SSample +{ + boolean m1; + int m2; + double m3; + String m4; +}; + +union USample +{ + boolean m1; + int m2; +}; + +struct SSample2 +{ + boolean m1; + byte m2; + short m3; + int m4; + long m5; + unsigned char m6; + unsigned short m7; + unsigned int m8; + unsigned long m9; + float m10; + double m11; +}; + +struct SSample3 +{ + String m1; + enum ESample m2; + struct SSample2 m3; + FileDescriptor m4; +}; + +struct SSample4 +{ + boolean[] m1; + byte[] m2; + short[] m3; + int[] m4; + long[] m5; + unsigned char[] m6; + unsigned short[] m7; + unsigned int[] m8; + unsigned long[] m9; + float[] m10; + double[] m11; + String[] m12; + enum ESample[] m13; + struct SSample[] m14; +}; + +struct SSample5 +{ + List m1; + List m2; + List m3; + List m4; + List m5; + List m6; + List m7; + List m8; + List m9; + List m10; + List m11; + List m12; + List m13; + List m14; +}; + +struct SSample6 { + union USample m1; + union USample[] m2; + List m3; +}; \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/array_test/v1_0/IArrayTest.idl b/tools/hdi-gen/test/cpp_test/array_test/v1_0/IArrayTest.idl new file mode 100755 index 000000000..a65dfc69e --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/array_test/v1_0/IArrayTest.idl @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.array_test.v1_0; + +sequenceable test.cpp_test.types.v1_0.SequenceData; + +import test.cpp_test.types.v1_0.Types; + +interface IArrayTest { + + BoolArrayTest([in] boolean[] param1, [out] boolean[] param2); + + ByteArrayTest([in] byte[] param1, [out] byte[] param2); + + ShortArrayTest([in] short[] param1, [out] short[] param2); + + IntArrayTest([in] int[] param1, [out] int[] param2); + + LongArrayTest([in] long[] param1, [out] long[] param2); + + UCharArrayTest([in] unsigned char[] param1, [out] unsigned char[] param2); + + UShortArrayTest([in] unsigned short[] param1, [out] unsigned short[] param2); + + UIntArrayTest([in] unsigned int[] param1, [out] unsigned int[] param2); + + ULongArrayTest([in] unsigned long[] param1, [out] unsigned long[] param2); + + FloatArrayTest([in] float[] param1, [out] float[] param2); + + DoubleArrayTest([in] double[] param1, [out] double[] param2); + + StringArrayTest([in] String[] param1, [out] String[] param2); + + FdArrayTest([in] FileDescriptor[] param1, [out] FileDescriptor[] param2); + + EnumArrayTest([in] enum ESample[] param1, [out] enum ESample[] param2); + + StructArrayTest([in] struct SSample[] param1, [out] struct SSample[] param2); + + UnionArrayTest([in] union USample[] param1, [out] union USample[] param2); + + SeqDataArrayTest([in] SequenceData[] param1, [out] SequenceData[] param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/array_test/v1_0/cpp_array_test.cpp b/tools/hdi-gen/test/cpp_test/array_test/v1_0/cpp_array_test.cpp new file mode 100755 index 000000000..474956ac7 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/array_test/v1_0/cpp_array_test.cpp @@ -0,0 +1,416 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/cpp_test/array_test/v1_0/client/array_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::array_test::v1_0; +using namespace test::cpp_test::types::v1_0; + +sptr g_testClient = nullptr; + +class ArrayTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void ArrayTest::SetUpTestCase() +{ + g_testClient = IArrayTest::Get(); + if (g_testClient == nullptr) { + printf("ArrayTest: get g_testClient failed.\n"); + + } +} + +HWTEST_F(ArrayTest, ArrayTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(ArrayTest, ArrayTest_002, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + if ((i+1)/2 == 0) { + inParam.push_back(false); + } else { + inParam.push_back(true); + } + } + + std::vector outParam; + + int32_t ec = g_testClient->BoolArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ((inParam[i] ? 1 : 0), (outParam[i]? 1 : 0)); + } +} + +HWTEST_F(ArrayTest, ArrayTest_003, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ByteArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_004, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ShortArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_005, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->IntArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_006, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->LongArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_007, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UCharArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_008, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UShortArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_009, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UIntArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_010, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ULongArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_011, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->FloatArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_FLOAT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_012, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->DoubleArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_DOUBLE_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_013, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back("inParam string"); + } + + std::vector outParam; + + int32_t ec = g_testClient->StringArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_014, TestSize.Level0) +{ + int fd1 = open("/ArrayTest_014_0.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + int fd2 = open("/ArrayTest_014_1.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + ASSERT_NE(fd1, -1); + ASSERT_NE(fd2, -1); + + std::vector inParam; + inParam.push_back(fd1); + inParam.push_back(fd2); + + std::vector outParam; + + int32_t ec = g_testClient->FdArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + + std::cout << "inParam[0]:"<< inParam[0] << ", inParam[1]" << inParam[1] << std::endl; + std::cout << "outParam[0]:"<< outParam[0] << ", outParam[1]" << outParam[1] << std::endl; + close(fd1); + close(fd2); +} + +HWTEST_F(ArrayTest, ArrayTest_015, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(ESample::MEM_ONE); + } + + std::vector outParam; + + int32_t ec = g_testClient->EnumArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ArrayTest, ArrayTest_016, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + SSample element; + element.m1 = true; + element.m2 = 1; + element.m3 = 10.5; + element.m4 = "hello"; + inParam.push_back(element); + } + + std::vector outParam; + + int32_t ec = g_testClient->StructArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i].m1? 1:0, outParam[i].m1? 1:0); + ASSERT_EQ(inParam[i].m2, outParam[i].m2); + ASSERT_DOUBLE_EQ(inParam[i].m3, outParam[i].m3); + ASSERT_EQ(inParam[i].m4, outParam[i].m4); + } +} + +HWTEST_F(ArrayTest, ArrayTest_017, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + USample element; + element.m2 = 10; + inParam.push_back(element); + } + + std::vector outParam; + + int32_t ec = g_testClient->UnionArrayTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i].m1? 1:0, outParam[i].m1? 1:0); + ASSERT_EQ(inParam[i].m2, outParam[i].m2); + } +} + +HWTEST_F(ArrayTest, ArrayTest_018, TestSize.Level0) +{ + std::vector> inParam = { + sptr(new SequenceData(1, 1.2, "hello")), + sptr(new SequenceData(2, 2.2, "world")), + }; + + std::vector> outParam; + + int32_t ec = g_testClient->SeqDataArrayTest(inParam, outParam); + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_NE(outParam[i], nullptr); + EXPECT_EQ(inParam[i]->m1_, outParam[i]->m1_); + EXPECT_DOUBLE_EQ(inParam[i]->m2_, outParam[i]->m2_); + EXPECT_EQ(inParam[i]->m3_, outParam[i]->m3_); + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICallback.idl b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICallback.idl new file mode 100755 index 000000000..54e31db0f --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICallback.idl @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.cb_test.v1_0; + +[callback] interface ICallback { + Ping([in] String message); + Plus([in] int num1, [in] int num2, [out] int result); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICbTest.idl b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICbTest.idl new file mode 100755 index 000000000..e71ad6314 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/ICbTest.idl @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.cb_test.v1_0; + +import test.cpp_test.cb_test.v1_0.ICallback; + +interface ICbTest { + CallbackTest([in] ICallback callbackObj); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/cb_test/v1_0/cpp_cb_test.cpp b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/cpp_cb_test.cpp new file mode 100755 index 000000000..749e5aaab --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/cb_test/v1_0/cpp_cb_test.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include "test/cpp_test/cb_test/v1_0/client/cb_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::cb_test::v1_0; + +#define HDF_LOG_TAG sapmle_c_client_test + +sptr g_testClient = nullptr; + +sptr g_callbackObj = nullptr; + +class CbTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void CbTest::SetUpTestCase() +{ + g_testClient = ICbTest::Get(); + if (g_testClient == nullptr) { + printf("CbTest: get g_testClient failed.\n"); + } + g_callbackObj = new CallbackService(); + if (g_callbackObj == nullptr) { + printf("CbTest: get g_callbackObj failed.\n"); + } +} + +HWTEST_F(CbTest, CbTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(CbTest, CbTest_002, TestSize.Level0) +{ + int32_t ec = g_testClient->CallbackTest(g_callbackObj); + ASSERT_EQ(ec, HDF_SUCCESS); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/data_test/v1_0/IDataTest.idl b/tools/hdi-gen/test/cpp_test/data_test/v1_0/IDataTest.idl new file mode 100755 index 000000000..7639283e9 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/data_test/v1_0/IDataTest.idl @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.data_test.v1_0; + +sequenceable test.cpp_test.types.v1_0.SequenceData; + +import test.cpp_test.types.v1_0.Types; + +interface IDataTest { + + BoolTest([in] boolean param1, [out] boolean param2); + + ByteTest([in] byte param1, [out] byte param2); + + ShortTest([in] short param1, [out] short param2); + + IntTest([in] int param1, [out] int param2); + + LongTest([in] long param1, [out] long param2); + + UCharTest([in] unsigned char param1, [out] unsigned char param2); + + UShortTest([in] unsigned short param1, [out] unsigned short param2); + + UIntTest([in] unsigned int param1, [out] unsigned int param2); + + ULongTest([in] unsigned long param1, [out] unsigned long param2); + + FloatTest([in] float param1, [out] float param2); + + DoubleTest([in] double param1, [out] double param2); + + StringTest([in] String param1, [out] String param2); + + FdTest([in] FileDescriptor fd); + + EnumTest([in] enum ESample param1, [out] enum ESample param2); + + StructTest([in] struct SSample param1, [out] struct SSample param2); + + UnionTest([in] union USample param1, [out] union USample param2); + + SequenceDataTest([in] SequenceData param1, [out] SequenceData param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/data_test/v1_0/cpp_data_test.cpp b/tools/hdi-gen/test/cpp_test/data_test/v1_0/cpp_data_test.cpp new file mode 100755 index 000000000..2dbe1de8d --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/data_test/v1_0/cpp_data_test.cpp @@ -0,0 +1,265 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cpp_test/data_test/v1_0/client/data_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::data_test::v1_0; +using namespace test::cpp_test::types::v1_0; + +sptr g_testClient = nullptr; + +class DataTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void DataTest::SetUpTestCase() +{ + g_testClient = IDataTest::Get(); + if (g_testClient == nullptr) { + printf("DataTest: get g_testClient failed.\n"); + } +} + +HWTEST_F(DataTest, DataTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(DataTest, DataTest_002, TestSize.Level0) +{ + bool inParam = true; + bool outParam = false; + int32_t ec = g_testClient->BoolTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_TRUE(inParam); + EXPECT_TRUE(outParam); +} + +HWTEST_F(DataTest, DataTest_003, TestSize.Level0) +{ + int8_t inParam = 10; + int8_t outParam = 0; + + int32_t ec = g_testClient->ByteTest(inParam, outParam); + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_004, TestSize.Level0) +{ + int16_t inParam = 10; + int16_t outParam = 0; + + int32_t ec = g_testClient->ShortTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_005, TestSize.Level0) +{ + int32_t inParam = 10; + int32_t outParam = 0; + + int32_t ec = g_testClient->IntTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_006, TestSize.Level0) +{ + int64_t inParam = 10; + int64_t outParam = 0; + + int32_t ec = g_testClient->LongTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_007, TestSize.Level0) +{ + uint8_t inParam = 10; + uint8_t outParam = 0; + + int32_t ec = g_testClient->UCharTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_008, TestSize.Level0) +{ + uint16_t inParam = 10; + uint16_t outParam = 0; + + int32_t ec = g_testClient->UShortTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_009, TestSize.Level0) +{ + uint32_t inParam = 10; + uint32_t outParam = 0; + + int32_t ec = g_testClient->UIntTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_010, TestSize.Level0) +{ + uint64_t inParam = 10; + uint64_t outParam = 0; + + int32_t ec = g_testClient->ULongTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_011, TestSize.Level0) +{ + float inParam = 10.5; + float outParam = 0; + + int32_t ec = g_testClient->FloatTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_FLOAT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_012, TestSize.Level0) +{ + double inParam = 10.5; + double outParam = 0; + + int32_t ec = g_testClient->DoubleTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_DOUBLE_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_013, TestSize.Level0) +{ + std::string inParam("hello"); + std::string outParam; + + int32_t ec = g_testClient->StringTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_014, TestSize.Level0) +{ + int fd = open("/cpp_data_test_014.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + printf("file open, fd = %d\n", fd); + + + const char* oldMsg = "client:message\n"; + int size = 0; + if ((size = write(fd, oldMsg, strlen(oldMsg))) > 0) { + printf("write oldMsg success, size:%d\n", size); + } + + lseek(fd, 0, SEEK_SET); + + int32_t ec = g_testClient->FdTest(fd); + + ASSERT_EQ(ec, HDF_SUCCESS); + + lseek(fd, 0, SEEK_SET); + + char recvMsg[1024] = {0}; + ssize_t readSize = read(fd, recvMsg, sizeof(recvMsg)); + if (readSize < 0) { + printf("read failed\n"); + goto finished; + } else { + printf("read size:%d\n", readSize); + } + printf("recvMsg:%s", recvMsg); + +finished: + close(fd); +} + +HWTEST_F(DataTest, DataTest_015, TestSize.Level0) +{ + ESample inParam = ESample::MEM_ONE; + ESample outParam = ESample::MEM_TWO; + + int32_t ec = g_testClient->EnumTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + EXPECT_EQ(inParam, outParam); +} + +HWTEST_F(DataTest, DataTest_016, TestSize.Level0) +{ + SSample inParam; + inParam.m1 = true; + inParam.m2 = 1; + inParam.m3 = 10.5; + inParam.m4 = "inParam string"; + + SSample outParam; + + int32_t ec = g_testClient->StructTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(inParam.m1? 1:0, outParam.m1? 1:0); + EXPECT_EQ(inParam.m2, outParam.m2); + EXPECT_DOUBLE_EQ(inParam.m3, outParam.m3); + EXPECT_EQ(inParam.m4, outParam.m4); +} + +HWTEST_F(DataTest, DataTest_017, TestSize.Level0) +{ + USample inParam; + inParam.m2 = 10; + + USample outParam; + + int32_t ec = g_testClient->UnionTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(inParam.m1?1:0, outParam.m1?1:0); + EXPECT_DOUBLE_EQ(inParam.m2, outParam.m2); +} + +HWTEST_F(DataTest, DataTest_018, TestSize.Level0) +{ + sptr inParam(new SequenceData(1, 1.2, "hello")); + + sptr outParam = nullptr; + + int32_t ec = g_testClient->SequenceDataTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(inParam->m1_, outParam->m1_); + EXPECT_DOUBLE_EQ(inParam->m2_, outParam->m2_); + EXPECT_EQ(inParam->m3_, outParam->m3_); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/list_test/v1_0/IListTest.idl b/tools/hdi-gen/test/cpp_test/list_test/v1_0/IListTest.idl new file mode 100755 index 000000000..1cfa43c57 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/list_test/v1_0/IListTest.idl @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.list_test.v1_0; + +sequenceable test.cpp_test.types.v1_0.SequenceData; + +import test.cpp_test.types.v1_0.Types; + +interface IListTest { + + BoolListTest([in] List param1, [out] List param2); + + ByteListTest([in] List param1, [out] List param2); + + ShortListTest([in] List param1, [out] List param2); + + IntListTest([in] List param1, [out] List param2); + + LongListTest([in] List param1, [out] List param2); + + UCharListTest([in] List param1, [out] List param2); + + UShortListTest([in] List param1, [out] List param2); + + UIntListTest([in] List param1, [out] List param2); + + ULongListTest([in] List param1, [out] List param2); + + FloatListTest([in] List param1, [out] List param2); + + DoubleListTest([in] List param1, [out] List param2); + + StringListTest([in] List param1, [out] List param2); + + FdListTest([in] List param1, [out] List param2); + + EnumListTest([in] List param1, [out] List param2); + + StructListTest([in] List param1, [out] List param2); + + UnionListTest([in] List param1, [out] List param2); + + SeqDataListTest([in] List param1, [out] List param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/list_test/v1_0/cpp_list_test.cpp b/tools/hdi-gen/test/cpp_test/list_test/v1_0/cpp_list_test.cpp new file mode 100755 index 000000000..89a6276f0 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/list_test/v1_0/cpp_list_test.cpp @@ -0,0 +1,416 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/cpp_test/list_test/v1_0/client/list_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::list_test::v1_0; +using namespace test::cpp_test::types::v1_0; + +sptr g_testClient = nullptr; + +class ListTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void ListTest::SetUpTestCase() +{ + g_testClient = IListTest::Get(); + if (g_testClient == nullptr) { + printf("ListTest: get g_testClient failed.\n"); + + } +} + +HWTEST_F(ListTest, ListTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(ListTest, ListTest_002, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + if ((i+1)/2 == 0) { + inParam.push_back(false); + } else { + inParam.push_back(true); + } + } + + std::vector outParam; + + int32_t ec = g_testClient->BoolListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ((inParam[i] ? 1 : 0), (outParam[i]? 1 : 0)); + } +} + +HWTEST_F(ListTest, ListTest_003, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ByteListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_004, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ShortListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_005, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->IntListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_006, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->LongListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_007, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UCharListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_008, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UShortListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_009, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->UIntListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_010, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->ULongListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_011, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->FloatListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_FLOAT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_012, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(4); + } + + std::vector outParam; + + int32_t ec = g_testClient->DoubleListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_DOUBLE_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_013, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back("inParam string"); + } + + std::vector outParam; + + int32_t ec = g_testClient->StringListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_014, TestSize.Level0) +{ + int fd1 = open("/ListTest_014_0.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + int fd2 = open("/ListTest_014_1.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + ASSERT_NE(fd1, -1); + ASSERT_NE(fd2, -1); + + std::vector inParam; + inParam.push_back(fd1); + inParam.push_back(fd2); + + std::vector outParam; + + int32_t ec = g_testClient->FdListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + + std::cout << "inParam[0]:"<< inParam[0] << ", inParam[1]" << inParam[1] << std::endl; + std::cout << "outParam[0]:"<< outParam[0] << ", outParam[1]" << outParam[1] << std::endl; + close(fd1); + close(fd2); +} + +HWTEST_F(ListTest, ListTest_015, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + inParam.push_back(ESample::MEM_ONE); + } + + std::vector outParam; + + int32_t ec = g_testClient->EnumListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i], outParam[i]); + } +} + +HWTEST_F(ListTest, ListTest_016, TestSize.Level0) +{ + uint32_t len = 4; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + SSample element; + element.m1 = true; + element.m2 = 1; + element.m3 = 10.5; + element.m4 = "hello"; + inParam.push_back(element); + } + + std::vector outParam; + + int32_t ec = g_testClient->StructListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i].m1? 1:0, outParam[i].m1? 1:0); + ASSERT_EQ(inParam[i].m2, outParam[i].m2); + ASSERT_DOUBLE_EQ(inParam[i].m3, outParam[i].m3); + ASSERT_EQ(inParam[i].m4, outParam[i].m4); + } +} + +HWTEST_F(ListTest, ListTest_017, TestSize.Level0) +{ + uint32_t len = 2; + std::vector inParam; + + for (uint32_t i = 0; i < len; i++) { + USample element; + element.m2 = 10; + inParam.push_back(element); + } + + std::vector outParam; + + int32_t ec = g_testClient->UnionListTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_EQ(inParam[i].m1? 1:0, outParam[i].m1? 1:0); + ASSERT_EQ(inParam[i].m2, outParam[i].m2); + } +} + +HWTEST_F(ListTest, ListTest_018, TestSize.Level0) +{ + std::vector> inParam = { + sptr(new SequenceData(1, 1.2, "hello")), + sptr(new SequenceData(2, 2.2, "world")), + }; + + std::vector> outParam; + + int32_t ec = g_testClient->SeqDataListTest(inParam, outParam); + ASSERT_EQ(ec, HDF_SUCCESS); + + ASSERT_EQ(inParam.size(), outParam.size()); + for (uint32_t i = 0; i < inParam.size(); i++) { + ASSERT_NE(outParam[i], nullptr); + EXPECT_EQ(inParam[i]->m1_, outParam[i]->m1_); + EXPECT_DOUBLE_EQ(inParam[i]->m2_, outParam[i]->m2_); + EXPECT_EQ(inParam[i]->m3_, outParam[i]->m3_); + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/map_test/v1_0/IMapTest.idl b/tools/hdi-gen/test/cpp_test/map_test/v1_0/IMapTest.idl new file mode 100755 index 000000000..0a5071143 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/map_test/v1_0/IMapTest.idl @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.map_test.v1_0; + +sequenceable test.cpp_test.types.v1_0.SequenceData; + +import test.cpp_test.types.v1_0.Types; + +interface IMapTest { + MapIntByteTest([in] Map param1, [out] Map param2); + + MapIntShortTest([in] Map param1, [out] Map param2); + + MapIntIntTest([in] Map param1, [out] Map param2); + + MapIntLongTest([in] Map param1, [out] Map param2); + + MapIntFloatTest([in] Map param1, [out] Map param2); + + MapIntDoubleTest([in] Map param1, [out] Map param2); + + MapIntStringTest([in] Map param1, [out] Map param2); + + MapIntFdTest([in] Map param1, [out] Map param2); + + MapIntSeqTest([in] Map param1, [out] Map param2); + + MapIntEnumTest([in] Map param1, [out] Map param2); + + MapIntStructTest([in] Map param1, [out] Map param2); + + MapIntUnionTest([in] Map param1, [out] Map param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/map_test/v1_0/cpp_map_test.cpp b/tools/hdi-gen/test/cpp_test/map_test/v1_0/cpp_map_test.cpp new file mode 100755 index 000000000..3fc9bfa74 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/map_test/v1_0/cpp_map_test.cpp @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include +#include +#include +#include "cpp_test/map_test/v1_0/client/map_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::map_test::v1_0; +using namespace test::cpp_test::types::v1_0; + +sptr g_testClient = nullptr; + +class MapTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(){} + void TearDown(){} +}; + +void MapTest::SetUpTestCase() +{ + g_testClient = IMapTest::Get(); + if (g_testClient == nullptr) { + std::cout << "MapTest: get g_testClient failed." << std::endl; + } +} + +void MapTest::TearDownTestCase() +{ + if (g_testClient != nullptr) { + delete g_testClient; + g_testClient = nullptr; + } +} + +HWTEST_F(MapTest, MapTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +HWTEST_F(MapTest, MapTest_002, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 'A'; + inParam[2] = 'B'; + + std::map outParam; + + int32_t ec = g_testClient->MapIntByteTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_002 TestCase is failed!" << std::endl; + } + } +} + + +HWTEST_F(MapTest, MapTest_003, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 1; + inParam[2] = 2; + + std::map outParam; + + int32_t ec = g_testClient->MapIntShortTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_003 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_004, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 1; + inParam[2] = 2; + + std::map outParam; + + int32_t ec = g_testClient->MapIntIntTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_004 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_005, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 100; + inParam[2] = 200; + + std::map outParam; + + int32_t ec = g_testClient->MapIntLongTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_005 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_006, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 10.5; + inParam[2] = 20.5; + + std::map outParam; + + int32_t ec = g_testClient->MapIntFloatTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_006 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_007, TestSize.Level0) +{ + std::map inParam; + inParam[1] = 10.55; + inParam[2] = 20.55; + + std::map outParam; + + int32_t ec = g_testClient->MapIntDoubleTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_DOUBLE_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_007 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_008, TestSize.Level0) +{ + std::map inParam; + inParam[1] = "hello"; + inParam[2] = "world"; + + std::map outParam; + + int32_t ec = g_testClient->MapIntStringTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_STREQ(inIter->second.c_str(), outIter->second.c_str()); + } else { + std::cout << "MapTest_008 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_009, TestSize.Level0) +{ + std::map inParam; + inParam[1] = open("/cpp_test_map_009.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + inParam[2] = open("/cpp_test_map_009.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + + std::map outParam; + + int32_t ec = g_testClient->MapIntFdTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + std::cout << "inParam[" << inIter->first << "]:" << inIter->second << std::endl; + std::cout << "outParam[" << outIter->first << "]:" << outIter->second << std::endl; + } else { + std::cout << "MapTest_009 TestCase is failed!" << std::endl; + } + } + + close(inParam[1]); + close(outParam[0]); +} + +HWTEST_F(MapTest, MapTest_010, TestSize.Level0) +{ + std::map> inParam = { + {0, sptr(new SequenceData(1, 1.2, "hello"))}, + {1, sptr(new SequenceData(2, 2.2, "world"))} + }; + + std::map> outParam; + + int32_t ec = g_testClient->MapIntSeqTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + EXPECT_EQ(inIter->second->m1_, outIter->second->m1_); + EXPECT_DOUBLE_EQ(inIter->second->m2_, outIter->second->m2_); + EXPECT_EQ(inIter->second->m3_, outIter->second->m3_); + } else { + std::cout << "MapTest_010 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_011, TestSize.Level0) +{ + std::map inParam; + inParam[1] = ESample::MEM_ONE; + inParam[2] = ESample::MEM_TWO; + + std::map outParam; + + int32_t ec = g_testClient->MapIntEnumTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ(inIter->second, outIter->second); + } else { + std::cout << "MapTest_011 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_012, TestSize.Level0) +{ + std::map inParam; + for (int32_t i = 0; i < 2; i++) { + SSample value; + value.m1 = true; + value.m2 = 10; + value.m3 = 10.5; + value.m4 = "inParam string"; + inParam[i] = value; + } + + std::map outParam; + + int32_t ec = g_testClient->MapIntStructTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ((inIter->second).m1?1:0, (outIter->second).m1?1:0); + ASSERT_EQ((inIter->second).m2, (outIter->second).m2); + ASSERT_DOUBLE_EQ((inIter->second).m3, (outIter->second).m3); + ASSERT_EQ((inIter->second).m4, (outIter->second).m4); + } else { + std::cout << "MapTest_012 TestCase is failed!" << std::endl; + } + } +} + +HWTEST_F(MapTest, MapTest_013, TestSize.Level0) +{ + std::map inParam; + for (int32_t i = 0; i < 2; i++) { + USample value; + value.m1 = true; + value.m2 = 10; + inParam[i] = value; + } + + std::map outParam; + + int32_t ec = g_testClient->MapIntUnionTest(inParam, outParam); + + ASSERT_EQ(ec, HDF_SUCCESS); + + for (auto inIter = inParam.begin(); inIter != inParam.end(); ++inIter) { + auto outIter = outParam.find(inIter->first); + if (outIter != outParam.end()) { + ASSERT_EQ((inIter->second).m1?1:0, (outIter->second).m1?1:0); + ASSERT_EQ((inIter->second).m2, (outIter->second).m2); + } else { + std::cout << "MapTest_013 TestCase is failed!" << std::endl; + } + } +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/struct_test/v1_0/IStructTest.idl b/tools/hdi-gen/test/cpp_test/struct_test/v1_0/IStructTest.idl new file mode 100755 index 000000000..fe002812f --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/struct_test/v1_0/IStructTest.idl @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.struct_test.v1_0; + +import test.cpp_test.types.v1_0.Types; + +interface IStructTest { + SSampleTest([in] struct SSample param1, [out] struct SSample param2); + SSample2Test([in] struct SSample2 param1, [out] struct SSample2 param2); + SSample3Test([in] struct SSample3 param1, [out] struct SSample3 param2); + SSample4Test([in] struct SSample4 param1, [out] struct SSample4 param2); + SSample5Test([in] struct SSample5 param1, [out] struct SSample5 param2); + SSample6Test([in] struct SSample6 param1, [out] struct SSample6 param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/struct_test/v1_0/cpp_struct_test.cpp b/tools/hdi-gen/test/cpp_test/struct_test/v1_0/cpp_struct_test.cpp new file mode 100755 index 000000000..3e87d5d8a --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/struct_test/v1_0/cpp_struct_test.cpp @@ -0,0 +1,719 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "test/cpp_test/struct_test/v1_0/client/struct_test_proxy.h" + +using namespace OHOS; +using namespace testing::ext; +using namespace test::cpp_test::struct_test::v1_0; +using namespace test::cpp_test::types::v1_0; + +sptr g_testClient = nullptr; + +class StructTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(){} + void SetUp(){} + void TearDown(){} +}; + +void StructTest::SetUpTestCase() +{ + g_testClient = IStructTest::Get(); + if (g_testClient == nullptr) { + printf("StructTest: get g_testClient failed.\n"); + } +} + +HWTEST_F(StructTest, StructTest_001, TestSize.Level0) +{ + ASSERT_NE(nullptr, g_testClient); +} + +static std::string ESampleToStr(ESample obj) +{ + switch (obj) { + case ESample::MEM_ONE: + return "MEM_ONE"; + case ESample::MEM_TWO: + return "MEM_TWO"; + case ESample::MEM_THREE: + return "MEM_THREE"; + } +} + +static void PrintSSample(const SSample& obj) +{ + std::cout << "{"; + std::cout << "m1:" << (obj.m1?1:0) << ", "; + std::cout << "m2:" << obj.m2 << ", "; + std::cout << "m3:" << obj.m3 << ", "; + std::cout << "m4:" << obj.m4; + std::cout << "}"; +} + +// static void PrintUSample(const USample& obj) +// { +// std::cout << "{"; +// std::cout << "m1:" << (obj.m1? 1:0) << ", "; +// std::cout << "m2:" << obj.m2; +// std::cout << "}"; +// } + +HWTEST_F(StructTest, StructTest_002, TestSize.Level0) +{ + SSample srcObj = {true, 1, 1000.125, "hello world"}; + + SSample destObj; + + int32_t ec = g_testClient->SSampleTest(srcObj, destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(srcObj.m1? 1:0 ,destObj.m1?1:0); + EXPECT_EQ(srcObj.m2, destObj.m2); + EXPECT_DOUBLE_EQ(srcObj.m3, destObj.m3); + EXPECT_EQ(srcObj.m4, destObj.m4); + + PrintSSample(srcObj); + std::cout << "\n"; + PrintSSample(destObj); + std::cout << "\n"; + std::cout << "----------------------------" << std::endl; +} + +static void PrintSSample2(const SSample2& obj) +{ + std::cout << "{"; + + std::cout << "m1:" << obj.m1 << ", "; + std::cout << "m2:" << (obj.m2? 1:0) << ", "; + std::cout << "m3:" << obj.m3 << ", "; + std::cout << "m4:" << obj.m4 << ", "; + std::cout << "m5:" << obj.m5 << ", "; + std::cout << "m6:" << obj.m6 << ", "; + std::cout << "m7:" << obj.m7 << ", "; + std::cout << "m8:" << obj.m8 << ", "; + std::cout << "m9:" << obj.m9 << ", "; + std::cout << "m10:" << obj.m10 << ", "; + std::cout << "m11:" << obj.m11; + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_003, TestSize.Level0) +{ + SSample2 srcObj = {true, 1, 2, 3, 4, 65, 20, 30, 40, 100.25, 1000.125}; + + SSample2 destObj; + + int32_t ec = g_testClient->SSample2Test(srcObj, destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(srcObj.m1? 1:0 ,destObj.m1?1:0); + EXPECT_EQ(srcObj.m2, destObj.m2); + EXPECT_EQ(srcObj.m3, destObj.m3); + EXPECT_EQ(srcObj.m4, destObj.m4); + EXPECT_EQ(srcObj.m5, destObj.m5); + EXPECT_EQ(srcObj.m6, destObj.m6); + EXPECT_EQ(srcObj.m7, destObj.m7); + EXPECT_EQ(srcObj.m8, destObj.m8); + EXPECT_EQ(srcObj.m9, destObj.m9); + EXPECT_FLOAT_EQ(srcObj.m10, destObj.m10); + EXPECT_DOUBLE_EQ(srcObj.m11, destObj.m11); + + PrintSSample2(srcObj); + std::cout << "\n"; + PrintSSample2(destObj); + std::cout << "\n"; + std::cout << "----------------------------" << std::endl; +} + +static void PrintSSample3(const SSample3& obj) +{ + std::cout << "{"; + std::cout << "m1:" << obj.m1 << ", "; + std::cout << "m2:" << ESampleToStr(obj.m2) << ", "; + + std::cout << "m3:"; + PrintSSample2(obj.m3); + std::cout << ", "; + + std::cout << "m4:" << obj.m4; +} + +HWTEST_F(StructTest, StructTest_004, TestSize.Level0) +{ + int fd = open("/fdtest3.txt", O_CREAT | O_RDWR | O_TRUNC, 0644); + SSample3 srcObj = { + "hello world", + ESample::MEM_ONE, + {true, 1, 2, 3, 4, 65, 20, 30, 40, 100.25, 1000.125}, + fd, + }; + + SSample3 destObj; + int32_t ec = g_testClient->SSample3Test(srcObj, destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + EXPECT_EQ(srcObj.m1, destObj.m1); + EXPECT_EQ(srcObj.m2, destObj.m2); + + EXPECT_EQ(srcObj.m3.m1? 1:0 ,destObj.m3.m1?1:0); + EXPECT_EQ(srcObj.m3.m2, destObj.m3.m2); + EXPECT_EQ(srcObj.m3.m3, destObj.m3.m3); + EXPECT_EQ(srcObj.m3.m4, destObj.m3.m4); + EXPECT_EQ(srcObj.m3.m5, destObj.m3.m5); + EXPECT_EQ(srcObj.m3.m6, destObj.m3.m6); + EXPECT_EQ(srcObj.m3.m7, destObj.m3.m7); + EXPECT_EQ(srcObj.m3.m8, destObj.m3.m8); + EXPECT_EQ(srcObj.m3.m9, destObj.m3.m9); + EXPECT_FLOAT_EQ(srcObj.m3.m10, destObj.m3.m10); + EXPECT_DOUBLE_EQ(srcObj.m3.m11, destObj.m3.m11); + + //m4 file descriptor + PrintSSample3(srcObj); + std::cout << "\n"; + PrintSSample3(destObj); + std::cout << "\n"; + std::cout << "----------------------------" << std::endl; + close(srcObj.m4); + close(destObj.m4); +} + +static void PrintSSample4(const SSample4& obj) +{ + std::cout << "{\n"; + + //m1 + std::cout << "m1:{"; + for (size_t i = 0; i < obj.m1.size(); i++) { + std::cout << (obj.m1[i]? 1:0) << ", "; + } + std::cout << "},\n"; + + //m2 + std::cout << "m2:{"; + for (size_t i = 0; i < obj.m2.size(); i++) { + std::cout << obj.m2[i] << ", "; + } + std::cout << "},\n"; + + //m3 + std::cout << "m3:{"; + for (size_t i = 0; i < obj.m3.size(); i++) { + std::cout << obj.m3[i] << ", "; + } + std::cout << "},\n"; + + //m4 + std::cout << "m4:{"; + for (size_t i = 0; i < obj.m4.size(); i++) { + std::cout << obj.m4[i] << ", "; + } + std::cout << "},\n"; + + //m5 + std::cout << "m5:{"; + for (size_t i = 0; i < obj.m5.size(); i++) { + std::cout << obj.m5[i] << ", "; + } + std::cout << "},\n"; + + //m6 + std::cout << "m6:{"; + for (size_t i = 0; i < obj.m6.size(); i++) { + std::cout << obj.m6[i] << ", "; + } + std::cout << "},\n"; + + //m7 + std::cout << "m7:{"; + for (size_t i = 0; i < obj.m7.size(); i++) { + std::cout << obj.m7[i] << ", "; + } + std::cout << "},\n"; + + //m8 + std::cout << "m8:{"; + for (size_t i = 0; i < obj.m8.size(); i++) { + std::cout << obj.m8[i] << ", "; + } + std::cout << "},\n"; + + //m9 + std::cout << "m9:{"; + for (size_t i = 0; i < obj.m9.size(); i++) { + std::cout << obj.m9[i] << ", "; + } + std::cout << "},\n"; + + //m10 + std::cout << "m10:{"; + for (size_t i = 0; i < obj.m10.size(); i++) { + std::cout << obj.m10[i] << ", "; + } + std::cout << "},\n"; + + //m11 + std::cout << "m11:{"; + for (size_t i = 0; i < obj.m11.size(); i++) { + std::cout << obj.m11[i] << ", "; + } + std::cout << "},\n"; + + //m12 + std::cout << "m12:{"; + for (size_t i = 0; i < obj.m12.size(); i++) { + std::cout << obj.m12[i] << ", "; + } + std::cout << "},\n"; + + //m13 + std::cout << "m13:{"; + for (size_t i = 0; i < obj.m13.size(); i++) { + std::cout << ESampleToStr(obj.m13[i]) << ", "; + } + std::cout << "},\n"; + + //m14 + std::cout << "m14:{"; + for (size_t i = 0; i < obj.m13.size(); i++) { + PrintSSample(obj.m14[i]); + std::cout << ", "; + } + std::cout << "},\n"; + + //m15 + std::cout << "m15:{"; + for (size_t i = 0; i < obj.m15.size(); i++) { + std::cout << obj.m15[i] << ", "; + } + std::cout << "}"; + std::cout << "}\n"; +} + +HWTEST_F(StructTest, StructTest_005, TestSize.Level0) +{ + SSample4 srcObj = { + {true, false}, + {65, 66}, + {3, 4}, + {5, 6}, + {7, 8}, + {97, 98}, + {30, 40}, + {50, 60}, + {70, 80}, + {10.5, 20.5}, + {30.125, 30.125}, + {"hello", "world"}, + {ESample::MEM_ONE, ESample::MEM_THREE}, + {{true, 1, 1000.125, "hello"}, {false, 1, 1000.125, "world"}}, + {sptr(new SequenceData(1, 1.2, "hello")), sptr(new SequenceData(2, 2.2, "world"))}, + }; + + SSample4 destObj; + + int32_t ec = g_testClient->SSample4Test(srcObj, destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + + //m1 + for (size_t i = 0; i < srcObj.m1.size(); i++) { + EXPECT_EQ(srcObj.m1[i]? 1:0, destObj.m1[i]? 1:0); + } + + //m2 + for (size_t i = 0; i < srcObj.m2.size(); i++) { + EXPECT_EQ(srcObj.m2[i], destObj.m2[i]); + } + + //m3 + for (size_t i = 0; i < srcObj.m3.size(); i++) { + EXPECT_EQ(srcObj.m3[i], destObj.m3[i]); + } + + //m4 + for (size_t i = 0; i < srcObj.m4.size(); i++) { + EXPECT_EQ(srcObj.m4[i], destObj.m4[i]); + } + + //m5 + for (size_t i = 0; i < srcObj.m5.size(); i++) { + EXPECT_EQ(srcObj.m5[i], destObj.m5[i]); + } + + //m6 + for (size_t i = 0; i < srcObj.m6.size(); i++) { + EXPECT_EQ(srcObj.m6[i], destObj.m6[i]); + } + + //m7 + for (size_t i = 0; i < srcObj.m7.size(); i++) { + EXPECT_EQ(srcObj.m7[i], destObj.m7[i]); + } + + //m8 + for (size_t i = 0; i < srcObj.m8.size(); i++) { + EXPECT_EQ(srcObj.m8[i], destObj.m8[i]); + } + + //m9 + for (size_t i = 0; i < srcObj.m9.size(); i++) { + EXPECT_EQ(srcObj.m9[i], destObj.m9[i]); + } + + //m10 + for (size_t i = 0; i < srcObj.m10.size(); i++) { + EXPECT_FLOAT_EQ(srcObj.m10[i], destObj.m10[i]); + } + + //m11 + for (size_t i = 0; i < srcObj.m11.size(); i++) { + EXPECT_DOUBLE_EQ(srcObj.m11[i], destObj.m11[i]); + } + + //m12 + for (size_t i = 0; i < srcObj.m12.size(); i++) { + EXPECT_EQ(srcObj.m12[i], destObj.m12[i]); + } + + //m13 + for (size_t i = 0; i < srcObj.m13.size(); i++) { + EXPECT_EQ(srcObj.m13[i], destObj.m13[i]); + } + + //m14 + for (size_t i = 0; i < srcObj.m14.size(); i++) { + EXPECT_EQ((srcObj.m14[i]).m1? 1:0 ,(destObj.m14[i]).m1?1:0); + EXPECT_EQ((srcObj.m14[i]).m2, (destObj.m14[i]).m2); + EXPECT_DOUBLE_EQ((srcObj.m14[i]).m3, (destObj.m14[i]).m3); + EXPECT_EQ((srcObj.m14[i]).m4, (destObj.m14[i]).m4); + } + + //m15 + for (size_t i = 0; i < srcObj.m15.size(); i++) { + sptr var1 = srcObj.m15[i]; + sptr var2 = destObj.m15[i]; + + if (var1 != nullptr && var2 != nullptr) { + EXPECT_EQ(var1->m1_, var2->m1_); + EXPECT_DOUBLE_EQ(var1->m2_, var2->m2_); + EXPECT_EQ(var1->m3_, var2->m3_); + } else { + std::cout << "var1 or var2 is nullptr" << std::endl; + } + } + + PrintSSample4(srcObj); + PrintSSample4(destObj); + std::cout << "\n"; + std::cout << "--------------------------------------\n"; +} + +static void PrintSSample5(const SSample5& obj) +{ + std::cout << "{\n"; + + //m1 + std::cout << "m1:{"; + for (size_t i = 0; i < obj.m1.size(); i++) { + std::cout << obj.m1[i] << ", "; + } + std::cout << "},\n"; + + //m2 + std::cout << "m2:{"; + for (size_t i = 0; i < obj.m2.size(); i++) { + std::cout << obj.m2[i] << ", "; + } + std::cout << "},\n"; + + //m3 + std::cout << "m3:{"; + for (size_t i = 0; i < obj.m3.size(); i++) { + std::cout << obj.m3[i] << ", "; + } + std::cout << "},\n"; + + //m4 + std::cout << "m4:{"; + for (size_t i = 0; i < obj.m4.size(); i++) { + std::cout << obj.m4[i] << ", "; + } + std::cout << "},\n"; + + //m5 + std::cout << "m5:{"; + for (size_t i = 0; i < obj.m5.size(); i++) { + std::cout << obj.m5[i] << ", "; + } + std::cout << "},\n"; + + //m6 + std::cout << "m6:{"; + for (size_t i = 0; i < obj.m6.size(); i++) { + std::cout << obj.m6[i] << ", "; + } + std::cout << "},\n"; + + //m7 + std::cout << "m7:{"; + for (size_t i = 0; i < obj.m7.size(); i++) { + std::cout << obj.m7[i] << ", "; + } + std::cout << "},\n"; + + //m8 + std::cout << "m8:{"; + for (size_t i = 0; i < obj.m8.size(); i++) { + std::cout << obj.m8[i] << ", "; + } + std::cout << "},\n"; + + //m9 + std::cout << "m9:{"; + for (size_t i = 0; i < obj.m9.size(); i++) { + std::cout << obj.m9[i] << ", "; + } + std::cout << "},\n"; + + //m10 + std::cout << "m10:{"; + for (size_t i = 0; i < obj.m10.size(); i++) { + std::cout << obj.m10[i] << ", "; + } + std::cout << "},\n"; + + //m11 + std::cout << "m11:{"; + for (size_t i = 0; i < obj.m11.size(); i++) { + std::cout << obj.m11[i] << ", "; + } + std::cout << "},\n"; + + //m12 + std::cout << "m12:{"; + for (size_t i = 0; i < obj.m12.size(); i++) { + std::cout << obj.m12[i] << ", "; + } + std::cout << "},\n"; + + //m13 + std::cout << "m13:{"; + for (size_t i = 0; i < obj.m13.size(); i++) { + std::cout << ESampleToStr(obj.m13[i]) << ", "; + } + std::cout << "},\n"; + + //m14 + std::cout << "m14:{"; + for (size_t i = 0; i < obj.m14.size(); i++) { + PrintSSample(obj.m14[i]); + std::cout << ", \n"; + } + std::cout << ",\n"; + + //m15 + std::cout << "m13:{"; + for (size_t i = 0; i < obj.m15.size(); i++) { + std::cout << obj.m15[i] << ", "; + } + std::cout << "},\n"; + + std::cout << "}"; +} + +HWTEST_F(StructTest, StructTest_006, TestSize.Level0) +{ + SSample5 srcObj = { + {true, false}, + {65, 66}, + {3, 4}, + {5, 6}, + {7, 8}, + {97, 98}, + {30, 40}, + {50, 60}, + {70, 80}, + {10.5, 20.5}, + {30.125, 30.125}, + {"hello", "world"}, + {ESample::MEM_ONE, ESample::MEM_THREE}, + {{true, 1, 1000.125, "hello"}, {false, 1, 1000.125, "world"}}, + {sptr(new SequenceData(1, 1.2, "hello")), sptr(new SequenceData(2, 2.2, "world"))}, + }; + + SSample5 destObj; + + int32_t ec = g_testClient->SSample5Test(srcObj, destObj); + ASSERT_EQ(ec, HDF_SUCCESS); + + //m1 + for (size_t i = 0; i < srcObj.m1.size(); i++) { + EXPECT_EQ(srcObj.m1[i]? 1:0, destObj.m1[i]? 1:0); + } + + //m2 + for (size_t i = 0; i < srcObj.m2.size(); i++) { + EXPECT_EQ(srcObj.m2[i], destObj.m2[i]); + } + + //m3 + for (size_t i = 0; i < srcObj.m3.size(); i++) { + EXPECT_EQ(srcObj.m3[i], destObj.m3[i]); + } + + //m4 + for (size_t i = 0; i < srcObj.m4.size(); i++) { + EXPECT_EQ(srcObj.m4[i], destObj.m4[i]); + } + + //m5 + for (size_t i = 0; i < srcObj.m5.size(); i++) { + EXPECT_EQ(srcObj.m5[i], destObj.m5[i]); + } + + //m6 + for (size_t i = 0; i < srcObj.m6.size(); i++) { + EXPECT_EQ(srcObj.m6[i], destObj.m6[i]); + } + + //m7 + for (size_t i = 0; i < srcObj.m7.size(); i++) { + EXPECT_EQ(srcObj.m7[i], destObj.m7[i]); + } + + // m8 + for (size_t i = 0; i < srcObj.m8.size(); i++) { + EXPECT_EQ(srcObj.m8[i], destObj.m8[i]); + } + + // m9 + for (size_t i = 0; i < srcObj.m9.size(); i++) { + EXPECT_EQ(srcObj.m9[i], destObj.m9[i]); + } + + // m10 + for (size_t i = 0; i < srcObj.m10.size(); i++) { + EXPECT_FLOAT_EQ(srcObj.m10[i], destObj.m10[i]); + } + + //m11 + for (size_t i = 0; i < srcObj.m11.size(); i++) { + EXPECT_DOUBLE_EQ(srcObj.m11[i], destObj.m11[i]); + } + + //m12 + for (size_t i = 0; i < srcObj.m12.size(); i++) { + EXPECT_EQ(srcObj.m12[i], destObj.m12[i]); + } + + //m13 + for (size_t i = 0; i < srcObj.m13.size(); i++) { + EXPECT_EQ(srcObj.m13[i], destObj.m13[i]); + } + + //m14 + for (size_t i = 0; i < srcObj.m14.size(); i++) { + EXPECT_EQ((srcObj.m14[i]).m1? 1:0 ,(destObj.m14[i]).m1?1:0); + EXPECT_EQ((srcObj.m14[i]).m2, (destObj.m14[i]).m2); + EXPECT_DOUBLE_EQ((srcObj.m14[i]).m3, (destObj.m14[i]).m3); + EXPECT_EQ((srcObj.m14[i]).m4, (destObj.m14[i]).m4); + } + + //m15 + for (size_t i = 0; i < srcObj.m15.size(); i++) { + sptr var1 = srcObj.m15[i]; + sptr var2 = destObj.m15[i]; + + if (var1 != nullptr && var2 != nullptr) { + EXPECT_EQ(var1->m1_, var2->m1_); + EXPECT_DOUBLE_EQ(var1->m2_, var2->m2_); + EXPECT_EQ(var1->m3_, var2->m3_); + } else { + std::cout << "var1 or var2 is nullptr" << std::endl; + } + } + + PrintSSample5(srcObj); + PrintSSample5(destObj); + std::cout << "\n"; + std::cout << "--------------------------------------\n"; +} + +// static void PrintSSample6(const SSample6& obj) +// { +// std::cout << "{\n"; + +// PrintUSample(obj.m1); +// std::cout << ",\n"; + +// std::cout << "{"; +// for (size_t i = 0; i < obj.m2.size(); i++) { +// PrintUSample(obj.m2[i]); +// std::cout << ", "; +// } +// std::cout << "},\n"; + +// std::cout << "{"; +// for (size_t i = 0; i < obj.m3.size(); i++) { +// PrintUSample(obj.m3[i]); +// std::cout << ", "; +// } +// std::cout << "}\n"; + +// std::cout << "}"; +// } + +// HWTEST_F(StructTest, StructTest_007, TestSize.Level0) +// { +// SSample6 srcObj; +// srcObj.m1.m1 = true; +// srcObj.m1.m2 = 10; + +// for (int i = 0; i < 2; i++) { +// USample data; +// data.m1 = true; +// data.m2 = i; +// srcObj.m2.push_back(data); +// } + +// for (int i = 2; i < 4; i++) { +// USample data; +// data.m1 = false; +// data.m2 = i; +// srcObj.m2.push_back(data); +// } + +// SSample6 destObj; + +// int32_t ec = g_testClient->SSample6Test(srcObj, destObj); +// ASSERT_EQ(ec, HDF_SUCCESS); + +// EXPECT_EQ(srcObj.m1.m1? 1:0, destObj.m1.m1? 1:0); +// EXPECT_EQ(srcObj.m1.m2, destObj.m1.m2); + +// for (size_t i = 0; i < srcObj.m2.size(); i++) { +// EXPECT_EQ(srcObj.m2[i].m1? 1:0, destObj.m2[i].m1? 1:0); +// EXPECT_EQ(srcObj.m2[i].m2, destObj.m2[i].m2); +// } + +// for (size_t i = 0; i < srcObj.m3.size(); i++) { +// EXPECT_EQ(srcObj.m3[i].m1? 1:0, destObj.m3[i].m1? 1:0); +// EXPECT_EQ(srcObj.m3[i].m2, destObj.m3[i].m2); +// } + +// PrintSSample6(srcObj); +// std::cout << "\n"; +// PrintSSample6(destObj); +// std::cout << "\n"; +// std::cout << "---------------------\n"; +// } \ No newline at end of file diff --git a/tools/hdi-gen/test/cpp_test/types/v1_0/Types.idl b/tools/hdi-gen/test/cpp_test/types/v1_0/Types.idl new file mode 100755 index 000000000..f96b0d4b9 --- /dev/null +++ b/tools/hdi-gen/test/cpp_test/types/v1_0/Types.idl @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.cpp_test.types.v1_0; + +sequenceable test.cpp_test.types.v1_0.SequenceData; + +enum ESample +{ + MEM_ONE, + MEM_TWO, + MEM_THREE, +}; + +struct SSample +{ + boolean m1; + int m2; + double m3; + String m4; +}; + +union USample +{ + boolean m1; + int m2; +}; + +struct SSample2 +{ + boolean m1; + byte m2; + short m3; + int m4; + long m5; + unsigned char m6; + unsigned short m7; + unsigned int m8; + unsigned long m9; + float m10; + double m11; +}; + +struct SSample3 +{ + String m1; + enum ESample m2; + struct SSample2 m3; + FileDescriptor m4; +}; + +struct SSample4 +{ + boolean[] m1; + byte[] m2; + short[] m3; + int[] m4; + long[] m5; + unsigned char[] m6; + unsigned short[] m7; + unsigned int[] m8; + unsigned long[] m9; + float[] m10; + double[] m11; + String[] m12; + enum ESample[] m13; + struct SSample[] m14; + SequenceData[] m15; +}; + +struct SSample5 +{ + List m1; + List m2; + List m3; + List m4; + List m5; + List m6; + List m7; + List m8; + List m9; + List m10; + List m11; + List m12; + List m13; + List m14; + List m15; +}; + +struct SSample6 { + union USample m1; + union USample[] m2; + List m3; +}; \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/array_test/v1_0/IArrayTest.idl b/tools/hdi-gen/test/java_test/array_test/v1_0/IArrayTest.idl new file mode 100755 index 000000000..48cb6c50d --- /dev/null +++ b/tools/hdi-gen/test/java_test/array_test/v1_0/IArrayTest.idl @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.array_test.v1_0; + +sequenceable test.java_test.types.v1_0.SequenceData; + +interface IArrayTest { + + BoolArrayTest([in] boolean[] param1, [out] boolean[] param2); + + ByteArrayTest([in] byte[] param1, [out] byte[] param2); + + ShortArrayTest([in] short[] param1, [out] short[] param2); + + IntArrayTest([in] int[] param1, [out] int[] param2); + + LongArrayTest([in] long[] param1, [out] long[] param2); + + FloatArrayTest([in] float[] param1, [out] float[] param2); + + DoubleArrayTest([in] double[] param1, [out] double[] param2); + + StringArrayTest([in] String[] param1, [out] String[] param2); + + FdArrayTest([in] FileDescriptor[] param1, [out] FileDescriptor[] param2); + + SequenceArrayTest([in] SequenceData[] param1, [out] SequenceData[] param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/cb_test/v1_0/ICallback.idl b/tools/hdi-gen/test/java_test/cb_test/v1_0/ICallback.idl new file mode 100755 index 000000000..893e505ca --- /dev/null +++ b/tools/hdi-gen/test/java_test/cb_test/v1_0/ICallback.idl @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.cb_test.v1_0; + +[callback] interface ICallback { + Ping([in] String message); + Plus([in] int num1, [in] int num2, [out] int result); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/cb_test/v1_0/ICbTest.idl b/tools/hdi-gen/test/java_test/cb_test/v1_0/ICbTest.idl new file mode 100755 index 000000000..fe22cb4c5 --- /dev/null +++ b/tools/hdi-gen/test/java_test/cb_test/v1_0/ICbTest.idl @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.cb_test.v1_0; + +import test.java_test.cb_test.v1_0.ICallback; + +interface ICbTest { + CallbackTest([in] ICallback callbackObj); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/data_test/v1_0/IDataTest.idl b/tools/hdi-gen/test/java_test/data_test/v1_0/IDataTest.idl new file mode 100755 index 000000000..8e09eaa90 --- /dev/null +++ b/tools/hdi-gen/test/java_test/data_test/v1_0/IDataTest.idl @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.data_test.v1_0; + +sequenceable test.java_test.types.v1_0.SequenceData; + +interface IDataTest { + + BoolTest([in] boolean param1, [out] boolean param2); + + ByteTest([in] byte param1, [out] byte param2); + + ShortTest([in] short param1, [out] short param2); + + IntTest([in] int param1, [out] int param2); + + LongTest([in] long param1, [out] long param2); + + FloatTest([in] float param1, [out] float param2); + + DoubleTest([in] double param1, [out] double param2); + + StringTest([in] String param1, [out] String param2); + + FdTest([in] FileDescriptor fd); + + SequenceTest([in] SequenceData param1, [out] SequenceData param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/list_test/v1_0/IListTest.idl b/tools/hdi-gen/test/java_test/list_test/v1_0/IListTest.idl new file mode 100755 index 000000000..2ee789bd7 --- /dev/null +++ b/tools/hdi-gen/test/java_test/list_test/v1_0/IListTest.idl @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.list_test.v1_0; + +sequenceable test.java_test.types.v1_0.SequenceData; + +interface IListTest { + + BoolListTest([in] List param1, [out] List param2); + + ByteListTest([in] List param1, [out] List param2); + + ShortListTest([in] List param1, [out] List param2); + + IntListTest([in] List param1, [out] List param2); + + LongListTest([in] List param1, [out] List param2); + + FloatListTest([in] List param1, [out] List param2); + + DoubleListTest([in] List param1, [out] List param2); + + StringListTest([in] List param1, [out] List param2); + + FdListTest([in] List param1, [out] List param2); + + SequenceListTest([in] List param1, [out] List param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/test/java_test/map_test/v1_0/IMapTest.idl b/tools/hdi-gen/test/java_test/map_test/v1_0/IMapTest.idl new file mode 100755 index 000000000..6081c1da5 --- /dev/null +++ b/tools/hdi-gen/test/java_test/map_test/v1_0/IMapTest.idl @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +package test.java_test.map_test.v1_0; + +sequenceable test.java_test.types.v1_0.SequenceData; + +interface IMapTest { + //same key + MapIntByteTest([in] Map param1, [out] Map param2); + + MapIntShortTest([in] Map param1, [out] Map param2); + + MapIntIntTest([in] Map param1, [out] Map param2); + + MapIntLongTest([in] Map param1, [out] Map param2); + + MapIntFloatTest([in] Map param1, [out] Map param2); + + MapIntDoubleTest([in] Map param1, [out] Map param2); + + MapIntStringTest([in] Map param1, [out] Map param2); + + MapIntFdTest([in] Map param1, [out] Map param2); + + MapIntSeqTest([in] Map param1, [out] Map param2); + + //same value + MapByteIntTest([in] Map param1, [out] Map param2); + + MapShortIntTest([in] Map param1, [out] Map param2); + + MapLongIntTest([in] Map param1, [out] Map param2); + + MapFloatIntTest([in] Map param1, [out] Map param2); + + MapDoubleIntTest([in] Map param1, [out] Map param2); + + MapStringIntTest([in] Map param1, [out] Map param2); + + MapFdIntTest([in] Map param1, [out] Map param2); + + MapSeqIntTest([in] Map param1, [out] Map param2); +} \ No newline at end of file diff --git a/tools/hdi-gen/util/Makefile b/tools/hdi-gen/util/Makefile new file mode 100755 index 000000000..dfae7c273 --- /dev/null +++ b/tools/hdi-gen/util/Makefile @@ -0,0 +1,14 @@ +OBJS_DIR:=$(BUILD_DIR)/util +TARGET = $(OBJS_DIR)/util.a +SOURCE:=$(wildcard *.cpp) +OBJS:=$(patsubst %.cpp, $(OBJS_DIR)/%.o, $(SOURCE)) + + + +$(TARGET):$(OBJS) + $(Q) echo $(TARGET) + $(Q) ar -rc $@ $^ + +$(OBJS_DIR)/%.o:%.cpp + $(Q) mkdir -p $(dir $@) + $(Q) $(CXX) $(CXXFLAGS) $(INCLUDES) -c $^ -o $@ \ No newline at end of file diff --git a/tools/hdi-gen/util/autoptr.h b/tools/hdi-gen/util/autoptr.h new file mode 100755 index 000000000..4015109d7 --- /dev/null +++ b/tools/hdi-gen/util/autoptr.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_AUTOPTR_H +#define OHOS_HDI_AUTOPTR_H + +namespace OHOS { +namespace HDI { +template +class AutoPtr { +public: + inline AutoPtr() + : mPtr(nullptr) {} + + AutoPtr(T* other); + + AutoPtr(const AutoPtr& other); + + AutoPtr(AutoPtr && other); + + ~AutoPtr(); + + AutoPtr& operator=(T* other); + + AutoPtr& operator=(const AutoPtr& other); + + AutoPtr& operator=(AutoPtr && other); + + void MoveTo(T** other); + + inline operator T* () const; + + inline T** operator&(); + + inline T* operator->() const; + + inline T& operator*() const; + + inline T* Get() const; + + inline bool operator==(T* other) const; + + inline bool operator==(const AutoPtr& other) const; + + inline bool operator!=(T* other) const; + + inline bool operator!=(const AutoPtr& other) const; + + inline bool operator>(T* other) const; + + inline bool operator>(const AutoPtr& other) const; + + inline bool operator<(T* other) const; + + inline bool operator<(const AutoPtr& other) const; + + inline bool operator<=(T* other) const; + + inline bool operator<=(const AutoPtr& other) const; + + inline bool operator>=(T* other) const; + + inline bool operator>=(const AutoPtr& other) const; + +private: + T* mPtr; +}; + +template +AutoPtr::AutoPtr(T* other) + : mPtr(other) +{ + if (mPtr != nullptr) { + mPtr->AddRef(); + } +} + +template +AutoPtr::AutoPtr(const AutoPtr& other) + : mPtr(other.mPtr) +{ + if (mPtr != nullptr) { + mPtr->AddRef(); + } +} + +template +AutoPtr::AutoPtr(AutoPtr && other) + : mPtr(other.mPtr) +{ + other.mPtr = nullptr; +} + +template +AutoPtr::~AutoPtr() +{ + if (mPtr != nullptr) { + mPtr->Release(); + } +} + +template +AutoPtr& AutoPtr::operator=(T* other) +{ + if (mPtr == other) return *this; + + if (other != nullptr) { + other->AddRef(); + } + if (mPtr != nullptr) { + mPtr->Release(); + } + mPtr = other; + return *this; +} + +template +AutoPtr& AutoPtr::operator=(const AutoPtr& other) +{ + if (mPtr == other.mPtr) return *this; + + if (other.mPtr != nullptr) { + other.mPtr->AddRef(); + } + if (mPtr != nullptr) { + mPtr->Release(); + } + mPtr = other.mPtr; + return *this; +} + +template +AutoPtr& AutoPtr::operator=(AutoPtr && other) +{ + if (mPtr != nullptr) { + mPtr->Release(); + } + mPtr = other.mPtr; + other.mPtr = nullptr; + return *this; +} + +template +void AutoPtr::MoveTo(T** other) +{ + if (other != nullptr) { + *other = mPtr; + mPtr = nullptr; + } +} + +template +AutoPtr::operator T* () const +{ + return mPtr; +} + +template +T** AutoPtr::operator&() +{ + return &mPtr; +} + +template +T* AutoPtr::operator->() const +{ + return mPtr; +} + +template +T& AutoPtr::operator*() const +{ + return *mPtr; +} + +template +T* AutoPtr::Get() const +{ + return mPtr; +} + +template +bool AutoPtr::operator==(T* other) const +{ + return mPtr == other; +} + +template +bool AutoPtr::operator==(const AutoPtr& other) const +{ + return mPtr == other.mPtr; +} + +template +bool AutoPtr::operator!=(T* other) const +{ + return mPtr != other; +} + +template +bool AutoPtr::operator!=(const AutoPtr& other) const +{ + return mPtr != other.mPtr; +} + +template +bool AutoPtr::operator>(T* other) const +{ + return mPtr > other; +} + +template +bool AutoPtr::operator>(const AutoPtr& other) const +{ + return mPtr > other.mPtr; +} + +template +bool AutoPtr::operator<(T* other) const +{ + return mPtr < other; +} + +template +bool AutoPtr::operator<(const AutoPtr& other) const +{ + return mPtr < other.mPtr; +} + +template +bool AutoPtr::operator<=(T* other) const +{ + return mPtr <= other; +} + +template +bool AutoPtr::operator<=(const AutoPtr& other) const +{ + return mPtr <= other.mPtr; +} + +template +bool AutoPtr::operator>=(T* other) const +{ + return mPtr >= other; +} + +template +bool AutoPtr::operator>=(const AutoPtr& other) const +{ + return mPtr >= other.mPtr; +} +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_AUTOPTR_H \ No newline at end of file diff --git a/tools/hdi-gen/util/file.cpp b/tools/hdi-gen/util/file.cpp new file mode 100755 index 000000000..72bb17381 --- /dev/null +++ b/tools/hdi-gen/util/file.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "util/file.h" +#include +#include +#include +#include +#include +#include "securec.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +#ifdef __MINGW32__ +constexpr unsigned int File::READ; +constexpr unsigned int File::WRITE; +constexpr unsigned int File::APPEND; +#endif + +File::File(const String& path, unsigned int mode) + : mode_(mode) +{ + if (path.IsEmpty()) { + return; + } + + if (mode_ & READ) { + if (!CheckValid(path)) { + return; + } + fd_ = fopen(path.string(), "r"); + } else if (mode_ & WRITE) { + fd_ = fopen(path.string(), "w+"); + } else if (mode_ & APPEND) { + fd_ = fopen(path.string(), "a+"); + } + + if (fd_ != nullptr) { +#ifndef __MINGW32__ + char* absolutePath = realpath(path.string(), nullptr); + if (absolutePath != nullptr) { + path_ = absolutePath; + free(absolutePath); + } else { + path_ = path; + } +#else + char absolutePath[_MAX_PATH]; + _fullpath(absolutePath, path.string(), _MAX_PATH); + path_ = absolutePath; +#endif + } +} + +File::~File() +{ + Close(); +} + +char File::GetChar() +{ + char c = PeekChar(); + + if (position_ + 1 <= size_) { + position_++; + + if (c != '\n') { + columnNo_++; + } else { + columnNo_ = 0; + lineNo_++; + } + } + return c; +} + +char File::PeekChar() +{ + if (position_ + 1 > size_) { + int ret = Read(); + if (ret == -1) { + isEof_ = true; + } + } + + return buffer_[position_]; +} + +bool File::IsEof() const +{ + return isEof_ || buffer_[position_] == -1; +} + +int File::Read() +{ + if (isEof_ || isError_) { + return -1; + } + + (void)memset_s(buffer_, BUFFER_SIZE, 0, BUFFER_SIZE); + size_t count = fread(buffer_, 1, BUFFER_SIZE - 1, fd_); + if (count < BUFFER_SIZE - 1) { + isError_ = ferror(fd_) != 0; + buffer_[count] = -1; + } + size_ = count; + position_ = 0; + return (count != 0) ? count : -1; +} + +bool File::ReadData(void* data, size_t size) +{ + if (data == nullptr || size == 0) { + return true; + } + + if (fd_ == nullptr) { + return false; + } + + size_t count = fread(data, size, 1, fd_); + return count == 1; +} + +bool File::WriteData(const void* data, size_t size) +{ + if (data == nullptr || size == 0) { + return true; + } + + if (fd_ == nullptr || !(mode_ & (WRITE | APPEND))) { + return false; + } + + size_t count = fwrite(data, size, 1, fd_); + return count == 1; +} + +void File::Flush() +{ + if ((mode_ & (WRITE | APPEND)) && fd_ != nullptr) { + fflush(fd_); + } +} + +bool File::Reset() +{ + if (fd_ == nullptr) { + return false; + } + + return fseek(fd_, 0, SEEK_SET) == 0; +} + +bool File::Skip(long size) +{ + if (fd_ == nullptr) { + return false; + } + + return fseek(fd_, size, SEEK_CUR) == 0; +} + +void File::Close() +{ + if (fd_ != nullptr) { + fclose(fd_); + fd_ = nullptr; + } +} + +bool File::CreateParentDir(const String& path) +{ + if (!access(path.string(), F_OK | R_OK | W_OK)) { + return true; + } + + int pos = 1; + while ((pos = path.IndexOf('/', pos)) != -1) { + String partPath = path.Substring(0, pos); + + struct stat st; + if (stat(partPath.string(), &st) < 0) { + if (errno != ENOENT) { + return false; + } + + if (mkdir(partPath.string(), S_IRWXU | S_IRWXG | S_IRWXO) < 0) { + return false; + } + } else if (!S_ISDIR(st.st_mode)) { + return false; + } + pos += 1; + } + return true; +} + +size_t File::GetHashKey() +{ + StringBuilder fileStr; + while (!IsEof()) { + fileStr.Append(GetChar()); + } + + return std::hash()(fileStr.ToString().string()); +} + +bool File::CheckValid(const String& path) +{ + if (access(path.string(), F_OK | R_OK | W_OK)) { + return false; + } + + struct stat st; + if (stat(path.string(), &st) < 0) { + return false; + } + + if (S_ISDIR(st.st_mode)) { + return false; + } + + return true; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/file.h b/tools/hdi-gen/util/file.h new file mode 100755 index 000000000..7120962cb --- /dev/null +++ b/tools/hdi-gen/util/file.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_FILE_H +#define OHOS_HDI_FILE_H + +#include +#include +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class File { +public: + File(const String& path, unsigned int mode); + + ~File(); + + inline bool IsValid() const + { + return fd_ != nullptr; + } + + inline String GetPath() const + { + return path_; + } + + char GetChar(); + + char PeekChar(); + + bool IsEof() const; + + inline int GetCharLineNumber() const + { + return lineNo_; + } + + inline int GetCharColumnNumber() const + { + return columnNo_; + } + + bool ReadData(void* data, size_t size); + + bool WriteData(const void* data, size_t size); + + void Flush(); + + bool Reset(); + + bool Skip(long size); + + void Close(); + + static bool CreateParentDir(const String& path); + + size_t GetHashKey(); + + static constexpr unsigned int READ = 0x1; + static constexpr unsigned int WRITE = 0x2; + static constexpr unsigned int APPEND = 0x4; + +private: + int Read(); + + bool CheckValid(const String& path); + + static constexpr int BUFFER_SIZE = 1024; + + char buffer_[BUFFER_SIZE] = {0}; + size_t size_ = 0; + size_t position_ = 0; + size_t columnNo_ = 1; + size_t lineNo_ = 1; + bool isEof_ = false; + bool isError_ = false; + + FILE* fd_ = nullptr; + String path_; + unsigned int mode_ = 0; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_FILE_H diff --git a/tools/hdi-gen/util/light_refcount_base.cpp b/tools/hdi-gen/util/light_refcount_base.cpp new file mode 100755 index 000000000..309fb4f06 --- /dev/null +++ b/tools/hdi-gen/util/light_refcount_base.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "util/light_refcount_base.h" + +namespace OHOS { +namespace HDI { +int LightRefCountBase::AddRef() +{ + const int beforeCount = refCount_.fetch_add(1, std::memory_order_relaxed); + return beforeCount + 1; +} + +int LightRefCountBase::Release() +{ + const int beforeCount = refCount_.fetch_sub(1, std::memory_order_release); + if (beforeCount - 1 == 0) { + delete this; + } + return beforeCount - 1; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/light_refcount_base.h b/tools/hdi-gen/util/light_refcount_base.h new file mode 100755 index 000000000..b0ea25471 --- /dev/null +++ b/tools/hdi-gen/util/light_refcount_base.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_LIGHTREFCOUNTBASE_H +#define OHOS_HDI_LIGHTREFCOUNTBASE_H + +#include + +namespace OHOS { +namespace HDI { +class LightRefCountBase { +public: + inline LightRefCountBase() + : refCount_(0) + {} + + int AddRef(); + + int Release(); + + inline int GetRefCount() const + { + return refCount_.load(std::memory_order_relaxed); + } + +protected: + inline virtual ~LightRefCountBase() + {} + +private: + std::atomic refCount_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_LIGHTREFCOUNTBASE_H diff --git a/tools/hdi-gen/util/logger.cpp b/tools/hdi-gen/util/logger.cpp new file mode 100755 index 000000000..697dbd29e --- /dev/null +++ b/tools/hdi-gen/util/logger.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "util/logger.h" +#include + +namespace OHOS { +namespace HDI { +int Logger::level_ = DEBUG; + +void Logger::D(const char* tag, const char* format, ...) +{ + if (level_ > DEBUG) return; + + va_list args; + va_start(args, format); + Log(tag, format, args); + va_end(args); +} + +void Logger::E(const char* tag, const char* format, ...) +{ + if (level_ > ERROR) return; + + va_list args; + va_start(args, format); + Err(tag, format, args); + va_end(args); +} + +void Logger::V(const char* tag, const char* format, ...) +{ + if (level_ > VERBOSE) return; + + va_list args; + va_start(args, format); + Log(tag, format, args); + va_end(args); +} + +void Logger::Log(const char* tag, const char* format, va_list args) +{ + printf("[%s]: ", tag); + vprintf(format, args); + printf("\n"); +} + +void Logger::Err(const char* tag, const char* format, va_list args) +{ + fprintf(stderr, "[%s]: ", tag); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/logger.h b/tools/hdi-gen/util/logger.h new file mode 100755 index 000000000..c2d6ad939 --- /dev/null +++ b/tools/hdi-gen/util/logger.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_LOGGER_H +#define OHOS_HDI_LOGGER_H + +#include + +namespace OHOS { +namespace HDI { +class Logger { +public: + + static void D(const char* tag, const char* format, ...); + + static void E(const char* tag, const char* format, ...); + + static void V(const char* tag, const char* format, ...); + + inline static void SetLevel(int level) + { + level_ = level; + } + + static constexpr int VERBOSE = 0; + static constexpr int DEBUG = 1; + static constexpr int ERROR = 2; + static constexpr int NOLOG = 3; + +private: + Logger(); + + ~Logger(); + + static void Log(const char* tag, const char* format, va_list args); + + static void Err(const char* tag, const char* format, va_list args); + + static int level_; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_LOGGER_H diff --git a/tools/hdi-gen/util/options.cpp b/tools/hdi-gen/util/options.cpp new file mode 100755 index 000000000..8273ff67a --- /dev/null +++ b/tools/hdi-gen/util/options.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "options.h" +#include +#include +#include +#include +#include +#include + +namespace OHOS { +namespace HDI { +const char* Options::OPT_SUPPORT_ARGS = "c:d:"; +static struct option g_longOpts[] = { + {"help", no_argument, nullptr, 'h'}, + {"version", no_argument, nullptr, 'v'}, + {"gen-c", no_argument, nullptr, 'C'}, + {"gen-cpp", no_argument, nullptr, 'P'}, + {"gen-java", no_argument, nullptr, 'J'}, + {"hash", no_argument, nullptr, 'H'}, + {"dump-ast", no_argument, nullptr, 'D'}, + {nullptr, 0, nullptr, 0} +}; + +Options& Options::GetInstance() +{ + static Options option; + return option; +} + +Options& Options::Parse(int argc, char** argv) +{ + program_ = argv[0]; + opterr = 1; + int op = 0; + int optIndex = 0; + + while ((op = getopt_long(argc, argv, OPT_SUPPORT_ARGS, g_longOpts, &optIndex)) != OPT_END) { + switch (op) { + case 'c': + doCompile_ = true; + sourceFilePath_ = optarg; + break; + case 'd': + doOutDir_ = true; + generationDirectory_ = optarg; + break; + case 'h': + doShowUsage_ = true; + break; + case 'v': + doShowVersion_ = true; + break; + case 'C': + doGenerateCode_ = true; + targetLanguage_ = "c"; + break; + case 'P': + doGenerateCode_ = true; + targetLanguage_ = "cpp"; + break; + case 'J': + doGenerateCode_ = true; + targetLanguage_ = "java"; + break; + case 'H': + doGetHashKey_ = true; + break; + case 'D': + doDumpAST_ = true; + break; + case '?': + default: + doShowUsage_ = true; + break; + } + } + CheckOptions(); + return *this; +} + +void Options::CheckOptions() +{ + if (doShowUsage_ || doShowVersion_) { + return; + } + + if (doCompile_) { + if (!doGetHashKey_ && !doDumpAST_ && !doGenerateCode_ && !doOutDir_) { + errors_.push_back(String::Format("%s: nothing to do.", program_.string())); + return; + } + + if (!doGenerateCode_ && doOutDir_) { + errors_.push_back(String::Format("%s: no target language.", program_.string())); + return; + } + + if (doGenerateCode_ && !doOutDir_) { + errors_.push_back(String::Format("%s: no out directory.", program_.string())); + return; + } + } else { + if (doGetHashKey_ || doDumpAST_ || doGenerateCode_ || doOutDir_) { + errors_.push_back(String::Format("%s: no '-c' option.", program_.string())); + return; + } + } +} + +void Options::ShowErrors() const +{ + for (auto error : errors_) { + printf("%s\n", error.string()); + } + printf("Use \"--help\" to show usage.\n"); +} + +void Options::ShowVersion() const +{ + printf("HDI-GEN: %d.%d\n" + "Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.\n\n", + VERSION_MAJOR, VERSION_MINOR); +} + +void Options::ShowUsage() const +{ + printf("Compile a .idl file and generate C/C++ and Java codes.\n" + "Usage: idl [options] file\n" + "Options:\n" + " --help Display command line options\n" + " --version Display toolchain version information\n" + " --hash Display hash key of the idl file\n" + " --dump-ast Display the AST of the compiled file\n" + " -c Compile the .idl file\n" + " --gen-c Generate C codes\n" + " --gen-cpp Generate C++ codes\n" + " --gen-java Generate Java codes\n" + " -d Place generated codes into \n"); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/options.h b/tools/hdi-gen/util/options.h new file mode 100755 index 000000000..1eee4583a --- /dev/null +++ b/tools/hdi-gen/util/options.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_OPTION_H +#define OHOS_HDI_OPTION_H + +#include +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class Options { +public: + static Options& GetInstance(); + + Options(const Options& other) = delete; + Options operator=(const Options& other) = delete; + + Options& Parse(int argc, char** argv); + + ~Options() = default; + + inline bool DoShowUsage() const + { + return doShowUsage_; + } + + inline bool DoShowVersion() const + { + return doShowVersion_; + } + + inline bool DoCompile() const + { + return doCompile_; + } + + inline bool DoDumpAST() const + { + return doDumpAST_; + } + + inline bool DoGetHashKey() const + { + return doGetHashKey_; + } + + inline bool DoGenerateCode() const + { + return doGenerateCode_; + } + + inline bool HasErrors() const + { + return !errors_.empty(); + } + + inline String GetSourceFile() const + { + return sourceFilePath_; + } + + inline String GetTargetLanguage() const + { + return targetLanguage_; + } + + inline String GetGenerationDirectory() const + { + return generationDirectory_; + } + + void ShowErrors() const; + + void ShowVersion() const; + + void ShowUsage() const; + +private: + Options() : program_(), + sourceFilePath_(), + targetLanguage_(), + generationDirectory_(), + illegalOptions_(), + errors_(), + doShowUsage_(false), + doShowVersion_(false), + doCompile_(false), + doDumpAST_(false), + doGetHashKey_(false), + doGenerateCode_(false), + doOutDir_(false) {} + + void CheckOptions(); + + static const char* OPT_SUPPORT_ARGS; + static constexpr int OPT_END = -1; + + static constexpr int VERSION_MAJOR = 0; + static constexpr int VERSION_MINOR = 1; + + String program_; + String sourceFilePath_; + String targetLanguage_; + String generationDirectory_; + String illegalOptions_; + std::vector errors_; + + bool doShowUsage_ = false; + bool doShowVersion_ = false; + bool doCompile_ = false; + bool doDumpAST_ = false; + bool doGetHashKey_ = false; + bool doGenerateCode_ = false; + bool doOutDir_ = false; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDIL_OPTION_H diff --git a/tools/hdi-gen/util/string.cpp b/tools/hdi-gen/util/string.cpp new file mode 100755 index 000000000..9be249aeb --- /dev/null +++ b/tools/hdi-gen/util/string.cpp @@ -0,0 +1,748 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "util/string.h" +#include +#include +#include +#include +#include +#include +#include "securec.h" +#include "util/logger.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace HDI { +constexpr int LINE_MAX_SIZE = 1024; + +using SharedData = struct SharedData { + SharedData(int refCount, int size) : refCount_(refCount), size_(size) {} + + static SharedData* Allocate(int size); + + static void AddRef(const void* handle); + + static void Release(const void* handle); + + inline static char* ToString(SharedData* header) + { + return reinterpret_cast(header + 1); + } + + inline static SharedData* GetHeader(const void* handle) + { + return reinterpret_cast(const_cast(handle)) - 1; + } + + std::atomic refCount_; + int size_; +}; + +SharedData* SharedData::Allocate(int size) +{ + if (size < 0) { + Logger::E(String::TAG, "Size %d is illegal.", size); + return nullptr; + } + if (size > String::MAX_SIZE) { + Logger::E(String::TAG, "The string is too large to alloc."); + return nullptr; + } + + auto handle = reinterpret_cast(malloc(sizeof(SharedData) + size + 1)); + if (handle == nullptr) { + Logger::E(String::TAG, "Fail to malloc %lu bytes memory", size); + return handle; + } + + new (handle)SharedData(1, size); + return handle; +} + +void SharedData::AddRef(const void* handle) +{ + if (handle == nullptr) { + return; + } + + SharedData* data = GetHeader(handle); + int before = data->refCount_.fetch_add(1); + if (before + 1 <= 1) { + Logger::E(String::TAG, "The refCount %d of %p is error in AddRef.", before, data); + }; +} + +void SharedData::Release(const void* handle) +{ + if (handle == nullptr) { + return; + } + + SharedData* data = GetHeader(handle); + int before = data->refCount_.fetch_sub(1); + if (before - 1 == 0) { + free(data); + } else if (before - 1 < 0) { + Logger::E(String::TAG, "The refCount %d of %p is error in Release.", before - 1, data); + }; +} + + +const char* String::TAG = "String"; + +String::String(const char* string) +{ + if (string != nullptr) { + string_ = SharedData::ToString(SharedData::Allocate(strlen(string))); + if (string_ == nullptr) { + return; + } + + if (strcpy_s(string_, strlen(string) + 1, string) != EOK) { + Logger::E(String::TAG, "The Construct of \"%s\" is failed.", string); + SharedData::Release(string_); + string_ = nullptr; + } + } +} + +String::String(const char* string, size_t length) +{ + if (string != nullptr) { + string_ = SharedData::ToString(SharedData::Allocate(length)); + if (string_ != nullptr) { + (void)memcpy_s(string_, length + 1, string, length); + string_[length] = '\0'; + } + } +} + +String::String(const String& other) +{ + string_ = other.string_; + SharedData::AddRef(string_); +} + +String::String(String && other) +{ + string_ = other.string_; + other.string_ = nullptr; +} + +String::String(int size) +{ + string_ = SharedData::ToString(SharedData::Allocate(size)); + if (string_ != nullptr) { + (void)memset_s(string_, size + 1, 0, size + 1); + } +} + +String::~String() +{ + SharedData::Release(string_); +} + +int String::GetLength() const +{ + if (string_ == nullptr) { + return 0; + } + + return SharedData::GetHeader(string_)->size_; +} + +char String::operator[](int index) const +{ + if (index < 0 || index >= GetLength()) { + return '\0'; + } + return string_[index]; +} + +bool String::Equals(const char* string) const +{ + if (string_ == nullptr && string == nullptr) { + return true; + } + + if (string != nullptr && string_ != nullptr) { + if ((size_t)GetLength() != strlen(string)) { + return false; + } + return strcmp(string, string_) == 0; + } + + return false; +} + +bool String::Equals(const String& other) const +{ + if (string_ == nullptr && other.string_ == nullptr) { + return true; + } + + if (string_ != nullptr && other.string_ != nullptr) { + if (GetLength() != other.GetLength()) { + return false; + } + return strcmp(string_, other.string_) == 0; + } + return false; +} + +int String::GetHashCode() const +{ + // BKDR Hash Function + unsigned int seed = 31; // 31 131 1313 13131 131313 etc.. + unsigned int hash = 0; + + const char* string = string_; + if (string != nullptr) { + for (; *string; ++string) { + hash = hash * seed + (*string); + } + } + return (hash & 0x7FFFFFFF); +} + +int String::IndexOf(char c, int fromIndex) const +{ + if (IsEmpty() || c == '\0') { + return -1; + } + + if (fromIndex < 0) { + fromIndex = 0; + } else if (fromIndex >= GetLength()) { + return -1; + } + + char* p = string_ + fromIndex; + char* end = string_ + GetLength(); + while (p != end) { + if (*p == c) { + return p - string_; + } + p++; + } + return -1; +} + +int String::IndexOf(const char* string, int fromIndex) const +{ + if (IsEmpty() || string == nullptr || string[0] == '\0') { + return -1; + } + + if (fromIndex < 0) { + fromIndex = 0; + } else if (fromIndex >= GetLength()) { + return -1; + } + + char* c = strstr(string_ + fromIndex, string); + return (c != nullptr) ? (c - string_) : -1; +} + +int String::IndexOf(const String& other, int fromIndex) const +{ + if (IsEmpty() || other.IsEmpty()) { + return -1; + } + + if (fromIndex < 0) { + fromIndex = 0; + } else if (fromIndex >= GetLength()) { + return -1; + } + + char* c = strstr(string_ + fromIndex, other.string_); + return (c != nullptr) ? (c - string_) : -1; +} + +int String::LastIndexOf(char c, int fromIndex) const +{ + if (IsEmpty() || c == '\0') { + return -1; + } + + if (fromIndex < 0) { + return -1; + } else if (fromIndex == 0 || fromIndex >= GetLength()) { + fromIndex = GetLength() - 1; + } + char* p = string_ + fromIndex; + while (p != string_) { + if (*p == c) { + return p - string_; + } + p--; + } + return -1; +} + +int String::LastIndexOf(const char* string, int fromIndex) const +{ + if (IsEmpty() || string == nullptr || string[0] == '\0') { + return -1; + } + + if (fromIndex < 0) { + return -1; + } else if (fromIndex == 0 || fromIndex >= GetLength()) { + fromIndex = GetLength() - 1; + } + + return LastIndexOfInternal(string, fromIndex); +} + +int String::LastIndexOf(const String& other, int fromIndex) const +{ + if (IsEmpty() || other.IsEmpty()) { + return -1; + } + + if (fromIndex < 0) { + return -1; + } else if (fromIndex == 0 || fromIndex >= GetLength()) { + fromIndex = GetLength() - 1; + } + + return LastIndexOfInternal(other.string(), fromIndex); +} + +int String::LastIndexOfInternal(const char* string, int fromIndex) const +{ + int sourceLen = GetLength(); + int stringLen = strlen(string); + int rightIndex = sourceLen - stringLen; + if (fromIndex > rightIndex) { + fromIndex = rightIndex; + } + + int stringLastIndex = stringLen - 1; + char stringLastChar = string[stringLastIndex]; + int min = stringLen - 1; + int i = min + fromIndex; + +startSearchLastChar: + while (true) { + while (i >= min && string_[i] != stringLastChar) { + i--; + } + if (i < min) { + return -1; + } + int j = i - 1; + int start = j - (stringLen - 1); + int k = stringLastIndex - 1; + + while (j > start) { + if (string_[j--] != string[k--]) { + i--; + goto startSearchLastChar; + } + } + return start + 1; + } +} + +bool String::StartsWith(const char* string) const +{ + if (string == nullptr || string_ == nullptr) { + return false; + } + + if (string[0] == '\0' && string_[0] == '\0') { + return true; + } + + size_t count = strlen(string); + if (count > (size_t)GetLength()) { + return false; + } + + return memcmp(string_, string, count) == 0; +} + +bool String::StartsWith(const String& other) const +{ + if (other.string_ == nullptr || string_ == nullptr) { + return false; + } + + if (other.string_[0] == '\0' && string_[0] == '\0') { + return true; + } + + size_t count = other.GetLength(); + if (count > (size_t)GetLength()) { + return false; + } + + return memcmp(string_, other.string_, count) == 0; +} + +bool String::EndsWith(const char* string) const +{ + if (string == nullptr || string_ == nullptr) { + return false; + } + + if (string[0] == '\0') { + return true; + } + + size_t count = strlen(string); + size_t len = GetLength(); + if (count > len) { + return false; + } + + return memcmp(string_ + len - count, string, count) == 0; +} + +bool String::EndsWith(const String& other) const +{ + if (other.string_ == nullptr || string_ == nullptr) { + return false; + } + + if (other.string_[0] == '\0') { + return true; + } + + size_t count = other.GetLength(); + size_t len = GetLength(); + if (count > len) { + return false; + } + + return memcmp(string_ + len - count, other.string_, count) == 0; +} + +String String::ToLowerCase() const +{ + if (IsEmpty()) { + return *this; + } + + size_t size = GetLength(); + for (size_t i = 0; i < size; i++) { + if (isupper(string_[i])) { + String newStr(string_); + for (size_t j = i; j < size; j++) { + newStr.string_[j] = tolower(newStr.string_[j]); + } + return newStr; + } + } + return *this; +} + +String String::ToUpperCase() const +{ + if (IsEmpty()) { + return *this; + } + + size_t size = GetLength(); + for (size_t i = 0; i < size; i++) { + if (islower(string_[i])) { + String newStr(string_); + for (size_t j = i; j < size; j++) { + newStr.string_[j] = toupper(newStr.string_[j]); + } + return newStr; + } + } + return *this; +} + +String String::Substring(int begin) const +{ + if (begin < 0 || begin >= GetLength()) { + return String(); + } + + return String(string_ + begin); +} + +String String::Substring(int begin, int end) const +{ + if (begin < 0 || end > GetLength() || begin > end) { + return String(); + } + + return String(string_ + begin, end - begin); +} + +String String::Replace(char oldChar, char newChar) const +{ + if (oldChar == newChar) { + return *this; + } + + size_t size = GetLength(); + for (size_t i = 0; i < size; i++) { + if (string_[i] != oldChar) { + continue; + } + + String newStr(string_); + for (size_t j = i; j < size; j++) { + if (newStr.string_[j] == oldChar) { + newStr.string_[j] = newChar; + } + } + return newStr; + } + return *this; +} + +String String::Replace(const char* target, const char* replacement) const +{ + if (target == nullptr || target[0] == '\0' || replacement == nullptr) { + return *this; + } + + int index = IndexOf(target); + if (index == -1) { + return *this; + } + + StringBuilder sb; + int begin = 0; + int step = strlen(target); + while (index != -1) { + sb.Append(Substring(begin, index)); + sb.Append(replacement); + begin = index + step; + index = IndexOf(target, begin); + } + sb.Append(Substring(begin)); + return sb.ToString(); +} + +String String::Replace(const String& target, const String& replacement) const +{ + if (target.IsEmpty() || replacement.IsNull()) { + return *this; + } + + int index = IndexOf(target); + if (index == -1) { + return *this; + } + + StringBuilder sb; + int begin = 0; + int step = target.GetLength(); + while (index != -1) { + sb.Append(Substring(begin, index)); + sb.Append(replacement); + begin = index + step; + index = IndexOf(target, begin); + } + sb.Append(Substring(begin)); + return sb.ToString(); +} + +String& String::Replace(int position, int len, const String& other) +{ + if (position < 0 || position > GetLength()) { + return *this; + } + + if (len < 0) { + return *this; + } + + if (other.IsEmpty()) { + return *this; + } + + String lStr = Substring(0, position); + String rStr = Substring(position + len); + String newStr; + newStr += lStr + other + rStr; + + SharedData::Release(string_); + SharedData::AddRef(newStr.string_); + string_ = newStr.string_; + return *this; +} + +String& String::insert(int index, const String& other) +{ + if (index < 0 || index > GetLength()) { + return *this; + } + + if (other.IsEmpty()) { + return *this; + } + + String newStr; + + String lStr = Substring(0, index); + String rStr = Substring(index); + + newStr += lStr + other + rStr; + + SharedData::Release(string_); + SharedData::AddRef(newStr.string_); + string_ = newStr.string_; + return *this; +} + +String& String::operator=(const char* string) +{ + SharedData::Release(string_); + + if (string == nullptr) { + string_ = nullptr; + return *this; + } + + string_ = SharedData::ToString(SharedData::Allocate(strlen(string))); + if (string_ == nullptr) { + return *this; + } + + if (strcpy_s(string_, strlen(string) + 1, string) != EOK) { + Logger::E(String::TAG, "The operator= of \"%s\" is failed.", string); + SharedData::Release(string_); + string_ = nullptr; + } + + return *this; +} + +String& String::operator=(const String& other) +{ + if (string_ == other.string_) { + return *this; + } + + SharedData::Release(string_); + SharedData::AddRef(other.string_); + string_ = other.string_; + return *this; +} + +String& String::operator=(String && other) +{ + SharedData::Release(string_); + string_ = other.string_; + other.string_ = nullptr; + return *this; +} + +String& String::operator+=(const char* other) +{ + if (other == nullptr || other[0] == '\0') { + return *this; + } + + int thisSize = GetLength(); + int newSize = thisSize + strlen(other); + String newString(newSize); + if (newString.string_ == nullptr) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed.", string_); + goto finished; + } + + if (string_ != nullptr && thisSize > 0) { + if (memcpy_s(newString.string_, newSize + 1, string_, thisSize) != EOK) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 2", string_); + goto finished; + } + } + + if (strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, other) != EOK) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed.", string_); + goto finished; + } + +finished: + SharedData::Release(string_); + SharedData::AddRef(newString.string_); + string_ = newString.string_; + return *this; +} + +String& String::operator+=(const String& other) +{ + if (other.IsEmpty()) { + return *this; + } + + int thisSize = GetLength(); + int newSize = thisSize + other.GetLength(); + String newString(newSize); + if (newString.string_ == nullptr) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 1", string_); + goto finished; + } + + if (string_ != nullptr && thisSize > 0) { + if (memcpy_s(newString.string_, newSize + 1, string_, thisSize) != EOK) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 2", string_); + goto finished; + } + } + + if (strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, other.string_) != EOK) { + Logger::E(String::TAG, "The operator+= of \"%s\" is failed. 3", string_); + goto finished; + } + +finished: + SharedData::Release(string_); + SharedData::AddRef(newString.string_); + string_ = newString.string_; + return *this; +} + +String String::Format(const char* format, ...) +{ + va_list args, argsCopy; + + va_start(args, format); + va_copy(argsCopy, args); + + char buf[LINE_MAX_SIZE] = {0}; + int len = vsnprintf_s(buf, LINE_MAX_SIZE, LINE_MAX_SIZE - 1, format, args); + String string; + if (len <= 0) { + va_end(args); + va_end(argsCopy); + return string; + } + + string = String(len); + if (string.string_ == nullptr) { + va_end(args); + va_end(argsCopy); + return string; + } + + if (vsnprintf_s(string.string_, len + 1, len, format, argsCopy) < 0) { + va_end(args); + va_end(argsCopy); + return string; + } + + va_end(args); + va_end(argsCopy); + return string; +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/string.h b/tools/hdi-gen/util/string.h new file mode 100755 index 000000000..fc7acf67c --- /dev/null +++ b/tools/hdi-gen/util/string.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_STRING_H +#define OHOS_HDI_STRING_H + +#include +#include + +namespace OHOS { +namespace HDI { +class String { +public: + inline String() + {} + + String(const char* string); + + String(const char* string, size_t length); + + String(const String& other); + + String(String && other); + + ~String(); + + inline const char* string() const + { + return string_; + } + + inline operator const char* () const + { + return string_; + } + + inline bool IsNull() const + { + return string_ == nullptr; + } + + inline bool IsEmpty() const + { + return string_ == nullptr || string_[0] == '\0'; + } + + int GetLength() const; + + char operator[](int index) const; + + bool Equals(const char* string) const; + + bool Equals(const String& other) const; + + int GetHashCode() const; + + int IndexOf(char c, int fromIndex = 0) const; + + int IndexOf(const char* string, int fromIndex = 0) const; + + int IndexOf(const String& other, int fromIndex = 0) const; + + int LastIndexOf(char c, int fromIndex = 0) const; + + int LastIndexOf(const char* string, int fromIndex = 0) const; + + int LastIndexOf(const String& other, int fromIndex = 0) const; + + bool StartsWith(const char* string) const; + + bool StartsWith(const String& other) const; + + bool EndsWith(const char* string) const; + + bool EndsWith(const String& other) const; + + String ToLowerCase() const; + + String ToUpperCase() const; + + String Substring(int begin) const; + + String Substring(int begin, int end) const; + + String Replace(char oldChar, char newChar) const; + + String Replace(const char* target, const char* replacement) const; + + String Replace(const String& target, const String& replacement) const; + + String& Replace(int position, int len, const String& other); + + String& insert(int index, const String& other); + + String& operator=(const char* string); + + String& operator=(const String& other); + + String& operator=(String && other); + + String& operator+=(const char* string); + + String& operator+=(const String& other); + + static String Format(const char* format, ...); + + static const char* TAG; + static constexpr int MAX_SIZE = 262144; // 2^18 + +private: + String(int size); + + int LastIndexOfInternal(const char* string, int fromIndex) const; + + char* string_ = nullptr; +}; + +inline String operator+(const String& string1, const String& string2) +{ + String newStr; + newStr += string1; + newStr += string2; + return newStr; +} + +struct StringHashFunc { + int operator()(const String& key) const + { + return key.GetHashCode(); + } +}; + +struct StringEqualFunc { + bool operator()(const String& lhs, const String& rhs) const + { + return lhs.Equals(rhs); + } +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_STRING_H \ No newline at end of file diff --git a/tools/hdi-gen/util/string_builder.cpp b/tools/hdi-gen/util/string_builder.cpp new file mode 100755 index 000000000..3b00d4bce --- /dev/null +++ b/tools/hdi-gen/util/string_builder.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#include "util/string_builder.h" +#include +#include +#include "securec.h" +#include "util/logger.h" + +namespace OHOS { +namespace HDI { +const char* StringBuilder::TAG = "StringBuilder"; +constexpr int LINE_MAX_SIZE = 1024; + +StringBuilder::~StringBuilder() +{ + if (buffer_ != nullptr) { + free(buffer_); + } +} + +StringBuilder& StringBuilder::Append(char c) +{ + if (position_ + 1 >= capacity_) { + if (!Grow(1)) { + return *this; + } + } + + buffer_[position_] = c; + position_ += 1; + return *this; +} + +StringBuilder& StringBuilder::Append(const char* string) +{ + if (string == nullptr || string[0] == '\0') { + return *this; + } + + size_t len = strlen(string); + if (position_ + len >= capacity_) { + if (!Grow(len)) { + return *this; + } + } + + (void)memcpy_s(buffer_ + position_, capacity_ - position_, string, len); + position_ += len; + return *this; +} + +StringBuilder& StringBuilder::Append(const String& string) +{ + if (string.IsEmpty()) { + return *this; + } + + size_t len = string.GetLength(); + if (position_ + len >= capacity_) { + if (!Grow(len)) { + return *this; + } + } + + (void)memcpy_s(buffer_ + position_, capacity_ - position_, string.string(), len); + position_ += len; + return *this; +} + +StringBuilder& StringBuilder::AppendFormat(const char* format, ...) +{ + va_list args, argsCopy; + + va_start(args, format); + va_copy(argsCopy, args); + + char buf[LINE_MAX_SIZE] = {0}; + int len = vsnprintf_s(buf, LINE_MAX_SIZE, LINE_MAX_SIZE - 1, format, args); + if (len <= 0) { + va_end(args); + va_end(argsCopy); + return *this; + } + + if (position_ + len >= capacity_) { + if (!Grow(len)) { + va_end(args); + va_end(argsCopy); + return *this; + } + } + + if (vsnprintf_s(buffer_ + position_, len + 1, len, format, argsCopy) < 0) { + va_end(args); + va_end(argsCopy); + return *this; + } + position_ += len; + + va_end(args); + va_end(argsCopy); + + return *this; +} + +bool StringBuilder::Grow(size_t size) +{ + if (capacity_ > String::MAX_SIZE) { + Logger::E(TAG, "The StringBuilder is full."); + return false; + } + // 256->the default capacity. + size_t newSize = (capacity_ == 0) ? 256 : (capacity_ * 2); + if (newSize < capacity_ + size) { + newSize = capacity_ + size; + } + if (newSize > String::MAX_SIZE) { + newSize = String::MAX_SIZE; + } + if (newSize <= capacity_) { + return false; + } + + char* newBuffer = reinterpret_cast(calloc(newSize, 1)); + if (newBuffer == nullptr) { + Logger::E(TAG, "Fail to malloc %lu bytes memory.", newSize); + return false; + } + + if (buffer_ != nullptr) { + (void)memcpy_s(newBuffer, newSize, buffer_, capacity_); + free(buffer_); + } + buffer_ = newBuffer; + capacity_ = newSize; + return true; +} + +String StringBuilder::ToString() const +{ + return String(buffer_, position_); +} +} // namespace HDI +} // namespace OHOS \ No newline at end of file diff --git a/tools/hdi-gen/util/string_builder.h b/tools/hdi-gen/util/string_builder.h new file mode 100755 index 000000000..21d5d954a --- /dev/null +++ b/tools/hdi-gen/util/string_builder.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * + * HDF is dual licensed: you can use it either under the terms of + * the GPL, or the BSD license, at your option. + * See the LICENSE file in the root of this repository for complete details. + */ + +#ifndef OHOS_HDI_STRINGBUILDER_H +#define OHOS_HDI_STRINGBUILDER_H + +#include "util/string.h" + +namespace OHOS { +namespace HDI { +class StringBuilder { +public: + ~StringBuilder(); + + StringBuilder& Append(char c); + + StringBuilder& Append(const char* string); + + StringBuilder& Append(const String& string); + + StringBuilder& AppendFormat(const char* format, ...); + + String ToString() const; + +private: + bool Grow(size_t size); + + static const char* TAG; + char* buffer_ = nullptr; + size_t position_ = 0; + size_t capacity_ = 0; +}; +} // namespace HDI +} // namespace OHOS + +#endif // OHOS_HDI_STRINGBUILDER_H \ No newline at end of file -- Gitee