diff --git a/zidl/BUILD.gn b/zidl/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3ff94170fda5566916b7959880fdbedb64d71044 --- /dev/null +++ b/zidl/BUILD.gn @@ -0,0 +1,76 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2019-2019. All rights reserved. + +import("//build/ohos.gni") + +config("zidl_config") { + include_dirs = [ + "./", + "//utils/native/base/include/", + ] +} + +common_sources = [ + "ast/ast_array_type.cpp", + "ast/ast_boolean_type.cpp", + "ast/ast_byte_type.cpp", + "ast/ast_char_type.cpp", + "ast/ast_double_type.cpp", + "ast/ast_float_type.cpp", + "ast/ast_integer_type.cpp", + "ast/ast_interface_type.cpp", + "ast/ast_list_type.cpp", + "ast/ast_long_type.cpp", + "ast/ast_map_type.cpp", + "ast/ast_method.cpp", + "ast/ast_module.cpp", + "ast/ast_namespace.cpp", + "ast/ast_node.cpp", + "ast/ast_parameter.cpp", + "ast/ast_sequenceable_type.cpp", + "ast/ast_short_type.cpp", + "ast/ast_string_type.cpp", + "ast/ast_type.cpp", + "ast/ast_void_type.cpp", +] + +common_sources += [ + "codegen/code_emitter.cpp", + "codegen/code_generator.cpp", + "codegen/cpp_code_emitter.cpp", + "codegen/java_code_emitter.cpp", + "codegen/js_code_emitter.cpp", +] + +common_sources += [ + "metadata/metadata_builder.cpp", + "metadata/metadata_dumper.cpp", + "metadata/metadata_reader.cpp", + "metadata/metadata_serializer.cpp", +] + +common_sources += [ + "parser/lexer.cpp", + "parser/parser.cpp", +] + +common_sources += [ + "util/file.cpp", + "util/light_refcount_base.cpp", + "util/logger.cpp", + "util/options.cpp", + "util/string.cpp", + "util/string_builder.cpp", + "util/string_pool.cpp", +] + +ohos_executable("zidl") { + sources = [ "main.cpp" ] + sources += common_sources + + configs = [ ":zidl_config" ] + + deps = [ "//utils/native/base:utilsecurec" ] + + part_name = "zidl" + subsystem_name = "aafwk" +} diff --git a/zidl/CMakeLists.txt b/zidl/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..491e5326b8dd438b89462af68af584766972caf2 --- /dev/null +++ b/zidl/CMakeLists.txt @@ -0,0 +1,43 @@ +# 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. + +cmake_minimum_required(VERSION 2.8) + +project(zidl CXX) + +set(ZIDL_DIR ${CMAKE_SOURCE_DIR}) + +include_directories( + ${ZIDL_DIR}) + +add_subdirectory(ast) +add_subdirectory(codegen) +add_subdirectory(metadata) +add_subdirectory(parser) +add_subdirectory(util) + +set(SOURCES + main.cpp) + +set(LINK_LIBS + -Wl,--whole-archive + ast + codegen + metadata + parser + util + -Wl,--no-whole-archive) + +add_executable(zidl ${SOURCES}) +target_link_libraries(zidl + ${LINK_LIBS}) \ No newline at end of file diff --git a/zidl/ast/CMakeLists.txt b/zidl/ast/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..bfcd05c10537716f0c3d80995e81b2e9c6814b0e --- /dev/null +++ b/zidl/ast/CMakeLists.txt @@ -0,0 +1,41 @@ +# 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_directories( + ${ZIDL_DIR}) + +set(SOURCES + ast_array_type.cpp + ast_boolean_type.cpp + ast_byte_type.cpp + ast_char_type.cpp + ast_double_type.cpp + ast_float_type.cpp + ast_integer_type.cpp + ast_interface_type.cpp + ast_list_type.cpp + ast_long_type.cpp + ast_map_type.cpp + ast_method.cpp + ast_module.cpp + ast_namespace.cpp + ast_node.cpp + ast_parameter.cpp + ast_sequenceable_type.cpp + ast_short_type.cpp + ast_string_type.cpp + ast_type.cpp + ast_void_type.cpp) + +add_library(ast STATIC + ${SOURCES}) \ No newline at end of file diff --git a/zidl/ast/ast_array_type.cpp b/zidl/ast/ast_array_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..01c08bfcbda255257902a8d9cedcf2fd3ffa49bc --- /dev/null +++ b/zidl/ast/ast_array_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_array_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTArrayType::GetSignature() +{ + return String::Format("[%s", elementType_->GetSignature().string()); +} + +bool ASTArrayType::IsArrayType() +{ + return true; +} + +String ASTArrayType::ToString() +{ + return String::Format("%s[]", elementType_->ToString().string()); +} + +} +} diff --git a/zidl/ast/ast_array_type.h b/zidl/ast/ast_array_type.h new file mode 100644 index 0000000000000000000000000000000000000000..8dc4541a83063f19ab317ee47b749fb6bced0272 --- /dev/null +++ b/zidl/ast/ast_array_type.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTARRAYTYPE_H +#define OHOS_ZIDL_ASTARRAYTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTArrayType : public ASTType { +public: + inline void SetElementType( + /* [in] */ ASTType* elementType) + { + elementType_ = elementType; + } + + inline AutoPtr GetElementType() + { + return elementType_; + } + + String GetSignature() override; + + bool IsArrayType() override; + + String ToString() override; + +private: + AutoPtr elementType_; +}; + +} +} + +#endif // OHOS_ZIDL_ASTARRAYTYPE_H \ No newline at end of file diff --git a/zidl/ast/ast_boolean_type.cpp b/zidl/ast/ast_boolean_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..011e51dc480499bdeed61beccc804c5d8c4c3779 --- /dev/null +++ b/zidl/ast/ast_boolean_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_boolean_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTBooleanType::GetSignature() +{ + return "Z"; +} + +bool ASTBooleanType::IsBooleanType() +{ + return true; +} + +String ASTBooleanType::ToString() +{ + return "boolean"; +} + +} +} diff --git a/zidl/ast/ast_boolean_type.h b/zidl/ast/ast_boolean_type.h new file mode 100644 index 0000000000000000000000000000000000000000..bc411737587d138dea37cdbc72d78b2e0eefab82 --- /dev/null +++ b/zidl/ast/ast_boolean_type.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTBOOLEANTYPE_H +#define OHOS_ZIDL_ASTBOOLEANTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTBooleanType : public ASTType { +public: + String GetSignature() override; + + bool IsBooleanType() override; + + String ToString() override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTBOOLEANTYPE_H diff --git a/zidl/ast/ast_byte_type.cpp b/zidl/ast/ast_byte_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be3e84298b3ec9c85a90e783064e89ac1c648dd2 --- /dev/null +++ b/zidl/ast/ast_byte_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_byte_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTByteType::GetSignature() +{ + return "B"; +} + +bool ASTByteType::IsByteType() +{ + return true; +} + +String ASTByteType::ToString() +{ + return "byte"; +} + +} +} diff --git a/zidl/ast/ast_byte_type.h b/zidl/ast/ast_byte_type.h new file mode 100644 index 0000000000000000000000000000000000000000..561fe580f8991402e59a1e3b2d41550cac78cf00 --- /dev/null +++ b/zidl/ast/ast_byte_type.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTBYTETYPE_H +#define OHOS_ZIDL_ASTBYTETYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTByteType : public ASTType { +public: + String GetSignature() override; + + bool IsByteType() override; + + String ToString() override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTBYTETYPE_H diff --git a/zidl/ast/ast_char_type.cpp b/zidl/ast/ast_char_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a8682dc9896456366520eda6bc2a013a2adf6c6 --- /dev/null +++ b/zidl/ast/ast_char_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_char_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTCharType::GetSignature() +{ + return "C"; +} + +bool ASTCharType::IsCharType() +{ + return true; +} + +String ASTCharType::ToString() +{ + return "char"; +} + +} +} diff --git a/zidl/ast/ast_char_type.h b/zidl/ast/ast_char_type.h new file mode 100644 index 0000000000000000000000000000000000000000..a2d2487a6f23296ff6ddf117073cce8ee48fb623 --- /dev/null +++ b/zidl/ast/ast_char_type.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTCHARTYPE_H +#define OHOS_ZIDL_ASTCHARTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTCharType : public ASTType { +public: + String GetSignature() override; + + bool IsCharType() override; + + String ToString() override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTCHARTYPE_H diff --git a/zidl/ast/ast_double_type.cpp b/zidl/ast/ast_double_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e6b773553ca98883c6d0a579a41ff2a0ae473a6 --- /dev/null +++ b/zidl/ast/ast_double_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_double_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTDoubleType::GetSignature() +{ + return "D"; +} + +bool ASTDoubleType::IsDoubleType() +{ + return true; +} + +String ASTDoubleType::ToString() +{ + return "double"; +} + +} +} diff --git a/zidl/ast/ast_double_type.h b/zidl/ast/ast_double_type.h new file mode 100644 index 0000000000000000000000000000000000000000..625111bbf869d012a4b037e9dcf70dcdf5f9ff48 --- /dev/null +++ b/zidl/ast/ast_double_type.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTDOUBLETYPE_H +#define OHOS_ZIDL_ASTDOUBLETYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTDoubleType : public ASTType { +public: + String GetSignature() override; + + bool IsDoubleType() override; + + String ToString() override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTDOUBLETYPE_H \ No newline at end of file diff --git a/zidl/ast/ast_float_type.cpp b/zidl/ast/ast_float_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..df699bba83b0f2c7ef6f098c2a5e18d422bfcef3 --- /dev/null +++ b/zidl/ast/ast_float_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_float_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTFloatType::GetSignature() +{ + return "F"; +} + +bool ASTFloatType::IsFloatType() +{ + return true; +} + +String ASTFloatType::ToString() +{ + return "float"; +} + +} +} diff --git a/zidl/ast/ast_float_type.h b/zidl/ast/ast_float_type.h new file mode 100644 index 0000000000000000000000000000000000000000..44ef0103c5b0866750873f98bd01ce2192448587 --- /dev/null +++ b/zidl/ast/ast_float_type.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTFLOATTYPE_H +#define OHOS_ZIDL_ASTFLOATTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTFloatType : public ASTType { +public: + String GetSignature() override; + + bool IsFloatType() override; + + String ToString() override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTFLOATTYPE_H diff --git a/zidl/ast/ast_integer_type.cpp b/zidl/ast/ast_integer_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16918c9a6e2a9c074442ae8a8684855de1d28928 --- /dev/null +++ b/zidl/ast/ast_integer_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_integer_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTIntegerType::GetSignature() +{ + return "I"; +} + +bool ASTIntegerType::IsIntegerType() +{ + return true; +} + +String ASTIntegerType::ToString() +{ + return "int"; +} + +} +} diff --git a/zidl/ast/ast_integer_type.h b/zidl/ast/ast_integer_type.h new file mode 100644 index 0000000000000000000000000000000000000000..cc30c15b4d3ab80628147fd842edf545a7489b86 --- /dev/null +++ b/zidl/ast/ast_integer_type.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTINTEGERTYPE_H +#define OHOS_ZIDL_ASTINTEGERTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTIntegerType : public ASTType { +public: + String GetSignature() override; + + bool IsIntegerType() override; + + String ToString() override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTINTEGERTYPE_H diff --git a/zidl/ast/ast_interface_type.cpp b/zidl/ast/ast_interface_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b92003f68161d4d727e678f287f36ae748910b7f --- /dev/null +++ b/zidl/ast/ast_interface_type.cpp @@ -0,0 +1,95 @@ +/* + * 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 "ast/ast_interface_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +void ASTInterfaceType::SetNamespace( + /* [in] */ ASTNamespace* nspace) +{ + ASTType::SetNamespace(nspace); + if (namespace_ != nullptr) { + namespace_->AddInterface(this); + } +} + +void ASTInterfaceType::AddMethod( + /* [in] */ ASTMethod* method) +{ + if (method == nullptr) { + return; + } + methods_.push_back(method); +} + +AutoPtr ASTInterfaceType::GetMethod( + /* [in] */ size_t index) +{ + if (index >= methods_.size()) { + return nullptr; + } + + return methods_[index]; +} + +String ASTInterfaceType::GetSignature() +{ + String fullName = namespace_ != nullptr ? + namespace_->ToString() + name_ : name_; + return "L" + fullName.Replace('.', '/') + ";"; +} + +bool ASTInterfaceType::IsInterfaceType() +{ + return true; +} + +String ASTInterfaceType::ToString() +{ + return name_; +} + +String ASTInterfaceType::Dump( + /* [in] */ const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix).Append("interface "); + if (namespace_ != nullptr) { + sb.Append(namespace_->ToString()); + } + sb.Append(name_); + if (isExternal_) { + sb.Append(";\n"); + } else { + sb.Append(" {\n"); + 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(); +} + +} +} diff --git a/zidl/ast/ast_interface_type.h b/zidl/ast/ast_interface_type.h new file mode 100644 index 0000000000000000000000000000000000000000..ff858591e0a03c45f78f15df47a272379351feed --- /dev/null +++ b/zidl/ast/ast_interface_type.h @@ -0,0 +1,95 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTINTERFACETYPE_H +#define OHOS_ZIDL_ASTINTERFACETYPE_H + +#include +#include "ast/ast_method.h" +#include "ast/ast_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace Zidl { + +class ASTInterfaceType : public ASTType { +public: + void SetNamespace( + /* [in] */ ASTNamespace* nspace) override; + + inline void SetLicense( + /* [in] */ const String& license) + { + license_ = license; + } + + inline String GetLicense() const + { + return license_; + } + + inline void SetOneway( + /* [in] */ bool oneway) + { + oneway_ = oneway; + } + + inline bool IsOneway() + { + return oneway_; + } + + void AddMethod( + /* [in] */ ASTMethod* method); + + AutoPtr GetMethod( + /* [in] */ size_t index); + + inline size_t GetMethodNumber() + { + return methods_.size(); + } + + void SetExternal( + /* [in] */ bool external) + { + isExternal_ = external; + } + + bool IsExternal() const + { + return isExternal_; + } + + String GetSignature() override; + + bool IsInterfaceType() override; + + String ToString() override; + + String Dump( + /* [in] */ const String& prefix) override; + +private: + String license_; + bool oneway_ = false; + std::vector> methods_; + bool isExternal_ = false; +}; + +} +} + +#endif // OHOS_ZIDL_ASTINTERFACETYPE_H diff --git a/zidl/ast/ast_list_type.cpp b/zidl/ast/ast_list_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c31c6f4cf01243f05c47c7a0cc409d5d5b2e810 --- /dev/null +++ b/zidl/ast/ast_list_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_list_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTListType::GetSignature() +{ + return String::Format("LList[%s];", elementType_->GetSignature().string()); +} + +bool ASTListType::IsListType() +{ + return true; +} + +String ASTListType::ToString() +{ + return String::Format("List<%s>", elementType_->ToString().string()); +} + +} +} diff --git a/zidl/ast/ast_list_type.h b/zidl/ast/ast_list_type.h new file mode 100644 index 0000000000000000000000000000000000000000..d6c80a6833a924dbe900a461cca99c072e355342 --- /dev/null +++ b/zidl/ast/ast_list_type.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTLISTTYPE_H +#define OHOS_ZIDL_ASTLISTTYPE_H + +#include "ast/ast_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace Zidl { + +class ASTListType : public ASTType { +public: + inline void SetElementType( + /* [in] */ ASTType* elementType) + { + elementType_ = elementType; + } + + inline AutoPtr GetElementType() + { + return elementType_; + } + + String GetSignature() override; + + bool IsListType() override; + + String ToString() override; + +private: + AutoPtr elementType_; +}; + +} +} + +#endif // OHOS_ZIDL_ASTLISTTYPE_H diff --git a/zidl/ast/ast_long_type.cpp b/zidl/ast/ast_long_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29c7bdd01ff9f9db0f9c5f719fe7bc92338d0d40 --- /dev/null +++ b/zidl/ast/ast_long_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_long_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTLongType::GetSignature() +{ + return "J"; +} + +bool ASTLongType::IsLongType() +{ + return true; +} + +String ASTLongType::ToString() +{ + return "long"; +} + +} +} diff --git a/zidl/ast/ast_long_type.h b/zidl/ast/ast_long_type.h new file mode 100644 index 0000000000000000000000000000000000000000..eec1873fc33b7237c6f21aa1658e9c67e12b6052 --- /dev/null +++ b/zidl/ast/ast_long_type.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTLONGTYPE_H +#define OHOS_ZIDL_ASTLONGTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTLongType : public ASTType { +public: + String GetSignature() override; + + bool IsLongType() override; + + String ToString() override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTLONGTYPE_H diff --git a/zidl/ast/ast_map_type.cpp b/zidl/ast/ast_map_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f41e6b4a2907a445adedf18b1c0a0d0bf20d407 --- /dev/null +++ b/zidl/ast/ast_map_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_map_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTMapType::GetSignature() +{ + return String::Format("LMap[%s%s];", keyType_->GetSignature().string(), valueType_->GetSignature().string()); +} + +bool ASTMapType::IsMapType() +{ + return true; +} + +String ASTMapType::ToString() +{ + return String::Format("Map<%s, %s>", keyType_->ToString().string(), valueType_->ToString().string()); +} + +} +} diff --git a/zidl/ast/ast_map_type.h b/zidl/ast/ast_map_type.h new file mode 100644 index 0000000000000000000000000000000000000000..3fcddce5404e8c6f4aa384fda7abde1bddf03018 --- /dev/null +++ b/zidl/ast/ast_map_type.h @@ -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. + */ + +#ifndef OHOS_ZIDL_ASTMAPTYPE_H +#define OHOS_ZIDL_ASTMAPTYPE_H + +#include "ast/ast_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace Zidl { + +class ASTMapType : public ASTType { +public: + inline void SetKeyType( + /* [in] */ ASTType* keyType) + { + keyType_ = keyType; + } + + inline AutoPtr GetKeyType() + { + return keyType_; + } + + inline void SetValueType( + /* [in] */ ASTType* valueType) + { + valueType_ = valueType; + } + + inline AutoPtr GetValueType() + { + return valueType_; + } + + String GetSignature() override; + + bool IsMapType() override; + + String ToString() override; + +private: + AutoPtr keyType_; + AutoPtr valueType_; +}; + +} +} + +#endif // OHOS_ZIDL_ASTMAPTYPE_H \ No newline at end of file diff --git a/zidl/ast/ast_method.cpp b/zidl/ast/ast_method.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9aff6b6d83ecd4af352a348089576acca17c419 --- /dev/null +++ b/zidl/ast/ast_method.cpp @@ -0,0 +1,84 @@ +/* + * 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 "ast/ast_method.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +String ASTMethod::GetSignature() +{ + if (signature_.IsEmpty()) { + BuildSignature(); + } + return signature_; +} + +void ASTMethod::BuildSignature() +{ + StringBuilder sb; + + sb.AppendFormat("(%s)", returnType_->GetSignature().string()); + for (size_t i = 0; i < parameters_.size(); i++) { + sb.Append(parameters_[i]->GetType()->GetSignature()); + } + signature_ = sb.ToString(); +} + +void ASTMethod::AddParameter( + /* [in] */ ASTParameter* parameter) +{ + if (parameter == nullptr) { + return; + } + parameters_.push_back(parameter); +} + +AutoPtr ASTMethod::GetParameter( + /* [in] */ size_t index) +{ + if (index >= parameters_.size()) { + return nullptr; + } + + return parameters_[index]; +} + +String ASTMethod::Dump( + /* [in] */ const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + sb.Append(returnType_->ToString()).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(); +} + +} +} diff --git a/zidl/ast/ast_method.h b/zidl/ast/ast_method.h new file mode 100644 index 0000000000000000000000000000000000000000..638b4a45840b25baab95ec9c6313a48a8fd831c1 --- /dev/null +++ b/zidl/ast/ast_method.h @@ -0,0 +1,92 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTMETHOD_H +#define OHOS_ZIDL_ASTMETHOD_H + +#include +#include "ast/ast_node.h" +#include "ast/ast_parameter.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class ASTMethod : public ASTNode { +public: + inline void SetName( + /* [in] */ const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + String GetSignature(); + + inline void SetOneway( + /* [in] */ bool oneway) + { + oneway_ = oneway; + } + + inline bool IsOneway() + { + return oneway_; + } + + inline void SetReturnType( + /* [in] */ ASTType* type) + { + returnType_ = type; + } + + inline AutoPtr GetReturnType() + { + return returnType_; + } + + void AddParameter( + /* [in] */ ASTParameter* parameter); + + AutoPtr GetParameter( + /* [in] */ size_t index); + + inline size_t GetParameterNumber() + { + return parameters_.size(); + } + + String Dump( + /* [in] */ const String& prefix) override; + +private: + void BuildSignature(); + + String name_; + String signature_; + bool oneway_ = false; + AutoPtr returnType_; + std::vector> parameters_; +}; + +} +} + +#endif // OHOS_ZIDL_ASTMETHOD_H diff --git a/zidl/ast/ast_module.cpp b/zidl/ast/ast_module.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39d949fad68960015d6e41305c0726cd38a65e6f --- /dev/null +++ b/zidl/ast/ast_module.cpp @@ -0,0 +1,261 @@ +/* + * 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 "ast/ast_module.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +ASTModule::ASTModule() +{ + booleanType_ = new ASTBooleanType(); + byteType_ = new ASTByteType(); + shortType_ = new ASTShortType(); + integerType_ = new ASTIntegerType(); + longType_ = new ASTLongType(); + floatType_ = new ASTFloatType(); + doubleType_ = new ASTDoubleType(); + charType_ = new ASTCharType(); + stringType_ = new ASTStringType(); + voidType_ = new ASTVoidType(); + + types_["boolean"] = booleanType_.Get(); + types_["byte"] = byteType_.Get(); + types_["short"] = shortType_.Get(); + types_["int"] = integerType_.Get(); + types_["long"] = longType_.Get(); + types_["float"] = floatType_.Get(); + types_["double"] = doubleType_.Get(); + types_["char"] = charType_.Get(); + types_["String"] = stringType_.Get(); + types_["void"] = voidType_.Get(); +} + +void ASTModule::SetZidlFile( + /* [in] */ const String& zidlFile) +{ + zidlFilePath_ = zidlFile; +#ifdef __MINGW32__ + int index = zidlFilePath_.LastIndexOf('\\'); +#else + int index = zidlFilePath_.LastIndexOf('/'); +#endif + int end = zidlFilePath_.LastIndexOf(".zidl") == -1 ? + zidlFilePath_.LastIndexOf(".idl") : zidlFilePath_.LastIndexOf(".zidl"); + name_ = zidlFilePath_.Substring((index == -1) ? 0 : (index + 1), end); +} + +AutoPtr ASTModule::ParseNamespace( + /* [in] */ 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 ASTModule::AddNamespace( + /* [in] */ ASTNamespace* nspace) +{ + if (nspace == nullptr) { + return; + } + namespaces_.push_back(nspace); +} + +AutoPtr ASTModule::FindNamespace( + /* [in] */ const String& nspaceStr) +{ + for (auto nspace : namespaces_) { + if (nspace->ToShortString().Equals(nspaceStr)) { + return nspace; + } + } + return nullptr; +} + +AutoPtr ASTModule::GetNamespace( + /* [in] */ size_t index) +{ + if (index >= namespaces_.size()) { + return nullptr; + } + + return namespaces_[index]; +} + +void ASTModule::AddInterface( + /* [in] */ ASTInterfaceType* interface) +{ + if (interface == nullptr) { + return; + } + + interfaces_.push_back(interface); + types_[interface->ToString()] = (ASTType*)interface; +} + +AutoPtr ASTModule::GetInterface( + /* [in] */ size_t index) +{ + if (index >= interfaces_.size()) { + return nullptr; + } + + return interfaces_[index]; +} + +int ASTModule::IndexOf( + /* [in] */ ASTInterfaceType* interface) +{ + for (size_t i = 0; i < interfaces_.size(); i++) { + if (interfaces_[i] == interface) { + return i; + } + } + return -1; +} + +void ASTModule::AddSequenceable( + /* [in] */ ASTSequenceableType* sequenceable) +{ + if (sequenceable == nullptr) { + return; + } + + sequenceables_.push_back(sequenceable); + types_[sequenceable->ToString()] = (ASTType*)sequenceable; +} + +AutoPtr ASTModule::GetSequenceable( + /* [in] */ size_t index) +{ + if (index >= sequenceables_.size()) { + return nullptr; + } + + return sequenceables_[index]; +} + +int ASTModule::IndexOf( + /* [in] */ ASTSequenceableType* sequenceable) +{ + for (size_t i = 0; i < sequenceables_.size(); i++) { + if (sequenceables_[i] == sequenceable) { + return i; + } + } + return -1; +} + +void ASTModule::AddType( + /* [in] */ ASTType* type) +{ + if (type == nullptr) { + return; + } + + types_[type->ToString()] = type; +} + +AutoPtr ASTModule::FindType( + /* [in] */ const String& typeName) +{ + if (typeName.IsEmpty()) { + return nullptr; + } + + auto it = types_.find(typeName); + return it != types_.end() ? it->second : nullptr; +} + +int ASTModule::IndexOf( + /* [in] */ ASTType* type) +{ + int i = 0; + for (auto it = types_.begin(); it != types_.end(); ++it, ++i) { + if (it->second == type) { + return i; + } + } + return -1; +} + +bool ASTModule::IsValid() +{ + if (name_.IsEmpty()) { + return false; + } + + return interfaces_.size() > 0; +} + +String ASTModule::Dump( + /* [in] */ const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + sb.Append("Module["); + sb.Append("name: ").Append(name_).Append(" "); + sb.Append("file: ").Append(zidlFilePath_); + sb.Append("]\n"); + + for (auto sequenceable : sequenceables_) { + String info = sequenceable->Dump(" "); + sb.Append(info); + } + sb.Append('\n'); + + for (auto interface : interfaces_) { + if (interface->IsExternal()) { + String info = interface->Dump(" "); + sb.Append(info); + } + } + sb.Append('\n'); + + for (auto interface : interfaces_) { + if (!interface->IsExternal()) { + String info = interface->Dump(" "); + sb.Append(info); + } + } + + return sb.ToString(); +} + +} +} diff --git a/zidl/ast/ast_module.h b/zidl/ast/ast_module.h new file mode 100644 index 0000000000000000000000000000000000000000..6256e15b3e0aadb3c20db6b09475b92de9a8beb9 --- /dev/null +++ b/zidl/ast/ast_module.h @@ -0,0 +1,159 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTMODULE_H +#define OHOS_ZIDL_ASTMODULE_H + +#include +#include +#include "ast/ast_boolean_type.h" +#include "ast/ast_byte_type.h" +#include "ast/ast_char_type.h" +#include "ast/ast_double_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_void_type.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace Zidl { + +class ASTModule : public ASTNode { +public: + ASTModule(); + + void SetZidlFile( + /* [in] */ const String& zidlFile); + + inline String GetName() + { + return name_; + } + + inline void SetLicense( + /* [in] */ const String& license) + { + license_ = license; + } + + inline String GetLicense() + { + return license_; + } + + AutoPtr ParseNamespace( + /* [in] */ const String& nspaceStr); + + void AddNamespace( + /* [in] */ ASTNamespace* nspace); + + AutoPtr FindNamespace( + /* [in] */ const String& nspaceStr); + + AutoPtr GetNamespace( + /* [in] */ size_t index); + + inline size_t GetNamespaceNumber() + { + return namespaces_.size(); + } + + void AddInterface( + /* [in] */ ASTInterfaceType* interface); + + AutoPtr GetInterface( + /* [in] */ size_t index); + + inline size_t GetInterfaceNumber() + { + return interfaces_.size(); + } + + int IndexOf( + /* [in] */ ASTInterfaceType* interface); + + void AddSequenceable( + /* [in] */ ASTSequenceableType* sequenceable); + + AutoPtr GetSequenceable( + /* [in] */ size_t index); + + inline size_t GetSequenceableNumber() + { + return sequenceables_.size(); + } + + int IndexOf( + /* [in] */ ASTSequenceableType* sequenceable); + + void AddType( + /* [in] */ ASTType* type); + + AutoPtr FindType( + /* [in] */ const String& typeName); + + using TypeStringMap = std::unordered_map, StringHashFunc, StringEqualFunc>; + + inline const TypeStringMap& GetTypes() + { + return types_; + } + + inline size_t GetTypeNumber() + { + return types_.size(); + } + + int IndexOf( + /* [in] */ ASTType* type); + + bool IsValid(); + + String Dump( + /* [in] */ const String& prefix) override; + +private: + String name_; + String license_; + std::vector> namespaces_; + std::vector> interfaces_; + std::vector> sequenceables_; + TypeStringMap types_; + + AutoPtr booleanType_; + AutoPtr byteType_; + AutoPtr shortType_; + AutoPtr integerType_; + AutoPtr longType_; + AutoPtr floatType_; + AutoPtr doubleType_; + AutoPtr charType_; + AutoPtr stringType_; + AutoPtr voidType_; + + String zidlFilePath_; +}; + +} +} + +#endif // OHOS_ZIDL_ASTMODULE_H diff --git a/zidl/ast/ast_namespace.cpp b/zidl/ast/ast_namespace.cpp new file mode 100644 index 0000000000000000000000000000000000000000..66b502a41fb691c0c4244a0484c8d24d45052bde --- /dev/null +++ b/zidl/ast/ast_namespace.cpp @@ -0,0 +1,117 @@ +/* + * 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 "ast/ast_namespace.h" +#include "ast/ast_interface_type.h" +#include "ast/ast_sequenceable_type.h" + +namespace OHOS { +namespace Zidl { + +ASTNamespace:: ASTNamespace( + /* [in] */ const String& nspaceStr) + : name_(nspaceStr), + outerNamespace_(nullptr) +{} + +void ASTNamespace::AddNamespace( + /* [in] */ ASTNamespace* innerNspace) +{ + if (innerNspace == nullptr) { + return; + } + + innerNamespaces_.push_back(innerNspace); + innerNspace->outerNamespace_ = this; +} + +AutoPtr ASTNamespace::FindNamespace( + /* [in] */ const String& nspaceStr) +{ + if (nspaceStr.IsEmpty()) { + return nullptr; + } + + for (auto nspace : innerNamespaces_) { + if (nspace->name_.Equals(nspaceStr)) { + return nspace; + } + } + return nullptr; +} + +AutoPtr ASTNamespace::GetNamespace( + /* [in] */ size_t index) +{ + if (index >= innerNamespaces_.size()) { + return nullptr; + } + + return innerNamespaces_[index]; +} + +void ASTNamespace::AddInterface( + /* [in] */ ASTInterfaceType* interface) +{ + if (interface == nullptr) { + return; + } + + interfaces_.push_back(interface); +} + +AutoPtr ASTNamespace::GetInterface( + /* [in] */ size_t index) +{ + if (index >= interfaces_.size()) { + return nullptr; + } + + return interfaces_[index]; +} + +void ASTNamespace::AddSequenceable( + /* [in] */ ASTSequenceableType* sequenceable) +{ + if (sequenceable == nullptr) { + return; + } + + sequenceables_.push_back(sequenceable); +} + +AutoPtr ASTNamespace::GetSequenceable( + /* [in] */ 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; +} + +} +} diff --git a/zidl/ast/ast_namespace.h b/zidl/ast/ast_namespace.h new file mode 100644 index 0000000000000000000000000000000000000000..d78d171de196176625de5a0b728dbc8c87f8ec8b --- /dev/null +++ b/zidl/ast/ast_namespace.h @@ -0,0 +1,93 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTNAMESPACE_H +#define OHOS_ZIDL_ASTNAMESPACE_H + +#include +#include "ast/ast_node.h" +#include "util/autoptr.h" + +namespace OHOS { +namespace Zidl { + +class ASTInterfaceType; +class ASTSequenceableType; + +class ASTNamespace : public ASTNode { +public: + ASTNamespace( + /* [in] */ const String& nspaceStr); + + inline String GetName() + { + return name_; + } + + void AddNamespace( + /* [in] */ ASTNamespace* innerNspace); + + AutoPtr FindNamespace( + /* [in] */ const String& nspaceStr); + + AutoPtr GetNamespace( + /* [in] */ size_t index); + + inline size_t GetNamespaceNumber() + { + return innerNamespaces_.size(); + } + + void AddInterface( + /* [in] */ ASTInterfaceType* interface); + + AutoPtr GetInterface( + /* [in] */ size_t index); + + inline size_t GetInterfaceNumber() + { + return interfaces_.size(); + } + + void AddSequenceable( + /* [in] */ ASTSequenceableType* sequenceable); + + AutoPtr GetSequenceable( + /* [in] */ 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> interfaces_; + std::vector> sequenceables_; +}; + +} +} + +#endif // OHOS_ZIDL_ASTNAMESPACE_H diff --git a/zidl/ast/ast_node.cpp b/zidl/ast/ast_node.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f16e2d6ef0b42f57a5d7b7bc68c2e250aa42ae3a --- /dev/null +++ b/zidl/ast/ast_node.cpp @@ -0,0 +1,36 @@ +/* + * 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 "ast/ast_node.h" + +namespace OHOS { +namespace Zidl { + +ASTNode::~ASTNode() +{} + +String ASTNode::ToString() +{ + return "ASTNode"; +} + +String ASTNode::Dump( + /* [in] */ const String& prefix) +{ + return prefix + "ASTNode"; +} + +} +} diff --git a/zidl/ast/ast_node.h b/zidl/ast/ast_node.h new file mode 100644 index 0000000000000000000000000000000000000000..abe435e6523aadafef9a30237530c3bb40d8ed59 --- /dev/null +++ b/zidl/ast/ast_node.h @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTNODE_H +#define OHOS_ZIDL_ASTNODE_H + +#include "util/light_refcount_base.h" +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class ASTNode : public LightRefCountBase { +public: + virtual ~ASTNode(); + + virtual String ToString(); + + virtual String Dump( + /* [in] */ const String& prefix); +}; + +} +} + +#endif // OHOS_ZIDL_ASTNODE_H diff --git a/zidl/ast/ast_parameter.cpp b/zidl/ast/ast_parameter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c62da3aeee4d015946d41765e4c7144607255f02 --- /dev/null +++ b/zidl/ast/ast_parameter.cpp @@ -0,0 +1,46 @@ +/* + * 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 "ast/ast_parameter.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +String ASTParameter::Dump( + /* [in] */ const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix); + sb.Append('['); + if (isInParameter_) { + sb.Append("in"); + } + if (isOutParameter_) { + if (isInParameter_) { + sb.Append(", "); + } + sb.Append("out"); + } + sb.Append("] "); + sb.Append(type_->ToString()).Append(' '); + sb.Append(name_); + + return sb.ToString(); +} + +} +} diff --git a/zidl/ast/ast_parameter.h b/zidl/ast/ast_parameter.h new file mode 100644 index 0000000000000000000000000000000000000000..84418edd8c11bb7fa2b9bc30c5d4a83f9cc86c59 --- /dev/null +++ b/zidl/ast/ast_parameter.h @@ -0,0 +1,86 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTPARAMETER_H +#define OHOS_ZIDL_ASTPARAMETER_H + +#include "ast/ast_node.h" +#include "ast/ast_type.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class ASTParameter : public ASTNode { +public: + inline void SetName( + /* [in] */ const String& name) + { + name_ = name; + } + + inline String GetName() + { + return name_; + } + + inline void SetType( + /* [in] */ ASTType* type) + { + type_ = type; + } + + inline AutoPtr GetType() + { + return type_; + } + + inline void SetInParameter( + /* [in] */ bool inParameter) + { + isInParameter_ = inParameter; + } + + inline bool IsInParameter() + { + return isInParameter_; + } + + inline void SetOutParameter( + /* [in] */ bool outParameter) + { + isOutParameter_ = outParameter; + } + + inline bool IsOutParameter() + { + return isOutParameter_; + } + + String Dump( + /* [in] */ const String& prefix) override; + +private: + String name_; + AutoPtr type_; + bool isInParameter_ = false; + bool isOutParameter_ = false; +}; + +} +} + +#endif // OHOS_ZIDL_ASTPARAMETER_H diff --git a/zidl/ast/ast_sequenceable_type.cpp b/zidl/ast/ast_sequenceable_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..680606733e8933bb156a92389d92fe2330fc9eac --- /dev/null +++ b/zidl/ast/ast_sequenceable_type.cpp @@ -0,0 +1,64 @@ +/* + * 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 "ast/ast_sequenceable_type.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +void ASTSequenceableType::SetNamespace( + /* [in] */ ASTNamespace* nspace) +{ + ASTType::SetNamespace(nspace); + if (namespace_ != nullptr) { + namespace_->AddSequenceable(this); + } +} + +String ASTSequenceableType::GetSignature() +{ + String fullName = namespace_ != nullptr ? + namespace_->ToString() + name_ : name_; + return "L" + fullName.Replace('.', '/') + ";"; +} + +bool ASTSequenceableType::IsSequenceableType() +{ + return true; +} + +String ASTSequenceableType::ToString() +{ + return name_; +} + +String ASTSequenceableType::Dump( + /* [in] */ 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(); +} + +} +} diff --git a/zidl/ast/ast_sequenceable_type.h b/zidl/ast/ast_sequenceable_type.h new file mode 100644 index 0000000000000000000000000000000000000000..d22b50d625d52908bee871d60b1e301678e44bd5 --- /dev/null +++ b/zidl/ast/ast_sequenceable_type.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTSEQUENCEABLETYPE_H +#define OHOS_ZIDL_ASTSEQUENCEABLETYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTSequenceableType : public ASTType { +public: + void SetNamespace( + /* [in] */ ASTNamespace* nspace) override; + + String GetSignature() override; + + bool IsSequenceableType() override; + + String ToString() override; + + String Dump( + /* [in] */ const String& prefix) override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTSEQUENCEABLETYPE_H diff --git a/zidl/ast/ast_short_type.cpp b/zidl/ast/ast_short_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2891aed192ccd6f5feb19749403717852d54cc29 --- /dev/null +++ b/zidl/ast/ast_short_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_short_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTShortType::GetSignature() +{ + return "S"; +} + +bool ASTShortType::IsShortType() +{ + return true; +} + +String ASTShortType::ToString() +{ + return "short"; +} + +} +} diff --git a/zidl/ast/ast_short_type.h b/zidl/ast/ast_short_type.h new file mode 100644 index 0000000000000000000000000000000000000000..da8766f207af4e9841f153e295652175cfd6a014 --- /dev/null +++ b/zidl/ast/ast_short_type.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTSHORTTYPE_H +#define OHOS_ZIDL_ASTSHORTTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTShortType : public ASTType { +public: + String GetSignature() override; + + bool IsShortType() override; + + String ToString() override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTSHORTTYPE_H diff --git a/zidl/ast/ast_string_type.cpp b/zidl/ast/ast_string_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3144aee55ead37984f4ec2094ac68301f39f7113 --- /dev/null +++ b/zidl/ast/ast_string_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_string_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTStringType::GetSignature() +{ + return "T"; +} + +bool ASTStringType::IsStringType() +{ + return true; +} + +String ASTStringType::ToString() +{ + return "String"; +} + +} +} diff --git a/zidl/ast/ast_string_type.h b/zidl/ast/ast_string_type.h new file mode 100644 index 0000000000000000000000000000000000000000..e7eab0a44310accb3a10fd1b49395fc8cbdb6f2a --- /dev/null +++ b/zidl/ast/ast_string_type.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTSTRINGTYPE_H +#define OHOS_ZIDL_ASTSTRINGTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTStringType : public ASTType { +public: + String GetSignature() override; + + bool IsStringType() override; + + String ToString() override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTSTRINGTYPE_H diff --git a/zidl/ast/ast_type.cpp b/zidl/ast/ast_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c31469907aba65b4863f36f2c18cd84e5105459 --- /dev/null +++ b/zidl/ast/ast_type.cpp @@ -0,0 +1,129 @@ +/* + * 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 "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +void ASTType::SetName( + /* [in] */ const String& name) +{ + name_ = name; +} + +String ASTType::GetName() +{ + return name_; +} + +void ASTType::SetNamespace( + /* [in] */ ASTNamespace* 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::IsFloatType() +{ + return false; +} + +bool ASTType::IsDoubleType() +{ + return false; +} + +bool ASTType::IsCharType() +{ + return false; +} + +bool ASTType::IsStringType() +{ + return false; +} + +bool ASTType::IsListType() +{ + return false; +} + +bool ASTType::IsMapType() +{ + return false; +} + +bool ASTType::IsInterfaceType() +{ + return false; +} + +bool ASTType::IsSequenceableType() +{ + return false; +} + +bool ASTType::IsVoidType() +{ + return false; +} + +bool ASTType::IsArrayType() +{ + return false; +} + +String ASTType::ToShortString() +{ + return name_; +} + +String ASTType::ToString() +{ + return namespace_ == nullptr ? name_ : namespace_->ToString() + name_; +} + +} +} \ No newline at end of file diff --git a/zidl/ast/ast_type.h b/zidl/ast/ast_type.h new file mode 100644 index 0000000000000000000000000000000000000000..1ecacde4d702a0724669a539df800ca814853841 --- /dev/null +++ b/zidl/ast/ast_type.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTTYPE_H +#define OHOS_ZIDL_ASTTYPE_H + +#include "ast/ast_namespace.h" +#include "ast/ast_node.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class ASTType : public ASTNode { +public: + virtual void SetName( + /* [in] */ const String& name); + + virtual String GetName(); + + virtual void SetNamespace( + /* [in] */ ASTNamespace* nspace); + + virtual AutoPtr GetNamespace(); + + virtual String GetSignature() = 0; + + virtual bool IsBooleanType(); + + virtual bool IsByteType(); + + virtual bool IsShortType(); + + virtual bool IsIntegerType(); + + virtual bool IsLongType(); + + virtual bool IsFloatType(); + + virtual bool IsDoubleType(); + + virtual bool IsCharType(); + + virtual bool IsStringType(); + + virtual bool IsListType(); + + virtual bool IsMapType(); + + virtual bool IsInterfaceType(); + + virtual bool IsSequenceableType(); + + virtual bool IsVoidType(); + + virtual bool IsArrayType(); + + virtual String ToShortString(); + + String ToString() override; + +protected: + String name_; + AutoPtr namespace_; +}; + +} +} + +#endif // OHOS_ZIDL_ASTTYPE_H diff --git a/zidl/ast/ast_void_type.cpp b/zidl/ast/ast_void_type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2cce08c685ef4613bd572a98dbb803c4ea65d56f --- /dev/null +++ b/zidl/ast/ast_void_type.cpp @@ -0,0 +1,37 @@ +/* + * 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 "ast/ast_void_type.h" + +namespace OHOS { +namespace Zidl { + +String ASTVoidType::GetSignature() +{ + return "V"; +} + +bool ASTVoidType::IsVoidType() +{ + return true; +} + +String ASTVoidType::ToString() +{ + return "void"; +} + +} +} diff --git a/zidl/ast/ast_void_type.h b/zidl/ast/ast_void_type.h new file mode 100644 index 0000000000000000000000000000000000000000..9a66b6f84031ea6456b60020c1cfc6fc68be7965 --- /dev/null +++ b/zidl/ast/ast_void_type.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_ASTVOIDTYPE_H +#define OHOS_ZIDL_ASTVOIDTYPE_H + +#include "ast/ast_type.h" + +namespace OHOS { +namespace Zidl { + +class ASTVoidType : public ASTType { +public: + String GetSignature() override; + + bool IsVoidType() override; + + String ToString() override; +}; + +} +} + +#endif // OHOS_ZIDL_ASTBOOLEANTYPE_H \ No newline at end of file diff --git a/zidl/bundle.json b/zidl/bundle.json index 5152547cc088f0c6bd4885e60a8aef3c9ba33613..93efa42db0a309bf30fb11c39edd605d75ca68b7 100644 --- a/zidl/bundle.json +++ b/zidl/bundle.json @@ -31,7 +31,8 @@ "build": { "sub_component": [ "//foundation/aafwk/standard/zidl/test/native:zidl_client_test", - "//foundation/aafwk/standard/zidl/test/native:zidl_server_test" + "//foundation/aafwk/standard/zidl/test/native:zidl_server_test", + "//foundation/aafwk/standard/zidl:zidl" ], "inner_kits": [], "test": [] diff --git a/zidl/codegen/CMakeLists.txt b/zidl/codegen/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..bd4a8f37e9880e17b92805792a67ebb14d66114f --- /dev/null +++ b/zidl/codegen/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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_directories( + ${ZIDL_DIR}) + +set(SOURCES + code_emitter.cpp + code_generator.cpp + cpp_code_emitter.cpp + java_code_emitter.cpp) + +add_library(codegen STATIC + ${SOURCES}) \ No newline at end of file diff --git a/zidl/codegen/code_emitter.cpp b/zidl/codegen/code_emitter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5dfda232720539a787947e9f86c80e698fc66969 --- /dev/null +++ b/zidl/codegen/code_emitter.cpp @@ -0,0 +1,48 @@ +/* + * 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 "codegen/code_emitter.h" + +namespace OHOS { +namespace Zidl { + +const char* CodeEmitter::TAB = " "; + +CodeEmitter::CodeEmitter( + /* [in] */ MetaComponent* mc) + : metaComponent_(mc) +{ + metaInterface_ = nullptr; + for (int i = 0; i < metaComponent_->interfaceNumber_; i++) { + metaInterface_ = metaComponent_->interfaces_[i]; + if (!metaInterface_->external_) { + break; + } + } + + if (metaInterface_ != nullptr) { + interfaceName_ = metaInterface_->name_; + interfaceFullName_ = metaInterface_->namespace_ + interfaceName_; + proxyName_ = interfaceName_.StartsWith("I") ? + interfaceName_.Substring(1) + "Proxy" : interfaceName_ + "Proxy"; + proxyFullName_ = metaInterface_->namespace_ + proxyName_; + stubName_ = interfaceName_.StartsWith("I") ? + interfaceName_.Substring(1) + "Stub" : interfaceName_ + "Stub"; + stubFullName_ = metaInterface_->namespace_ + stubName_; + } +} + +} +} diff --git a/zidl/codegen/code_emitter.h b/zidl/codegen/code_emitter.h new file mode 100644 index 0000000000000000000000000000000000000000..4fd84ffd8b7a4d5cad2a7c950cdbce2c2d4f8a76 --- /dev/null +++ b/zidl/codegen/code_emitter.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_CODEEMITTER_H +#define OHOS_ZIDL_CODEEMITTER_H + +#include "metadata/metadata.h" +#include "util/light_refcount_base.h" +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class CodeEmitter : public LightRefCountBase { +public: + CodeEmitter( + /* [in] */ MetaComponent* mc); + + inline void SetDirectory( + /* [in] */ const String& directory) + { + directory_ = directory; + } + + virtual void EmitInterface() = 0; + + virtual void EmitInterfaceProxy() = 0; + + virtual void EmitInterfaceStub() = 0; + +protected: + static const char* TAB; + + MetaComponent* metaComponent_; + MetaInterface* metaInterface_; + String directory_; + String interfaceName_; + String interfaceFullName_; + String proxyName_; + String proxyFullName_; + String stubName_; + String stubFullName_; +}; + +} +} + +#endif // OHOS_ZIDL_CODEEMITTER_H diff --git a/zidl/codegen/code_generator.cpp b/zidl/codegen/code_generator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e0c190cf29f13bcc69cb81c004a9d4ec232fe35 --- /dev/null +++ b/zidl/codegen/code_generator.cpp @@ -0,0 +1,95 @@ +/* + * 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 "codegen/code_generator.h" +#include +#include +#include +#include "codegen/cpp_code_emitter.h" +#include "codegen/java_code_emitter.h" +#include "codegen/js_code_emitter.h" +#include "util/logger.h" + +namespace OHOS { +namespace Zidl { + +const char* CodeGenerator::TAG = "CodeGenerator"; + +CodeGenerator::CodeGenerator( + /* [in] */ MetaComponent* mc, + /* [in] */ const String& language, + /* [in] */ const String& dir) + : targetLanguage_(language), + targetDirectory_(dir), + metaComponent_(mc) +{ + if (language.Equals("cpp")) { + emitter_ = new CppCodeEmitter(metaComponent_); + } else if (language.Equals("java")) { + emitter_ = new JavaCodeEmitter(metaComponent_); + } else if (language.Equals("js")) { + emitter_ = new JsCodeEmitter(metaComponent_); + } +} + +bool CodeGenerator::ResolveDirectory() +{ +#ifdef __MINGW32__ + if(targetDirectory_.IndexOf(":\\") == -1) { + char* cmd = getcwd(nullptr, 0); + targetDirectory_ = String::Format("%s\\%s", cmd, targetDirectory_.string()); + free(cmd); + } +#else + if (!targetDirectory_.StartsWith("/")) { + char* cwd = getcwd(nullptr, 0); + targetDirectory_ = String::Format("%s/%s", cwd, targetDirectory_.string()); + free(cwd); + } +#endif + + if (!access(targetDirectory_.string(), R_OK | W_OK)) { + return true; + } + +#ifdef __MINGW32__ + if (mkdir(targetDirectory_.string()) != 0) { +#else + if (mkdir(targetDirectory_.string(), S_IRWXU | S_IRWXG | S_IRWXO) != 0) { +#endif + Logger::E(TAG, "Create \"%s\" directory failed.", targetDirectory_.string()); + return false; + } + + return true; +} + +bool CodeGenerator::Generate() +{ + if (!ResolveDirectory()) { + return false; + } + + emitter_->SetDirectory(targetDirectory_); + + emitter_->EmitInterface(); + emitter_->EmitInterfaceProxy(); + emitter_->EmitInterfaceStub(); + + return true; +} + +} +} diff --git a/zidl/codegen/code_generator.h b/zidl/codegen/code_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..43eca9157fec14d2bd40e7f38acbc44956c77cd1 --- /dev/null +++ b/zidl/codegen/code_generator.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_CODEGENERATOR_H +#define OHOS_ZIDL_CODEGENERATOR_H + +#include "codegen/code_emitter.h" +#include "metadata/metadata.h" +#include "util/autoptr.h" +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class CodeGenerator { +public: + CodeGenerator( + /* [in] */ MetaComponent* mc, + /* [in] */ const String& language, + /* [in] */ const String& dir); + + ~CodeGenerator() = default; + + bool Generate(); + +private: + bool ResolveDirectory(); + + + static const char* TAG; + String targetLanguage_; + String targetDirectory_; + MetaComponent* metaComponent_; + AutoPtr emitter_; +}; + +} +} + +#endif // OHOS_ZIDL_CODEGENERATOR_H diff --git a/zidl/codegen/cpp_code_emitter.cpp b/zidl/codegen/cpp_code_emitter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e23b8989ce2651b7d958eb58d077d3bdcb05484 --- /dev/null +++ b/zidl/codegen/cpp_code_emitter.cpp @@ -0,0 +1,1175 @@ +/* + * 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 "codegen/cpp_code_emitter.h" + +#include +#include + +#include "securec.h" +#include "util/file.h" + +namespace OHOS { +namespace Zidl { + +void CppCodeEmitter::EmitInterface() +{ + EmitInterfaceHeaderFile(); +} + +void CppCodeEmitter::EmitInterfaceHeaderFile() +{ + String filePath = String::Format("%s/%s.h", directory_.string(), FileName(interfaceName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + sb.Append("\n"); + EmitHeadMacro(sb, interfaceFullName_); + sb.Append("\n"); + EmitInterfaceInclusions(sb); + sb.Append("\n"); + if (EmitInterfaceUsings(sb)) { + sb.Append("\n"); + } + EmitInterfaceDefinition(sb); + EmitTailMacro(sb, interfaceFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppCodeEmitter::EmitInterfaceInclusions( + /* [in] */ StringBuilder& sb) +{ + EmitInterfaceStdlibInclusions(sb); + EmitInterfaceDBinderInclusions(sb); + // EmitInterfaceParametersInclusions(sb); no idea what does this do + EmitInterfaceSelfDefinedTypeInclusions(sb); +} + +void CppCodeEmitter::EmitInterfaceStdlibInclusions( + /* [in] */ StringBuilder& sb) +{ + bool includeString = false; + bool includeList = false; + bool includeMap = false; + bool includeNum = false; + for (int i = 0; i < metaComponent_->typeNumber_; i++) { + MetaType* mt = metaComponent_->types_[i]; + switch(mt->kind_) { + case TypeKind::Byte: { + if (!includeNum) { + sb.Append("#include \n"); + includeNum = true; + } + break; + } + case TypeKind::String: { + if (!includeString) { + sb.Append("#include \n"); + includeString = true; + } + break; + } + case TypeKind::Array: + case TypeKind::List: { + if (!includeList) { + sb.Append("#include \n"); + includeList = true; + } + break; + } + case TypeKind::Map: { + if (!includeMap) { + sb.Append("#include \n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void CppCodeEmitter::EmitInterfaceDBinderInclusions( + /* [in] */ StringBuilder& sb) +{ + sb.Append("#include \n"); +} + +void CppCodeEmitter::EmitInterfaceParametersInclusions( + /* [in] */ StringBuilder& sb) +{ + sb.Append("#include \"parameters.h\"\n"); +} + +String CppCodeEmitter::GetFilePath(const String& fpnp) +{ + int pos = fpnp.IndexOf(".."); + if (pos == -1) { + return String(); + } + String res = fpnp.Substring(0, pos + 1); + return res; +} + +String CppCodeEmitter::GetNamespace(const String& fpnp) +{ + int pos = fpnp.IndexOf(".."); + if (pos == -1) { + return fpnp; + } + String res = fpnp.Substring(pos + 2); + return res; +} + +void CppCodeEmitter::EmitInterfaceSelfDefinedTypeInclusions( + /* [in] */ StringBuilder& sb) +{ + for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) { + MetaSequenceable* mp = metaComponent_->sequenceables_[i]; + String filePath = GetFilePath(String(mp->namespace_)); + String fileName = FileName(filePath + mp->name_); + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } + + for (int i = 0; i < metaComponent_->interfaceNumber_; i++) { + MetaInterface* mi = metaComponent_->interfaces_[i]; + if (mi->external_) { + String filePath = GetFilePath(String(mi->namespace_)); + String fileName = FileName(filePath + mi->name_); + sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string()); + } + } +} + +bool CppCodeEmitter::EmitInterfaceUsings( + /* [in] */ StringBuilder& sb) +{ + bool ret = false; + for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) { + MetaSequenceable* mp = metaComponent_->sequenceables_[i]; + String np = GetNamespace(String(mp->namespace_)); + if (np.IsEmpty()) { + continue; + } + String fullName = CppFullName(np + mp->name_); + sb.Append("using ").AppendFormat("%s;\n", fullName.string()); + ret = true; + } + + for (int i = 0; i < metaComponent_->interfaceNumber_; i++) { + MetaInterface* mi = metaComponent_->interfaces_[i]; + if (mi->external_) { + String np = GetNamespace(String(mi->namespace_)); + if (np.IsEmpty()) { + continue; + } + String fullName = CppFullName(np + mi->name_); + sb.Append("using ").AppendFormat("%s;\n", fullName.string()); + ret = true; + } + } + return ret; +} + +void CppCodeEmitter::EmitInterfaceDefinition( + /* [in] */ StringBuilder& sb) +{ + EmitBeginNamespace(sb); + sb.AppendFormat("class %s : public IRemoteBroker {\n", metaInterface_->name_); + sb.Append("public:\n"); + EmitInterfaceBody(sb, TAB); + sb.Append("};\n"); + EmitEndNamespace(sb); +} + +void CppCodeEmitter::EmitInterfaceBody( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + String nameWithoutPath = GetNamespace(interfaceFullName_); + sb.Append(TAB).AppendFormat("DECLARE_INTERFACE_DESCRIPTOR(u\"%s\");\n", nameWithoutPath.string()); + sb.Append("\n"); + EmitInterfaceMethods(sb, TAB); +} + +void CppCodeEmitter::EmitInterfaceMethods( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + if (metaInterface_->methodNumber_ > 0) { + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + EmitInterfaceMethod(mm, sb, prefix); + if (i != metaInterface_->methodNumber_ - 1) { + sb.Append("\n"); + } + } + } +} + +void CppCodeEmitter::EmitInterfaceMethod( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) { + sb.Append(prefix).AppendFormat("virtual ErrCode %s() = 0;\n", mm->name_); + } else { + sb.Append(prefix).AppendFormat("virtual ErrCode %s(\n", mm->name_); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + EmitInterfaceMethodParameter(mp, sb, prefix + TAB); + if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) { + sb.Append(",\n"); + } + } + if (returnType->kind_ != TypeKind::Void) { + EmitInterfaceMethodReturn(returnType, sb, prefix + TAB); + } + sb.Append(") = 0;\n"); + } +} + +void CppCodeEmitter::EmitInterfaceMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + if ((mp->attributes_ & ATTR_MASK) == (ATTR_IN | ATTR_OUT)) { + sb.Append(prefix).Append("/* [in, out] */ "); + } else if (mp->attributes_ & ATTR_IN) { + sb.Append(prefix).Append("/* [in] */ "); + } else { + sb.Append(prefix).Append("/* [out] */ "); + } + + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + const std::string name = UnderlineAdded(mp->name_); + sb.AppendFormat("%s %s", EmitType(mt, mp->attributes_, false).string(), name.c_str()); +} + +void CppCodeEmitter::EmitInterfaceMethodReturn( + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("/* [out] */ %s result", EmitType(mt, ATTR_OUT, false).string()); +} + +void CppCodeEmitter::EmitInterfaceProxy() +{ + EmitInterfaceProxyHeaderFile(); + EmitInterfaceProxyCppFile(); +} + +void CppCodeEmitter::EmitInterfaceProxyHeaderFile() +{ + String filePath = String::Format("%s/%s.h", directory_.string(), FileName(proxyName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + sb.Append("\n"); + EmitHeadMacro(sb, proxyFullName_); + sb.Append("\n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + sb.Append("#include \n"); + sb.Append("\n"); + EmitInterfaceProxyInHeaderFile(sb); + EmitTailMacro(sb, proxyFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppCodeEmitter::EmitInterfaceProxyInHeaderFile( + /* [in] */ StringBuilder& sb) +{ + EmitBeginNamespace(sb); + sb.AppendFormat("class %s : public IRemoteProxy<%s> {\n", + proxyName_.string(), interfaceName_.string()); + sb.Append("public:\n"); + EmitInterfaceProxyConstructor(sb, TAB); + sb.Append("\n"); + EmitInterfaceProxyMethodDecls(sb, TAB); + sb.Append("\n"); + sb.Append("private:\n"); + EmitInterfaceProxyConstants(sb, TAB); + sb.Append("};\n"); + EmitEndNamespace(sb); +} + +void CppCodeEmitter::EmitInterfaceProxyConstructor( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("explicit %s(\n", proxyName_.string()); + sb.Append(prefix + TAB).Append("/* [in] */ 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()); + sb.Append(prefix).Append("{}\n"); +} + +void CppCodeEmitter::EmitInterfaceProxyMethodDecls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + if (metaInterface_->methodNumber_ > 0) { + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + EmitInterfaceProxyMethodDecl(mm, sb, prefix); + if (i != metaInterface_->methodNumber_ - 1) { + sb.Append("\n"); + } + } + } +} + +void CppCodeEmitter::EmitInterfaceProxyMethodDecl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) { + sb.Append(prefix).AppendFormat("ErrCode %s() override;\n", mm->name_); + } else { + sb.Append(prefix).AppendFormat("ErrCode %s(\n", mm->name_); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + EmitInterfaceMethodParameter(mp, sb, prefix + TAB); + if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) { + sb.Append(",\n"); + } + } + if (returnType->kind_ != TypeKind::Void) { + EmitInterfaceMethodReturn(returnType, sb, prefix + TAB); + } + sb.Append(") override;\n"); + } +} + +void CppCodeEmitter::EmitInterfaceProxyConstants( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + EmitInterfaceMethodCommands(sb, prefix); + sb.Append("\n"); + sb.Append(prefix).AppendFormat("static inline BrokerDelegator<%s> delegator_;\n", proxyName_.string()); +} + +void CppCodeEmitter::EmitInterfaceProxyCppFile() +{ + String filePath = String::Format("%s/%s.cpp", directory_.string(), FileName(proxyName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + sb.Append("\n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(proxyName_).string()); + sb.Append("\n"); + EmitBeginNamespace(sb); + EmitInterfaceProxyMethodImpls(sb, ""); + EmitEndNamespace(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppCodeEmitter::EmitInterfaceProxyMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + if (metaInterface_->methodNumber_ > 0) { + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + EmitInterfaceProxyMethodImpl(mm, sb, prefix); + if (i != metaInterface_->methodNumber_ - 1) { + sb.Append("\n"); + } + } + } +} + +void CppCodeEmitter::EmitInterfaceProxyMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) { + sb.Append(prefix).AppendFormat("ErrCode %s::%s()\n", proxyName_.string(), mm->name_); + } else { + sb.Append(prefix).AppendFormat("ErrCode %s::%s(\n", proxyName_.string(), mm->name_); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + EmitInterfaceMethodParameter(mp, sb, prefix + TAB); + if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) { + sb.Append(",\n"); + } + } + if (returnType->kind_ != TypeKind::Void) { + EmitInterfaceMethodReturn(returnType, sb, prefix + TAB); + } + sb.Append(")\n"); + } + EmitInterfaceProxyMethodBody(mm, sb, prefix); +} + +void CppCodeEmitter::EmitInterfaceProxyMethodBody( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ 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).AppendFormat("MessageOption option(%s);\n", + (mm->properties_ & METHOD_PROPERTY_ONEWAY) != 0 + ? "MessageOption::TF_ASYNC" : "MessageOption::TF_SYNC"); + sb.Append("\n"); + + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_IN) != 0) { + EmitWriteMethodParameter(mp, "data.", sb, prefix + TAB); + } + } + sb.Append("\n"); + sb.Append(prefix + TAB).AppendFormat("int32_t st = Remote()->SendRequest(COMMAND_%s, data, reply, option);\n", + ConstantName(mm->name_).string()); + sb.Append(prefix + TAB).Append("if (st != ERR_NONE) {\n"); + sb.Append(prefix + TAB).Append(" return st;\n"); + sb.Append(prefix + TAB).Append("}\n"); + if ((mm->properties_ & METHOD_PROPERTY_ONEWAY) == 0) { + sb.Append("\n"); + sb.Append(prefix + TAB).Append("ErrCode ec = reply.ReadInt32();\n"); + sb.Append(prefix + TAB).Append("if (FAILED(ec)) {\n"); + sb.Append(prefix + TAB).Append(" return ec;\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("\n"); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_OUT) != 0) { + EmitReadMethodParameter(mp, "reply.", sb, prefix + TAB); + } + } + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (returnType->kind_ != TypeKind::Void) { + EmitReadVariable("reply.", "result", returnType, sb, prefix + TAB, false); + } + } + sb.Append(prefix + TAB).Append("return ERR_OK;\n"); + sb.Append(prefix).Append("}\n"); +} + +void CppCodeEmitter::EmitWriteMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + const std::string name = UnderlineAdded(mp->name_); + EmitWriteVariable(parcelName, name, mt, sb, prefix); +} + +void CppCodeEmitter::EmitReadMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + const std::string name = UnderlineAdded(mp->name_); + EmitReadVariable(parcelName, name, mt, sb, prefix, false); +} + +void CppCodeEmitter::EmitInterfaceStub() +{ + EmitInterfaceStubHeaderFile(); + EmitInterfaceStubCppFile(); +} + +void CppCodeEmitter::EmitInterfaceStubHeaderFile() +{ + String filePath = String::Format("%s/%s.h", directory_.string(), FileName(stubName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + sb.Append("\n"); + EmitHeadMacro(sb, stubFullName_); + sb.Append("\n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string()); + sb.Append("#include \n"); + sb.Append("\n"); + EmitInterfaceStubInHeaderFile(sb); + EmitTailMacro(sb, stubFullName_); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppCodeEmitter::EmitInterfaceStubInHeaderFile( + /* [in] */ StringBuilder& sb) +{ + EmitBeginNamespace(sb); + sb.AppendFormat("class %s : public IRemoteStub<%s> {\n", stubName_.string(), interfaceName_.string()); + sb.Append("public:\n"); + EmitInterfaceStubMethodDecls(sb, TAB); + sb.Append("\n"); + sb.Append("private:\n"); + EmitInterfaceStubConstants(sb, TAB); + sb.Append("};\n"); + EmitEndNamespace(sb); +} + +void CppCodeEmitter::EmitInterfaceStubMethodDecls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).Append("int OnRemoteRequest(\n"); + sb.Append(prefix + TAB).Append("/* [in] */ uint32_t code,\n"); + sb.Append(prefix + TAB).Append("/* [in] */ MessageParcel& data,\n"); + sb.Append(prefix + TAB).Append("/* [out] */ MessageParcel& reply,\n"); + sb.Append(prefix + TAB).Append("/* [in] */ MessageOption& option) override;\n"); +} + +void CppCodeEmitter::EmitInterfaceStubConstants( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + EmitInterfaceMethodCommands(sb, prefix); +} + +void CppCodeEmitter::EmitInterfaceStubCppFile() +{ + String filePath = String::Format("%s/%s.cpp", directory_.string(), FileName(stubName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + sb.Append("\n"); + sb.AppendFormat("#include \"%s.h\"\n", FileName(stubName_).string()); + sb.Append("\n"); + EmitBeginNamespace(sb); + EmitInterfaceStubMethodImpls(sb, ""); + EmitEndNamespace(sb); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void CppCodeEmitter::EmitInterfaceStubMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("int %s::OnRemoteRequest(\n", stubName_.string()); + sb.Append(prefix + TAB).Append("/* [in] */ uint32_t code,\n"); + sb.Append(prefix + TAB).Append("/* [in] */ MessageParcel& data,\n"); + sb.Append(prefix + TAB).Append("/* [out] */ MessageParcel& reply,\n"); + sb.Append(prefix + TAB).Append("/* [in] */ MessageOption& option)\n"); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).Append("switch (code) {\n"); + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + EmitInterfaceStubMethodImpl(mm, sb, prefix + TAB + TAB); + } + sb.Append(prefix + TAB).Append(TAB).Append("default:\n"); + sb.Append(prefix + TAB).Append(TAB).Append(TAB).Append( + "return IPCObjectStub::OnRemoteRequest(code, data, reply, option);\n"); + sb.Append(prefix + TAB).Append("}\n\n"); + sb.Append(prefix + TAB).Append("return ERR_TRANSACTION_FAILED;\n"); + sb.Append(prefix).Append("}\n"); +} + +void CppCodeEmitter::EmitInterfaceStubMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("case COMMAND_%s: {\n", ConstantName(mm->name_).string()); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_IN) != 0) { + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + const std::string name = UnderlineAdded(mp->name_); + EmitReadVariable("data.", name, mt, sb, prefix + TAB); + } else if ((mp->attributes_ & ATTR_OUT) != 0) { + EmitLocalVariable(mp, sb, prefix + TAB); + } + } + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (returnType->kind_ != TypeKind::Void) { + if ((returnType->kind_ == TypeKind::Sequenceable) || (returnType->kind_ == TypeKind::Interface)) { + sb.Append(prefix + TAB).AppendFormat("%s result = nullptr;\n", EmitType(returnType, ATTR_IN, true).string()); + } else { + sb.Append(prefix + TAB).AppendFormat("%s result;\n", EmitType(returnType, ATTR_IN, true).string()); + } + } + if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) { + sb.Append(prefix + TAB).AppendFormat("ErrCode ec = %s();\n", mm->name_); + } else { + sb.Append(prefix + TAB).AppendFormat("ErrCode ec = %s(", mm->name_); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + const std::string name = UnderlineAdded(mp->name_); + sb.Append(name.c_str()); + if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) { + sb.Append(", "); + } + } + if (returnType->kind_ != TypeKind::Void) { + EmitReturnParameter("result", returnType, sb); + } + sb.AppendFormat(");\n", mm->name_); + } + sb.Append(prefix + TAB).Append("reply.WriteInt32(ec);\n"); + bool hasOutParameter = false; + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_OUT) != 0) { + hasOutParameter = true; + } + } + if (hasOutParameter || returnType->kind_ != TypeKind::Void) { + sb.Append(prefix + TAB).Append("if (SUCCEEDED(ec)) {\n"); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_OUT) != 0) { + EmitWriteMethodParameter(mp, "reply.", sb, prefix + TAB + TAB); + } + } + if (returnType->kind_ != TypeKind::Void) { + EmitWriteVariable("reply.", "result", returnType, sb, prefix + TAB + TAB); + } + sb.Append(prefix + TAB).Append("}\n"); + } + sb.Append(prefix + TAB).Append("return ERR_NONE;\n"); + sb.Append(prefix).Append("}\n"); +} + +void CppCodeEmitter::EmitInterfaceMethodCommands( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + sb.Append(prefix).AppendFormat("static constexpr int COMMAND_%s = MIN_TRANSACTION_ID + %d;\n", ConstantName(mm->name_).string(), i); + } +} + +void CppCodeEmitter::EmitLicense( + /* [in] */ StringBuilder& sb) +{ + sb.Append(metaInterface_->license_).Append("\n"); +} + +void CppCodeEmitter::EmitHeadMacro( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& fullName) +{ + String macroName = MacroName(fullName); + sb.Append("#ifndef ").Append(macroName).Append("\n"); + sb.Append("#define ").Append(macroName).Append("\n"); +} + +void CppCodeEmitter::EmitTailMacro( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& fullName) +{ + String macroName = MacroName(fullName); + sb.Append("#endif // ").Append(macroName).Append("\n\n"); +} + +void CppCodeEmitter::EmitBeginNamespace( + /* [in] */ StringBuilder& sb) +{ + String nspace = GetNamespace(metaInterface_->namespace_); + 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( + /* [in] */ StringBuilder& sb) +{ + String nspace = GetNamespace(metaInterface_->namespace_); + nspace = nspace.Substring(0, nspace.GetLength() - 1); + while (!nspace.IsEmpty()) { + int index = nspace.LastIndexOf('.'); + sb.AppendFormat("} // namespace %s\n", index != -1 + ? nspace.Substring(index + 1, nspace.GetLength()).string() + : nspace.string()); + nspace = nspace.Substring(0, index); + } +} + +void CppCodeEmitter::EmitWriteVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%sWriteInt32(%s ? 1 : 0);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Char: + case TypeKind::Byte: + case TypeKind::Short: + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%sWriteInt32(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%sWriteInt64(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%sWriteFloat(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%sWriteDouble(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%sWriteString16(Str8ToStr16(%s));\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Sequenceable: + sb.Append(prefix).AppendFormat("%sWriteParcelable(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Interface: + sb.Append(prefix).AppendFormat("%sWriteRemoteObject(%s->AsObject());\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Array: + case TypeKind::List: { + sb.Append(prefix).AppendFormat("%sWriteInt32(%s.size());\n", parcelName.string(), name.c_str()); + sb.Append(prefix).AppendFormat("for (auto it = %s.begin(); it != %s.end(); ++it) {\n", + name.c_str(), name.c_str()); + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + EmitWriteVariable(parcelName, "(*it)", innerType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Map: { + sb.Append(prefix).AppendFormat("%sWriteInt32(%s.size());\n", parcelName.string(), name.c_str()); + sb.Append(prefix).AppendFormat("for (auto it = %s.begin(); it != %s.end(); ++it) {\n", + name.c_str(), name.c_str()); + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + EmitWriteVariable(parcelName, "(it->first)", keyType, sb, prefix + TAB); + EmitWriteVariable(parcelName, "(it->second)", valueType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + default: + break; + } +} + +void CppCodeEmitter::EmitReadVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix, + /* [in] */ bool emitType) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %sReadInt32() == 1 ? true : false;\n", + EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %sReadInt32() == 1 ? true : false;\n", + name.c_str(), parcelName.string()); + } + break; + case TypeKind::Char: + case TypeKind::Byte: + case TypeKind::Short: + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = (%s)%sReadInt32();\n", EmitType(mt, ATTR_IN, true).string(), + name.c_str(), EmitType(mt, ATTR_IN, true).string(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = (%s)%sReadInt32();\n", name.c_str(), + EmitType(mt, ATTR_IN, true).string(), parcelName.string()); + } + break; + case TypeKind::Integer: + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %sReadInt32();\n", + EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %sReadInt32();\n", name.c_str(), parcelName.string()); + } + break; + case TypeKind::Long: + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %sReadInt64();\n", + EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %sReadInt64();\n", name.c_str(), parcelName.string()); + } + break; + case TypeKind::Float: + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %sReadFloat();\n", + EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %sReadFloat();\n", name.c_str(), parcelName.string()); + } + break; + case TypeKind::Double: + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %sReadDouble();\n", + EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = %sReadDouble();\n", name.c_str(), parcelName.string()); + } + break; + case TypeKind::String: + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = Str16ToStr8(%sReadString16());\n", + EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = Str16ToStr8(%sReadString16());\n", + name.c_str(), parcelName.string()); + } + break; + case TypeKind::Sequenceable: { + MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_]; + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = %sReadParcelable<%s>();\n", + EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string(), mp->name_); + } else { + sb.Append(prefix).AppendFormat("%s = %sReadParcelable<%s>();\n", + name.c_str(), parcelName.string(), mp->name_); + } + break; + } + case TypeKind::Interface: { + MetaInterface* mi = metaComponent_->interfaces_[mt->index_]; + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s = iface_cast<%s>(%sReadRemoteObject());\n", + EmitType(mt, ATTR_IN, true).string(), name.c_str(), mi->name_, parcelName.string()); + } else { + sb.Append(prefix).AppendFormat("%s = iface_cast<%s>(%sReadRemoteObject());\n", + name.c_str(), mi->name_, parcelName.string()); + } + break; + } + case TypeKind::Array: + case TypeKind::List: { + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str()); + } + sb.Append(prefix).AppendFormat("int %sSize = %sReadInt32();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + EmitReadVariable(parcelName, "value", innerType, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.push_back(value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Map: { + if (emitType) { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str()); + } + sb.Append(prefix).AppendFormat("int %sSize = %sReadInt32();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + EmitReadVariable(parcelName, "key", keyType, sb, prefix + TAB); + EmitReadVariable(parcelName, "value", valueType, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s[key] = value;\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + default: + break; + } +} + +void CppCodeEmitter::EmitLocalVariable( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + const std::string name = UnderlineAdded(mp->name_); + if ((mt->kind_ == TypeKind::Sequenceable) || (mt->kind_ == TypeKind::Interface)) { + sb.Append(prefix).AppendFormat("%s %s = nullptr;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str()); + } else { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str()); + } +} + +void CppCodeEmitter::EmitReturnParameter( + /* [in] */ const String& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb) +{ + switch (mt->kind_) { + case TypeKind::Char: + case TypeKind::Boolean: + case TypeKind::Byte: + case TypeKind::Short: + case TypeKind::Integer: + case TypeKind::Long: + case TypeKind::Float: + case TypeKind::Double: + case TypeKind::String: + case TypeKind::Sequenceable: + case TypeKind::Interface: + case TypeKind::List: + case TypeKind::Map: + case TypeKind::Array: + sb.Append(name); + break; + default: + break; + } +} + +String CppCodeEmitter::EmitType( + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ bool isInnerType) +{ + switch(mt->kind_) { + case TypeKind::Char: + if (attributes & ATTR_IN) { + return "zchar"; + } else { + return "zchar&"; + } + case TypeKind::Boolean: + if (attributes & ATTR_IN) { + return "bool"; + } else { + return "bool&"; + } + case TypeKind::Byte: + if (attributes & ATTR_IN) { + return "int8_t"; + } else { + return "int8_t&"; + } + case TypeKind::Short: + if (attributes & ATTR_IN) { + return "short"; + } else { + return "short&"; + } + case TypeKind::Integer: + if (attributes & ATTR_IN) { + return "int"; + } else { + return "int&"; + } + case TypeKind::Long: + if (attributes & ATTR_IN) { + return "long"; + } else { + return "long&"; + } + case TypeKind::Float: + if (attributes & ATTR_IN) { + return "float"; + } else { + return "float&"; + } + case TypeKind::Double: + if (attributes & ATTR_IN) { + return "double"; + } else { + return "double&"; + } + case TypeKind::String: + if (attributes & ATTR_IN) { + if (!isInnerType) { + return "const std::string&"; + } else { + return "std::string"; + } + } else { + return "std::string&"; + } + case TypeKind::Void: + return "void"; + case TypeKind::Sequenceable: { + MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_]; + if ((attributes & ATTR_MASK) == (ATTR_IN | ATTR_OUT)) { + return String::Format("%s*", mp->name_); + } else if (attributes & ATTR_IN) { + return String::Format("%s*", mp->name_); + } else { + return String::Format("%s*", mp->name_); + } + } + case TypeKind::Interface: { + MetaInterface* mi = metaComponent_->interfaces_[mt->index_]; + if (attributes & ATTR_IN) { + if (!isInnerType) { + return String::Format("sptr<%s>", mi->name_); + } else { + return String::Format("sptr<%s>", mi->name_); + } + } else { + return String::Format("sptr<%s>&", mi->name_); + } + } + case TypeKind::Array: + case TypeKind::List: { + MetaType* elementType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + if (attributes & ATTR_OUT) { + return String::Format("std::vector<%s>&", + EmitType(elementType, ATTR_IN, true).string()); + } else { + if (!isInnerType) { + return String::Format("const std::vector<%s>&", + EmitType(elementType, ATTR_IN, true).string()); + } else { + return String::Format("std::vector<%s>", + EmitType(elementType, ATTR_IN, true).string()); + } + } + } + case TypeKind::Map: { + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + if (attributes & ATTR_OUT) { + return String::Format("std::unordered_map<%s, %s>&", + EmitType(keyType, ATTR_IN, true).string(), EmitType(valueType, ATTR_IN, true).string()); + } else { + if (!isInnerType) { + return String::Format("const std::unordered_map<%s, %s>&", + EmitType(keyType, ATTR_IN, true).string(), EmitType(valueType, ATTR_IN, true).string()); + } else { + return String::Format("std::unordered_map<%s, %s>", + EmitType(keyType, ATTR_IN, true).string(), EmitType(valueType, ATTR_IN, true).string()); + } + } + break; + } + default: + return "unknown type"; + } +} + +String CppCodeEmitter::CppFullName( + /* [in] */ const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + return name.Replace(".", "::"); +} + +String CppCodeEmitter::FileName( + /* [in] */ 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('.', '/'); +} + +String CppCodeEmitter::MacroName( + /* [in] */ const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + String macro = name.Replace('.', '_').ToUpperCase() + "_H"; + return macro; +} + +String CppCodeEmitter::ConstantName( + /* [in] */ 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(); +} + +const std::string CppCodeEmitter::UnderlineAdded(const String& originName) +{ + std::string underline("_"); + return underline + std::string(originName.string()); +} + +} +} diff --git a/zidl/codegen/cpp_code_emitter.h b/zidl/codegen/cpp_code_emitter.h new file mode 100644 index 0000000000000000000000000000000000000000..f130be83af312d886a76752c9d311ee8552ff54e --- /dev/null +++ b/zidl/codegen/cpp_code_emitter.h @@ -0,0 +1,237 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_CPPCODEEMITTER_H +#define OHOS_ZIDL_CPPCODEEMITTER_H + +#include + +#include "codegen/code_emitter.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +class CppCodeEmitter : public CodeEmitter { +public: + CppCodeEmitter( + /* [in] */ MetaComponent* mc) + : CodeEmitter(mc) + {} + + void EmitInterface() override; + + void EmitInterfaceProxy() override; + + void EmitInterfaceStub() override; + +private: + void EmitInterfaceHeaderFile(); + + void EmitInterfaceInclusions( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceStdlibInclusions( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceDBinderInclusions( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceParametersInclusions( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeInclusions( + /* [in] */ StringBuilder& sb); + + bool EmitInterfaceUsings( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeUsings( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceDefinition( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceBody( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethods( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethod( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethodReturn( + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyHeaderFile(); + + void EmitInterfaceProxyInHeaderFile( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyConstructor( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyMethodDecls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyMethodDecl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyConstants( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyCppFile(); + + void EmitInterfaceProxyMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyMethodBody( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitWriteMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubHeaderFile(); + + void EmitInterfaceStubInHeaderFile( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceStubMethodDecls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubConstants( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubCppFile(); + + void EmitInterfaceStubMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethodCommands( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitLicense( + /* [in] */ StringBuilder& sb); + + void EmitHeadMacro( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& fullName); + + void EmitTailMacro( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& fullName); + + void EmitBeginNamespace( + /* [in] */ StringBuilder& sb); + + void EmitEndNamespace( + /* [in] */ StringBuilder& sb); + + void EmitWriteVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix, + /* [in] */ bool emitType = true); + + void EmitLocalVariable( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReturnParameter( + /* [in] */ const String& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb); + + String EmitType( + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ bool isInnerType); + + String FileName( + /* [in] */ const String& name); + + String GetFilePath(const String& fpnp); + + String GetNamespace(const String& fpnp); + + String MacroName( + /* [in] */ const String& name); + + String CppFullName( + /* [in] */ const String& name); + + String ConstantName( + /* [in] */ const String& name); + + const std::string UnderlineAdded(const String& name); +}; + +} +} + +#endif // OHOS_ZIDL_CPPCODEEMITTER_H diff --git a/zidl/codegen/java_code_emitter.cpp b/zidl/codegen/java_code_emitter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e12fa8b2bd7d4efd30c596b90cf27132ef13e5c0 --- /dev/null +++ b/zidl/codegen/java_code_emitter.cpp @@ -0,0 +1,1178 @@ +/* + * 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 "codegen/java_code_emitter.h" + +#include + +#include "securec.h" +#include "util/file.h" + +namespace OHOS { +namespace Zidl { + +void JavaCodeEmitter::EmitInterface() +{ + String filePath = String::Format("%s/%s.java", directory_.string(), FileName(interfaceName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + sb.Append("\n"); + EmitPackage(sb); + sb.Append("\n"); + EmitInterfaceImports(sb); + sb.Append("\n"); + EmitInterfaceDefinition(sb); + sb.Append("\n"); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void JavaCodeEmitter::EmitInterfaceImports( + /* [in] */ StringBuilder& sb) +{ + EmitInterfaceCorelibImports(sb); + EmitInterfaceSelfDefinedTypeImports(sb); + EmitInterfaceDBinderImports(sb); +} + +void JavaCodeEmitter::EmitInterfaceCorelibImports( + /* [in] */ StringBuilder& sb) +{ + bool includeList = false; + bool includeMap = false; + for (int i = 0; i < metaComponent_->typeNumber_; i++) { + MetaType* mt = metaComponent_->types_[i]; + switch (mt->kind_) { + case TypeKind::List: { + if (!includeList) { + sb.Append("import java.util.List;\n"); + includeList = true; + } + break; + } + case TypeKind::Map: { + if (!includeMap) { + sb.Append("import java.util.Map;\n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void JavaCodeEmitter::EmitInterfaceDBinderImports( + /* [in] */ StringBuilder& sb) +{ + sb.Append("import ohos.rpc.IRemoteBroker;\n"); + sb.Append("import ohos.rpc.RemoteException;\n"); +} + +void JavaCodeEmitter::EmitInterfaceSelfDefinedTypeImports( + /* [in] */ StringBuilder& sb) +{ + for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) { + MetaSequenceable* mp = metaComponent_->sequenceables_[i]; + sb.AppendFormat("import %s%s;\n", mp->namespace_, mp->name_); + } + + for (int i = 0; i < metaComponent_->interfaceNumber_; i++) { + MetaInterface* mi = metaComponent_->interfaces_[i]; + if (mi->external_) { + sb.AppendFormat("import %s%s;\n", mi->namespace_, mi->name_); + } + } +} + +void JavaCodeEmitter::EmitInterfaceDefinition( + /* [in] */ StringBuilder& sb) +{ + sb.AppendFormat("public interface %s extends IRemoteBroker {\n", metaInterface_->name_); + EmitInterfaceMethods(sb, TAB); + sb.Append("};\n"); +} + +void JavaCodeEmitter::EmitInterfaceMethods( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + if (metaInterface_->methodNumber_ > 0) { + sb.Append("\n"); + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + EmitInterfaceMethod(mm, sb, prefix); + if (i != metaInterface_->methodNumber_ - 1) { + sb.Append("\n"); + } + } + } +} + +void JavaCodeEmitter::EmitInterfaceMethod( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (mm->parameterNumber_ == 0) { + sb.Append(prefix).AppendFormat("%s %s() throws RemoteException;\n", EmitType(returnType).string(), MethodName(mm->name_).string()); + } else { + sb.Append(prefix).AppendFormat("%s %s(\n", EmitType(returnType).string(), MethodName(mm->name_).string()); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + EmitInterfaceMethodParameter(mp, sb, prefix + TAB); + if (i != mm->parameterNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append(") throws RemoteException;\n"); + } +} + +void JavaCodeEmitter::EmitInterfaceMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + if ((mp->attributes_ & ATTR_MASK) == (ATTR_IN | ATTR_OUT)) { + sb.Append(prefix).Append("/* [inout] */ "); + } else if (mp->attributes_ & ATTR_IN) { + sb.Append(prefix).Append("/* [in] */ "); + } else { + sb.Append(prefix).Append("/* [out] */ "); + } + + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + std::string name = UnderlineAdded(mp->name_); + sb.AppendFormat("%s %s", EmitType(mt).string(), name.c_str()); +} + +void JavaCodeEmitter::EmitInterfaceProxy() +{ + String filePath = String::Format("%s/%s.java", directory_.string(), FileName(proxyName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + sb.Append("\n"); + EmitPackage(sb); + sb.Append("\n"); + EmitInterfaceProxyImports(sb); + sb.Append("\n"); + EmitInterfaceProxyImpl(sb); + sb.Append("\n"); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void JavaCodeEmitter::EmitInterfaceProxyImports( + /* [in] */ StringBuilder& sb) +{ + EmitInterfaceProxyCorelibImports(sb); + EmitInterfaceProxySelfDefinedTypeImports(sb); + EmitInterfaceProxyDBinderImports(sb); + EmitInterfaceProxyParametersImports(sb); +} + +void JavaCodeEmitter::EmitInterfaceProxyCorelibImports( + /* [in] */ StringBuilder& sb) +{ + bool includeList = false; + bool includeMap = false; + for (int i = 0; i < metaComponent_->typeNumber_; i++) { + MetaType* mt = metaComponent_->types_[i]; + switch(mt->kind_) { + case TypeKind::List: { + if (!includeList) { + sb.Append("import java.util.List;\n"); + sb.Append("import java.util.ArrayList;\n"); + includeList = true; + } + break; + } + case TypeKind::Map: { + if (!includeMap) { + sb.Append("import java.util.Map;\n"); + sb.Append("import java.util.HashMap;\n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void JavaCodeEmitter::EmitInterfaceProxySelfDefinedTypeImports( + /* [in] */ StringBuilder& sb) +{ + for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) { + MetaSequenceable* mp = metaComponent_->sequenceables_[i]; + sb.AppendFormat("import %s%s;\n", mp->namespace_, mp->name_); + } + + for (int i = 0; i < metaComponent_->interfaceNumber_; i++) { + MetaInterface* mi = metaComponent_->interfaces_[i]; + if (mi->external_) { + sb.AppendFormat("import %s%s;\n", mi->namespace_, mi->name_); + sb.AppendFormat("import %s%s;\n", mi->namespace_, StubName(String(mi->name_)).string()); + } + } +} + +void JavaCodeEmitter::EmitInterfaceProxyDBinderImports( + /* [in] */ StringBuilder& sb) +{ + 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 JavaCodeEmitter::EmitInterfaceProxyParametersImports( + /* [in] */ StringBuilder& sb) +{ + sb.Append("import ohos.system.version.SystemVersion;\n"); +} + +void JavaCodeEmitter::EmitInterfaceProxyImpl( + /* [in] */ StringBuilder& sb) +{ + sb.AppendFormat("public class %s implements %s {\n", proxyName_.string(), interfaceName_.string()); + EmitInterfaceProxyConstants(sb, TAB); + sb.Append("\n"); + sb.Append(TAB).Append("private final IRemoteObject remote;\n"); + sb.Append(TAB).Append("private static final int ERR_OK = 0;\n"); + sb.Append("\n"); + EmitInterfaceProxyConstructor(sb, TAB); + sb.Append("\n"); + EmitInterfaceProxyMethodImpls(sb, TAB); + sb.Append("};\n"); +} + +void JavaCodeEmitter::EmitInterfaceProxyConstants( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("private static final String DESCRIPTOR = \"%s\";\n\n", interfaceFullName_.string()); + EmitInterfaceMethodCommands(sb, prefix); +} + +void JavaCodeEmitter::EmitInterfaceProxyConstructor( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("public %s(\n", proxyName_.string()); + sb.Append(prefix + TAB).Append("/* [in] */ IRemoteObject remote) {\n"); + 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 JavaCodeEmitter::EmitInterfaceProxyMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + if (metaInterface_->methodNumber_ > 0) { + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + EmitInterfaceProxyMethodImpl(mm, sb, prefix); + if (i != metaInterface_->methodNumber_ - 1) { + sb.Append("\n"); + } + } + } +} + +void JavaCodeEmitter::EmitInterfaceProxyMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + sb.Append(prefix).Append("@Override\n"); + if (mm->parameterNumber_ == 0) { + sb.Append(prefix).AppendFormat("public %s %s() throws RemoteException ", EmitType(returnType).string(), MethodName(mm->name_).string()); + } else { + sb.Append(prefix).AppendFormat("public %s %s(\n", EmitType(returnType).string(), MethodName(mm->name_).string()); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + EmitInterfaceMethodParameter(mp, sb, prefix + TAB); + if (i != mm->parameterNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append(") throws RemoteException "); + } + EmitInterfaceProxyMethodBody(mm, sb, prefix); +} + +void JavaCodeEmitter::EmitInterfaceProxyMethodBody( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.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(%s);\n", + (mm->properties_ & METHOD_PROPERTY_ONEWAY) != 0 ? "MessageOption.TF_ASYNC" : "MessageOption.TF_SYNC"); + sb.Append("\n"); + int32_t R_API_VERSION = 6; + sb.Append(prefix + TAB).AppendFormat("if (SystemVersion.getApiVersion() >= %d) {\n", R_API_VERSION); + sb.Append(prefix + TAB).Append(" data.updateDataVersion(remote);\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix).AppendFormat(" data.writeInterfaceToken(DESCRIPTOR);\n"); + + bool needBlankLine = false; + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_IN) != 0) { + EmitWriteMethodParameter(mp, "data", sb, prefix + TAB); + needBlankLine = true; + } else if ((mp->attributes_ & ATTR_OUT) != 0) { + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + if (mt->kind_ == TypeKind::Array) { + std::string name = UnderlineAdded(mp->name_); + EmitWriteOutArrayVariable("data", name, mt, sb, prefix + TAB); + } + } + } + if (needBlankLine) { + sb.Append("\n"); + } + sb.Append(prefix + TAB).Append("try {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("remote.sendRequest(COMMAND_%s, data, reply, option);\n", + ConstantName(mm->name_).string()); + sb.Append(prefix + TAB).Append(" reply.readException();\n"); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_OUT) != 0) { + EmitReadMethodParameter(mp, "reply", sb, prefix + TAB + TAB); + } + } + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (returnType->kind_ != TypeKind::Void) { + EmitReadVariable("reply", "result", returnType, ATTR_IN, sb, prefix + TAB + TAB); + } + if (returnType->kind_ != TypeKind::Void) { + sb.Append(prefix + TAB + TAB).Append("return result;\n"); + } + + 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).Append("}\n"); +} + +void JavaCodeEmitter::EmitWriteMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + std::string name = UnderlineAdded(mp->name_); + EmitWriteVariable(parcelName, name, mt, sb, prefix); +} + +void JavaCodeEmitter::EmitReadMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + std::string name = UnderlineAdded(mp->name_); + EmitReadOutVariable(parcelName, name, mt, sb, prefix); +} + +void JavaCodeEmitter::EmitInterfaceStub() +{ + String filePath = String::Format("%s/%s.java", directory_.string(), FileName(stubName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitLicense(sb); + sb.Append("\n"); + EmitPackage(sb); + sb.Append("\n"); + EmitInterfaceStubImports(sb); + sb.Append("\n"); + EmitInterfaceStubImpl(sb); + sb.Append("\n"); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void JavaCodeEmitter::EmitInterfaceStubImports( + /* [in] */ StringBuilder& sb) +{ + EmitInterfaceStubCorelibImports(sb); + EmitInterfaceStubSelfDefinedTypeImports(sb); + EmitInterfaceStubDBinderImports(sb); +} + +void JavaCodeEmitter::EmitInterfaceStubCorelibImports( + /* [in] */ StringBuilder& sb) +{ + EmitInterfaceProxyCorelibImports(sb); +} + +void JavaCodeEmitter::EmitInterfaceStubSelfDefinedTypeImports( + /* [in] */ StringBuilder& sb) +{ + for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) { + MetaSequenceable* mp = metaComponent_->sequenceables_[i]; + sb.AppendFormat("import %s%s;\n", mp->namespace_, mp->name_); + } + + for (int i = 0; i < metaComponent_->interfaceNumber_; i++) { + MetaInterface* mi = metaComponent_->interfaces_[i]; + if (mi->external_) { + sb.AppendFormat("import %s%s;\n", mi->namespace_, mi->name_); + sb.AppendFormat("import %s%s;\n", mi->namespace_, StubName(String(mi->name_)).string()); + } + } + sb.AppendFormat("import %s;\n", proxyFullName_.string()); +} + +void JavaCodeEmitter::EmitInterfaceStubDBinderImports( + /* [in] */ StringBuilder& sb) +{ + sb.Append("import ohos.rpc.IRemoteBroker;\n"); + sb.Append("import ohos.rpc.IRemoteObject;\n"); + sb.Append("import ohos.rpc.RemoteException;\n"); + sb.Append("import ohos.rpc.RemoteObject;\n"); + sb.Append("import ohos.rpc.MessageParcel;\n"); + sb.Append("import ohos.rpc.MessageOption;\n"); +} + +void JavaCodeEmitter::EmitInterfaceStubImpl( + /* [in] */ StringBuilder& sb) +{ + sb.AppendFormat("public abstract class %s extends RemoteObject implements %s {\n", stubName_.string(), interfaceName_.string()); + EmitInterfaceStubConstants(sb, TAB); + sb.Append("\n"); + sb.Append(TAB).Append("private static final int ERR_OK = 0;\n"); + sb.Append(TAB).Append("private static final int ERR_RUNTIME_EXCEPTION = -1;\n"); + sb.Append("\n"); + EmitInterfaceStubConstructor(sb, TAB); + sb.Append("\n"); + EmitInterfaceStubMethodImpls(sb, TAB); + sb.Append("};\n"); +} + +void JavaCodeEmitter::EmitInterfaceStubConstants( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("private static final String DESCRIPTOR = \"%s\";\n\n", interfaceFullName_.string()); + EmitInterfaceMethodCommands(sb, prefix); +} + +void JavaCodeEmitter::EmitInterfaceStubConstructor( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("public %s(\n", stubName_.string()); + sb.Append(prefix + TAB).Append("/* [in] */ String descriptor) {\n"); + sb.Append(prefix + TAB).Append("super(descriptor);\n"); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + sb.Append(prefix).Append("@Override\n"); + sb.Append(prefix).Append("public IRemoteObject asObject() {\n"); + sb.Append(prefix + TAB).Append("return this;\n"); + sb.Append(prefix).Append("}\n"); + sb.Append("\n"); + sb.Append(prefix).AppendFormat("public static %s asInterface(IRemoteObject object) {\n", interfaceName_.string()); + sb.Append(prefix + TAB).Append("if (object == null) {\n"); + sb.Append(prefix + TAB).Append(TAB).Append("return null;\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("\n"); + sb.Append(prefix + TAB).AppendFormat("%s result = null;\n", interfaceName_.string()); + sb.Append(prefix + TAB).Append("IRemoteBroker broker = object.queryLocalInterface(DESCRIPTOR);\n"); + sb.Append(prefix + TAB).Append("if (broker != null) {\n"); + sb.Append(prefix + TAB).Append(TAB).AppendFormat("if (broker instanceof %s) {\n", interfaceName_.string()); + sb.Append(prefix + TAB).Append(TAB).Append(TAB).AppendFormat("result = (%s)broker;\n", interfaceName_.string()); + sb.Append(prefix + TAB).Append(TAB).Append("}\n"); + sb.Append(prefix + TAB).Append("} else {\n"); + sb.Append(prefix + TAB).Append(TAB).AppendFormat("result = new %s(object);\n", proxyName_.string()); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append("\n"); + sb.Append(prefix + TAB).Append("return result;\n"); + sb.Append(prefix).Append("}\n"); +} + +void JavaCodeEmitter::EmitInterfaceStubMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).Append("@Override\n"); + sb.Append(prefix).Append("public boolean onRemoteRequest(\n"); + sb.Append(prefix + TAB).Append("/* [in] */ int code,\n"); + sb.Append(prefix + TAB).Append("/* [in] */ MessageParcel data,\n"); + sb.Append(prefix + TAB).Append("/* [out] */ MessageParcel reply,\n"); + sb.Append(prefix + TAB).Append("/* [in] */ MessageOption option) throws RemoteException {\n"); + sb.Append(prefix + TAB).Append("String token = data.readInterfaceToken();\n"); + sb.Append(prefix + TAB).Append("if (!DESCRIPTOR.equals(token)) {\n"); + sb.Append(prefix + TAB).Append(" return false;\n"); + sb.Append(prefix + TAB).Append("}\n"); + + sb.Append(prefix + TAB).Append("switch (code) {\n"); + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + EmitInterfaceStubMethodImpl(mm, sb, prefix + TAB + TAB); + } + sb.Append(prefix + TAB).Append(TAB).Append("default:\n"); + sb.Append(prefix + TAB).Append(TAB).Append(TAB).Append( + "return super.onRemoteRequest(code, data, reply, option);\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix).Append("}\n"); +} + +void JavaCodeEmitter::EmitInterfaceStubMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("case COMMAND_%s: {\n", ConstantName(mm->name_).string()); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_IN) != 0) { + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + EmitReadVariable("data", UnderlineAdded(mp->name_), mt, ATTR_IN, sb, prefix + TAB); + } else if ((mp->attributes_ & ATTR_OUT) != 0) { + EmitLocalVariable(mp, sb, prefix + TAB); + } + } + + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (returnType->kind_ != TypeKind::Void) { + sb.Append(prefix + TAB).AppendFormat("%s result;\n", EmitType(returnType).string()); + } + + if (mm->parameterNumber_ == 0) { + if (returnType->kind_ == TypeKind::Void) { + sb.Append(prefix + TAB).AppendFormat("%s();\n", mm->name_); + } else { + sb.Append(prefix + TAB).AppendFormat("result = %s();\n", mm->name_); + } + } else { + if (returnType->kind_ == TypeKind::Void) { + sb.Append(prefix + TAB).AppendFormat("%s(", mm->name_); + } else { + sb.Append(prefix + TAB).AppendFormat("result = %s(", mm->name_); + } + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + sb.Append(UnderlineAdded(mp->name_).c_str()); + if (i != mm->parameterNumber_ - 1) { + sb.Append(", "); + } + } + sb.AppendFormat(");\n", mm->name_); + } + + sb.Append(prefix + TAB).Append("reply.writeNoException();\n"); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_OUT) != 0) { + EmitWriteMethodParameter(mp, "reply", sb, prefix + TAB); + } + } + if (returnType->kind_ != TypeKind::Void) { + EmitWriteVariable("reply", "result", returnType, sb, prefix + TAB); + } + sb.Append(prefix + TAB).Append("return true;\n"); + sb.Append(prefix).Append("}\n"); +} + +void JavaCodeEmitter::EmitInterfaceMethodCommands( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + sb.Append(prefix).AppendFormat("private static final int COMMAND_%s = IRemoteObject.MIN_TRANSACTION_ID + %d;\n", + ConstantName(mm->name_).string(), i); + } +} + +void JavaCodeEmitter::EmitLicense( + /* [in] */ StringBuilder& sb) +{ + sb.Append(metaInterface_->license_).Append("\n"); +} + +void JavaCodeEmitter::EmitPackage( + /* [in] */ StringBuilder& sb) +{ + String package = metaInterface_->namespace_; + int index = package.LastIndexOf('.'); + sb.AppendFormat("package %s;\n", index != -1 ? package.Substring(0, index).string() : package.string()); +} + +void JavaCodeEmitter::EmitWriteVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%s.writeInt(%s ? 1 : 0);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Char: + case TypeKind::Byte: + case TypeKind::Short: + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%s.writeInt(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%s.writeLong(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%s.writeFloat(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%s.writeDouble(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%s.writeString(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Sequenceable: + if (EmitType(mt).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s);\n", parcelName.string(), name.c_str()); + break; + } + sb.Append(prefix).AppendFormat("%s.writeSequenceable(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Interface: + sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s.asObject());\n", parcelName.string(), + name.c_str()); + break; + case TypeKind::List: { + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + sb.Append(prefix).AppendFormat("%s.writeInt(%s.size());\n", parcelName.string(), name.c_str()); + sb.Append(prefix).AppendFormat("for (%s element : %s) {\n", + EmitType(innerType).string(), name.c_str()); + EmitWriteVariable(parcelName, "element", innerType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Map: { + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + sb.Append(prefix).AppendFormat("%s.writeInt(%s.size());\n", parcelName.string(), name.c_str()); + sb.Append(prefix).AppendFormat("for (Map.Entry<%s, %s> entry : %s.entrySet()) {\n", + EmitType(keyType).string(), EmitType(valueType).string(), name.c_str()); + EmitWriteVariable(parcelName, "entry.getKey()", keyType, sb, prefix + TAB); + EmitWriteVariable(parcelName, "entry.getValue()", valueType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Array: { + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + sb.Append(prefix).AppendFormat("if (%s == null) {\n", name.c_str()); + sb.Append(prefix).AppendFormat(" %s.writeInt(-1);\n", parcelName.string()); + sb.Append(prefix).Append("} else { \n"); + EmitWriteArrayVariable(parcelName, name, innerType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + default: + break; + } +} + +void JavaCodeEmitter::EmitWriteArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%s.writeBooleanArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Char: + sb.Append(prefix).AppendFormat("%s.writeCharArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Byte: + sb.Append(prefix).AppendFormat("%s.writeByteArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Short: + sb.Append(prefix).AppendFormat("%s.writeShortArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%s.writeIntArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%s.writeLongArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%s.writeFloatArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%s.writeDoubleArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%s.writeStringArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Sequenceable: + sb.Append(prefix).AppendFormat("%s.writeSequenceableArray(%s);\n", parcelName.string(), name.c_str()); + break; + default: + break; + } +} + +void JavaCodeEmitter::EmitWriteOutArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("if (%s == null) {\n", name.c_str()); + 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.c_str()); + sb.Append(prefix).Append("}\n"); +} + +void JavaCodeEmitter::EmitReadVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%s %s = %s.readInt() == 1 ? true : false;\n", + EmitType(mt).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Char: + case TypeKind::Byte: + case TypeKind::Short: + sb.Append(prefix).AppendFormat("%s %s = (%s)%s.readInt();\n", + EmitType(mt).string(), name.c_str(), EmitType(mt).string(), parcelName.string()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%s %s = %s.readInt();\n", + EmitType(mt).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%s %s = %s.readLong();\n", + EmitType(mt).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%s %s = %s.readFloat();\n", + EmitType(mt).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%s %s = %s.readDouble();\n", + EmitType(mt).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%s %s = %s.readString();\n", + EmitType(mt).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Sequenceable: + if ((attributes & ATTR_OUT) == 0 && EmitType(mt).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("IRemoteObject %s = %s.readRemoteObject();\n", + name.c_str(), parcelName.string()); + break; + } + if ((attributes & ATTR_OUT) == 0) { + sb.Append(prefix).AppendFormat("%s %s = new %s();\n", + EmitType(mt).string(), name.c_str(), EmitType(mt).string()); + } + sb.Append(prefix).AppendFormat("%s.readSequenceable(%s);\n", parcelName.string(), name.c_str()); + + break; + case TypeKind::Interface: + sb.Append(prefix).AppendFormat("%s %s = %s.asInterface(%s.readRemoteObject());\n", EmitType(mt).string(), + name.c_str(), StubName(EmitType(mt)).string(), parcelName.string()); + break; + case TypeKind::List: { + sb.Append(prefix).AppendFormat("%s %s = new Array%s();\n", + EmitType(mt).string(), name.c_str(), EmitType(mt).string()); + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + EmitReadVariable(parcelName, "value", innerType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.add(value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Map: { + sb.Append(prefix).AppendFormat("%s %s = new Hash%s();\n", + EmitType(mt).string(), name.c_str(), EmitType(mt).string()); + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + EmitReadVariable(parcelName, "key", keyType, ATTR_IN, sb, prefix + TAB); + EmitReadVariable(parcelName, "value", valueType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.put(key, value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Array: { + if ((attributes & ATTR_MASK) == ATTR_OUT) { + EmitReadOutArrayVariable(parcelName, name, mt, sb, prefix); + } else { + EmitReadArrayVariable(parcelName, name, mt, attributes, sb, prefix); + } + break; + } + default: + break; + } +} + +void JavaCodeEmitter::EmitReadArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + switch (innerType->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readBooleanArray();\n", + EmitType(innerType).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Char: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readCharArray();\n", + EmitType(innerType).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Byte: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readByteArray();\n", + EmitType(innerType).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Short: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readShortArray();\n", + EmitType(innerType).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readIntArray();\n", + EmitType(innerType).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readLongArray();\n", + EmitType(innerType).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readFloatArray();\n", + EmitType(innerType).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readDoubleArray();\n", + EmitType(innerType).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%s[] %s = %s.readStringArray();\n", + EmitType(innerType).string(), name.c_str(), parcelName.string()); + break; + case TypeKind::Sequenceable: + sb.Append(prefix).AppendFormat("int size = %s.readInt();\n", parcelName.string()); + sb.Append(prefix).AppendFormat("%s %s = new %s[size];\n", + EmitType(mt).string(), name.c_str(), EmitType(innerType).string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < size; ++i) {\n"); + EmitReadVariable(parcelName, "value", innerType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s[i] = value;\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + default: + break; + } +} + +void JavaCodeEmitter::EmitReadOutArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + switch (innerType->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%s.readBooleanArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Char: + sb.Append(prefix).AppendFormat("%s.readCharArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Byte: + sb.Append(prefix).AppendFormat("%s.readByteArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Short: + sb.Append(prefix).AppendFormat("%s.readShortArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%s.readIntArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%s.readLongArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%s.readFloatArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%s.readDoubleArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%s.readStringArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Sequenceable: + sb.Append(prefix).AppendFormat("%s.readSequenceableArray(%s);\n", parcelName.string(), name.c_str()); + break; + default: + break; + } +} + +void JavaCodeEmitter::EmitReadOutVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%s = %s.readInt() == 1 ? true : false;\n", + name.c_str(), parcelName.string()); + break; + case TypeKind::Char: + case TypeKind::Byte: + case TypeKind::Short: + sb.Append(prefix).AppendFormat("%s = (%s)%s.readInt();\n", + name.c_str(), EmitType(mt).string(), parcelName.string()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%s = %s.readInt();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%s = %s.readLong();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%s = %s.readFloat();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%s = %s.readDouble();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%s = %s.readString();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Sequenceable: + if (EmitType(mt).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("%s = %s.readRemoteObject();\n", name.c_str(), parcelName.string()); + break; + } + sb.Append(prefix).AppendFormat("%s.readSequenceable(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Interface: + sb.Append(prefix).AppendFormat("%s = %s.asInterface(%s.readRemoteObject());\n", name.c_str(), + StubName(EmitType(mt)).string(), parcelName.string()); + break; + case TypeKind::List: { + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + EmitReadVariable(parcelName, "value", innerType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.add(value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Map: { + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + EmitReadVariable(parcelName, "key", keyType, ATTR_IN, sb, prefix + TAB); + EmitReadVariable(parcelName, "value", valueType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.put(key, value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Array: { + EmitReadOutArrayVariable(parcelName, name, mt, sb, prefix); + break; + } + default: + break; + } +} + +void JavaCodeEmitter::EmitLocalVariable( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + std::string name = UnderlineAdded(mp->name_); + if (mt->kind_ == TypeKind::Sequenceable) { + sb.Append(prefix).AppendFormat("%s %s = new %s();\n", EmitType(mt).string(), name.c_str(), + EmitType(mt).string()); + } else if (mt->kind_ == TypeKind::List) { + sb.Append(prefix).AppendFormat("%s %s = new Array%s();\n", EmitType(mt).string(), name.c_str(), + EmitType(mt).string()); + } else if (mt->kind_ == TypeKind::Map) { + sb.Append(prefix).AppendFormat("%s %s = new Hash%s();\n", EmitType(mt).string(), name.c_str(), + EmitType(mt).string()); + } else { + sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt).string(), name.c_str()); + } +} + +String JavaCodeEmitter::EmitType( + /* [in] */ MetaType* mt) +{ + switch(mt->kind_) { + case TypeKind::Char: + return "char"; + case TypeKind::Boolean: + return "boolean"; + case TypeKind::Byte: + return "byte"; + case TypeKind::Short: + return "short"; + case TypeKind::Integer: + return "int"; + case TypeKind::Long: + return "long"; + case TypeKind::Float: + return "float"; + case TypeKind::Double: + return "double"; + case TypeKind::String: + return "String"; + case TypeKind::Void: + return "void"; + case TypeKind::Sequenceable: { + MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_]; + return mp->name_; + } + case TypeKind::Interface: { + MetaInterface* mi = metaComponent_->interfaces_[mt->index_]; + return mi->name_; + } + case TypeKind::List: { + MetaType* elementType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + return String::Format("List<%s>", EmitType(elementType).string()); + } + case TypeKind::Map: { + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + return String::Format("Map<%s, %s>", EmitType(keyType).string(), EmitType(valueType).string()); + } + case TypeKind::Array: { + MetaType* elementType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + return String::Format("%s[]", EmitType(elementType).string()); + } + default: + return "unknown type"; + } +} + +String JavaCodeEmitter::FileName( + /* [in] */ const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + return name.Replace('.', '/'); +} + +String JavaCodeEmitter::MethodName( + /* [in] */ 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( + /* [in] */ 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::StubName( + /* [in] */ const String& name) +{ + return name.StartsWith("I") ? (name.Substring(1) + "Stub") : (name + "Stub"); +} + +const std::string JavaCodeEmitter::UnderlineAdded(const String& originName) +{ + std::string underline("_"); + return underline + std::string(originName.string()); +} + +} +} diff --git a/zidl/codegen/java_code_emitter.h b/zidl/codegen/java_code_emitter.h new file mode 100644 index 0000000000000000000000000000000000000000..777f74c310ca09163a493d0154b57c165770a648 --- /dev/null +++ b/zidl/codegen/java_code_emitter.h @@ -0,0 +1,241 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_JAVACODEEMITTER_H +#define OHOS_ZIDL_JAVACODEEMITTER_H + +#include + +#include "codegen/code_emitter.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +class JavaCodeEmitter : public CodeEmitter { +public: + JavaCodeEmitter( + /* [in] */ MetaComponent* mc) + : CodeEmitter(mc) + {} + + void EmitInterface() override; + + void EmitInterfaceProxy() override; + + void EmitInterfaceStub() override; + +private: + void EmitInterfaceImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceCorelibImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceDBinderImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceDefinition( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceMethods( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethod( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyCorelibImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxySelfDefinedTypeImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyDBinderImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyParametersImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyImpl( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyConstants( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyConstructor( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyMethodBody( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitWriteMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceStubCorelibImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceStubSelfDefinedTypeImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceStubDBinderImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceStubImpl( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceStubConstants( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubConstructor( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethodCommands( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitLicense( + /* [in] */ StringBuilder& sb); + + void EmitPackage( + /* [in] */ StringBuilder& sb); + + void EmitWriteVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadOutVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitWriteArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitWriteOutArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadOutArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitLocalVariable( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + String EmitType( + /* [in] */ MetaType* mt); + + String FileName( + /* [in] */ const String& name); + + String MethodName( + /* [in] */ const String& name); + + String ConstantName( + /* [in] */ const String& name); + + String StubName( + /* [in] */ const String& name); + + const std::string UnderlineAdded(const String& name); +}; + +} +} + +#endif // OHOS_ZIDL_JAVACODEEMITTER_H diff --git a/zidl/codegen/js_code_emitter.cpp b/zidl/codegen/js_code_emitter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95c7c048ebf70741c45d1a91922626c38b7f5ea2 --- /dev/null +++ b/zidl/codegen/js_code_emitter.cpp @@ -0,0 +1,1167 @@ +/* + * 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 "codegen/js_code_emitter.h" + +#include +#include + +#include "securec.h" +#include "util/file.h" + +namespace OHOS { +namespace Zidl { + + +void JsCodeEmitter::EmitInterface() +{ +} + +void JsCodeEmitter::EmitInterfaceImports( + /* [in] */ StringBuilder& sb) +{ + sb.Append("import rpc from \"@ohos.rpc\";\n"); +} + +void JsCodeEmitter::EmitInterfaceCorelibImports( + /* [in] */ StringBuilder& sb) +{ + bool includeList = false; + bool includeMap = false; + for (int i = 0; i < metaComponent_->typeNumber_; i++) { + MetaType* mt = metaComponent_->types_[i]; + switch (mt->kind_) { + case TypeKind::List: { + if (!includeList) { + sb.Append("import java.util.List;\n"); + includeList = true; + } + break; + } + case TypeKind::Map: { + if (!includeMap) { + sb.Append("import java.util.Map;\n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void JsCodeEmitter::EmitInterfaceDBinderImports( + /* [in] */ StringBuilder& sb) +{ + sb.Append("import ohos.rpc.IRemoteBroker;\n"); + sb.Append("import ohos.rpc.RemoteException;\n"); +} + +void JsCodeEmitter::EmitInterfaceSelfDefinedTypeImports( + /* [in] */ StringBuilder& sb) +{ + for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) { + MetaSequenceable* mp = metaComponent_->sequenceables_[i]; + sb.AppendFormat("import %s%s;\n", mp->namespace_, mp->name_); + } + + for (int i = 0; i < metaComponent_->interfaceNumber_; i++) { + MetaInterface* mi = metaComponent_->interfaces_[i]; + if (mi->external_) { + sb.AppendFormat("import %s%s;\n", mi->namespace_, mi->name_); + } + } +} + +void JsCodeEmitter::EmitInterfaceDefinition( + /* [in] */ StringBuilder& sb) +{ + sb.AppendFormat("public interface %s extends IRemoteBroker {\n", metaInterface_->name_); + EmitInterfaceMethods(sb, TAB); + sb.Append("};\n"); +} + +void JsCodeEmitter::EmitInterfaceMethods( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + if (metaInterface_->methodNumber_ > 0) { + sb.Append("\n"); + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + EmitInterfaceMethod(mm, sb, prefix); + if (i != metaInterface_->methodNumber_ - 1) { + sb.Append("\n"); + } + } + } +} + +void JsCodeEmitter::EmitInterfaceMethod( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (mm->parameterNumber_ == 0) { + sb.Append(prefix).AppendFormat( + "%s %s() throws RemoteException;\n", EmitType(returnType).string(), MethodName(mm->name_).string()); + } else { + sb.Append(prefix).AppendFormat("%s %s(\n", EmitType(returnType).string(), MethodName(mm->name_).string()); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + EmitInterfaceMethodParameter(mp, sb, prefix + TAB); + if (i != mm->parameterNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append(") throws RemoteException;\n"); + } +} + +void JsCodeEmitter::EmitInterfaceMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + std::string name = UnderlineAdded(mp->name_); + sb.AppendFormat("%s", name.c_str()); +} + +void JsCodeEmitter::EmitInterfaceProxy() +{ + String filePath = String::Format("%s/%s.js", directory_.string(), FileName(proxyName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + + EmitInterfaceImports(sb); + sb.Append("\n"); + EmitInterfaceStubConstants(sb); + sb.Append("\n"); + EmitJsCallBack(sb); + sb.Append("\n"); + EmitInterfaceProxyImpl(sb); + sb.Append("\n"); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void JsCodeEmitter::EmitInterfaceProxyImports( + /* [in] */ StringBuilder& sb) +{ + EmitInterfaceProxyCorelibImports(sb); + EmitInterfaceProxySelfDefinedTypeImports(sb); + EmitInterfaceProxyDBinderImports(sb); + EmitInterfaceProxyParametersImports(sb); +} + +void JsCodeEmitter::EmitInterfaceProxyCorelibImports( + /* [in] */ StringBuilder& sb) +{ + bool includeList = false; + bool includeMap = false; + for (int i = 0; i < metaComponent_->typeNumber_; i++) { + MetaType* mt = metaComponent_->types_[i]; + switch(mt->kind_) { + case TypeKind::List: { + if (!includeList) { + sb.Append("import java.util.List;\n"); + sb.Append("import java.util.ArrayList;\n"); + includeList = true; + } + break; + } + case TypeKind::Map: { + if (!includeMap) { + sb.Append("import java.util.Map;\n"); + sb.Append("import java.util.HashMap;\n"); + includeMap = true; + } + break; + } + default: + break; + } + } +} + +void JsCodeEmitter::EmitInterfaceProxySelfDefinedTypeImports( + /* [in] */ StringBuilder& sb) +{ + for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) { + MetaSequenceable* mp = metaComponent_->sequenceables_[i]; + sb.AppendFormat("import %s%s;\n", mp->namespace_, mp->name_); + } + + for (int i = 0; i < metaComponent_->interfaceNumber_; i++) { + MetaInterface* mi = metaComponent_->interfaces_[i]; + if (mi->external_) { + sb.AppendFormat("import %s%s;\n", mi->namespace_, mi->name_); + sb.AppendFormat("import %s%s;\n", mi->namespace_, StubName(String(mi->name_)).string()); + } + } +} + +void JsCodeEmitter::EmitInterfaceProxyDBinderImports( + /* [in] */ StringBuilder& sb) +{ + 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 JsCodeEmitter::EmitInterfaceProxyParametersImports( + /* [in] */ StringBuilder& sb) +{ + sb.Append("import ohos.system.version.SystemVersion;\n"); +} + +void JsCodeEmitter::EmitInterfaceProxyImpl( + /* [in] */ StringBuilder& sb) +{ + sb.AppendFormat("export default {\n", proxyName_.string(), interfaceName_.string()); + EmitInterfaceProxyMethodImpls(sb, TAB); + sb.Append("}\n"); +} + +void JsCodeEmitter::EmitInterfaceProxyConstants( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat( + "private static final String DESCRIPTOR = \"%s\";\n\n", interfaceFullName_.string()); + EmitInterfaceMethodCommands(sb); +} + +void JsCodeEmitter::EmitInterfaceProxyConstructor( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("public %s(\n", proxyName_.string()); + sb.Append(prefix + TAB).Append("/* [in] */ IRemoteObject remote) {\n"); + 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 JsCodeEmitter::EmitInterfaceProxyMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + if (metaInterface_->methodNumber_ > 0) { + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + EmitInterfaceProxyMethodImpl(mm, sb, prefix); + if (i != metaInterface_->methodNumber_ - 1) { + sb.Append("\n"); + } + } + } +} + +void JsCodeEmitter::EmitInterfaceProxyMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + if (mm->parameterNumber_ == 0) { + sb.Append(prefix).AppendFormat("%s() ", MethodName(mm->name_).string()); + } else { + sb.Append(prefix).AppendFormat("%s(", MethodName(mm->name_).string()); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + EmitInterfaceMethodParameter(mp, sb, prefix + TAB); + if (i != mm->parameterNumber_ - 1) { + sb.Append(", "); + } + } + sb.Append(") "); + } + EmitInterfaceProxyMethodBody(mm, sb, prefix); +} + +void JsCodeEmitter::EmitInterfaceProxyMethodBody( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("let option = new rpc.MessageOption();\n"); + sb.Append(prefix + TAB).Append("let data = new rpc.MessageParcel();\n"); + sb.Append(prefix + TAB).Append("let reply = new rpc.MessageParcel();\n"); + sb.Append("\n"); + + bool needBlankLine = false; + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_IN) != 0) { + EmitWriteMethodParameter(mp, "data", sb, prefix + TAB); + needBlankLine = true; + } else if ((mp->attributes_ & ATTR_OUT) != 0) { + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + if (mt->kind_ == TypeKind::Array) { + std::string name = UnderlineAdded(mp->name_); + EmitWriteOutArrayVariable("data", name, mt, sb, prefix + TAB); + } + } + } + if (needBlankLine) { + sb.Append("\n"); + } + + if ((mm->properties_ & METHOD_PROPERTY_ONEWAY) == 0) { + sb.Append(prefix + TAB).AppendFormat("let ret = proxy.sendRequest(COMMAND_%s, data, reply, option)\n", + ConstantName(mm->name_).string()); + sb.Append(prefix + TAB + TAB).AppendFormat(".then(function (result) {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("if (result.errCode === 0) {\n"); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_OUT) != 0) { + EmitReadMethodParameter(mp, "reply", sb, prefix + TAB + TAB); + } + } + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (returnType->kind_ != TypeKind::Void) { + EmitReadVariable("reply", "result", "msg", returnType, ATTR_IN, sb, prefix + TAB + TAB + TAB); + } else { + sb.Append(prefix + TAB + TAB + TAB).Append("console.log(\"void function call success\");\n"); + } + if (returnType->kind_ != TypeKind::Void) { + sb.Append(prefix + TAB + TAB + TAB).Append("console.log(\"reply msg: \" + msg);\n"); + } + sb.Append(prefix + TAB + TAB).AppendFormat("} else {\n"); + sb.Append(prefix + TAB + TAB + TAB).Append( + "console.log(\"sendRequest failed, errCode: \" + result.errCode);\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("}\n"); + sb.Append(prefix + TAB).AppendFormat("}).catch(function (e) {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("console.log(\"sendRequest exception:\" + e);\n"); + sb.Append(prefix + TAB).AppendFormat("}).finally (() => {\n"); + sb.Append(prefix + TAB).AppendFormat("console.log(\"sendRequest ends, reclaim parcels\");\n"); + sb.Append(prefix + TAB + TAB).Append("data.reclaim();\n"); + sb.Append(prefix + TAB + TAB).Append("reply.reclaim();\n"); + sb.Append(prefix + TAB).AppendFormat("});\n"); + } else { + sb.Append(prefix + TAB).Append("try {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat( + "let ret = proxy.sendRequest(COMMAND_%s, data, reply, option, %sCallback)\n", + ConstantName(mm->name_).string(), MethodName(mm->name_).string()); + sb.Append(prefix + TAB).Append("} catch(e) {\n"); + sb.Append(prefix + TAB + TAB).AppendFormat("console.log(\"sendRequest exception:\" + e);\n"); + sb.Append(prefix + TAB).AppendFormat("}\n"); + } + sb.Append(prefix).Append("},\n"); +} + +void JsCodeEmitter::EmitWriteMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + std::string name = UnderlineAdded(mp->name_); + EmitWriteVariable(parcelName, name, mt, sb, prefix); +} + +void JsCodeEmitter::EmitReadMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + std::string name = UnderlineAdded(mp->name_); + EmitReadOutVariable(parcelName, name, mt, sb, prefix); +} + +void JsCodeEmitter::EmitInterfaceStub() +{ + String filePath = String::Format("%s/%s.js", directory_.string(), FileName(stubName_).string()); + File file(filePath, File::WRITE); + + StringBuilder sb; + EmitInterfaceImports(sb); + sb.Append("\n"); + EmitInterfaceStubConstants(sb); + sb.Append("\n"); + EmitInterfaceStubImpl(sb); + sb.Append("\n"); + + String data = sb.ToString(); + file.WriteData(data.string(), data.GetLength()); + file.Flush(); + file.Close(); +} + +void JsCodeEmitter::EmitInterfaceStubImpl( + /* [in] */ StringBuilder& sb) +{ + sb.AppendFormat("class %s extends rpc.RemoteObject {\n", stubName_.string()); + EmitInterfaceStubConstructor(sb, TAB); + sb.Append("\n"); + EmitInterfaceStubMethodImpls(sb, TAB); + sb.Append("}\n"); +} + +void JsCodeEmitter::EmitInterfaceStubConstants(/* [in] */ StringBuilder& sb) +{ + EmitInterfaceMethodCommands(sb); +} + +void JsCodeEmitter::EmitJsCallBack(/* [in] */ StringBuilder& sb) +{ + if (metaInterface_->methodNumber_ > 0) { + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + if ((mm->properties_ & METHOD_PROPERTY_ONEWAY) == 1) { + sb.AppendFormat("function %sCallback(result) {\n", MethodName(mm->name_).string()); + sb.Append(TAB).AppendFormat("if (result.errCode === 0) {\n"); + + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (returnType->kind_ != TypeKind::Void) { + EmitReadVariable("reply", "msg", returnType, ATTR_IN, sb, String(TAB) + TAB + TAB); + } else { + sb.Append(String(TAB) + TAB + TAB).Append("console.log(\"void function call success\");\n"); + } + if (returnType->kind_ != TypeKind::Void) { + sb.Append(String(TAB) + TAB + TAB).Append("console.log(\"reply msg: \" + msg);\n"); + } + sb.Append(String(TAB)).AppendFormat("} else {\n"); + sb.Append(String(TAB) + TAB).Append( + "console.log(\"sendRequest failed, errCode: \" + result.errCode);\n"); + sb.Append(String(TAB)).AppendFormat("}\n"); + sb.Append(String(TAB)).AppendFormat("console.log(\"sendRequest ends, reclaim parcels\");\n"); + sb.Append(String(TAB)).Append("data.reclaim();\n"); + sb.Append(String(TAB)).Append("reply.reclaim();\n"); + sb.Append("}\n"); + } + if (i != metaInterface_->methodNumber_ - 1) { + sb.Append("\n"); + } + } + } +} + +void JsCodeEmitter::EmitInterfaceStubConstructor( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("constructor(des) {\n"); + sb.Append(prefix + TAB).Append("super(des);\n"); + sb.Append(prefix).Append("}\n"); +} + +void JsCodeEmitter::EmitInterfaceStubMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).Append("onRemoteRequest(code, data, reply, option) {\n"); + sb.Append(prefix + TAB).Append("switch (code) {\n"); + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + EmitInterfaceStubMethodImpl(mm, sb, prefix + TAB + TAB); + } + sb.Append(prefix + TAB).Append(TAB).Append("default:\n"); + sb.Append(prefix + TAB).Append(TAB).Append(TAB).Append( + "return super.onRemoteRequest(code, data, reply, option);\n"); + sb.Append(prefix + TAB).Append("}\n"); + sb.Append(prefix).Append("}\n"); +} + +void JsCodeEmitter::EmitInterfaceStubMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("case COMMAND_%s: {\n", ConstantName(mm->name_).string()); + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_IN) != 0) { + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + EmitReadVariable("data", UnderlineAdded(mp->name_), mt, ATTR_IN, sb, prefix + TAB); + } else if ((mp->attributes_ & ATTR_OUT) != 0) { + EmitLocalVariable(mp, sb, prefix + TAB); + } + } + + MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_]; + if (mm->parameterNumber_ == 0) { + if (returnType->kind_ == TypeKind::Void) { + sb.Append(prefix + TAB).AppendFormat("%s();\n", mm->name_); + } else { + sb.Append(prefix + TAB).AppendFormat("let result = %s();\n", mm->name_); + } + } else { + if (returnType->kind_ == TypeKind::Void) { + sb.Append(prefix + TAB).AppendFormat("%s(", mm->name_); + } else { + sb.Append(prefix + TAB).AppendFormat("let result = %s(", mm->name_); + } + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + sb.Append(UnderlineAdded(mp->name_).c_str()); + if (i != mm->parameterNumber_ - 1) { + sb.Append(", "); + } + } + sb.AppendFormat(");\n", mm->name_); + } + + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + if ((mp->attributes_ & ATTR_OUT) != 0) { + EmitWriteMethodParameter(mp, "reply", sb, prefix + TAB); + } + } + if (returnType->kind_ != TypeKind::Void) { + EmitWriteVariable("reply", "result", returnType, sb, prefix + TAB); + } + sb.Append(prefix + TAB).Append("return true;\n"); + sb.Append(prefix).Append("}\n"); +} + +void JsCodeEmitter::EmitInterfaceMethodCommands(/* [in] */ StringBuilder& sb) +{ + for (int i = 0; i < metaInterface_->methodNumber_; i++) { + MetaMethod* mm = metaInterface_->methods_[i]; + sb.AppendFormat("const COMMAND_%s = %d;\n", ConstantName(mm->name_).string(), i); + } +} + +void JsCodeEmitter::EmitLicense( + /* [in] */ StringBuilder& sb) +{ + sb.Append(metaInterface_->license_).Append("\n"); +} + +void JsCodeEmitter::EmitPackage( + /* [in] */ StringBuilder& sb) +{ + String package = metaInterface_->namespace_; + int index = package.LastIndexOf('.'); + sb.AppendFormat("package %s;\n", index != -1 ? package.Substring(0, index).string() : package.string()); +} + +void JsCodeEmitter::EmitWriteVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%s.writeInt(%s ? 1 : 0);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Char: + case TypeKind::Byte: + case TypeKind::Short: + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%s.writeInt(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%s.writeLong(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%s.writeFloat(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%s.writeDouble(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%s.writeString(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Sequenceable: + if (EmitType(mt).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s);\n", parcelName.string(), name.c_str()); + break; + } + sb.Append(prefix).AppendFormat("%s.writeSequenceable(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Interface: + sb.Append(prefix).AppendFormat("%s.writeRemoteObject(%s.asObject());\n", parcelName.string(), + name.c_str()); + break; + case TypeKind::List: { + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + sb.Append(prefix).AppendFormat("%s.writeInt(%s.size());\n", parcelName.string(), name.c_str()); + sb.Append(prefix).AppendFormat("for (%s element : %s) {\n", + EmitType(innerType).string(), name.c_str()); + EmitWriteVariable(parcelName, "element", innerType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Map: { + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + sb.Append(prefix).AppendFormat("%s.writeInt(%s.size());\n", parcelName.string(), name.c_str()); + sb.Append(prefix).AppendFormat("for (Map.Entry<%s, %s> entry : %s.entrySet()) {\n", + EmitType(keyType).string(), EmitType(valueType).string(), name.c_str()); + EmitWriteVariable(parcelName, "entry.getKey()", keyType, sb, prefix + TAB); + EmitWriteVariable(parcelName, "entry.getValue()", valueType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Array: { + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + sb.Append(prefix).AppendFormat("if (%s == null) {\n", name.c_str()); + sb.Append(prefix).AppendFormat(" %s.writeInt(-1);\n", parcelName.string()); + sb.Append(prefix).Append("} else { \n"); + EmitWriteArrayVariable(parcelName, name, innerType, sb, prefix + TAB); + sb.Append(prefix).Append("}\n"); + break; + } + default: + break; + } +} + +void JsCodeEmitter::EmitWriteArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%s.writeBooleanArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Char: + sb.Append(prefix).AppendFormat("%s.writeCharArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Byte: + sb.Append(prefix).AppendFormat("%s.writeByteArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Short: + sb.Append(prefix).AppendFormat("%s.writeShortArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%s.writeIntArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%s.writeLongArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%s.writeFloatArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%s.writeDoubleArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%s.writeStringArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Sequenceable: + sb.Append(prefix).AppendFormat("%s.writeSequenceableArray(%s);\n", parcelName.string(), name.c_str()); + break; + default: + break; + } +} + +void JsCodeEmitter::EmitWriteOutArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).AppendFormat("if (%s == null) {\n", name.c_str()); + 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.c_str()); + sb.Append(prefix).Append("}\n"); +} + +void JsCodeEmitter::EmitReadVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("let %s = %s.readInt() == 1 ? true : false;\n", name.c_str(), + parcelName.string()); + break; + case TypeKind::Char: + case TypeKind::Byte: + case TypeKind::Short: + sb.Append(prefix).AppendFormat("let %s = %s.readInt();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("let %s = %s.readInt();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("let %s = %s.readLong();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("let %s = %s.readFloat();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("let %s = %s.readDouble();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("let %s = %s.readString();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Sequenceable: + if ((attributes & ATTR_OUT) == 0 && EmitType(mt).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("IRemoteObject %s = %s.readRemoteObject();\n", + name.c_str(), parcelName.string()); + break; + } + if ((attributes & ATTR_OUT) == 0) { + sb.Append(prefix).AppendFormat("%s %s = new %s();\n", + EmitType(mt).string(), name.c_str(), EmitType(mt).string()); + } + sb.Append(prefix).AppendFormat("%s.readSequenceable(%s);\n", parcelName.string(), name.c_str()); + + break; + case TypeKind::Interface: + sb.Append(prefix).AppendFormat("let %s = %s.asInterface(%s.readRemoteObject());\n", name.c_str(), + StubName(EmitType(mt)).string(), parcelName.string()); + break; + case TypeKind::List: { + sb.Append(prefix).AppendFormat("let %s = new Array%s();\n", name.c_str(), EmitType(mt).string()); + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + EmitReadVariable(parcelName, "value", innerType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.add(value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Map: { + sb.Append(prefix).AppendFormat("let %s = new Hash%s();\n", name.c_str(), EmitType(mt).string()); + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + EmitReadVariable(parcelName, "key", keyType, ATTR_IN, sb, prefix + TAB); + EmitReadVariable(parcelName, "value", valueType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.put(key, value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Array: { + if ((attributes & ATTR_MASK) == ATTR_OUT) { + EmitReadOutArrayVariable(parcelName, name, mt, sb, prefix); + } else { + EmitReadArrayVariable(parcelName, name, mt, attributes, sb, prefix); + } + break; + } + default: + break; + } +} + +void JsCodeEmitter::EmitReadVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& returnName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("let %s = %s.%s.readInt() == 1 ? true : false;\n", name.c_str(), + returnName.c_str(), parcelName.string()); + break; + case TypeKind::Char: + case TypeKind::Byte: + case TypeKind::Short: + sb.Append(prefix).AppendFormat("let %s = %s.%s.readInt();\n", name.c_str(), returnName.c_str(), + parcelName.string()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("let %s = %s.%s.readInt();\n", name.c_str(), returnName.c_str(), + parcelName.string()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("let %s = %s.%s.readLong();\n", name.c_str(), returnName.c_str(), + parcelName.string()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("let %s = %s.%s.readFloat();\n", name.c_str(), returnName.c_str(), + parcelName.string()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("let %s = %s.%s.readDouble();\n", name.c_str(), returnName.c_str(), + parcelName.string()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("let %s = %s.%s.readString();\n", name.c_str(), returnName.c_str(), + parcelName.string()); + break; + case TypeKind::Sequenceable: + if ((attributes & ATTR_OUT) == 0 && EmitType(mt).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("IRemoteObject %s = %s.%s.readRemoteObject();\n", + name.c_str(), parcelName.string()); + break; + } + if ((attributes & ATTR_OUT) == 0) { + sb.Append(prefix).AppendFormat("%s %s = new %s();\n", + EmitType(mt).string(), name.c_str(), EmitType(mt).string()); + } + sb.Append(prefix).AppendFormat("%s.readSequenceable(%s);\n", parcelName.string(), name.c_str()); + + break; + case TypeKind::Interface: + sb.Append(prefix).AppendFormat("let %s = %s.%s.asInterface(%s.readRemoteObject());\n", name.c_str(), + StubName(EmitType(mt)).string(), parcelName.string()); + break; + case TypeKind::List: { + sb.Append(prefix).AppendFormat("let %s = new Array%s();\n", name.c_str(), EmitType(mt).string()); + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + EmitReadVariable(parcelName, "value", innerType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.add(value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Map: { + sb.Append(prefix).AppendFormat("let %s = new Hash%s();\n", name.c_str(), EmitType(mt).string()); + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + EmitReadVariable(parcelName, "key", keyType, ATTR_IN, sb, prefix + TAB); + EmitReadVariable(parcelName, "value", valueType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.put(key, value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Array: { + if ((attributes & ATTR_MASK) == ATTR_OUT) { + EmitReadOutArrayVariable(parcelName, name, mt, sb, prefix); + } else { + EmitReadArrayVariable(parcelName, name, mt, attributes, sb, prefix); + } + break; + } + default: + break; + } +} + +void JsCodeEmitter::EmitReadArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + switch (innerType->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("let %s = %s.readBooleanArray();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Char: + sb.Append(prefix).AppendFormat("let %s = %s.readCharArray();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Byte: + sb.Append(prefix).AppendFormat("let %s = %s.readByteArray();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Short: + sb.Append(prefix).AppendFormat("let %s = %s.readShortArray();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("let %s = %s.readIntArray();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("let %s = %s.readLongArray();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("let %s = %s.readFloatArray();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("let %s = %s.readDoubleArray();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("let %s = %s.readStringArray();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Sequenceable: + sb.Append(prefix).AppendFormat("int size = %s.readInt();\n", parcelName.string()); + sb.Append(prefix).AppendFormat("%s %s = new %s[size];\n", + EmitType(mt).string(), name.c_str(), EmitType(innerType).string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < size; ++i) {\n"); + EmitReadVariable(parcelName, "value", innerType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s[i] = value;\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + default: + break; + } +} + +void JsCodeEmitter::EmitReadOutArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + switch (innerType->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%s.readBooleanArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Char: + sb.Append(prefix).AppendFormat("%s.readCharArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Byte: + sb.Append(prefix).AppendFormat("%s.readByteArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Short: + sb.Append(prefix).AppendFormat("%s.readShortArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%s.readIntArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%s.readLongArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%s.readFloatArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%s.readDoubleArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%s.readStringArray(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Sequenceable: + sb.Append(prefix).AppendFormat("%s.readSequenceableArray(%s);\n", parcelName.string(), name.c_str()); + break; + default: + break; + } +} + +void JsCodeEmitter::EmitReadOutVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + switch (mt->kind_) { + case TypeKind::Boolean: + sb.Append(prefix).AppendFormat("%s = %s.readInt() == 1 ? true : false;\n", + name.c_str(), parcelName.string()); + break; + case TypeKind::Char: + case TypeKind::Byte: + case TypeKind::Short: + sb.Append(prefix).AppendFormat("%s = (%s)%s.readInt();\n", + name.c_str(), EmitType(mt).string(), parcelName.string()); + break; + case TypeKind::Integer: + sb.Append(prefix).AppendFormat("%s = %s.readInt();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Long: + sb.Append(prefix).AppendFormat("%s = %s.readLong();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Float: + sb.Append(prefix).AppendFormat("%s = %s.readFloat();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Double: + sb.Append(prefix).AppendFormat("%s = %s.readDouble();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::String: + sb.Append(prefix).AppendFormat("%s = %s.readString();\n", name.c_str(), parcelName.string()); + break; + case TypeKind::Sequenceable: + if (EmitType(mt).Equals("IRemoteObject")) { + sb.Append(prefix).AppendFormat("%s = %s.readRemoteObject();\n", name.c_str(), parcelName.string()); + break; + } + sb.Append(prefix).AppendFormat("%s.readSequenceable(%s);\n", parcelName.string(), name.c_str()); + break; + case TypeKind::Interface: + sb.Append(prefix).AppendFormat("%s = %s.asInterface(%s.readRemoteObject());\n", name.c_str(), + StubName(EmitType(mt)).string(), parcelName.string()); + break; + case TypeKind::List: { + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + EmitReadVariable(parcelName, "value", innerType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.add(value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Map: { + sb.Append(prefix).AppendFormat("int %sSize = %s.readInt();\n", name.c_str(), parcelName.string()); + sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str()); + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + EmitReadVariable(parcelName, "key", keyType, ATTR_IN, sb, prefix + TAB); + EmitReadVariable(parcelName, "value", valueType, ATTR_IN, sb, prefix + TAB); + sb.Append(prefix + TAB).AppendFormat("%s.put(key, value);\n", name.c_str()); + sb.Append(prefix).Append("}\n"); + break; + } + case TypeKind::Array: { + EmitReadOutArrayVariable(parcelName, name, mt, sb, prefix); + break; + } + default: + break; + } +} + +void JsCodeEmitter::EmitLocalVariable( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix) +{ + MetaType* mt = metaComponent_->types_[mp->typeIndex_]; + std::string name = UnderlineAdded(mp->name_); + if (mt->kind_ == TypeKind::Sequenceable) { + sb.Append(prefix).AppendFormat("let %s = new %s();\n", name.c_str(), EmitType(mt).string()); + } else if (mt->kind_ == TypeKind::List) { + sb.Append(prefix).AppendFormat("let %s = new Array%s();\n", name.c_str(), EmitType(mt).string()); + } else if (mt->kind_ == TypeKind::Map) { + sb.Append(prefix).AppendFormat("let %s = new Hash%s();\n", name.c_str(), EmitType(mt).string()); + } else { + sb.Append(prefix).AppendFormat("let %s;\n", name.c_str()); + } +} + +String JsCodeEmitter::EmitType( + /* [in] */ MetaType* mt) +{ + switch(mt->kind_) { + case TypeKind::Char: + return "char"; + case TypeKind::Boolean: + return "boolean"; + case TypeKind::Byte: + return "byte"; + case TypeKind::Short: + return "short"; + case TypeKind::Integer: + return "int"; + case TypeKind::Long: + return "long"; + case TypeKind::Float: + return "float"; + case TypeKind::Double: + return "double"; + case TypeKind::String: + return "String"; + case TypeKind::Void: + return "void"; + case TypeKind::Sequenceable: { + MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_]; + return mp->name_; + } + case TypeKind::Interface: { + MetaInterface* mi = metaComponent_->interfaces_[mt->index_]; + return mi->name_; + } + case TypeKind::List: { + MetaType* elementType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + return String::Format("List<%s>", EmitType(elementType).string()); + } + case TypeKind::Map: { + MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + return String::Format("Map<%s, %s>", EmitType(keyType).string(), EmitType(valueType).string()); + } + case TypeKind::Array: { + MetaType* elementType = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + return String::Format("%s[]", EmitType(elementType).string()); + } + default: + return "unknown type"; + } +} + +String JsCodeEmitter::FileName( + /* [in] */ const String& name) +{ + if (name.IsEmpty()) { + return name; + } + + return name.Replace('.', '/'); +} + +String JsCodeEmitter::MethodName( + /* [in] */ const String& name) +{ + if (name.IsEmpty() || islower(name[0])) { + return name; + } + return String::Format("%c%s", tolower(name[0]), name.Substring(1).string()); +} + +String JsCodeEmitter::ConstantName( + /* [in] */ 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 JsCodeEmitter::StubName( + /* [in] */ const String& name) +{ + return name.StartsWith("I") ? (name.Substring(1) + "Stub") : (name + "Stub"); +} + +const std::string JsCodeEmitter::UnderlineAdded(const String& originName) +{ + std::string underline("_"); + return underline + std::string(originName.string()); +} + +} +} diff --git a/zidl/codegen/js_code_emitter.h b/zidl/codegen/js_code_emitter.h new file mode 100644 index 0000000000000000000000000000000000000000..ad822f914480055d9a3407f90c482d82dbc6093d --- /dev/null +++ b/zidl/codegen/js_code_emitter.h @@ -0,0 +1,236 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_JSCODEEMITTER_H +#define OHOS_ZIDL_JSCODEEMITTER_H + +#include + +#include "codegen/code_emitter.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +class JsCodeEmitter : public CodeEmitter { +public: + JsCodeEmitter( + /* [in] */ MetaComponent* mc) + : CodeEmitter(mc) + {} + + void EmitInterface() override; + + void EmitInterfaceProxy() override; + + void EmitInterfaceStub() override; + +private: + void EmitInterfaceImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceCorelibImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceDBinderImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceSelfDefinedTypeImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceDefinition( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceMethods( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethod( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyCorelibImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxySelfDefinedTypeImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyDBinderImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyParametersImports( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyImpl( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceProxyConstants( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyConstructor( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceProxyMethodBody( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitWriteMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadMethodParameter( + /* [in] */ MetaParameter* mp, + /* [in] */ const String& parcelName, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubImpl( + /* [in] */ StringBuilder& sb); + + void EmitInterfaceStubConstants(/* [in] */ StringBuilder& sb); + + void EmitJsCallBack(/* [in] */ StringBuilder& sb); + + void EmitInterfaceStubConstructor( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubMethodImpls( + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceStubMethodImpl( + /* [in] */ MetaMethod* mm, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitInterfaceMethodCommands(/* [in] */ StringBuilder& sb); + + void EmitLicense( + /* [in] */ StringBuilder& sb); + + void EmitPackage( + /* [in] */ StringBuilder& sb); + + void EmitWriteVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& returnName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadOutVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ unsigned int attributes, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitWriteArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitWriteOutArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitReadOutArrayVariable( + /* [in] */ const String& parcelName, + /* [in] */ const std::string& name, + /* [in] */ MetaType* mt, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + void EmitLocalVariable( + /* [in] */ MetaParameter* mp, + /* [in] */ StringBuilder& sb, + /* [in] */ const String& prefix); + + String EmitType( + /* [in] */ MetaType* mt); + + String FileName( + /* [in] */ const String& name); + + String MethodName( + /* [in] */ const String& name); + + String ConstantName( + /* [in] */ const String& name); + + String StubName( + /* [in] */ const String& name); + + const std::string UnderlineAdded(const String& name); +}; + +} +} + +#endif // OHOS_ZIDL_JSCODEEMITTER_H diff --git a/zidl/main.cpp b/zidl/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0e314a6ce97dfe742118f15f68a1b9e2fda22c7 --- /dev/null +++ b/zidl/main.cpp @@ -0,0 +1,106 @@ +/* + * 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 "codegen/code_generator.h" +#include "metadata/metadata_builder.h" +#include "metadata/metadata_dumper.h" +#include "metadata/metadata_reader.h" +#include "metadata/metadata_serializer.h" +#include "parser/parser.h" +#include "util/logger.h" +#include "util/options.h" + +using namespace OHOS::Zidl; + +static const char* TAG = "zidl"; + +int main(int argc, char** argv) +{ + Options options(argc, argv); + + if (options.DoShowUsage()) { + options.ShowUsage(); + return 0; + } + + if (options.DoShowVersion()) { + options.ShowVersion(); + return 0; + } + + if (options.HasErrors()) { + options.ShowErrors(); + return 0; + } + + std::shared_ptr metadata; + + if (options.DoCompile()) { + Parser parser(options); + if (!parser.Parse(options.GetSourceFile())) { + Logger::E(TAG, "Parsing .zidl failed."); + return -1; + } + + MetadataBuilder builder(parser.GetModule()); + metadata = builder.Build(); + if (metadata == nullptr) { + Logger::E(TAG, "Generate metadata failed."); + return -1; + } + } + + if (options.DoDumpMetadata()) { + MetadataDumper dumper(metadata.get()); + dumper.Dump(""); + } + + if (options.DoSaveMetadata()) { + File metadataFile(options.GetMetadataFile(), File::WRITE); + if (!metadataFile.IsValid()) { + Logger::E(TAG, "Create metadata file failed."); + return -1; + } + + MetadataSerializer serializer(metadata.get()); + serializer.Serialize(); + uintptr_t data = serializer.GetData(); + int size = serializer.GetDataSize(); + + metadataFile.WriteData(reinterpret_cast(data), size); + metadataFile.Flush(); + metadataFile.Close(); + } + + if (options.DoGenerateCode()) { + if (metadata == nullptr) { + String metadataFile = options.GetMetadataFile(); + metadata = MetadataReader::ReadMetadataFromFile(metadataFile); + if (metadata == nullptr) { + Logger::E(TAG, "Get metadata from \"%s\" failed.", metadataFile.string()); + return -1; + } + } + + CodeGenerator codeGen(metadata.get(), options.GetTargetLanguage(), + options.GetGenerationDirectory()); + if (!codeGen.Generate()) { + Logger::E(TAG, "Generate \"%s\" codes failed.", options.GetTargetLanguage().string()); + return -1; + } + } + + return 0; +} diff --git a/zidl/metadata/CMakeLists.txt b/zidl/metadata/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..448c9d75914255be67760d91226adc3223630355 --- /dev/null +++ b/zidl/metadata/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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_directories( + ${ZIDL_DIR}) + +set(SOURCES + metadata_builder.cpp + metadata_dumper.cpp + metadata_reader.cpp + metadata_serializer.cpp) + +add_library(metadata STATIC + ${SOURCES}) \ No newline at end of file diff --git a/zidl/metadata/metadata.h b/zidl/metadata/metadata.h new file mode 100644 index 0000000000000000000000000000000000000000..0b405f06e4ceacdbe459f4d9c4270e484c106354 --- /dev/null +++ b/zidl/metadata/metadata.h @@ -0,0 +1,124 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_METADATA_H +#define OHOS_ZIDL_METADATA_H + +namespace OHOS { +namespace Zidl { + +static constexpr int METADATA_MAGIC_NUMBER = 0x1DF02ED1; + +enum class TypeKind { + Unknown = 0, + Char = 1, + Boolean = 2, + Byte = 3, + Short = 4, + Integer = 5, + Long = 6, + Float = 7, + Double = 8, + String = 9, + Void = 10, + Sequenceable = 11, + Interface = 12, + List = 13, + Map = 14, + Array = 15, +}; + +struct MetaNamespace; +struct MetaSequenceable; +struct MetaInterface; +struct MetaMethod; +struct MetaParameter; +struct MetaType; + +struct MetaComponent { + int magic_; + int size_; + char* name_; + int namespaceNumber_; + int sequenceableNumber_; + int interfaceNumber_; + int typeNumber_; + MetaNamespace** namespaces_; + MetaSequenceable** sequenceables_; + MetaInterface** interfaces_; + MetaType** types_; + int stringPoolSize_; + char* stringPool_; +}; + +struct MetaNamespace { + char* name_; + int sequenceableNumber_; + int interfaceNumber_; + int namespaceNumber_; + int* sequenceableIndexes_; + int* interfaceIndexes_; + MetaNamespace** namespaces_; +}; + +struct MetaSequenceable { + char* name_; + char* namespace_; +}; + +static constexpr unsigned int INTERFACE_PROPERTY_ONEWAY = 0x1; + +struct MetaInterface { + char* license_; + char* name_; + char* namespace_; + unsigned int properties_; + int methodNumber_; + MetaMethod** methods_; + bool external_; +}; + +static constexpr unsigned int METHOD_PROPERTY_ONEWAY = 0x1; + +struct MetaMethod { + char* name_; + char* signature_; + unsigned int properties_; + int returnTypeIndex_; + int parameterNumber_; + MetaParameter** parameters_; +}; + +static constexpr unsigned int ATTR_IN = 0x1; +static constexpr unsigned int ATTR_OUT = 0x2; +static constexpr unsigned int ATTR_MASK = 0x3; + +struct MetaParameter { + char* name_; + unsigned int attributes_; + int typeIndex_; +}; + +struct MetaType { + TypeKind kind_; + int index_; + int nestedTypeNumber_; + int* nestedTypeIndexes_; +}; + +} +} + +#endif // OHOS_ZIDL_METADATA_H diff --git a/zidl/metadata/metadata_builder.cpp b/zidl/metadata/metadata_builder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ba08529d4f30a1b0fff1b74dd5fbf4244369a11 --- /dev/null +++ b/zidl/metadata/metadata_builder.cpp @@ -0,0 +1,502 @@ +/* + * 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 "metadata/metadata_builder.h" +#include +#include "securec.h" +#include "ast/ast_array_type.h" +#include "ast/ast_list_type.h" +#include "ast/ast_map_type.h" +#include "util/logger.h" + +#define ALIGN8(v) (((v) + 7) & ~7) + +namespace OHOS { +namespace Zidl { + +const char* MetadataBuilder::TAG = "MetadataBuilder"; + +std::shared_ptr MetadataBuilder::Build() +{ + if (!module_->IsValid()) { + Logger::E(TAG, "The module is not validate."); + return nullptr; + } + + size_ = CalculateMetadataSize(); + void* metadata = calloc(size_, 1); + if (metadata == nullptr) { + Logger::E(TAG, "Out of memory."); + return nullptr; + } + + metaComponent_.reset( + new(metadata) MetaComponent, + [](MetaComponent* p){ free(p); }); + + WriteMetadata(reinterpret_cast(metadata)); + + return metaComponent_; +} + +size_t MetadataBuilder::CalculateMetadataSize() +{ + baseAddr_ = 0; + CalculateMetaComponent(module_); + return baseAddr_; +} + +void MetadataBuilder::CalculateMetaComponent( + /* [in] */ ASTModule* module) +{ + int namespaceNumber = module->GetNamespaceNumber(); + int sequenceableNumber = module->GetSequenceableNumber(); + int interfaceNumber = module->GetInterfaceNumber(); + int typeNumber = module->GetTypeNumber(); + + // begin address + baseAddr_ = ALIGN8(baseAddr_); + stringPool_.Add(module_->GetName()); + // namespaces_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaComponent)); + // sequenceables_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaNamespace*) * namespaceNumber); + // interfaces_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaSequenceable*) * sequenceableNumber); + // types_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaInterface*) * interfaceNumber); + // stringPool_'s address + baseAddr_ = baseAddr_ + sizeof(MetaType*) * typeNumber; + + for (int i = 0; i < namespaceNumber; i++) { + CalculateMetaNamespace(module->GetNamespace(i)); + } + + for (int i = 0; i < sequenceableNumber; i++) { + CalculateMetaSequenceable(module->GetSequenceable(i)); + } + + for (int i = 0; i < interfaceNumber; i++) { + CalculateMetaInterface(module->GetInterface(i)); + } + + const ASTModule::TypeStringMap& types = module_->GetTypes(); + for (const auto& pair : types) { + CalculateMetaType(pair.second); + } + + // end address + CalculateStringPool(); +} + +void MetadataBuilder::CalculateMetaNamespace( + /* [in] */ ASTNamespace* nspace) +{ + int sequenceableNumber = nspace->GetSequenceableNumber(); + int interfaceNumber = nspace->GetInterfaceNumber(); + int namespaceNumber = nspace->GetNamespaceNumber(); + + // begin address + baseAddr_ = ALIGN8(baseAddr_); + stringPool_.Add(nspace->GetName()); + // sequenceables_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaNamespace)); + // interfaces_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(int) * sequenceableNumber); + // namespaces_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(int) * interfaceNumber); + // end address + baseAddr_ = baseAddr_ + sizeof(MetaNamespace*) * namespaceNumber; + + for (int i = 0; i < namespaceNumber; i++) { + CalculateMetaNamespace(nspace->GetNamespace(i)); + } +} + +void MetadataBuilder::CalculateMetaSequenceable( + /* [in] */ ASTSequenceableType* sequenceable) +{ + // begin address + baseAddr_ = ALIGN8(baseAddr_); + stringPool_.Add(sequenceable->GetName()); + stringPool_.Add(sequenceable->GetNamespace()->ToString()); + // end address + baseAddr_ = baseAddr_ + sizeof(MetaSequenceable); +} + +void MetadataBuilder::CalculateMetaInterface( + /* [in] */ ASTInterfaceType* interface) +{ + int methodNumber = interface->GetMethodNumber(); + + // begin address + baseAddr_ = ALIGN8(baseAddr_); + stringPool_.Add(interface->GetLicense()); + stringPool_.Add(interface->GetName()); + stringPool_.Add(interface->GetNamespace()->ToString()); + // methods_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaInterface)); + // end address + baseAddr_ = baseAddr_ + sizeof(MetaMethod*) * methodNumber; + + for (int i = 0; i < methodNumber; i++) { + CalculateMetaMethod(interface->GetMethod(i)); + } +} + +void MetadataBuilder::CalculateMetaMethod( + /* [in] */ ASTMethod* method) +{ + int parameterNumber = method->GetParameterNumber(); + + // begin address + baseAddr_ = ALIGN8(baseAddr_); + stringPool_.Add(method->GetName()); + stringPool_.Add(method->GetSignature()); + // parameters_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaMethod)); + // end address + baseAddr_ = baseAddr_ + sizeof(MetaParameter*) * parameterNumber; + + for (int i = 0; i < parameterNumber; i++) { + CalculateMetaParameter(method->GetParameter(i)); + } +} + +void MetadataBuilder::CalculateMetaParameter( + /* [in] */ ASTParameter* parameter) +{ + // begin address + baseAddr_ = ALIGN8(baseAddr_); + stringPool_.Add(parameter->GetName()); + // end address + baseAddr_ = baseAddr_ + sizeof(MetaParameter); +} + +void MetadataBuilder::CalculateMetaType( + /* [in] */ ASTType* type) +{ + // begin address + baseAddr_ = ALIGN8(baseAddr_); + // nestedTypeIndexes_'s address + baseAddr_ = baseAddr_ + sizeof(MetaType); + if (type->IsListType()) { + baseAddr_ = ALIGN8(baseAddr_); + // end address + baseAddr_ = baseAddr_ + sizeof(int*); + } else if (type->IsMapType()) { + // end address + baseAddr_ = baseAddr_ + sizeof(int*) * 2; + } +} + +void MetadataBuilder::CalculateStringPool() +{ + // begin address + baseAddr_ = ALIGN8(baseAddr_); + // end address + baseAddr_ = baseAddr_ + stringPool_.GetSize(); +} + +void MetadataBuilder::WriteMetadata( + /* [in] */ uintptr_t base) +{ + baseAddr_ = base; + WriteMetaComponent(module_); +} + +void MetadataBuilder::WriteMetaComponent( + /* [in] */ ASTModule* module) +{ + int namespaceNumber = module->GetNamespaceNumber(); + int sequenceableNumber = module->GetSequenceableNumber(); + int interfaceNumber = module->GetInterfaceNumber(); + int typeNumber = module->GetTypeNumber(); + + // begin address + baseAddr_ = ALIGN8(baseAddr_); + MetaComponent* mc = reinterpret_cast(baseAddr_); + mc->magic_ = METADATA_MAGIC_NUMBER; + mc->size_ = size_; + mc->namespaceNumber_ = namespaceNumber; + mc->sequenceableNumber_ = sequenceableNumber; + mc->interfaceNumber_ = interfaceNumber; + mc->typeNumber_ = typeNumber; + mc->stringPoolSize_ = stringPool_.GetSize(); + // namespaces_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaComponent)); + mc->namespaces_ = reinterpret_cast(baseAddr_); + // sequenceables_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaNamespace*) * namespaceNumber); + mc->sequenceables_ = reinterpret_cast(baseAddr_); + // interfaces_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaSequenceable*) * sequenceableNumber); + mc->interfaces_ = reinterpret_cast(baseAddr_); + // types_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaInterface*) * interfaceNumber); + mc->types_ = reinterpret_cast(baseAddr_); + // stringPool_'s address + baseAddr_ = baseAddr_ + sizeof(MetaType*) * typeNumber; + mc->stringPool_ = reinterpret_cast(baseAddr_); + // end address + baseAddr_ = baseAddr_ + stringPool_.GetSize(); + (void)memcpy_s(mc->stringPool_, stringPool_.GetSize(), stringPool_.GetData(), stringPool_.GetSize()); + + mc->name_ = WriteString(module->GetName()); + + for (int i = 0; i < namespaceNumber; i++) { + mc->namespaces_[i] = WriteMetaNamespace(module->GetNamespace(i)); + } + + for (int i = 0; i < sequenceableNumber; i++) { + mc->sequenceables_[i] = WriteMetaSequenceable(module->GetSequenceable(i)); + } + + for (int i = 0; i < interfaceNumber; i++) { + mc->interfaces_[i] = WriteMetaInterface(module->GetInterface(i)); + } + + const ASTModule::TypeStringMap& types = module->GetTypes(); + int i = 0; + for (const auto& pair : types) { + mc->types_[i++] = WriteMetaType(pair.second); + } +} + +MetaNamespace* MetadataBuilder::WriteMetaNamespace( + /* [in] */ ASTNamespace* nspace) +{ + int sequenceableNumber = nspace->GetSequenceableNumber(); + int interfaceNumber = nspace->GetInterfaceNumber(); + int namespaceNumber = nspace->GetNamespaceNumber(); + + // begin address + baseAddr_ = ALIGN8(baseAddr_); + MetaNamespace* mn = reinterpret_cast(baseAddr_); + mn->name_ = WriteString(nspace->GetName()); + mn->sequenceableNumber_ = sequenceableNumber; + mn->interfaceNumber_ = interfaceNumber; + mn->namespaceNumber_ = namespaceNumber; + // sequenceables_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaNamespace)); + mn->sequenceableIndexes_ = reinterpret_cast(baseAddr_); + // interfaces_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(int) * sequenceableNumber); + mn->interfaceIndexes_ = reinterpret_cast(baseAddr_); + // namespaces_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(int) * interfaceNumber); + mn->namespaces_ = reinterpret_cast(baseAddr_); + // end address + baseAddr_ = baseAddr_ + sizeof(MetaNamespace*) * namespaceNumber; + + for (int i = 0; i < sequenceableNumber; i++) { + AutoPtr sequenceable = nspace->GetSequenceable(i); + mn->sequenceableIndexes_[i] = module_->IndexOf(sequenceable); + } + + for (int i = 0; i < interfaceNumber; i++) { + AutoPtr interface = nspace->GetInterface(i); + mn->interfaceIndexes_[i] = module_->IndexOf(interface); + } + + for (int i = 0; i < namespaceNumber; i++) { + AutoPtr inner = nspace->GetNamespace(i); + mn->namespaces_[i] = WriteMetaNamespace(inner); + } + + return mn; +} + +MetaSequenceable* MetadataBuilder::WriteMetaSequenceable( + /* [in] */ ASTSequenceableType* parcelabe) +{ + // begin address + baseAddr_ = ALIGN8(baseAddr_); + MetaSequenceable* mp = reinterpret_cast(baseAddr_); + mp->name_ = WriteString(parcelabe->GetName()); + mp->namespace_ = WriteString(parcelabe->GetNamespace()->ToString()); + // end address + baseAddr_ = baseAddr_ + sizeof(MetaSequenceable); + + return mp; +} + +MetaInterface* MetadataBuilder::WriteMetaInterface( + /* [in] */ ASTInterfaceType* interface) +{ + int methodNumber = interface->GetMethodNumber(); + + // begin address + baseAddr_ = ALIGN8(baseAddr_); + MetaInterface* mi = reinterpret_cast(baseAddr_); + mi->license_ = WriteString(interface->GetLicense()); + mi->name_ = WriteString(interface->GetName()); + mi->namespace_ = WriteString(interface->GetNamespace()->ToString()); + mi->properties_ = interface->IsOneway() ? INTERFACE_PROPERTY_ONEWAY : 0; + mi->methodNumber_ = methodNumber; + mi->external_ = interface->IsExternal(); + // methods_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaInterface)); + mi->methods_ = reinterpret_cast(baseAddr_); + // end address + baseAddr_ = baseAddr_ + sizeof(MetaMethod*) * methodNumber; + + for (int i = 0; i < methodNumber; i++) { + mi->methods_[i] = WriteMetaMethod(interface->GetMethod(i)); + } + + return mi; +} + +MetaMethod* MetadataBuilder::WriteMetaMethod( + /* [in] */ ASTMethod* method) +{ + int parameterNumber = method->GetParameterNumber(); + + // begin address + baseAddr_ = ALIGN8(baseAddr_); + MetaMethod* mm = reinterpret_cast(baseAddr_); + mm->name_ = WriteString(method->GetName()); + mm->signature_ = WriteString(method->GetSignature()); + mm->properties_ = method->IsOneway() ? METHOD_PROPERTY_ONEWAY : 0; + mm->returnTypeIndex_ = module_->IndexOf(method->GetReturnType()); + mm->parameterNumber_ = parameterNumber; + // parameters_'s address + baseAddr_ = ALIGN8(baseAddr_ + sizeof(MetaMethod)); + mm->parameters_ = reinterpret_cast(baseAddr_); + // end address + baseAddr_ = baseAddr_ + sizeof(MetaParameter*) * parameterNumber; + + for (int i = 0; i < parameterNumber; i++) { + mm->parameters_[i] = WriteMetaParameter(method->GetParameter(i)); + } + + return mm; +} + +MetaParameter* MetadataBuilder::WriteMetaParameter( + /* [in] */ ASTParameter* parameter) +{ + // begin address + baseAddr_ = ALIGN8(baseAddr_); + MetaParameter* mp = reinterpret_cast(baseAddr_); + mp->name_ = WriteString(parameter->GetName()); + if (parameter->IsInParameter()) { + mp->attributes_ |= ATTR_IN; + } + if (parameter->IsOutParameter()) { + mp->attributes_ |= ATTR_OUT; + } + mp->typeIndex_ = module_->IndexOf(parameter->GetType()); + // end address + baseAddr_ = baseAddr_ + sizeof(MetaParameter); + + return mp; +} + +MetaType* MetadataBuilder::WriteMetaType( + /* [in] */ ASTType* type) +{ + // begin address + baseAddr_ = ALIGN8(baseAddr_); + MetaType* mt = reinterpret_cast(baseAddr_); + mt->kind_ = Type2Kind(type); + if (type->IsSequenceableType()) { + mt->index_ = module_->IndexOf(static_cast(type)); + } else if (type->IsInterfaceType()) { + mt->index_ = module_->IndexOf(static_cast(type)); + } else { + mt->index_ = module_->IndexOf(type); + } + baseAddr_ = baseAddr_ + sizeof(MetaType); + if (type->IsListType()) { + mt->nestedTypeNumber_ = 1; + // nestedTypeIndexes_'s address + baseAddr_ = ALIGN8(baseAddr_); + mt->nestedTypeIndexes_ = reinterpret_cast(baseAddr_); + AutoPtr elementType = (static_cast(type))->GetElementType(); + mt->nestedTypeIndexes_[0] = module_->IndexOf(elementType); + // end address + baseAddr_ = baseAddr_ + sizeof(int*); + } else if (type->IsMapType()) { + mt->nestedTypeNumber_ = 2; + // nestedTypeIndexes_'s address + baseAddr_ = ALIGN8(baseAddr_); + mt->nestedTypeIndexes_ = reinterpret_cast(baseAddr_); + AutoPtr keyType = (static_cast(type))->GetKeyType(); + AutoPtr valueType = (static_cast(type))->GetValueType(); + mt->nestedTypeIndexes_[0] = module_->IndexOf(keyType); + mt->nestedTypeIndexes_[1] = module_->IndexOf(valueType); + // end address + baseAddr_ = baseAddr_ + sizeof(int*) * 2; + } else if (type->IsArrayType()) { + mt->nestedTypeNumber_ = 1; + // nestedTypeIndexes_'s address + baseAddr_ = ALIGN8(baseAddr_); + mt->nestedTypeIndexes_ = reinterpret_cast(baseAddr_); + AutoPtr elementType = (static_cast(type))->GetElementType(); + mt->nestedTypeIndexes_[0] = module_->IndexOf(elementType); + // end address + baseAddr_ = baseAddr_ + sizeof(int*); + } + + return mt; +} + +char* MetadataBuilder::WriteString( + /* [in] */ const String& string) +{ + return string.IsNull() ? nullptr : metaComponent_->stringPool_ + stringPool_.GetOffset(string); +} + +TypeKind MetadataBuilder::Type2Kind( + /* [in] */ ASTType* type) +{ + if (type->IsCharType()) { + return TypeKind::Char; + } else if (type->IsBooleanType()) { + return TypeKind::Boolean; + } else if (type->IsByteType()) { + return TypeKind::Byte; + } else if (type->IsShortType()) { + return TypeKind::Short; + } else if (type->IsIntegerType()) { + return TypeKind::Integer; + } else if (type->IsLongType()) { + return TypeKind::Long; + } else if (type->IsFloatType()) { + return TypeKind::Float; + } else if (type->IsDoubleType()) { + return TypeKind::Double; + } else if (type->IsStringType()) { + return TypeKind::String; + } else if (type->IsVoidType()) { + return TypeKind::Void; + } else if (type->IsSequenceableType()) { + return TypeKind::Sequenceable; + } else if (type->IsInterfaceType()) { + return TypeKind::Interface; + } else if (type->IsListType()) { + return TypeKind::List; + } else if (type->IsMapType()) { + return TypeKind::Map; + } else if (type->IsArrayType()) { + return TypeKind::Array; + } + return TypeKind::Unknown; +} + +} +} diff --git a/zidl/metadata/metadata_builder.h b/zidl/metadata/metadata_builder.h new file mode 100644 index 0000000000000000000000000000000000000000..1d0801fbef6884f4ce6a715796ed78562fba1917 --- /dev/null +++ b/zidl/metadata/metadata_builder.h @@ -0,0 +1,107 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_METADATABUILDER_H +#define OHOS_ZIDL_METADATABUILDER_H + +#include +#include "ast/ast_module.h" +#include "metadata/metadata.h" +#include "util/autoptr.h" +#include "util/string.h" +#include "util/string_pool.h" + +namespace OHOS { +namespace Zidl { + +class MetadataBuilder { +public: + explicit MetadataBuilder( + /* [in] */ ASTModule* module) + : module_(module) + {} + + ~MetadataBuilder() = default; + + std::shared_ptr Build(); + +private: + size_t CalculateMetadataSize(); + + void CalculateMetaComponent( + /* [in] */ ASTModule* module); + + void CalculateMetaNamespace( + /* [in] */ ASTNamespace* nspace); + + void CalculateMetaSequenceable( + /* [in] */ ASTSequenceableType* sequenceable); + + void CalculateMetaInterface( + /* [in] */ ASTInterfaceType* interface); + + void CalculateMetaMethod( + /* [in] */ ASTMethod* method); + + void CalculateMetaParameter( + /* [in] */ ASTParameter* parameter); + + void CalculateMetaType( + /* [in] */ ASTType* type); + + void CalculateStringPool(); + + void WriteMetadata( + /* [in] */ uintptr_t base); + + void WriteMetaComponent( + /* [in] */ ASTModule* module); + + MetaNamespace* WriteMetaNamespace( + /* [in] */ ASTNamespace* nspace); + + MetaSequenceable* WriteMetaSequenceable( + /* [in] */ ASTSequenceableType* parcelabe); + + MetaInterface* WriteMetaInterface( + /* [in] */ ASTInterfaceType* interface); + + MetaMethod* WriteMetaMethod( + /* [in] */ ASTMethod* method); + + MetaParameter* WriteMetaParameter( + /* [in] */ ASTParameter* parameter); + + MetaType* WriteMetaType( + /* [in] */ ASTType* type); + + char* WriteString( + /* [in] */ const String& string); + + TypeKind Type2Kind( + /* [in] */ ASTType* type); + + static const char* TAG; + AutoPtr module_; + std::shared_ptr metaComponent_; + uintptr_t baseAddr_ = 0; + size_t size_ = 0; + StringPool stringPool_; +}; + +} +} + +#endif // OHOS_ZIDL_METADATABUILDER_H diff --git a/zidl/metadata/metadata_dumper.cpp b/zidl/metadata/metadata_dumper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cba7aec6990e9415d7e9f4c0bf16d8227078e557 --- /dev/null +++ b/zidl/metadata/metadata_dumper.cpp @@ -0,0 +1,299 @@ +/* + * 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 "metadata/metadata_dumper.h" +#include +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +const char* MetadataDumper::TAB = " "; + +void MetadataDumper::Dump( + /* [in] */ const String& prefix) +{ + if (metaComponent_ == nullptr) { + return; + } + + String dumpStr = DumpMetaComponent(metaComponent_, prefix); + printf("%s\n", dumpStr.string()); +} + +String MetadataDumper::DumpMetaComponent( + /* [in] */ MetaComponent* mc, + /* [in] */ const String& prefix) +{ + StringBuilder sb; + + sb.Append(prefix).Append("MetaComponent\n"); + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("\"magic_\" : \"0x%x\",\n", mc->magic_); + sb.Append(prefix + TAB).AppendFormat("\"size_\" : \"%d\",\n", mc->size_); + sb.Append(prefix + TAB).AppendFormat("\"name_\" : \"%s\",\n", mc->name_); + sb.Append(prefix + TAB).AppendFormat("\"namespaceNumber_\" : \"%d\",\n", mc->namespaceNumber_); + sb.Append(prefix + TAB).AppendFormat("\"sequenceableNumber_\" : \"%d\",\n", mc->sequenceableNumber_); + sb.Append(prefix + TAB).AppendFormat("\"interfaceNumber_\" : \"%d\",\n", mc->interfaceNumber_); + sb.Append(prefix + TAB).AppendFormat("\"typeNumber_\" : \"%d\",\n", mc->typeNumber_); + + if (mc->namespaceNumber_ == 0) { + sb.Append(prefix + TAB).Append("\"namespaces_\" : [],\n"); + } else { + sb.Append(prefix + TAB).Append("\"namespaces_\" : [\n"); + for (int i = 0; i < mc->namespaceNumber_; i++) { + DumpMetaNamespace(sb, mc->namespaces_[i], prefix + TAB + TAB); + if (i != mc->namespaceNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append("\n" + prefix + TAB).Append("],\n"); + } + + if (mc->sequenceableNumber_ == 0) { + sb.Append(prefix + TAB).Append("\"sequenceables_\" : [],\n"); + } else { + sb.Append(prefix + TAB).Append("\"sequenceables_\" : [\n"); + for (int i = 0; i < mc->sequenceableNumber_; i++) { + DumpMetaSequenceable(sb, mc->sequenceables_[i], prefix + TAB + TAB); + if (i != mc->sequenceableNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append("\n" + prefix + TAB).Append("],\n"); + } + + if (mc->interfaceNumber_ == 0) { + sb.Append(prefix + TAB).Append("\"interfaces_\" : [],\n"); + } else { + sb.Append(prefix + TAB).Append("\"interfaces_\" : [\n"); + for (int i = 0; i < mc->interfaceNumber_; i++) { + DumpMetaInterface(sb, mc->interfaces_[i], prefix + TAB + TAB); + if (i != mc->interfaceNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append("\n" + prefix + TAB).Append("],\n"); + } + + sb.Append(prefix + TAB).AppendFormat("\"stringPoolSize_\" : \"%d\"\n", mc->stringPoolSize_); + + sb.Append(prefix).Append("}\n"); + + return sb.ToString(); +} + +void MetadataDumper::DumpMetaNamespace( + /* [in] */ StringBuilder& sb, + /* [in] */ MetaNamespace* mn, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("\"name_\" : \"%s\",\n", mn->name_); + sb.Append(prefix + TAB).AppendFormat("\"sequenceableNumber_\" : \"%d\",\n", mn->sequenceableNumber_); + sb.Append(prefix + TAB).AppendFormat("\"interfaceNumber_\" : \"%d\",\n", mn->interfaceNumber_); + sb.Append(prefix + TAB).AppendFormat("\"namespaceNumber_\" : \"%d\",\n", mn->namespaceNumber_); + + if (mn->sequenceableNumber_ == 0) { + sb.Append(prefix + TAB).Append("\"sequenceableIndexes_\" : [],\n"); + } else { + sb.Append(prefix + TAB).Append("\"sequenceableIndexes_\" : [\n"); + for (int i = 0; i < mn->sequenceableNumber_; i++) { + MetaSequenceable* mp = metaComponent_->sequenceables_[mn->sequenceableIndexes_[i]]; + sb.Append(prefix + TAB + TAB).AppendFormat("{ \"name\" : \"%s\" }", mp->name_); + if (i != mn->sequenceableNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append("\n" + prefix + TAB).Append("],\n"); + } + + if (mn->interfaceNumber_ == 0) { + sb.Append(prefix + TAB).Append("\"interfaceIndexes_\" : [],\n"); + } else { + sb.Append(prefix + TAB).Append("\"interfaceIndexes_\" : [\n"); + for (int i = 0; i < mn->interfaceNumber_; i++) { + MetaInterface* mi = metaComponent_->interfaces_[mn->interfaceIndexes_[i]]; + sb.Append(prefix + TAB + TAB).AppendFormat("{ \"name\" : \"%s\" }", mi->name_); + if (i != mn->interfaceNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append("\n" + prefix + TAB).Append("],\n"); + } + + if (mn->namespaceNumber_ == 0) { + sb.Append(prefix + TAB).Append("\"namespaces_\" : []\n"); + } else { + sb.Append(prefix + TAB).Append("\"namespaces_\" : [\n"); + for (int i = 0; i < mn->namespaceNumber_; i++) { + MetaNamespace* innermn = mn->namespaces_[i]; + DumpMetaNamespace(sb, innermn, prefix + TAB + TAB); + if (i != mn->namespaceNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append("\n" + prefix + TAB).Append("]\n"); + } + + sb.Append(prefix).Append("}"); +} + +void MetadataDumper::DumpMetaSequenceable( + /* [in] */ StringBuilder& sb, + /* [in] */ MetaSequenceable* mp, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("\"name_\" : \"%s\",\n", mp->name_); + sb.Append(prefix + TAB).AppendFormat("\"namespace_\" : \"%s\"\n", mp->namespace_); + sb.Append(prefix).Append("}"); +} + +void MetadataDumper::DumpMetaInterface( + /* [in] */ StringBuilder& sb, + /* [in] */ MetaInterface* mi, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("\"name_\" : \"%s\",\n", mi->name_); + sb.Append(prefix + TAB).AppendFormat("\"namespace_\" : \"%s\",\n", mi->namespace_); + sb.Append(prefix + TAB).AppendFormat("\"properties_\" : \"%s\",\n", + (mi->properties_ & INTERFACE_PROPERTY_ONEWAY) != 0 ? "oneway" : ""); + sb.Append(prefix + TAB).AppendFormat("\"methodNumber_\" : \"%d\",\n", mi->methodNumber_); + sb.Append(prefix + TAB).AppendFormat("\"external_\" : \"%d\",\n", mi->external_); + + if (mi->methodNumber_ == 0) { + sb.Append(prefix + TAB).Append("\"methods_\" : []\n"); + } else { + sb.Append(prefix + TAB).Append("\"methods_\" : [\n"); + for (int i = 0; i < mi->methodNumber_; i++) { + DumpMetaMethod(sb, mi->methods_[i], prefix + TAB + TAB); + if (i != mi->methodNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append("\n" + prefix + TAB).Append("]\n"); + } + + sb.Append(prefix).Append("}"); +} + +void MetadataDumper::DumpMetaMethod( + /* [in] */ StringBuilder& sb, + /* [in] */ MetaMethod* mm, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("\"name_\" : \"%s\",\n", mm->name_); + sb.Append(prefix + TAB).AppendFormat("\"signature_\" : \"%s\",\n", mm->signature_); + sb.Append(prefix + TAB).AppendFormat("\"properties_\" : \"%s\",\n", + (mm->properties_ & METHOD_PROPERTY_ONEWAY) != 0 ? "oneway" : ""); + MetaType* type = metaComponent_->types_[mm->returnTypeIndex_]; + sb.Append(prefix + TAB).AppendFormat("\"returnType_\" : \"%s\",\n", DumpMetaType(type).string()); + sb.Append(prefix + TAB).AppendFormat("\"parameterNumber_\" : \"%d\",\n", mm->parameterNumber_); + + if (mm->parameterNumber_ == 0) { + sb.Append(prefix + TAB).Append("\"parameters_\" : []\n"); + } else { + sb.Append(prefix + TAB).Append("\"parameters_\" : [\n"); + for (int i = 0; i < mm->parameterNumber_; i++) { + DumpMetaParameter(sb, mm->parameters_[i], prefix + TAB + TAB); + if (i != mm->parameterNumber_ - 1) { + sb.Append(",\n"); + } + } + sb.Append("\n" + prefix + TAB).Append("]\n"); + } + + sb.Append(prefix).Append("}"); +} + +void MetadataDumper::DumpMetaParameter( + /* [in] */ StringBuilder& sb, + /* [in] */ MetaParameter* mp, + /* [in] */ const String& prefix) +{ + sb.Append(prefix).Append("{\n"); + sb.Append(prefix + TAB).AppendFormat("\"name_\" : \"%s\",\n", mp->name_); + sb.Append(prefix + TAB).Append("\"attributes_\" : \""); + bool addComma = false; + if ((mp->attributes_ & ATTR_IN) == ATTR_IN) { + sb.Append("in"); + addComma = true; + } + if ((mp->attributes_ & ATTR_OUT) == ATTR_OUT) { + sb.Append(addComma ? ", out" : "out"); + } + sb.Append("\",\n"); + MetaType* type = metaComponent_->types_[mp->typeIndex_]; + sb.Append(prefix + TAB).AppendFormat("\"type_\" : \"%s\"\n", DumpMetaType(type).string()); + + sb.Append(prefix).Append("}"); +} + +String MetadataDumper::DumpMetaType( + /* [in] */ MetaType* mt) +{ + switch (mt->kind_) { + case TypeKind::Char: + return "char"; + case TypeKind::Boolean: + return "boolean"; + case TypeKind::Byte: + return "byte"; + case TypeKind::Short: + return "short"; + case TypeKind::Integer: + return "int"; + case TypeKind::Long: + return "long"; + case TypeKind::Float: + return "float"; + case TypeKind::Double: + return "double"; + case TypeKind::String: + return "String"; + case TypeKind::Void: + return "void"; + case TypeKind::Sequenceable: { + MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_]; + return mp->name_; + } + case TypeKind::Interface: { + MetaInterface* mi = metaComponent_->interfaces_[mt->index_]; + return mi->name_; + } + case TypeKind::List: { + MetaType* elementMt = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + return "List<" + DumpMetaType(elementMt) + ">"; + } + case TypeKind::Map: { + MetaType* keyMt = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + MetaType* valueMt = metaComponent_->types_[mt->nestedTypeIndexes_[1]]; + return "Map<" + DumpMetaType(keyMt) + ", " + DumpMetaType(valueMt) + ">"; + } + case TypeKind::Array: { + MetaType* elementMt = metaComponent_->types_[mt->nestedTypeIndexes_[0]]; + return DumpMetaType(elementMt) + "[]"; + } + case TypeKind::Unknown: + default: + return "unknown"; + } +} + +} +} diff --git a/zidl/metadata/metadata_dumper.h b/zidl/metadata/metadata_dumper.h new file mode 100644 index 0000000000000000000000000000000000000000..ec30a2b65377fb888f0bd7b2084916e71b441c04 --- /dev/null +++ b/zidl/metadata/metadata_dumper.h @@ -0,0 +1,78 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_METADATADUMPER_H +#define OHOS_ZIDL_METADATADUMPER_H + +#include "metadata/metadata.h" +#include "util/string.h" +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +class MetadataDumper { +public: + explicit MetadataDumper( + /* [in] */ MetaComponent* mc) + : metaComponent_(mc) + {} + + ~MetadataDumper() = default; + + void Dump( + /* [in] */ const String& prefix); + +private: + String DumpMetaComponent( + /* [in] */ MetaComponent* mc, + /* [in] */ const String& prefix); + + void DumpMetaNamespace( + /* [in] */ StringBuilder& sb, + /* [in] */ MetaNamespace* mn, + /* [in] */ const String& prefix); + + void DumpMetaSequenceable( + /* [in] */ StringBuilder& sb, + /* [in] */ MetaSequenceable* mp, + /* [in] */ const String& prefix); + + void DumpMetaInterface( + /* [in] */ StringBuilder& sb, + /* [in] */ MetaInterface* mi, + /* [in] */ const String& prefix); + + void DumpMetaMethod( + /* [in] */ StringBuilder& sb, + /* [in] */ MetaMethod* mm, + /* [in] */ const String& prefix); + + void DumpMetaParameter( + /* [in] */ StringBuilder& sb, + /* [in] */ MetaParameter* mp, + /* [in] */ const String& prefix); + + String DumpMetaType( + /* [in] */ MetaType* mt); + + static const char* TAB; + MetaComponent* metaComponent_; +}; + +} +} + +#endif // OHOS_ZIDL_METADATADUMPER_H diff --git a/zidl/metadata/metadata_reader.cpp b/zidl/metadata/metadata_reader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fcd1250bae4fea02c5a49db308c33ac74b637493 --- /dev/null +++ b/zidl/metadata/metadata_reader.cpp @@ -0,0 +1,80 @@ +/* + * 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 "metadata/metadata_reader.h" +#include "metadata/metadata_serializer.h" +#include "util/file.h" +#include "util/logger.h" + +namespace OHOS { +namespace Zidl { + +const char* MetadataReader::TAG = "MetadataReader"; + +std::shared_ptr MetadataReader::ReadMetadataFromFile( + /* [in] */ const String& filePath) +{ + File file(filePath, File::READ); + if (!file.IsValid()) { + Logger::E(TAG, "Open \"%s\" file failed.", filePath.string()); + return nullptr; + } + + if (!file.Reset()) { + Logger::E(TAG, "Reset \"%s\" file failed.", filePath.string()); + return nullptr; + } + + MetaComponent header; + + if (!file.ReadData((void*)&header, sizeof(MetaComponent))) { + Logger::E(TAG, "Read \"%s\" file failed.", filePath.string()); + return nullptr; + } + + if (header.magic_ != METADATA_MAGIC_NUMBER || header.size_ < 0) { + Logger::E(TAG, "The metadata in \"%s\" file is bad.", filePath.string()); + return nullptr; + } + + if (!file.Reset()) { + Logger::E(TAG, "Reset \"%s\" file failed.", filePath.string()); + return nullptr; + } + + void* data = malloc(header.size_); + if (data == nullptr) { + Logger::E(TAG, "Malloc metadata failed."); + return nullptr; + } + + if (!file.ReadData(data, header.size_)) { + Logger::E(TAG, "Read \"%s\" file failed.", filePath.string()); + free(data); + return nullptr; + } + + std::shared_ptr metadata( + (MetaComponent*)data, + [](MetaComponent* p){ free(p); }); + + MetadataSerializer serializer((uintptr_t)data); + serializer.Deserialize(); + + return metadata; +} + +} +} diff --git a/zidl/metadata/metadata_reader.h b/zidl/metadata/metadata_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..1d7054b67d43278ac60449b80403112a80b8ea64 --- /dev/null +++ b/zidl/metadata/metadata_reader.h @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_METADATAREADER_H +#define OHOS_ZIDL_METADATAREADER_H + +#include +#include "metadata/metadata.h" +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class MetadataReader { +public: + static std::shared_ptr ReadMetadataFromFile( + /* [in] */ const String& filePath); + +private: + static const char* TAG; +}; + +} +} + +#endif // OHOS_ZIDL_METADATAREADER_H diff --git a/zidl/metadata/metadata_serializer.cpp b/zidl/metadata/metadata_serializer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ee9031e5b67f016d02f9068c560f978b1a522d0 --- /dev/null +++ b/zidl/metadata/metadata_serializer.cpp @@ -0,0 +1,242 @@ +/* + * 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 "metadata/metadata_serializer.h" + +namespace OHOS { +namespace Zidl { + +void MetadataSerializer::Serialize() +{ + SerializeMetaComponent(metaComponent_); +} + +void MetadataSerializer::SerializeMetaComponent( + /* [in] */ MetaComponent* mc) +{ + mc->name_ = reinterpret_cast(SerializeAdjust(mc->name_)); + + for (int i = 0; i < mc->namespaceNumber_; i++) { + MetaNamespace* mn = mc->namespaces_[i]; + SerializeMetaNamespace(mn); + mc->namespaces_[i] = reinterpret_cast(SerializeAdjust(mn)); + } + mc->namespaces_ = reinterpret_cast(SerializeAdjust(mc->namespaces_)); + + for (int i = 0; i < mc->sequenceableNumber_; i++) { + MetaSequenceable* mp = mc->sequenceables_[i]; + SerializeMetaSequenceable(mp); + mc->sequenceables_[i] = reinterpret_cast(SerializeAdjust(mp)); + } + mc->sequenceables_ = reinterpret_cast(SerializeAdjust(mc->sequenceables_)); + + for (int i = 0; i < mc->interfaceNumber_; i++) { + MetaInterface* mi = mc->interfaces_[i]; + SerializeMetaInterface(mi); + mc->interfaces_[i] = reinterpret_cast(SerializeAdjust(mi)); + } + mc->interfaces_ = reinterpret_cast(SerializeAdjust(mc->interfaces_)); + + for (int i = 0; i < mc->typeNumber_; i++) { + MetaType* mt = mc->types_[i]; + SerializeMetaType(mt); + mc->types_[i] = reinterpret_cast(SerializeAdjust(mt)); + } + mc->types_ = reinterpret_cast(SerializeAdjust(mc->types_)); + + mc->stringPool_ = reinterpret_cast(SerializeAdjust(mc->stringPool_)); +} + +void MetadataSerializer::SerializeMetaNamespace( + /* [in] */ MetaNamespace* mn) +{ + mn->name_ = reinterpret_cast(SerializeAdjust(mn->name_)); + mn->sequenceableIndexes_ = reinterpret_cast(SerializeAdjust(mn->sequenceableIndexes_)); + mn->interfaceIndexes_ = reinterpret_cast(SerializeAdjust(mn->interfaceIndexes_)); + + for (int i = 0; i < mn->namespaceNumber_; i++) { + MetaNamespace* innermn = mn->namespaces_[i]; + SerializeMetaNamespace(innermn); + mn->namespaces_[i] = reinterpret_cast(SerializeAdjust(innermn)); + } + mn->namespaces_ = reinterpret_cast(SerializeAdjust(mn->namespaces_)); +} + +void MetadataSerializer::SerializeMetaSequenceable( + /* [in] */ MetaSequenceable* mp) +{ + mp->name_ = reinterpret_cast(SerializeAdjust(mp->name_)); + mp->namespace_ = reinterpret_cast(SerializeAdjust(mp->namespace_)); +} + +void MetadataSerializer::SerializeMetaInterface( + /* [in] */ MetaInterface* mi) +{ + mi->license_ = reinterpret_cast(SerializeAdjust(mi->license_)); + mi->name_ = reinterpret_cast(SerializeAdjust(mi->name_)); + mi->namespace_ = reinterpret_cast(SerializeAdjust(mi->namespace_)); + + for (int i = 0; i < mi->methodNumber_; i++) { + MetaMethod* mm = mi->methods_[i]; + SerializeMetaMethod(mm); + mi->methods_[i] = reinterpret_cast(SerializeAdjust(mm)); + } + mi->methods_ = reinterpret_cast(SerializeAdjust(mi->methods_)); +} + +void MetadataSerializer::SerializeMetaMethod( + /* [in] */ MetaMethod* mm) +{ + mm->name_ = reinterpret_cast(SerializeAdjust(mm->name_)); + mm->signature_ = reinterpret_cast(SerializeAdjust(mm->signature_)); + + for (int i = 0; i < mm->parameterNumber_; i++) { + MetaParameter* mp = mm->parameters_[i]; + SerializeMetaParameter(mp); + mm->parameters_[i] = reinterpret_cast(SerializeAdjust(mp)); + } + mm->parameters_ = reinterpret_cast(SerializeAdjust(mm->parameters_)); +} + +void MetadataSerializer::SerializeMetaParameter( + /* [in] */ MetaParameter* mp) +{ + mp->name_ = reinterpret_cast(SerializeAdjust(mp->name_)); +} + +void MetadataSerializer::SerializeMetaType( + /* [in] */ MetaType* mt) +{ + mt->nestedTypeIndexes_ = reinterpret_cast(SerializeAdjust(mt->nestedTypeIndexes_)); +} + +ptrdiff_t MetadataSerializer::SerializeAdjust( + /* [in] */ const void* addr) +{ + return reinterpret_cast(addr) - baseAddr_; +} + +void MetadataSerializer::Deserialize() +{ + DeserializeMetaComponent(metaComponent_); +} + +void MetadataSerializer::DeserializeMetaComponent( + /* [in] */ MetaComponent* mc) +{ + mc->name_ = reinterpret_cast(DeserializeAdjust(mc->name_)); + + mc->namespaces_ = reinterpret_cast(DeserializeAdjust(mc->namespaces_)); + for (int i = 0; i < mc->namespaceNumber_; i++) { + mc->namespaces_[i] = reinterpret_cast(DeserializeAdjust(mc->namespaces_[i])); + MetaNamespace* mn = mc->namespaces_[i]; + DeserializeMetaNamespace(mn); + } + + mc->sequenceables_ = reinterpret_cast(DeserializeAdjust(mc->sequenceables_)); + for (int i = 0; i < mc->sequenceableNumber_; i++) { + mc->sequenceables_[i] = reinterpret_cast(DeserializeAdjust(mc->sequenceables_[i])); + MetaSequenceable* mp = mc->sequenceables_[i]; + DeserializeMetaSequenceable(mp); + } + + mc->interfaces_ = reinterpret_cast(DeserializeAdjust(mc->interfaces_)); + for (int i = 0; i < mc->interfaceNumber_; i++) { + mc->interfaces_[i] = reinterpret_cast(DeserializeAdjust(mc->interfaces_[i])); + MetaInterface* mi = mc->interfaces_[i]; + DeserializeMetaInterface(mi); + } + + mc->types_ = reinterpret_cast(DeserializeAdjust(mc->types_)); + for (int i = 0; i < mc->typeNumber_; i++) { + mc->types_[i] = reinterpret_cast(DeserializeAdjust(mc->types_[i])); + MetaType* mt = mc->types_[i]; + DeserializeMetaType(mt); + } + + mc->stringPool_ = reinterpret_cast(DeserializeAdjust(mc->stringPool_)); +} + +void MetadataSerializer::DeserializeMetaNamespace( + /* [in] */ MetaNamespace* mn) +{ + mn->name_ = reinterpret_cast(DeserializeAdjust(mn->name_)); + mn->sequenceableIndexes_ = reinterpret_cast(DeserializeAdjust(mn->sequenceableIndexes_)); + mn->interfaceIndexes_ = reinterpret_cast(DeserializeAdjust(mn->interfaceIndexes_)); + + mn->namespaces_ = reinterpret_cast(DeserializeAdjust(mn->namespaces_)); + for (int i = 0; i < mn->namespaceNumber_; i++) { + mn->namespaces_[i] = reinterpret_cast(DeserializeAdjust(mn->namespaces_[i])); + MetaNamespace* innermn = mn->namespaces_[i]; + DeserializeMetaNamespace(innermn); + } +} + +void MetadataSerializer::DeserializeMetaSequenceable( + /* [in] */ MetaSequenceable* mp) +{ + mp->name_ = reinterpret_cast(DeserializeAdjust(mp->name_)); + mp->namespace_ = reinterpret_cast(DeserializeAdjust(mp->namespace_)); +} + +void MetadataSerializer::DeserializeMetaInterface( + /* [in] */ MetaInterface* mi) +{ + mi->license_ = reinterpret_cast(DeserializeAdjust(mi->license_)); + mi->name_ = reinterpret_cast(DeserializeAdjust(mi->name_)); + mi->namespace_ = reinterpret_cast(DeserializeAdjust(mi->namespace_)); + + mi->methods_ = reinterpret_cast(DeserializeAdjust(mi->methods_)); + for (int i = 0; i < mi->methodNumber_; i++) { + mi->methods_[i] = reinterpret_cast(DeserializeAdjust(mi->methods_[i])); + MetaMethod* mm = mi->methods_[i]; + DeserializeMetaMethod(mm); + } +} + +void MetadataSerializer::DeserializeMetaMethod( + /* [in] */ MetaMethod* mm) +{ + mm->name_ = reinterpret_cast(DeserializeAdjust(mm->name_)); + mm->signature_ = reinterpret_cast(DeserializeAdjust(mm->signature_)); + + mm->parameters_ = reinterpret_cast(DeserializeAdjust(mm->parameters_)); + for (int i = 0; i < mm->parameterNumber_; i++) { + mm->parameters_[i] = reinterpret_cast(DeserializeAdjust(mm->parameters_[i])); + MetaParameter* mp = mm->parameters_[i]; + DeserializeMetaParameter(mp); + } +} + +void MetadataSerializer::DeserializeMetaParameter( + /* [in] */ MetaParameter* mp) +{ + mp->name_ = reinterpret_cast(DeserializeAdjust(mp->name_)); +} + +void MetadataSerializer::DeserializeMetaType( + /* [in] */ MetaType* mt) +{ + mt->nestedTypeIndexes_ = reinterpret_cast(DeserializeAdjust(mt->nestedTypeIndexes_)); +} + +uintptr_t MetadataSerializer::DeserializeAdjust( + /* [in] */ const void* addr) +{ + return reinterpret_cast(addr) + baseAddr_; +} + +} +} diff --git a/zidl/metadata/metadata_serializer.h b/zidl/metadata/metadata_serializer.h new file mode 100644 index 0000000000000000000000000000000000000000..7a5e3a5189945f26a01bdf71a6ce4526c18ad90b --- /dev/null +++ b/zidl/metadata/metadata_serializer.h @@ -0,0 +1,112 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_METADATASERIALIZER_H +#define OHOS_ZIDL_METADATASERIALIZER_H + +#include +#include +#include "metadata/metadata.h" + +namespace OHOS { +namespace Zidl { + +class MetadataSerializer { +public: + explicit MetadataSerializer( + /* [in] */ MetaComponent* mc) + : metaComponent_(mc), + baseAddr_(reinterpret_cast(mc)) + {} + + explicit MetadataSerializer( + /* [in] */ uintptr_t addr) + : metaComponent_(reinterpret_cast(addr)), + baseAddr_(addr) + {} + + ~MetadataSerializer() = default; + + void Serialize(); + + void Deserialize(); + + inline uintptr_t GetData() const + { + return baseAddr_; + } + + inline int GetDataSize() const + { + return metaComponent_->size_; + } + +private: + void SerializeMetaComponent( + /* [in] */ MetaComponent* mc); + + void SerializeMetaNamespace( + /* [in] */ MetaNamespace* mn); + + void SerializeMetaSequenceable( + /* [in] */ MetaSequenceable* mp); + + void SerializeMetaInterface( + /* [in] */ MetaInterface* mi); + + void SerializeMetaMethod( + /* [in] */ MetaMethod* mm); + + void SerializeMetaParameter( + /* [in] */ MetaParameter* mp); + + void SerializeMetaType( + /* [in] */ MetaType* mt); + + ptrdiff_t SerializeAdjust( + /* [in] */ const void* addr); + + void DeserializeMetaComponent( + /* [in] */ MetaComponent* mc); + + void DeserializeMetaNamespace( + /* [in] */ MetaNamespace* mn); + + void DeserializeMetaSequenceable( + /* [in] */ MetaSequenceable* mp); + + void DeserializeMetaInterface( + /* [in] */ MetaInterface* mi); + + void DeserializeMetaMethod( + /* [in] */ MetaMethod* mm); + + void DeserializeMetaParameter( + /* [in] */ MetaParameter* mp); + + void DeserializeMetaType( + /* [in] */ MetaType* mt); + + uintptr_t DeserializeAdjust( + /* [in] */ const void* addr); + + MetaComponent* metaComponent_; + uintptr_t baseAddr_; +}; + +} +} + +#endif // OHOS_ZIDL_METADATASERIALIZER_H diff --git a/zidl/parser/CMakeLists.txt b/zidl/parser/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..40b2194801ed3e8cb5afa2143d6744d5b91f6a2a --- /dev/null +++ b/zidl/parser/CMakeLists.txt @@ -0,0 +1,22 @@ +# 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_directories( + ${ZIDL_DIR}) + +set(SOURCES + lexer.cpp + parser.cpp) + +add_library(parser STATIC + ${SOURCES}) \ No newline at end of file diff --git a/zidl/parser/lexer.cpp b/zidl/parser/lexer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8680d4a6dc82a886569e8207184b911cc72be79 --- /dev/null +++ b/zidl/parser/lexer.cpp @@ -0,0 +1,383 @@ +/* + * 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 "parser/lexer.h" + +#include +#include "util/string_builder.h" + +namespace OHOS { +namespace Zidl { + +static struct Keywords { + String key_; + Token token_; +} g_keywords[] = { + { String("boolean"), Token::BOOLEAN }, + { String("byte"), Token::BYTE }, + { String("char"), Token::CHAR }, + { String("double"), Token::DOUBLE }, + { String("float"), Token::FLOAT }, + { String("in"), Token::IN }, + { String("inout"), Token::INOUT }, + { String("int"), Token::INTEGER }, + { String("interface"), Token::INTERFACE }, + { String("List"), Token::LIST }, + { String("long"), Token::LONG }, + { String("Map"), Token::MAP }, + { String("oneway"), Token::ONEWAY }, + { String("out"), Token::OUT }, + { String("sequenceable"), Token::SEQUENCEABLE }, + { String("short"), Token::SHORT }, + { String("String"), Token::STRING }, +}; + +Lexer::Lexer() +{ + InitializeKeywords(); +} + +Lexer::~Lexer() +{ + if (currentFile_ != nullptr) { + currentFile_->Close(); + } +} + +void Lexer::InitializeKeywords() +{ + for (size_t i = 0; i < sizeof(g_keywords) / sizeof(struct Keywords); i++) { + keywords_[g_keywords[i].key_] = g_keywords[i].token_; + } +} + +bool Lexer::OpenSourceFile( + /* [in] */ const String& filePath) +{ + currentFile_ = std::make_shared(filePath, File::READ); + if (!currentFile_->IsValid()) { + return false; + } + + return true; +} + +Token Lexer::GetToken( + /* [in] */ bool skipComment) +{ + if (!havePeek_) { + currentToken_ = ReadToken(skipComment); + } + havePeek_ = false; + return currentToken_; +} + +Token Lexer::PeekToken( + /* [in] */ bool skipComment) +{ + if (!havePeek_) { + currentToken_ = ReadToken(skipComment); + havePeek_ = true; + } + return currentToken_; +} + +Token Lexer::ReadToken( + /* [in] */ bool skipComment) +{ + while (!currentFile_->IsEof()) { + char c = currentFile_->GetChar(); + tokenLineNo_ = currentFile_->GetCharLineNumber(); + tokenColumnNo_ = currentFile_->GetCharColumnNumber(); + if (IsSpace(c)) { + continue; + } else if (IsAlphabet(c) || c == '_') { + return ReadIdentifier(c); + } + switch (c) { + case '<': + currentToken_ = Token::ANGLE_BRACKETS_LEFT; + return currentToken_; + case '>': + currentToken_ = Token::ANGLE_BRACKETS_RIGHT; + return currentToken_; + case '{': + currentToken_ = Token::BRACES_LEFT; + return currentToken_; + case '}': + currentToken_ = Token::BRACES_RIGHT; + return currentToken_; + case '[': + currentToken_ = Token::BRACKETS_LEFT; + return currentToken_; + case ']': + currentToken_ = Token::BRACKETS_RIGHT; + return currentToken_; + case ',': + currentToken_ = Token::COMMA; + return currentToken_; + case '/': + 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_; + case '(': + currentToken_ = Token::PARENTHESES_LEFT; + return currentToken_; + case ')': + currentToken_ = Token::PARENTHESES_RIGHT; + return currentToken_; + case '.': + currentToken_ = Token::DOT; + return currentToken_; + case ';': + currentToken_ = Token::SEMICOLON; + return currentToken_; + default: + currentToken_ = Token::UNKNOWN; + return currentToken_; + } + } + currentToken_ = Token::END_OF_FILE; + return currentToken_; +} + +Token Lexer::ReadIdentifier( + /* [in] */ 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::ReadLineComment( + /* [in] */ 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( + /* [in] */ 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( + /* [in] */ char untilChar) +{ + while (!currentFile_->IsEof()) { + int c = currentFile_->GetChar(); + if (c == untilChar) { + return true; + } + if (c == '\n') { + currentFile_->GetChar(); + return false; + } + } + return true; +} + +int Lexer::TokenToChar( + /* [in] */ 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::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::INOUT: + 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 +{ + switch (currentToken_) { + case Token::ANGLE_BRACKETS_LEFT: + return "<"; + case Token::ANGLE_BRACKETS_RIGHT: + return ">"; + case Token::BOOLEAN: + return "boolean"; + case Token::BRACES_LEFT: + return "{"; + case Token::BRACES_RIGHT: + return "}"; + case Token::BRACKETS_LEFT: + return "["; + case Token::BRACKETS_RIGHT: + return "]"; + case Token::BYTE: + return "byte"; + case Token::CHAR: + return "char"; + case Token::COMMA: + return ","; + case Token::COMMENT_BLOCK: + case Token::COMMENT_LINE: + return comment_; + case Token::DOT: + return "."; + case Token::DOUBLE: + return "double"; + case Token::END_OF_FILE: + return "eof"; + case Token::FLOAT: + return "float"; + case Token::IDENTIFIER: + return identifier_; + case Token::IN: + return "in"; + case Token::INOUT: + return "inout"; + case Token::INTEGER: + return "int"; + case Token::LIST: + return "List"; + case Token::LONG: + return "long"; + case Token::MAP: + return "Map"; + case Token::ONEWAY: + return "oneway"; + case Token::OUT: + return "out"; + case Token::SEQUENCEABLE: + return "sequenceable"; + case Token::PARENTHESES_LEFT: + return "("; + case Token::PARENTHESES_RIGHT: + return ")"; + case Token::SEMICOLON: + return ";"; + case Token::SHORT: + return "short"; + case Token::STRING: + return "String"; + default: + return "unknown token"; + } +} + +} +} diff --git a/zidl/parser/lexer.h b/zidl/parser/lexer.h new file mode 100644 index 0000000000000000000000000000000000000000..d43c7050ceb212009d24a9b1640901b7ec319885 --- /dev/null +++ b/zidl/parser/lexer.h @@ -0,0 +1,127 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_LEXER_H +#define OHOS_ZIDL_LEXER_H + +#include +#include +#include + +#include "parser/token.h" +#include "util/file.h" +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class Lexer { +public: + Lexer(); + + ~Lexer(); + + bool OpenSourceFile( + /* [in] */ const String& filePath); + + Token GetToken( + /* [in] */ bool skipComment = true); + + Token PeekToken( + /* [in] */ bool skipComment = true); + + inline String GetIdentifier() const + { + return identifier_; + } + + inline String GetComment() const + { + return comment_; + } + + void SkipCurrentLine(); + + bool SkipCurrentLine( + /* [in] */ char untilChar); + + inline std::shared_ptr GetSourceFile() const + { + return currentFile_; + } + + String DumpToken() const; + + inline int GetTokenLineNumber() const + { + return tokenLineNo_; + } + + inline int GetTokenColumnNumber() const + { + return tokenColumnNo_; + } + + static int TokenToChar( + /* [in] */ Token token); + +private: + void InitializeKeywords(); + + Token ReadToken( + /* [in] */ bool skipComment); + + Token ReadIdentifier( + /* [in] */ char c); + + Token ReadLineComment( + /* [in] */ char c); + + Token ReadBlockComment( + /* [in] */ char c); + + inline static bool IsAlphabet( + /* [in] */ char c) + { + return isalpha(c); + } + + inline static bool IsDecimalDigital( + /* [in] */ char c) + { + return isdigit(c); + } + + inline static bool IsSpace( + /* [in] */ char c) + { + return isspace(c); + } + + static const char* TAG; + std::unordered_map keywords_; + Token currentToken_ = Token::UNKNOWN; + int tokenLineNo_ = 0; + int tokenColumnNo_ = 0; + String identifier_; + String comment_; + bool havePeek_ = false; + std::shared_ptr currentFile_; +}; + +} +} + +#endif // OHOS_ZIDL_LEXER_H diff --git a/zidl/parser/parser.cpp b/zidl/parser/parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..43bc428c659b034265268bd0ecf193db8fd997b0 --- /dev/null +++ b/zidl/parser/parser.cpp @@ -0,0 +1,688 @@ +/* + * 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 "parser/parser.h" +#include "ast/ast_array_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 "util/logger.h" +#include "util/string_builder.h" +#include + +namespace OHOS { +namespace Zidl { + +const char* Parser::TAG = "Parser"; + +Parser::Parser( + /* [in] */ const Options& options) + : options_(options) +{} + +bool Parser::Parse( + /* [in] */ const String& sourceFile) +{ + bool ret = lexer_.OpenSourceFile(sourceFile); + if (!ret) { + Logger::E(TAG, "Fail to open file \"%s\".", sourceFile.string()); + return false; + } + + ret = ParseFile(); + ret = CheckIntegrity() && ret; + + if (!ret) { + ShowError(); + return false; + } + + if (options_.DoDumpAST()) { + String astStr = module_->Dump(""); + printf("%s\n", astStr.string()); + } + + return ret; +} + +bool Parser::ParseFile() +{ + bool ret = true; + + module_ = new ASTModule(); + module_->SetZidlFile(lexer_.GetSourceFile()->GetPath()); + + ParseLicense(); + + Token token; + while ((token = lexer_.PeekToken()) != Token::END_OF_FILE) { + switch (token) { + case Token::BRACKETS_LEFT: + case Token::INTERFACE: + ret = ParseInterface() && ret; + continue; + case Token::SEQUENCEABLE: + ret = ParseSequenceable() && ret; + continue; + case Token::COMMENT_LINE: + lexer_.GetToken(); + continue; + default: + LogError(token, String::Format("%s is not expected.", lexer_.DumpToken().string())); + lexer_.GetToken(); + ret = false; + continue; + } + } + lexer_.GetToken(); + + return ret; +} + +bool Parser::ParseLicense() +{ + Token token = lexer_.PeekToken(false); + if (token != Token::COMMENT_BLOCK) { + return false; + } + + lexer_.GetToken(false); + + module_->SetLicense(lexer_.GetComment()); + + return true; +} + +bool Parser::ParseInterface() +{ + bool ret = true; + bool hasProperties = false; + bool oneway = false; + Token token = lexer_.GetToken(); + if (token == Token::BRACKETS_LEFT) { + token = lexer_.PeekToken(); + if (token != Token::ONEWAY) { + LogError(Token::IDENTIFIER, String::Format("\"%s\" is an illegal interface property.", lexer_.DumpToken().string())); + + if (token != Token::BRACKETS_RIGHT) { + lexer_.SkipCurrentLine(Lexer::TokenToChar(Token::BRACKETS_RIGHT)); + } + ret = false; + } + lexer_.GetToken(); + + oneway = true; + hasProperties = true; + + token = lexer_.PeekToken(); + if (token != Token::BRACKETS_RIGHT) { + LogError(Token::IDENTIFIER, String("\"]\" is expected.")); + while (token != Token::BRACKETS_RIGHT && token != Token::INTERFACE && token != Token::END_OF_FILE) { + lexer_.GetToken(); + token = lexer_.PeekToken(); + } + ret = false; + } else { + lexer_.GetToken(); + } + + token = lexer_.PeekToken(); + if (token != Token::INTERFACE) { + LogError(Token::IDENTIFIER, String("\"interface\" is expected.")); + ret = false; + } else { + lexer_.GetToken(); + } + } + + String interfaceFullName; + + token = lexer_.PeekToken(); + + if (token != Token::IDENTIFIER) { + LogError(token, String::Format("%s is not expected.", lexer_.DumpToken().string())); + lexer_.SkipCurrentLine(); + return false; + } else { + lexer_.GetToken(); + interfaceFullName = lexer_.GetIdentifier(); + token = lexer_.PeekToken(); + } + if (token != Token::SEMICOLON && token != Token::BRACES_LEFT) { + LogError(token, String::Format("%s is not expected.", lexer_.DumpToken().string())); + lexer_.SkipCurrentLine(); + return false; + } + + if (interfaceFullName.IsEmpty()) { + LogError(Token::IDENTIFIER, String("Interface name is expected.")); + return false; + } else if (!IsValidTypeName(interfaceFullName)) { + LogError(Token::IDENTIFIER, String::Format("Interface name \"%s\" is illegal.", interfaceFullName.string())); + return false; + } else if (interfaceFullName.IndexOf(".") == -1) { + LogError(Token::IDENTIFIER, String::Format("Interface name \"%s\" does not have namespace.", + interfaceFullName.string())); + return false; + } + + AutoPtr interface = new ASTInterfaceType(); + parsingInterface_ = interface; + int index = interfaceFullName.LastIndexOf('.'); + if (index != -1) { + interface->SetName(interfaceFullName.Substring(index + 1)); + interface->SetNamespace(module_->ParseNamespace(interfaceFullName.Substring(0, index + 1))); + } else { + interface->SetName(interfaceFullName); + } + + // read ';' + lexer_.GetToken(); + if (token == Token::SEMICOLON) { + if (hasProperties) { + LogError(Token::IDENTIFIER, String("Interface forward declaration should not have properties.")); + return false; + } + interface->SetExternal(true); + module_->AddInterface(interface); + return true; + } else { + if (!interface->GetName().Equals(module_->GetName())) { + LogError(Token::IDENTIFIER, String::Format("Module name \"%s\" is not equal to interface name \"%s\".", + module_->GetName().string(), interface->GetName().string())); + return false; + } + + interface->SetLicense(module_->GetLicense()); + interface->SetOneway(oneway); + + while (token != Token::BRACES_RIGHT && token != Token::END_OF_FILE) { + ret = ParseMethod(interface) && ret; + token = lexer_.PeekToken(); + } + + if (token != Token::BRACES_RIGHT) { + ret = false; + } else { + lexer_.GetToken(); + module_->AddInterface(interface); + } + + return ret; + } +} + +bool Parser::ParseMethod( + /* [in] */ ASTInterfaceType* interface) +{ + bool ret = true; + bool oneway = false; + Token token; + + token = lexer_.PeekToken(); + if (token == Token::BRACKETS_LEFT) { + lexer_.GetToken(); + token = lexer_.PeekToken(); + if (token != Token::ONEWAY) { + LogError(Token::IDENTIFIER, String::Format("\"%s\" is an illegal method property.", + lexer_.DumpToken().string())); + + if (token != Token::BRACKETS_RIGHT) { + lexer_.SkipCurrentLine(Lexer::TokenToChar(Token::BRACKETS_RIGHT)); + } + ret = false; + } + lexer_.GetToken(); + + oneway = true; + + token = lexer_.PeekToken(); + if (token != Token::BRACKETS_RIGHT) { + LogError(Token::IDENTIFIER, String("\"]\" is expected.")); + ret = false; + } else { + lexer_.GetToken(); + } + } + AutoPtr type = ParseType(); + if (type == nullptr) { + token = lexer_.PeekToken(); + if (token != Token::BRACES_RIGHT) { + // 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_.PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(token, String("Method name is expected.")); + if (token != Token::BRACES_RIGHT) { + // 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()); + method->SetOneway(oneway); + method->SetReturnType(type); + + token = lexer_.PeekToken(); + if (token != Token::PARENTHESES_LEFT) { + LogError(token, String("\"(\" is expected.")); + if (token != Token::BRACES_RIGHT) { + // 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(); + } + } + lexer_.GetToken(); + if (!ret) { + lexer_.SkipCurrentLine(); + return false; + } + + token = lexer_.PeekToken(); + if (token != Token::SEMICOLON) { + LogError(token, String("\";\" is expected.")); + if (token != Token::BRACES_RIGHT) { + lexer_.SkipCurrentLine(Lexer::TokenToChar(Token::BRACES_RIGHT)); + } + return false; + } + lexer_.GetToken(); + + interface->AddMethod(method); + + return ret; +} + +bool Parser::ParseParameter( + /* [in] */ ASTMethod* method) +{ + Token token = lexer_.PeekToken(); + if (token != Token::BRACKETS_LEFT) { + LogError(token, String("\"[\" is expected.")); + // jump to ',' or ')' + 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(); + + token = lexer_.PeekToken(); + while (token != Token::BRACKETS_RIGHT && token != Token::END_OF_FILE) { + switch (token) { + case Token::IN: + lexer_.GetToken(); + parameter->SetInParameter(true); + break; + case Token::OUT: + lexer_.GetToken(); + parameter->SetOutParameter(true); + break; + case Token::INOUT: + lexer_.GetToken(); + parameter->SetInParameter(true); + parameter->SetOutParameter(true); + break; + default: + LogError(token, String("\"in\" or \"out\" or \"inout\" is expected.")); + break; + } + token = lexer_.PeekToken(); + if (token == Token::COMMA) { + lexer_.GetToken(); + token = lexer_.PeekToken(); + continue; + } + if (token != Token::BRACKETS_RIGHT) { + LogError(token, String("\",\" or \"]\" is expected.")); + // jump to ',' or ')' + while (token != Token::COMMA && token != Token::PARENTHESES_RIGHT && token != Token::END_OF_FILE) { + lexer_.GetToken(); + token = lexer_.PeekToken(); + } + return false; + } + } + // read ']' + lexer_.GetToken(); + + AutoPtr type = ParseType(); + if (type == nullptr) { + // jump to ',' or ')' + 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(token, String("Parameter name is expected.")); + // jump to ',' or ')' + 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; +} + +AutoPtr Parser::ParseType() +{ + AutoPtr type; + + Token token = lexer_.PeekToken(); + if (IsPrimitiveType(token)) { + lexer_.GetToken(); + type = module_->FindType(lexer_.DumpToken()); + } else if (token == Token::LIST) { + type = ParseList(); + } else if (token == Token::MAP) { + type = ParseMap(); + } else if (token == Token::IDENTIFIER) { + lexer_.GetToken(); + if (parsingInterface_ != nullptr && + parsingInterface_->GetName().Equals(lexer_.GetIdentifier())) { + type = parsingInterface_.Get(); + } else { + type = module_->FindType(lexer_.GetIdentifier()); + } + } else { + LogError(token, String("Type name is expected.")); + return nullptr; + } + + if (type == nullptr) { + LogError(token, String::Format("Type \"%s\" was not declared in the module.", lexer_.DumpToken().string())); + } + + token = lexer_.PeekToken(); + if (token == Token::BRACKETS_LEFT) { + lexer_.GetToken(); + token = lexer_.PeekToken(); + if (token != Token::BRACKETS_RIGHT) { + LogError(token, String("\"]\" is expected.")); + return nullptr; + } + lexer_.GetToken(); + + AutoPtr arrayType = new ASTArrayType(); + arrayType->SetElementType(type); + + type = module_->FindType(arrayType->ToString()); + if (type == nullptr) { + module_->AddType(arrayType); + type = static_cast(arrayType.Get()); + } + } + + return type; +} + +AutoPtr Parser::ParseList() +{ + lexer_.GetToken(); + + Token token = lexer_.PeekToken(); + if (token != Token::ANGLE_BRACKETS_LEFT) { + LogError(token, String("\"<\" is expected.")); + return nullptr; + } + lexer_.GetToken(); + + AutoPtr type = ParseType(); + if (type == nullptr) { + lexer_.SkipCurrentLine('>'); + return nullptr; + } + + token = lexer_.PeekToken(); + if (token != Token::ANGLE_BRACKETS_RIGHT) { + LogError(token, String("\">\" is expected.")); + return nullptr; + } + lexer_.GetToken(); + + AutoPtr list = new ASTListType(); + list->SetElementType(type); + + AutoPtr ret = module_->FindType(list->ToString()); + if (ret == nullptr) { + module_->AddType(list); + ret = list.Get(); + } + + return ret; +} + +AutoPtr Parser::ParseMap() +{ + lexer_.GetToken(); + + Token token = lexer_.PeekToken(); + if (token != Token::ANGLE_BRACKETS_LEFT) { + LogError(token, 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(token, 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(token, String("\">\" is expected.")); + return nullptr; + } + lexer_.GetToken(); + + AutoPtr map = new ASTMapType(); + map->SetKeyType(keyType); + map->SetValueType(valueType); + + AutoPtr ret = module_->FindType(map->ToString()); + if (ret == nullptr) { + module_->AddType(map); + ret = map.Get(); + } + + return ret; +} + +bool Parser::ParseSequenceable() +{ + lexer_.GetToken(); + + String classFullName; + + Token token = lexer_.PeekToken(); + if (token != Token::IDENTIFIER) { + LogError(token, String::Format("%s is not expected.", lexer_.DumpToken().string())); + lexer_.SkipCurrentLine(); + return false; + } else { + lexer_.GetToken(); + classFullName = lexer_.GetIdentifier(); + token = lexer_.PeekToken(); + } + + if (token != Token::SEMICOLON) { + LogError(token, String::Format("%s is not expected.", lexer_.DumpToken().string())); + lexer_.SkipCurrentLine(); + return false; + } + + // read ';' + lexer_.GetToken(); + + if (classFullName.IsEmpty()) { + LogError(Token::IDENTIFIER, String("Class name is expected.")); + return false; + } else if (!IsValidTypeName(classFullName)) { + LogError(Token::IDENTIFIER, 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(module_->ParseNamespace(classFullName.Substring(0, index + 1))); + } else { + sequenceable->SetName(classFullName); + } + module_->AddSequenceable(sequenceable); + + return true; +} + +bool Parser::CheckIntegrity() +{ + bool definedInterface = false; + int interfaceNumber = module_->GetInterfaceNumber(); + for (int i = 0; i < interfaceNumber; i++) { + if (!module_->GetInterface(i)->IsExternal()) { + definedInterface = true; + break; + } + } + if (!definedInterface) { + LogError(Token::UNKNOWN, String("An interface is not defined.")); + return false; + } + + return true; +} + +bool Parser::IsValidTypeName( + /* [in] */ const String& typeName) +{ + if (typeName[0] == '.') { + return false; + } + + if (typeName[typeName.GetLength() - 1] == '.') { + return false; + } + + return true; +} + +void Parser::LogError( + /* [in] */ Token token, + /* [in] */ const String& message) +{ + AutoPtr error = new ErrorInfo(); + + String sourceFile = lexer_.GetSourceFile()->GetPath(); +#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 { + ErrorInfo* pos = errors_; + while (pos->next_ != nullptr) { + pos = pos->next_; + } + pos->next_ = error; + } +} + +void Parser::ShowError() +{ + ErrorInfo* 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_; + } +} + +} +} diff --git a/zidl/parser/parser.h b/zidl/parser/parser.h new file mode 100644 index 0000000000000000000000000000000000000000..b0e4f5ec3b10f0ea716624750f4fb68dafec039c --- /dev/null +++ b/zidl/parser/parser.h @@ -0,0 +1,108 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_PARSER_H +#define OHOS_ZIDL_PARSER_H + +#include "ast/ast_interface_type.h" +#include "ast/ast_method.h" +#include "ast/ast_module.h" +#include "ast/ast_type.h" +#include "parser/lexer.h" +#include "parser/token.h" +#include "util/autoptr.h" +#include "util/light_refcount_base.h" +#include "util/options.h" +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class Parser { +public: + explicit Parser( + /* [in] */ const Options& options); + + ~Parser() = default; + + bool Parse( + /* [in] */ const String& sourceFile); + + inline AutoPtr GetModule() const + { + return module_; + } + +private: + class ErrorInfo : public LightRefCountBase { + public: + String file_; + Token token_; + int lineNo_; + int columnNo_; + String message_; + AutoPtr next_; + }; + + bool ParseFile(); + + bool ParseLicense(); + + bool ParseInterface(); + + bool ParseMethod( + /* [in] */ ASTInterfaceType* interface); + + bool ParseParameter( + /* [in] */ ASTMethod* method); + + AutoPtr ParseType(); + + AutoPtr ParseList(); + + AutoPtr ParseMap(); + + bool ParseSequenceable(); + + bool CheckIntegrity(); + + bool IsValidTypeName( + /* [in] */ const String& typeName); + + inline static bool IsPrimitiveType( + /* [in] */ Token token) + { + return token >= Token::BOOLEAN && token <= Token::STRING; + } + + void LogError( + /* [in] */ Token token, + /* [in] */ const String& message); + + void ShowError(); + + static const char* TAG; + + const Options& options_; + AutoPtr module_; + AutoPtr parsingInterface_; + Lexer lexer_; + AutoPtr errors_; +}; + +} +} + +#endif // OHOS_ZIDL_PARSER_H diff --git a/zidl/parser/token.h b/zidl/parser/token.h new file mode 100644 index 0000000000000000000000000000000000000000..a121f147ef60eeabb4f14edbd8c46f35be6bd882 --- /dev/null +++ b/zidl/parser/token.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_TOKEN_H +#define OHOS_ZIDL_TOKEN_H + +namespace OHOS { +namespace Zidl { + +enum class Token { + UNKNOWN = 0, + // types + BOOLEAN, + CHAR, + BYTE, + SHORT, + INTEGER, + LONG, + FLOAT, + DOUBLE, + STRING, + LIST, + MAP, + // keywords + IN, + INTERFACE, + ONEWAY, + OUT, + INOUT, + SEQUENCEABLE, + // symbols + DOT, // '.' + COMMA, // ',' + SEMICOLON, // ';' + BRACES_LEFT, // '{' + BRACES_RIGHT, // '}' + BRACKETS_LEFT, // '[' + BRACKETS_RIGHT, // ']' + PARENTHESES_LEFT, // '(' + PARENTHESES_RIGHT, // ')' + ANGLE_BRACKETS_LEFT, // '<' + ANGLE_BRACKETS_RIGHT, // '>' + // others + IDENTIFIER, + COMMENT_BLOCK, + COMMENT_LINE, + END_OF_FILE, +}; + +} +} + +#endif // OHOS_ZIDL_TOKEN_H diff --git a/zidl/util/CMakeLists.txt b/zidl/util/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..753b0bb189ba431cb0dc993156215a6292624e65 --- /dev/null +++ b/zidl/util/CMakeLists.txt @@ -0,0 +1,27 @@ +# 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_directories( + ${ZIDL_DIR}) + +set(SOURCES + file.cpp + light_refcount_base.cpp + logger.cpp + options.cpp + string.cpp + string_builder.cpp + string_pool.cpp) + +add_library(util STATIC + ${SOURCES}) \ No newline at end of file diff --git a/zidl/util/autoptr.h b/zidl/util/autoptr.h new file mode 100644 index 0000000000000000000000000000000000000000..3574bf9f861f60cef992da0c162f6968e29147ca --- /dev/null +++ b/zidl/util/autoptr.h @@ -0,0 +1,309 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_AUTOPTR_H +#define OHOS_ZIDL_AUTOPTR_H + +namespace OHOS { +namespace Zidl { + +template +class AutoPtr { +public: + inline AutoPtr() + : mPtr(nullptr) + {} + + AutoPtr( + /* [in] */ T* other); + + AutoPtr( + /* [in] */ const AutoPtr& other); + + AutoPtr( + /* [in] */ AutoPtr&& other); + + ~AutoPtr(); + + AutoPtr& operator=( + /* [in] */ T* other); + + AutoPtr& operator=( + /* [in] */ const AutoPtr& other); + + AutoPtr& operator=( + /* [in] */ AutoPtr&& other); + + void MoveTo( + /* [out] */ T** other); + + inline operator T*() const; + + inline T** operator&(); + + inline T* operator->() const; + + inline T& operator*() const; + + inline T* Get() const; + + inline bool operator==( + /* [in] */ T* other) const; + + inline bool operator==( + /* [in] */ const AutoPtr& other) const; + + inline bool operator!=( + /* [in] */ T* other) const; + + inline bool operator!=( + /* [in] */ const AutoPtr& other) const; + + inline bool operator>( + /* [in] */ T* other) const; + + inline bool operator>( + /* [in] */ const AutoPtr& other) const; + + inline bool operator<( + /* [in] */ T* other) const; + + inline bool operator<( + /* [in] */ const AutoPtr& other) const; + + inline bool operator<=( + /* [in] */ T* other) const; + + inline bool operator<=( + /* [in] */ const AutoPtr& other) const; + + inline bool operator>=( + /* [in] */ T* other) const; + + inline bool operator>=( + /* [in] */ const AutoPtr& other) const; + +private: + T* mPtr; +}; + +template +AutoPtr::AutoPtr( + /* [in] */ T* other) + : mPtr(other) +{ + if (mPtr != nullptr) { + mPtr->AddRef(); + } +} + +template +AutoPtr::AutoPtr( + /* [in] */ const AutoPtr& other) + : mPtr(other.mPtr) +{ + if (mPtr != nullptr) { + mPtr->AddRef(); + } +} + +template +AutoPtr::AutoPtr( + /* [in] */ AutoPtr&& other) + : mPtr(other.mPtr) +{ + other.mPtr = nullptr; +} + +template +AutoPtr::~AutoPtr() +{ + if (mPtr != nullptr) { + mPtr->Release(); + } +} + +template +AutoPtr& AutoPtr::operator=( + /* [in] */ 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=( + /* [in] */ 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=( + /* [in] */ AutoPtr&& other) +{ + if (mPtr != nullptr) { + mPtr->Release(); + } + mPtr = other.mPtr; + other.mPtr = nullptr; + return *this; +} + +template +void AutoPtr::MoveTo( + /* [out] */ 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==( + /* [in] */ T* other) const +{ + return mPtr == other; +} + +template +bool AutoPtr::operator==( + /* [in] */ const AutoPtr& other) const +{ + return mPtr == other.mPtr; +} + +template +bool AutoPtr::operator!=( + /* [in] */ T* other) const +{ + return mPtr != other; +} + +template +bool AutoPtr::operator!=( + /* [in] */ const AutoPtr& other) const +{ + return mPtr != other.mPtr; +} + +template +bool AutoPtr::operator>( + /* [in] */ T* other) const +{ + return mPtr > other; +} + +template +bool AutoPtr::operator>( + /* [in] */ const AutoPtr& other) const +{ + return mPtr > other.mPtr; +} + +template +bool AutoPtr::operator<( + /* [in] */ T* other) const +{ + return mPtr < other; +} + +template +bool AutoPtr::operator<( + /* [in] */ const AutoPtr& other) const +{ + return mPtr < other.mPtr; +} + +template +bool AutoPtr::operator<=( + /* [in] */ T* other) const +{ + return mPtr <= other; +} + +template +bool AutoPtr::operator<=( + /* [in] */ const AutoPtr& other) const +{ + return mPtr <= other.mPtr; +} + +template +bool AutoPtr::operator>=( + /* [in] */ T* other) const +{ + return mPtr >= other; +} + +template +bool AutoPtr::operator>=( + /* [in] */ const AutoPtr& other) const +{ + return mPtr >= other.mPtr; +} + +} +} + +#endif // OHOS_ZIDL_AUTOPTR_H diff --git a/zidl/util/file.cpp b/zidl/util/file.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1bba24f9127af66c9aa1fb4f0c1fdb26a4c98711 --- /dev/null +++ b/zidl/util/file.cpp @@ -0,0 +1,190 @@ +/* + * 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 "util/file.h" + +#include +#include +#include "securec.h" + +namespace OHOS { +namespace Zidl { + +#ifdef __MINGW32__ +constexpr unsigned int File::READ; +constexpr unsigned int File::WRITE; +constexpr unsigned int File::APPEND; +#endif + +File::File( + /* [in] */ const String& path, + /* [in] */ int mode) + : mode_(mode) +{ + if (path.IsEmpty()) { + return; + } + + if (mode_ & READ) { + 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_] == static_cast(-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( + /* [out] */ void* data, + /* [in] */ 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( + /* [in] */ const void* data, + /* [in] */ 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( + /* [in] */ long size) +{ + if (fd_ == nullptr) { + return false; + } + + return fseek(fd_, size, SEEK_CUR) == 0; +} + +void File::Close() +{ + if (fd_ != nullptr) { + fclose(fd_); + fd_ = nullptr; + } +} + +} +} diff --git a/zidl/util/file.h b/zidl/util/file.h new file mode 100644 index 0000000000000000000000000000000000000000..1f5f3acc7bf74b9812ffb146acd567949819e5d8 --- /dev/null +++ b/zidl/util/file.h @@ -0,0 +1,103 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_FILE_H +#define OHOS_ZIDL_FILE_H + +#include +#include + +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class File { +public: + File( + /* [in] */ const String& path, + /* [in] */ int mode); + + ~File(); + + inline bool IsValid() + { + return fd_ != nullptr; + } + + inline String GetPath() + { + return path_; + } + + char GetChar(); + + char PeekChar(); + + bool IsEof() const; + + inline int GetCharLineNumber() const + { + return lineNo_; + } + + inline int GetCharColumnNumber() const + { + return columnNo_; + } + + bool ReadData( + /* [out] */ void* data, + /* [in] */ size_t size); + + bool WriteData( + /* [in] */ const void* data, + /* [in] */ size_t size); + + void Flush(); + + bool Reset(); + + bool Skip( + /* [in] */ long size); + + void Close(); + + static constexpr unsigned int READ = 0x1; + static constexpr unsigned int WRITE = 0x2; + static constexpr unsigned int APPEND = 0x4; + +private: + int Read(); + + 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; +}; + +} +} + +#endif // OHOS_ZIDL_STRING_H diff --git a/zidl/util/light_refcount_base.cpp b/zidl/util/light_refcount_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb0bedd02aeff79e65ce69f587d3ece758045ff5 --- /dev/null +++ b/zidl/util/light_refcount_base.cpp @@ -0,0 +1,37 @@ +/* + * 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 "util/light_refcount_base.h" + +namespace OHOS { +namespace Zidl { + +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; +} + +} +} diff --git a/zidl/util/light_refcount_base.h b/zidl/util/light_refcount_base.h new file mode 100644 index 0000000000000000000000000000000000000000..55df3d3ece28851193b6a7b85763a0145d599069 --- /dev/null +++ b/zidl/util/light_refcount_base.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_LIGHTREFCOUNTBASE_H +#define OHOS_ZIDL_LIGHTREFCOUNTBASE_H + +#include + +namespace OHOS { +namespace Zidl { + +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_; +}; + +} +} + +#endif // OHOS_ZIDL_LIGHTREFCOUNTBASE_H diff --git a/zidl/util/logger.cpp b/zidl/util/logger.cpp new file mode 100644 index 0000000000000000000000000000000000000000..acc50e1edb30c71aec1a52a3febfa5531bd5801c --- /dev/null +++ b/zidl/util/logger.cpp @@ -0,0 +1,82 @@ +/* + * 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 "util/logger.h" + +#include + +namespace OHOS { +namespace Zidl { + +int Logger::level_ = DEBUG; + +void Logger::D( + /* [in] */ const char* tag, + /* [in] */ const char* format, ...) +{ + if (level_ > DEBUG) return; + + va_list args; + va_start(args, format); + Log(tag, format, args); + va_end(args); +} + +void Logger::E( + /* [in] */ const char* tag, + /* [in] */ const char* format, ...) +{ + if (level_ > ERROR) return; + + va_list args; + va_start(args, format); + Err(tag, format, args); + va_end(args); +} + +void Logger::V( + /* [in] */ const char* tag, + /* [in] */ const char* format, ...) +{ + if (level_ > VERBOSE) return; + + va_list args; + va_start(args, format); + Log(tag, format, args); + va_end(args); +} + +void Logger::Log( + /* [in] */ const char* tag, + /* [in] */ const char* format, + /* [in] */ va_list args) +{ + printf("[%s]: ", tag); + vprintf(format, args); + printf("\n"); +} + +void Logger::Err( + /* [in] */ const char* tag, + /* [in] */ const char* format, + /* [in] */ va_list args) +{ + fprintf(stderr, "[%s]: ", tag); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); +} + +} +} diff --git a/zidl/util/logger.h b/zidl/util/logger.h new file mode 100644 index 0000000000000000000000000000000000000000..f31a20ad9a6f14f9b424c1f5a4f7fcf45c4a934a --- /dev/null +++ b/zidl/util/logger.h @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_LOGGER_H +#define OHOS_ZIDL_LOGGER_H + +#include + +namespace OHOS { +namespace Zidl { + +class Logger { +public: + static void D( + /* [in] */ const char* tag, + /* [in] */ const char* format, ...); + + static void E( + /* [in] */ const char* tag, + /* [in] */ const char* format, ...); + + static void V( + /* [in] */ const char* tag, + /* [in] */ const char* format, ...); + + inline static void SetLevel( + /* [in] */ 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( + /* [in] */ const char* tag, + /* [in] */ const char* format, + /* [in] */ va_list args); + + static void Err( + /* [in] */ const char* tag, + /* [in] */ const char* format, + /* [in] */ va_list args); + + static int level_; +}; + +} +} + +#endif // OHOS_ZIDL_LOGGER_H diff --git a/zidl/util/options.cpp b/zidl/util/options.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d210eac9780740baf3a72fcef8d88ac92cb0e08 --- /dev/null +++ b/zidl/util/options.cpp @@ -0,0 +1,108 @@ +/* + * 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 "options.h" +#include "util/string_builder.h" + +#include +#include + +namespace OHOS { +namespace Zidl { + +void Options::Parse( + /* [in] */ int argc, + /* [in] */ char** argv) +{ + StringBuilder errors; + program_ = argv[0]; + + int i = 1; + while (i < argc) { + String option(argv[i++]); + if (option.Equals("--help")) { + doShowUsage_ = true; + } else if (option.Equals("--version")) { + doShowVersion_ = true; + } else if (option.Equals("-c")) { + doCompile_ = true; + } else if (option.Equals("-dump-ast")) { + doDumpAST_ = true; + } else if (option.Equals("-dump-metadata")) { + doDumpMetadata_ = true; + } else if (option.Equals("-s")) { + doSaveMetadata_ = true; + metadataFile_ = argv[i++]; + } else if (option.Equals("-gen-cpp")) { + doGenerateCode_ = true; + targetLanguage_ = "cpp"; + } else if (option.Equals("-gen-java")) { + doGenerateCode_ = true; + targetLanguage_ = "java"; + } else if (option.Equals("-gen-js")) { + doGenerateCode_ = true; + targetLanguage_ = "js"; + }else if (option.Equals("-d")) { + generationDirectory_ = argv[i++]; + } else if (!option.StartsWith("-")) { + sourceFile_ = option; + } else { + errors.Append(option); + errors.Append(" "); + } + } + + illegalOptions_ = errors.ToString(); +} + +void Options::ShowErrors() +{ + if (!illegalOptions_.IsEmpty()) { + String options = illegalOptions_; + int index; + while ((index = options.IndexOf(' ')) != -1) { + printf("The Option \"%s\" is illegal.\n", options.Substring(0, index).string()); + options = options.Substring(index + 1); + } + } + printf("Use \"--help\" to show usage.\n"); +} + +void Options::ShowVersion() +{ + printf("zidl %d.%d\n" + "Copyright (c) Huawei Technologies Co., Ltd. 2019-2019. All rights reserved.\n\n", + VERSION_MAJOR, VERSION_MINOR); +} + +void Options::ShowUsage() +{ + printf("Compile a .zidl file and generate metadata, or generate C++ and Java codes from metadata.\n" + "Usage: zidl [options] file\n" + "Options:\n" + " --help Display command line options\n" + " --version Display toolchain version information\n" + " -dump-ast Display the AST of the compiled file\n" + " -dump-metadata Display the metadata generated from the compiled file\n" + " -c Compile the .zidl file\n" + " -s Place the metadata into \n" + " -gen-cpp Generate C++ codes\n" + " -gen-java Generate Java codes\n" + " -gen-js Generate Js codes\n" + " -d Place generated codes into \n"); +} + +} +} diff --git a/zidl/util/options.h b/zidl/util/options.h new file mode 100644 index 0000000000000000000000000000000000000000..9d7895052ef29359109996d5e30e321cdd141162 --- /dev/null +++ b/zidl/util/options.h @@ -0,0 +1,128 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_OPTIONS_H +#define OHOS_ZIDL_OPTIONS_H + +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class Options { +public: + inline Options( + /* [in] */ int argc, + /* [in] */ char** argv) + { + Parse(argc, 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 DoDumpMetadata() const + { + return doDumpMetadata_; + } + + inline bool DoSaveMetadata() const + { + return doSaveMetadata_; + } + + inline bool DoGenerateCode() const + { + return doGenerateCode_; + } + + inline bool HasErrors() const + { + return !illegalOptions_.IsEmpty() || sourceFile_.IsEmpty(); + } + + inline String GetSourceFile() const + { + return sourceFile_; + } + + inline String GetMetadataFile() const + { + return metadataFile_; + } + + inline String GetTargetLanguage() const + { + return targetLanguage_; + } + + inline String GetGenerationDirectory() const + { + return generationDirectory_; + } + + void ShowErrors(); + + void ShowVersion(); + + void ShowUsage(); + +private: + void Parse( + /* [in] */ int argc, + /* [in] */ char** argv); + + static constexpr int VERSION_MAJOR = 0; + static constexpr int VERSION_MINOR = 1; + + String program_; + String sourceFile_; + String metadataFile_; + String targetLanguage_; + String generationDirectory_; + String illegalOptions_; + + bool doShowUsage_ = false; + bool doShowVersion_ = false; + bool doCompile_ = false; + bool doDumpAST_ = false; + bool doDumpMetadata_ = false; + bool doSaveMetadata_ = false; + bool doGenerateCode_ = false; +}; + +} +} + +#endif // OHOS_ZIDL_OPTIONS_H diff --git a/zidl/util/string.cpp b/zidl/util/string.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d640223f146b8f602a8a8e648d06bf9d83c93812 --- /dev/null +++ b/zidl/util/string.cpp @@ -0,0 +1,720 @@ +/* + * 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 "util/string.h" +#include "util/string_builder.h" +#include +#include +#include +#include +#include +#include +#include +#include "securec.h" + +#include "util/logger.h" + +namespace OHOS { +namespace Zidl { +constexpr int LINE_MAX_SIZE = 1024; + +using SharedData = struct SharedData { + SharedData( + /* [in] */ int refCount, + /* [in] */ int size) + : refCount_(refCount), size_(size) + {} + + static SharedData* Allocate( + /* [in] */ int size); + + static void AddRef( + /* [in] */ const void* handle); + + static void Release( + /* [in] */ const void* handle); + + inline static char* ToString( + /* [in] */ SharedData* header) + { + return reinterpret_cast(header + 1); + } + + inline static SharedData* GetHeader( + /* [in] */ const void* handle) + { + return reinterpret_cast(const_cast(handle)) - 1; + } + + std::atomic refCount_; + int size_; +}; + +SharedData* SharedData::Allocate( + /* [in] */ 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; + } + + SharedData* 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( + /* [in] */ 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( + /* [in] */ 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( + /* [in] */ const char* string) +{ + if (string != nullptr) { + string_ = SharedData::ToString(SharedData::Allocate(strlen(string))); + if (string_ != nullptr) { + (void)strcpy_s(string_, strlen(string) + 1, string); + } + } +} + +String::String( + /* [in] */ const char* string, + /* [in] */ size_t length) +{ + if (string != nullptr) { + string_ = SharedData::ToString(SharedData::Allocate(length)); + if (string_ != nullptr) { + errno_t ret = memcpy_s(string_, length + 1, string, length); + if (ret == EOK) { + string_[length] = '\0'; + } else { + free(string_); + string_ = nullptr; + } + } + } +} + +String::String( + /* [in] */ const String& other) +{ + string_ = other.string_; + SharedData::AddRef(string_); +} + +String::String( + /* [in] */ String&& other) +{ + string_ = other.string_; + other.string_ = nullptr; +} + +String::String( + /* [in] */ 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[]( + /* [in] */ int index) const +{ + if (index < 0 || index >= GetLength()) { + return '\0'; + } + return string_[index]; +} + +bool String::Equals( + /* [in] */ 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( + /* [in] */ 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( + /* [in] */ char c, + /* [in] */ 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( + /* [in] */ const char* string, + /* [in] */ 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( + /* [in] */ const String& other, + /* [in] */ 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( + /* [in] */ char c, + /* [in] */ 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( + /* [in] */ const char* string, + /* [in] */ 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( + /* [in] */ const String& other, + /* [in] */ 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( + /* [in] */ const char* string, + /* [in] */ 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( + /* [in] */ 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( + /* [in] */ 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( + /* [in] */ 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( + /* [in] */ 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( + /* [in] */ int begin) const +{ + if (begin < 0 || begin >= GetLength()) { + return String(); + } + + return String(string_ + begin); +} + +String String::Substring( + /* [in] */ int begin, + /* [in] */ int end) const +{ + if (begin < 0 || end > GetLength() || begin > end) { + return String(); + } + + return String(string_ + begin, end - begin); +} + +String String::Replace( + /* [in] */ char oldChar, + /* [in] */ char newChar) const +{ + if (oldChar == newChar) { + return *this; + } + + size_t size = GetLength(); + for (size_t i = 0; i < size; i++) { + if (string_[i] == oldChar) { + 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( + /* [in] */ const char* target, + /* [in] */ 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( + /* [in] */ const String& target, + /* [in] */ 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::operator=( + /* [in] */ const char* string) +{ + SharedData::Release(string_); + + if (string == nullptr) { + string_ = nullptr; + return *this; + } + + string_ = SharedData::ToString(SharedData::Allocate(strlen(string))); + if (string_ != nullptr) { + (void)strcpy_s(string_, strlen(string) + 1, string); + } + return *this; +} + +String& String::operator=( + /* [in] */ const String& other) +{ + if (string_ == other.string_) { + return *this; + } + + SharedData::Release(string_); + SharedData::AddRef(other.string_); + string_ = other.string_; + return *this; +} + +String& String::operator=( + /* [in] */ String&& other) +{ + SharedData::Release(string_); + string_ = other.string_; + other.string_ = nullptr; + return *this; +} + +String String::operator+=( + /* [in] */ const char* string) const +{ + if (string == nullptr || string[0] == '\0') { + return *this; + } + + int thisSize = GetLength(); + int newSize = thisSize + strlen(string); + String newString(newSize); + if (newString.string_ != nullptr) { + (void)memcpy_s(newString.string_, newSize + 1, string_, thisSize); + (void)strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, string); + } + return newString; +} + +String String::operator+=( + /* [in] */ const String& other) const +{ + if (other.IsEmpty()) { + return *this; + } + + int thisSize = GetLength(); + int newSize = thisSize + other.GetLength(); + String newString(newSize); + if (newString.string_ != nullptr) { + (void)memcpy_s(newString.string_, newSize + 1, string_, thisSize); + (void)strcpy_s(newString.string_ + thisSize, newSize + 1 - thisSize, other.string_); + } + return newString; +} + +String String::Format( + /* [in] */ 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; +} + +} +} diff --git a/zidl/util/string.h b/zidl/util/string.h new file mode 100644 index 0000000000000000000000000000000000000000..d0f3250315b89e745b222cb2b9244309411f315d --- /dev/null +++ b/zidl/util/string.h @@ -0,0 +1,192 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_STRING_H +#define OHOS_ZIDL_STRING_H + +#include + +namespace OHOS { +namespace Zidl { + +class String { +public: + inline String() + {} + + String( + /* [in] */ const char* string); + + String( + /* [in] */ const char* string, + /* [in] */ size_t length); + + String( + /* [in] */ const String& other); + + String( + /* [in] */ 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[]( + /* [in] */ int index) const; + + bool Equals( + /* [in] */ const char* string) const; + + bool Equals( + /* [in] */ const String& other) const; + + int GetHashCode() const; + + int IndexOf( + /* [in] */ char c, + /* [in] */ int fromIndex = 0) const; + + int IndexOf( + /* [in] */ const char* string, + /* [in] */ int fromIndex = 0) const; + + int IndexOf( + /* [in] */ const String& other, + /* [in] */ int fromIndex = 0) const; + + int LastIndexOf( + /* [in] */ char c, + /* [in] */ int fromIndex = 0) const; + + int LastIndexOf( + /* [in] */ const char* string, + /* [in] */ int fromIndex = 0) const; + + int LastIndexOf( + /* [in] */ const String& other, + /* [in] */ int fromIndex = 0) const; + + bool StartsWith( + /* [in] */ const char* string) const; + + bool StartsWith( + /* [in] */ const String& other) const; + + bool EndsWith( + /* [in] */ const char* string) const; + + bool EndsWith( + /* [in] */ const String& other) const; + + String ToLowerCase() const; + + String ToUpperCase() const; + + String Substring( + /* [in] */ int begin) const; + + String Substring( + /* [in] */ int begin, + /* [in] */ int end) const; + + String Replace( + /* [in] */ char oldChar, + /* [in] */ char newChar) const; + + String Replace( + /* [in] */ const char* target, + /* [in] */ const char* replacement) const; + + String Replace( + /* [in] */ const String& target, + /* [in] */ const String& replacement) const; + + String& operator=( + /* [in] */ const char* string); + + String& operator=( + /* [in] */ const String& other); + + String& operator=( + /* [in] */ String&& other); + + String operator+=( + /* [in] */ const char* string) const; + + String operator+=( + /* [in] */ const String& other) const; + + static String Format( + /* [in] */ const char* format, ...); + + static const char* TAG; + static constexpr int MAX_SIZE = 262144; // 2^18 + +private: + String( + /* [in] */ int size); + + int LastIndexOfInternal( + /* [in] */ const char* string, + /* [in] */ int fromIndex) const; + + char* string_ = nullptr; +}; + +inline String operator+( + /* [in] */ const String& string1, + /* [in] */ const char* string2) +{ + return string1 += string2; +} + +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); + } +}; + +} +} + +#endif // OHOS_ZIDL_STRING_H diff --git a/zidl/util/string_builder.cpp b/zidl/util/string_builder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2caea4b58304e7ab7d0317361617e60f61c6935 --- /dev/null +++ b/zidl/util/string_builder.cpp @@ -0,0 +1,171 @@ +/* + * 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 "util/string_builder.h" + +#include +#include +#include +#include "securec.h" + +#include "util/logger.h" + +namespace OHOS { +namespace Zidl { + +const char* StringBuilder::TAG = "StringBuilder"; +constexpr int LINE_MAX_SIZE = 1024; + +StringBuilder::~StringBuilder() +{ + if (buffer_ != nullptr) { + free(buffer_); + } +} + +StringBuilder& StringBuilder::Append( + /* [in] */ char c) +{ + if (position_ + 1 >= capacity_) { + if (!Grow(1)) { + return *this; + } + } + + buffer_[position_] = c; + position_ += 1; + return *this; +} + +StringBuilder& StringBuilder::Append( + /* [in] */ 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( + /* [in] */ 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( + /* [in] */ 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( + /* [in] */ 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) { + errno_t ret = memcpy_s(newBuffer, newSize, buffer_, capacity_); + if (ret != EOK) { + free(newBuffer); + newBuffer = nullptr; + return false; + } + free(buffer_); + } + buffer_ = newBuffer; + capacity_ = newSize; + return true; +} + +String StringBuilder::ToString() const +{ + return String(buffer_, position_); +} + +} +} diff --git a/zidl/util/string_builder.h b/zidl/util/string_builder.h new file mode 100644 index 0000000000000000000000000000000000000000..54f4331d27ce0c04872349408edc301e246c21f7 --- /dev/null +++ b/zidl/util/string_builder.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_STRINGBUILDER_H +#define OHOS_ZIDL_STRINGBUILDER_H + +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class StringBuilder { +public: + ~StringBuilder(); + + StringBuilder& Append( + /* [in] */ char c); + + StringBuilder& Append( + /* [in] */ const char* string); + + StringBuilder& Append( + /* [in] */ const String& string); + + StringBuilder& AppendFormat( + /* [in] */ const char* format, ...); + + String ToString() const; + +private: + bool Grow( + /* [in] */ size_t size); + + static const char* TAG; + char* buffer_ = nullptr; + size_t position_ = 0; + size_t capacity_ = 0; +}; + +} +} + +#endif // OHOS_ZIDL_STRINGBUILDER_H diff --git a/zidl/util/string_pool.cpp b/zidl/util/string_pool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..026bcffdeec26d4da388e5115dccc5890c8a2f6a --- /dev/null +++ b/zidl/util/string_pool.cpp @@ -0,0 +1,101 @@ +/* + * 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 "util/string_pool.h" +#include +#include "securec.h" +#include "util/logger.h" + +namespace OHOS { +namespace Zidl { + +const char* StringPool::TAG = "StringPool"; + +StringPool::StringPool() +{ + data_ = reinterpret_cast(calloc(1, dataCapacity_)); + if (data_ == nullptr) { + Logger::E(TAG, "Out of memory."); + } +} + +StringPool::~StringPool() +{ + if (data_ != nullptr) { + free(data_); + } +} + +void StringPool::Add( + /* [in] */ const String& string) +{ + if (string.IsEmpty() || stringOffsets_.find(string) != stringOffsets_.end()) { + return; + } + + ptrdiff_t offset = AddInternal(string); + if (offset != -1) { + stringOffsets_[string] = offset; + } +} + +ptrdiff_t StringPool::GetOffset( + /* [in] */ const String& string) +{ + return stringOffsets_[string]; +} + +ptrdiff_t StringPool::AddInternal( + /* [in] */ const String& string) +{ + if (!Grow(string.GetLength() + 1)) { + return -1; + } + + char* addr = data_ + dataOffset_; + (void)strcpy_s(addr, dataCapacity_ - dataOffset_, string.string()); + dataOffset_ += string.GetLength() + 1; + return addr - data_; +} + +bool StringPool::Grow( + /* [in] */ size_t expand) +{ + size_t newSize = dataOffset_ + expand; + if (newSize < dataCapacity_) { + return true; + } + // 3->3x capacity expansion + size_t step = dataCapacity_ * 3; + newSize = step > newSize ? step : step + newSize; + char* newData = reinterpret_cast(calloc(1, newSize)); + if (newData == nullptr) { + Logger::E(TAG, "Out of memory."); + return false; + } + errno_t ret = memcpy_s(newData, newSize, data_, dataOffset_); + if (ret != EOK) { + free(newData); + newData = nullptr; + return false; + } + free(data_); + data_ = newData; + dataCapacity_ = newSize; + return true; +} + +} +} diff --git a/zidl/util/string_pool.h b/zidl/util/string_pool.h new file mode 100644 index 0000000000000000000000000000000000000000..7b991512c4c20848afa4620ebf3b8553dcaa8fd1 --- /dev/null +++ b/zidl/util/string_pool.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#ifndef OHOS_ZIDL_STRINGPOOL_H +#define OHOS_ZIDL_STRINGPOOL_H + +#include +#include "util/string.h" + +namespace OHOS { +namespace Zidl { + +class StringPool { +public: + StringPool(); + + ~StringPool(); + + void Add( + /* [in] */ const String& string); + + ptrdiff_t GetOffset( + /* [in] */ const String& string); + + inline size_t GetSize() + { + return dataOffset_; + } + + inline char* GetData() + { + return data_; + } + +private: + ptrdiff_t AddInternal( + /* [in] */ const String& string); + + bool Grow( + /* [in] */ size_t expand); + + static const char* TAG; + char* data_ = nullptr; + size_t dataCapacity_ = 256; + ptrdiff_t dataOffset_ = 0; + std::unordered_map stringOffsets_; +}; + +} +} + +#endif // OHOS_ZIDL_STRINGPOOL_H