工具合一hdi codegen部分上库

Signed-off-by: millerluo <luoxueting2@huawei.com>
Change-Id: I294d55182142f967bcd25f0d1327558f50e18e62
This commit is contained in:
millerluo 2024-05-15 18:08:03 +08:00
parent c80c144c9a
commit 0c8d118a3b
41 changed files with 9427 additions and 2 deletions

View File

@ -35,9 +35,12 @@ OpenHarmony IDL接口描述语言主要用于
```
foundation/ability/idl_tool
├── ast # idl语法解析定义代码
├── codegen # 跨进程通信模板生成模块代码
├── codegen # 模板生成模块代码
├── hash # hash生成模块代码
├── lexer # 词法解析模块代码
├── metadata # matedata自定义数据解析模块代码
├── parser # idl解析模块代码
├── parser # 语法解析模块代码
├── preprocessor # 预处理模块代码
├── test # 测试目录
└── util # 公共方法代码
```

View File

@ -0,0 +1,850 @@
/*
* Copyright (c) 2024 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 "c_client_proxy_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
bool CClientProxyCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
directory_ = GetFileParentPath(targetDirectory);
} else {
return false;
}
if (!File::CreateParentDir(directory_)) {
Logger::E("CClientProxyCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CClientProxyCodeEmitter::EmitCode()
{
switch (mode_) {
case GenMode::PASSTHROUGH: {
if (!interface_->IsSerializable()) {
EmitPassthroughProxySourceFile();
}
break;
}
case GenMode::IPC:
case GenMode::KERNEL: {
EmitProxySourceFile();
break;
}
default:
break;
}
}
void CClientProxyCodeEmitter::EmitPassthroughProxySourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(proxyName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitPassthroughProxyInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(proxyName_));
sb.Append("\n");
EmitProxyGetMethodImpl(sb);
sb.Append("\n");
EmitPassthroughGetInstanceMethod(sb);
sb.Append("\n");
EmitProxyReleaseMethodImpl(sb);
sb.Append("\n");
EmitPassthroughReleaseInstanceMethod(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CClientProxyCodeEmitter::EmitPassthroughProxyInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CClientProxyCodeEmitter::EmitPassthroughGetInstanceMethod(StringBuilder &sb) const
{
sb.AppendFormat("struct %s *%sGetInstance(const char *serviceName, bool isStub)\n",
interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
EmitProxyLoadOrUnLoadHdiImpl("serviceName", true, sb, TAB);
sb.Append(TAB).Append("return NULL;\n");
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitPassthroughReleaseInstanceMethod(StringBuilder &sb) const
{
sb.AppendFormat("void %sReleaseInstance(const char *serviceName, struct %s *instance, bool isStub)\n",
interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("if (instance == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n\n");
EmitProxyLoadOrUnLoadHdiImpl("serviceName", false, sb, TAB);
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxySourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(proxyName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitProxyInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(proxyName_));
sb.Append("\n");
EmitProxyDefinition(sb);
sb.Append("\n");
EmitUtilMethods(sb, true);
sb.Append("\n");
EmitUtilMethods(sb, false);
sb.Append("\n");
if (mode_ != GenMode::KERNEL) {
EmitProxyCallMethodImpl(sb);
} else {
EmitProxyKernelCallMethodImpl(sb);
}
sb.Append("\n");
EmitProxyMethodImpls(sb);
sb.Append("\n");
EmitProxyConstruction(sb);
sb.Append("\n");
EmitProxyExternalMethodImpl(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CClientProxyCodeEmitter::EmitProxyInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
GetHeaderOtherLibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CClientProxyCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_sbuf");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
if (mode_ == GenMode::KERNEL) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_io_service_if");
} else {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "servmgr_hdi");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_dlist");
if (!interface_->IsSerializable()) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "stub_collector");
}
}
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
AutoPtr<ASTType> paramType = param->GetType();
if ((param->GetAttribute() == ASTParamAttr::PARAM_IN) &&
(paramType->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "stub_collector");
}
}
}
}
void CClientProxyCodeEmitter::EmitProxyDefinition(StringBuilder &sb) const
{
sb.AppendFormat("struct %sProxy {\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("struct %s impl;\n", interfaceName_.c_str());
if (mode_ == GenMode::KERNEL) {
sb.Append(TAB).Append("struct HdfIoService *serv;\n");
} else {
sb.Append(TAB).Append("struct HdfRemoteService *remote;\n");
}
sb.Append("};\n");
}
void CClientProxyCodeEmitter::EmitProxyCallMethodImpl(StringBuilder &sb) const
{
sb.AppendFormat("static int32_t %sProxyCall(struct %s *self, int32_t id, struct HdfSBuf *data,\n",
baseName_.c_str(), interfaceName_.c_str());
sb.Append(TAB).Append("struct HdfSBuf *reply, bool isOneWay)\n");
sb.Append("{\n");
std::string remoteName = "remote";
sb.Append(TAB).AppendFormat("struct HdfRemoteService *%s = self->AsObject(self);\n", remoteName.c_str());
sb.Append(TAB).AppendFormat("if (%s == NULL ||\n", remoteName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("%s->dispatcher == NULL ||\n", remoteName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("%s->dispatcher->Dispatch == NULL ||\n", remoteName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("%s->dispatcher->DispatchAsync == NULL) {\n", remoteName.c_str());
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: Invalid HdfRemoteService obj\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).AppendFormat("if (isOneWay) {\n");
sb.Append(TAB).Append(TAB).AppendFormat(
"return %s->dispatcher->DispatchAsync(%s, id, data, reply);\n", remoteName.c_str(), remoteName.c_str());
sb.Append(TAB).AppendFormat("} else {\n");
sb.Append(TAB).Append(TAB).AppendFormat(
"return %s->dispatcher->Dispatch(%s, id, data, reply);\n", remoteName.c_str(), remoteName.c_str());
sb.Append(TAB).AppendFormat("}\n");
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyKernelCallMethodImpl(StringBuilder &sb) const
{
sb.AppendFormat("static int32_t %sProxyCall(struct %s *self, int32_t id, struct HdfSBuf *data,\n",
baseName_.c_str(), interfaceName_.c_str());
sb.Append(TAB).Append("struct HdfSBuf *reply)\n");
sb.Append("{\n");
std::string remoteName = "serv";
sb.Append(TAB).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(self, struct %sProxy, impl);\n",
baseName_.c_str(), baseName_.c_str(), remoteName.c_str());
sb.Append(TAB).AppendFormat("struct HdfIoService *%s = proxy->%s;\n", remoteName.c_str(), remoteName.c_str());
sb.Append(TAB).AppendFormat("if (%s == NULL ||\n", remoteName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("%s->dispatcher == NULL ||\n", remoteName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("%s->dispatcher->Dispatch == NULL) {\n", remoteName.c_str());
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: Invalid HdfRemoteService obj\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("return %s->dispatcher->Dispatch(", remoteName.c_str());
sb.AppendFormat("(struct HdfObject *)&(%s->object), id, data, reply);\n", remoteName.c_str());
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder &sb)
{
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitProxyMethodImpl(method, sb);
sb.Append("\n");
}
EmitProxyMethodImpl(interface_->GetVersionMethod(), sb);
if (mode_ != GenMode::KERNEL) {
sb.Append("\n");
EmitProxyAsObjectMethodImpl(sb);
}
}
void CClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr<ASTMethod> &method, StringBuilder &sb)
{
if (method->GetParameterNumber() == 0) {
sb.AppendFormat("static int32_t %sProxy%s(struct %s *self)\n", baseName_.c_str(), method->GetName().c_str(),
interfaceName_.c_str());
} else {
StringBuilder paramStr;
paramStr.AppendFormat("static int32_t %sProxy%s(", baseName_.c_str(), method->GetName().c_str());
paramStr.AppendFormat("struct %s *self, ", interfaceName_.c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
if (i + 1 < method->GetParameterNumber()) {
paramStr.Append(", ");
}
}
paramStr.Append(")");
sb.Append(SpecificationParam(paramStr, TAB));
sb.Append("\n");
}
EmitProxyMethodBody(method, sb, "");
}
void CClientProxyCodeEmitter::EmitProxyMethodBody(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
{
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("int32_t %s = HDF_FAILURE;\n", HdiTypeEmitter::errorCodeName_.c_str());
// Local variable definitions must precede all execution statements.
EmitMethodNeedLoopVar(method, true, false, sb, prefix + TAB);
sb.Append("\n");
EmitCreateBuf(HdiTypeEmitter::dataParcelName_, HdiTypeEmitter::replyParcelName_, sb, prefix + TAB);
sb.Append("\n");
EmitCheckThisPointer(sb, prefix + TAB);
if (mode_ != GenMode::KERNEL) {
sb.Append("\n");
EmitWriteInterfaceToken(HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
}
sb.Append("\n");
EmitWriteFlagOfNeedSetMem(method, HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
typeEmitter->EmitCWriteVar(TypeMode::PARAM_IN, param->GetName(), finishedLabel_, sb, prefix + TAB);
sb.Append("\n");
} else {
typeEmitter->EmitCProxyWriteOutVar(param->GetName(), finishedLabel_, sb, prefix + TAB);
}
}
EmitStubCallMethod(method, sb, prefix + TAB);
sb.Append("\n");
if (!method->IsOneWay()) {
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
if (param->GetAttribute() == ASTParamAttr::PARAM_OUT) {
EmitReadProxyMethodParameter(param, finishedLabel_, sb, prefix + TAB);
sb.Append("\n");
}
}
}
sb.Append(prefix).AppendFormat("%s:\n", finishedLabel_);
EmitReleaseBuf(HdiTypeEmitter::dataParcelName_, HdiTypeEmitter::replyParcelName_, sb, prefix + TAB);
sb.Append(prefix + TAB).AppendFormat("return %s;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitCreateBuf(const std::string &dataBufName,
const std::string &replyBufName, StringBuilder &sb, const std::string &prefix) const
{
if (mode_ == GenMode::KERNEL) {
sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufObtainDefaultSize();\n", dataBufName.c_str());
sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufObtainDefaultSize();\n", replyBufName.c_str());
} else {
sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufTypedObtain(SBUF_IPC);\n", dataBufName.c_str());
sb.Append(prefix).AppendFormat("struct HdfSBuf *%s = HdfSbufTypedObtain(SBUF_IPC);\n", replyBufName.c_str());
}
sb.Append("\n");
sb.Append(prefix).AppendFormat("if (%s == NULL || %s == NULL) {\n", dataBufName.c_str(), replyBufName.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: HdfSubf malloc failed!\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabel_);
sb.Append(prefix).Append("}\n");
}
void CClientProxyCodeEmitter::EmitCheckThisPointer(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).Append("if (self == NULL) {\n");
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: invalid interface object\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_OBJECT;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabel_);
sb.Append(prefix).Append("}\n");
}
void CClientProxyCodeEmitter::EmitWriteInterfaceToken(
const std::string &dataBufName, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat(
"if (!HdfRemoteServiceWriteInterfaceToken(self->AsObject(self), %s)) {\n", dataBufName.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: write interface token failed!\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabel_);
sb.Append(prefix).Append("}\n");
}
void CClientProxyCodeEmitter::EmitWriteFlagOfNeedSetMem(const AutoPtr<ASTMethod> &method,
const std::string &dataBufName, StringBuilder &sb, const std::string &prefix) const
{
if (NeedFlag(method)) {
sb.Append(prefix).AppendFormat("if (!HdfSbufWriteUint8(%s, 1)) {\n", dataBufName.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: write flag of memory setting failed!\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabel_);
sb.Append(prefix).Append("}\n\n");
}
}
void CClientProxyCodeEmitter::EmitReleaseBuf(const std::string &dataBufName,
const std::string &replyBufName, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", dataBufName.c_str());
sb.Append(prefix + TAB).AppendFormat("HdfSbufRecycle(%s);\n", dataBufName.c_str());
sb.Append(prefix).Append("}\n");
sb.Append(prefix).AppendFormat("if (%s != NULL) {\n", replyBufName.c_str());
sb.Append(prefix + TAB).AppendFormat("HdfSbufRecycle(%s);\n", replyBufName.c_str());
sb.Append(prefix).Append("}\n");
}
void CClientProxyCodeEmitter::EmitReadProxyMethodParameter(const AutoPtr<ASTParameter> &param,
const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTType> type = param->GetType();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
std::string name = param->GetName();
if (type->GetTypeKind() == TypeKind::TYPE_STRING) {
std::string cloneName = StringHelper::Format("%sCopy", name.c_str());
typeEmitter->EmitCProxyReadVar(cloneName, false, gotoLabel, sb, prefix);
sb.Append(prefix).AppendFormat("if (strcpy_s(%s, %sLen, %s) != EOK) {\n", name.c_str(),
name.c_str(), cloneName.c_str());
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", name.c_str());
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
sb.Append(prefix).Append("}\n");
} else if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
std::string cpName = StringHelper::Format("%sCp", name.c_str());
typeEmitter->EmitCProxyReadVar(cpName, false, gotoLabel, sb, prefix);
sb.Append(prefix).AppendFormat("if (memcpy_s(%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n",
name.c_str(), typeEmitter->EmitCType().c_str(), cpName.c_str(), typeEmitter->EmitCType().c_str());
sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: failed to memcpy %s\", __func__);\n",
name.c_str());
sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix).Append("}\n");
} else {
typeEmitter->EmitCProxyReadVar(name, false, gotoLabel, sb, prefix);
}
}
void CClientProxyCodeEmitter::EmitStubCallMethod(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
{
if (mode_ != GenMode::KERNEL) {
sb.Append(prefix).AppendFormat("%s = %sCall(self, %s, %s, %s, %s);\n", HdiTypeEmitter::errorCodeName_.c_str(),
proxyName_.c_str(), EmitMethodCmdID(method).c_str(), HdiTypeEmitter::dataParcelName_.c_str(),
HdiTypeEmitter::replyParcelName_.c_str(),
method->IsOneWay() ? "true" : "false");
} else {
sb.Append(prefix).AppendFormat("%s = %sCall(self, %s, %s, %s);\n", HdiTypeEmitter::errorCodeName_.c_str(),
proxyName_.c_str(), EmitMethodCmdID(method).c_str(), HdiTypeEmitter::dataParcelName_.c_str(),
HdiTypeEmitter::replyParcelName_.c_str());
}
sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat(
"HDF_LOGE(\"%%{public}s: call failed! error code is %%{public}d\", __func__, %s);\n",
HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabel_);
sb.Append(prefix).Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyAsObjectMethodImpl(StringBuilder &sb) const
{
sb.AppendFormat("static struct HdfRemoteService *%sProxyAsObject(struct %s *self)\n", baseName_.c_str(),
interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("if (self == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return NULL;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).AppendFormat(
"struct %sProxy *proxy = CONTAINER_OF(self, struct %sProxy, impl);\n", baseName_.c_str(), baseName_.c_str());
sb.Append(TAB).Append("return proxy->remote;\n");
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyConstruction(StringBuilder &sb) const
{
std::string objName = "impl";
sb.AppendFormat(
"static void %sProxyConstruct(struct %s *%s)\n", baseName_.c_str(), interfaceName_.c_str(), objName.c_str());
sb.Append("{\n");
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
sb.Append(TAB).AppendFormat("%s->%s = %sProxy%s;\n", objName.c_str(), method->GetName().c_str(),
baseName_.c_str(), method->GetName().c_str());
}
AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
sb.Append(TAB).AppendFormat("%s->%s = %sProxy%s;\n", objName.c_str(), getVerMethod->GetName().c_str(),
baseName_.c_str(), getVerMethod->GetName().c_str());
if (mode_ != GenMode::KERNEL) {
sb.Append(TAB).AppendFormat("%s->AsObject = %sProxyAsObject;\n", objName.c_str(), baseName_.c_str());
}
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyExternalMethodImpl(StringBuilder &sb)
{
if (mode_ == GenMode::KERNEL) {
EmitKernelProxyExternalMethodImpl(sb);
} else if (interface_->IsSerializable()) {
EmitSerialProxyExternalMethodImpl(sb);
} else {
EmitProxyExternalMethod(sb);
}
}
void CClientProxyCodeEmitter::EmitKernelProxyExternalMethodImpl(StringBuilder &sb)
{
std::string remoteName = "serv";
EmitKernelProxyGetMethodImpl(sb);
sb.Append("\n");
EmitKernelProxyGetInstanceMethodImpl(remoteName, sb);
sb.Append("\n");
EmitKernelProxyReleaseMethodImpl(remoteName, "HdfIoServiceRecycle", sb);
}
void CClientProxyCodeEmitter::EmitKernelProxyGetMethodImpl(StringBuilder &sb) const
{
sb.AppendFormat("struct %s *%sGet()\n", interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat("return %sGetInstance(\"%s\");\n", interfaceName_.c_str(),
FileName(implName_).c_str());
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitKernelProxyGetInstanceMethodImpl(const std::string &remoteName,
StringBuilder &sb) const
{
std::string objName = "client";
std::string serMajorName = "serMajorVer";
std::string serMinorName = "serMinorVer";
std::string serviceName = "serviceName";
sb.AppendFormat("struct %s *%sGetInstance(const char* %s)\n", interfaceName_.c_str(), interfaceName_.c_str(),
serviceName.c_str());
sb.Append("{\n");
EmitProxyGetRemoteService(remoteName, serviceName, sb, TAB);
sb.Append("\n");
EmitProxyCreateProxyObject(objName, remoteName, "HdfIoServiceRecycle", sb, TAB);
sb.Append("\n");
EmitProxyCheckVersion(objName, serMajorName, serMinorName, sb, TAB);
sb.Append("\n");
sb.Append(TAB).AppendFormat("return %s;\n", objName.c_str());
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitKernelProxyReleaseMethodImpl(
const std::string &remoteName, const std::string &recycleFuncName, StringBuilder &sb) const
{
sb.AppendFormat("void %sRelease(struct %s *instance)\n", interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("if (instance == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(instance, struct %sProxy, impl);\n",
baseName_.c_str(), baseName_.c_str());
sb.Append(TAB).AppendFormat("%s(proxy->%s);\n", recycleFuncName.c_str(), remoteName.c_str());
sb.Append(TAB).Append("OsalMemFree(proxy);\n");
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitSerialProxyExternalMethodImpl(StringBuilder &sb)
{
std::string serMajorName = "serMajorVer";
std::string serMinorName = "serMinorVer";
std::string remoteName = "remote";
EmitIfaceProxyGetMethodImpl(serMajorName, serMinorName, remoteName, sb);
sb.Append("\n");
if (interface_->IsCallback()) {
EmitCbProxyReleaseMethodImpl(remoteName, "HdfRemoteServiceRecycle", sb);
} else {
EmitIfaceProxyReleaseMethodImpl(remoteName, "HdfRemoteServiceRecycle", sb);
}
}
void CClientProxyCodeEmitter::EmitIfaceProxyGetMethodImpl(const std::string &serMajorName,
const std::string &serMinorName, const std::string &remoteName, StringBuilder &sb)
{
std::string objName = "client";
sb.AppendFormat("struct %s *%sGet(struct HdfRemoteService *%s)\n", interfaceName_.c_str(), interfaceName_.c_str(),
remoteName.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", remoteName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("HDF_LOGE(\"%%{public}s: remote is null\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return NULL;\n");
sb.Append(TAB).Append("}\n\n");
EmitProxySetInterfaceDesc(remoteName, "HdfRemoteServiceRecycle", sb, TAB);
sb.Append("\n");
EmitProxyCreateProxyObject(objName, remoteName, "HdfRemoteServiceRecycle", sb, TAB);
sb.Append("\n");
EmitProxyCheckVersion(objName, serMajorName, serMinorName, sb, TAB);
sb.Append("\n");
sb.Append(TAB).AppendFormat("return %s;\n", objName.c_str());
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitIfaceProxyReleaseMethodImpl(
const std::string &remoteName, const std::string &recycleFuncName, StringBuilder &sb) const
{
std::string implReleaseMethodName = StringHelper::Format("%sImplRelease", interfaceName_.c_str());
sb.AppendFormat("void %s(struct %s *instance) __attribute__((weak));\n", implReleaseMethodName.c_str(),
interfaceName_.c_str());
sb.AppendFormat("void %sRelease(struct %s *instance, bool isStub)\n", interfaceName_.c_str(),
interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("if (instance == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).Append("if (isStub) {\n");
sb.Append(TAB).Append(TAB).AppendFormat("if (%s != NULL) {\n", implReleaseMethodName.c_str());
sb.Append(TAB).Append(TAB).Append(TAB).AppendFormat("%s(instance);\n", implReleaseMethodName.c_str());
sb.Append(TAB).Append(TAB).Append("}\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(instance, struct %sProxy, impl);\n",
baseName_.c_str(), baseName_.c_str());
sb.Append(TAB).AppendFormat("%s(proxy->%s);\n", recycleFuncName.c_str(), remoteName.c_str());
sb.Append(TAB).Append("OsalMemFree(proxy);\n");
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitCbProxyReleaseMethodImpl(const std::string &remoteName,
const std::string &recycleFuncName, StringBuilder &sb) const
{
sb.AppendFormat("void %sRelease(struct %s *instance)\n", interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("if (instance == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(instance, struct %sProxy, impl);\n",
baseName_.c_str(), baseName_.c_str());
sb.Append(TAB).AppendFormat("%s(proxy->%s);\n", recycleFuncName.c_str(), remoteName.c_str());
sb.Append(TAB).Append("OsalMemFree(proxy);\n");
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyExternalMethod(StringBuilder &sb)
{
std::string remoteName = "remote";
std::string serviceName = "serviceName";
EmitProxyGetMethodImpl(sb);
sb.Append("\n");
EmitProxyGetInstanceMethodImpl(remoteName, serviceName, sb);
sb.Append("\n");
EmitProxyReleaseMethodImpl(sb);
sb.Append("\n");
EmitProxyReleaseInstanceMethodImpl(serviceName, remoteName, "HdfRemoteServiceRecycle", sb);
}
void CClientProxyCodeEmitter::EmitProxyGetMethodImpl(StringBuilder &sb) const
{
sb.AppendFormat("struct %s *%sGet(bool isStub)\n", interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat("return %sGetInstance(\"%s\", isStub);\n", interfaceName_.c_str(),
FileName(implName_).c_str());
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyGetInstanceMethodImpl(const std::string &remoteName,
const std::string &serviceName, StringBuilder &sb) const
{
std::string objName = "client";
std::string serMajorName = "serMajorVer";
std::string serMinorName = "serMinorVer";
sb.AppendFormat("struct %s *%sGetInstance(const char *%s, bool isStub)\n", interfaceName_.c_str(),
interfaceName_.c_str(), serviceName.c_str());
sb.Append("{\n");
EmitProxyLoadOrUnLoadHdiImpl(serviceName, true, sb, TAB);
sb.Append("\n");
EmitProxyGetRemoteService(remoteName, serviceName, sb, TAB);
sb.Append("\n");
EmitProxySetInterfaceDesc(remoteName, "HdfRemoteServiceRecycle", sb, TAB);
sb.Append("\n");
EmitProxyCreateProxyObject(objName, remoteName, "HdfRemoteServiceRecycle", sb, TAB);
sb.Append("\n");
EmitProxyCheckVersion(objName, serMajorName, serMinorName, sb, TAB);
sb.Append("\n");
sb.Append(TAB).AppendFormat("return %s;\n", objName.c_str());
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyGetRemoteService(const std::string &remoteName,
const std::string &serviceName, StringBuilder &sb, const std::string &prefix) const
{
if (mode_ != GenMode::KERNEL) {
sb.Append(prefix).Append("struct HDIServiceManager *serviceMgr = HDIServiceManagerGet();\n");
sb.Append(prefix).Append("if (serviceMgr == NULL) {\n");
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: HDIServiceManager not found!\", __func__);\n");
sb.Append(prefix + TAB).Append("return NULL;\n");
sb.Append(prefix).Append("}\n\n");
sb.Append(prefix).AppendFormat("struct HdfRemoteService *%s = ", remoteName.c_str());
sb.AppendFormat("serviceMgr->GetService(serviceMgr, %s);\n", serviceName.c_str());
sb.Append(prefix).Append("HDIServiceManagerRelease(serviceMgr);\n");
sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", remoteName.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to get remote!\", __func__);\n");
sb.Append(prefix + TAB).Append("return NULL;\n");
sb.Append(prefix).Append("}\n");
} else {
sb.Append(prefix).AppendFormat("struct HdfIoService *%s = ", remoteName.c_str());
sb.AppendFormat("HdfIoServiceBind(%s);\n", serviceName.c_str());
sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", remoteName.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to get io service!\", __func__);\n");
sb.Append(prefix + TAB).Append("return NULL;\n");
sb.Append(prefix).Append("}\n");
}
}
void CClientProxyCodeEmitter::EmitProxySetInterfaceDesc(const std::string &remoteName,
const std::string &recycleFuncName, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("if (!HdfRemoteServiceSetInterfaceDesc(%s, %s)) {\n", remoteName.c_str(),
EmitDescMacroName().c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: set interface token failed!\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("%s(%s);\n", recycleFuncName.c_str(), remoteName.c_str());
sb.Append(prefix + TAB).Append("return NULL;\n");
sb.Append(prefix).Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyCreateProxyObject(const std::string &clientObjName,
const std::string &remoteName, const std::string &recycleFuncName, StringBuilder &sb,
const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("struct %sProxy *proxy = (struct %sProxy *)OsalMemCalloc(sizeof(struct %sProxy));\n",
baseName_.c_str(), baseName_.c_str(), baseName_.c_str());
sb.Append(prefix).Append("if (proxy == NULL) {\n");
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s proxy failed!\", __func__);\n", interfaceName_.c_str());
if (!interface_->IsSerializable()) {
sb.Append(prefix + TAB).AppendFormat("%s(%s);\n", recycleFuncName.c_str(), remoteName.c_str());
}
sb.Append(prefix + TAB).Append("return NULL;\n");
sb.Append(prefix).Append("}\n");
sb.Append("\n");
sb.Append(prefix).AppendFormat("proxy->%s = %s;\n", remoteName.c_str(), remoteName.c_str());
sb.Append(prefix).AppendFormat("%sProxyConstruct(&proxy->impl);\n", baseName_.c_str());
sb.Append(prefix).AppendFormat("struct %s *%s = &proxy->impl;\n", interfaceName_.c_str(), clientObjName.c_str());
}
void CClientProxyCodeEmitter::EmitProxyCheckVersion(const std::string &clientObjName, const std::string &serMajorName,
const std::string &serMinorName, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("uint32_t %s = 0;\n", serMajorName.c_str());
sb.Append(prefix).AppendFormat("uint32_t %s = 0;\n", serMinorName.c_str());
sb.Append(prefix).AppendFormat("int32_t %s = %s->GetVersion(%s, &%s, &%s);\n",
HdiTypeEmitter::errorCodeName_.c_str(), clientObjName.c_str(), clientObjName.c_str(), serMajorName.c_str(),
serMinorName.c_str());
sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: get version failed!\", __func__);\n");
if (mode_ == GenMode::KERNEL) {
sb.Append(prefix + TAB).AppendFormat("%sRelease(%s);\n", interfaceName_.c_str(), clientObjName.c_str());
} else if (interface_->IsCallback()) {
sb.Append(prefix + TAB).AppendFormat("%sRelease(%s);\n", interfaceName_.c_str(), clientObjName.c_str());
} else {
sb.Append(prefix + TAB).AppendFormat("%sRelease(false, %s);\n", interfaceName_.c_str(), clientObjName.c_str());
}
sb.Append(prefix + TAB).Append("return NULL;\n");
sb.Append(prefix).Append("}\n\n");
sb.Append(prefix).AppendFormat("if (%s != %s) {\n", serMajorName.c_str(), majorVerName_.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s:check version failed! ");
sb.Append("version of service:%u.%u, version of client:%u.%u\", __func__,\n");
sb.Append(prefix + TAB + TAB).AppendFormat("%s, %s, %s, %s);\n", serMajorName.c_str(), serMinorName.c_str(),
majorVerName_.c_str(), minorVerName_.c_str());
if (mode_ == GenMode::KERNEL) {
sb.Append(prefix + TAB).AppendFormat("%sRelease(%s);\n", interfaceName_.c_str(), clientObjName.c_str());
} else if (interface_->IsCallback()) {
sb.Append(prefix + TAB).AppendFormat("%sRelease(%s);\n", interfaceName_.c_str(), clientObjName.c_str());
} else {
sb.Append(prefix + TAB).AppendFormat("%sRelease(false, %s);\n", interfaceName_.c_str(), clientObjName.c_str());
}
sb.Append(prefix + TAB).Append("return NULL;\n");
sb.Append(prefix).Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyReleaseMethodImpl(StringBuilder &sb) const
{
sb.AppendFormat(
"void %sRelease(struct %s *instance, bool isStub)\n", interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat(
"%sReleaseInstance(\"%s\", instance, isStub);\n", interfaceName_.c_str(), FileName(implName_).c_str());
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyReleaseInstanceMethodImpl(const std::string &serviceName,
const std::string &remoteName, const std::string &recycleFuncName, StringBuilder &sb)
{
sb.AppendFormat("void %sReleaseInstance(const char *%s, struct %s *instance, bool isStub)\n",
interfaceName_.c_str(), serviceName.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("if (instance == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n\n");
EmitProxyLoadOrUnLoadHdiImpl(serviceName, false, sb, TAB);
sb.Append("\n");
sb.Append(TAB).AppendFormat("struct %sProxy *proxy = CONTAINER_OF(instance, struct %sProxy, impl);\n",
baseName_.c_str(), baseName_.c_str());
sb.Append(TAB).AppendFormat("%s(proxy->%s);\n", recycleFuncName.c_str(), remoteName.c_str());
sb.Append(TAB).Append("OsalMemFree(proxy);\n");
sb.Append("}\n");
}
void CClientProxyCodeEmitter::EmitProxyLoadOrUnLoadHdiImpl(const std::string &serviceName, bool isLoad,
StringBuilder &sb, const std::string &prefix) const
{
std::string instName = "instName";
sb.Append(prefix).Append("if (isStub) {\n");
sb.Append(prefix + TAB).AppendFormat("const char *%s = %s;\n", instName.c_str(), serviceName.c_str());
sb.Append(prefix + TAB)
.AppendFormat("if (strcmp(%s, \"%s\") == 0) {\n", instName.c_str(), FileName(implName_).c_str());
sb.Append(prefix + TAB + TAB).AppendFormat("%s = \"service\";\n", instName.c_str());
sb.Append(prefix + TAB).Append("}\n");
if (isLoad) {
sb.Append(prefix + TAB).AppendFormat("return LoadHdiImpl(%s, %s);\n",
EmitDescMacroName().c_str(), instName.c_str());
} else {
sb.Append(prefix + TAB).AppendFormat("UnloadHdiImpl(%s, %s, instance);\n",
EmitDescMacroName().c_str(), instName.c_str());
sb.Append(prefix + TAB).Append("return;\n");
}
sb.Append(prefix).Append("}\n");
}
void CClientProxyCodeEmitter::EmitUtilMethods(StringBuilder &sb, bool isDecl)
{
UtilMethodMap methods;
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
typeEmitter->EmitCWriteMethods(methods, "", "", isDecl);
} else {
typeEmitter->EmitCReadMethods(methods, "", "", isDecl);
}
}
}
EmitUtilMethodMap(sb, methods);
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2024 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_IDL_HDI_C_CLIENT_PROXY_CODE_EMITTER_H
#define OHOS_IDL_HDI_C_CLIENT_PROXY_CODE_EMITTER_H
#include "hdi_c_code_emitter.h"
namespace OHOS {
namespace Idl {
class CClientProxyCodeEmitter : public HDICCodeEmitter {
public:
CClientProxyCodeEmitter() : HDICCodeEmitter() {}
~CClientProxyCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitPassthroughProxySourceFile();
void EmitPassthroughProxyInclusions(StringBuilder &sb);
void EmitPassthroughGetInstanceMethod(StringBuilder &sb) const;
void EmitPassthroughReleaseInstanceMethod(StringBuilder &sb) const;
void EmitProxySourceFile();
void EmitProxyDefinition(StringBuilder &sb) const;
void EmitProxyInclusions(StringBuilder &sb);
void GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitProxyCallMethodImpl(StringBuilder &sb) const;
void EmitProxyKernelCallMethodImpl(StringBuilder &sb) const;
void EmitProxyMethodImpls(StringBuilder &sb);
void EmitProxyMethodImpl(const AutoPtr<ASTMethod> &method, StringBuilder &sb);
void EmitProxyMethodBody(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix);
void EmitCreateBuf(const std::string &dataBufName,
const std::string &replyBufName, StringBuilder &sb, const std::string &prefix) const;
void EmitCheckThisPointer(StringBuilder &sb, const std::string &prefix) const;
void EmitWriteInterfaceToken(const std::string &dataBufName, StringBuilder &sb, const std::string &prefix) const;
void EmitWriteFlagOfNeedSetMem(const AutoPtr<ASTMethod> &method,
const std::string &dataBufName, StringBuilder &sb, const std::string &prefix) const;
void EmitReleaseBuf(const std::string &dataBufName,
const std::string &replyBufName, StringBuilder &sb, const std::string &prefix) const;
void EmitReadProxyMethodParameter(const AutoPtr<ASTParameter> &param, const std::string &gotoLabel,
StringBuilder &sb, const std::string &prefix) const;
void EmitStubCallMethod(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix);
void EmitProxyAsObjectMethodImpl(StringBuilder &sb) const;
void EmitProxyConstruction(StringBuilder &sb) const;
void EmitProxyExternalMethodImpl(StringBuilder &sb);
void EmitKernelProxyExternalMethodImpl(StringBuilder &sb);
// the get method for getting kernel driver client object
void EmitKernelProxyGetMethodImpl(StringBuilder &sb) const;
void EmitKernelProxyGetInstanceMethodImpl(const std::string &remoteName, StringBuilder &sb) const;
// the release metod for releasing kernel driver client object
void EmitKernelProxyReleaseMethodImpl(const std::string &remoteName, const std::string &recycleFuncName,
StringBuilder &sb) const;
void EmitSerialProxyExternalMethodImpl(StringBuilder &sb);
// the get method for getting interface object
void EmitIfaceProxyGetMethodImpl(const std::string &serMajorName, const std::string &serMinorName,
const std::string &remoteName, StringBuilder &sb);
// the release metod for releasing interface obj
void EmitIfaceProxyReleaseMethodImpl(
const std::string &remoteName, const std::string &recycleFuncName, StringBuilder &sb) const;
void EmitCbProxyReleaseMethodImpl(
const std::string &remoteName, const std::string &recycleFuncName, StringBuilder &sb) const;
void EmitProxyExternalMethod(StringBuilder &sb);
// the get method for getting driver client object
void EmitProxyGetMethodImpl(StringBuilder &sb) const;
void EmitProxyGetInstanceMethodImpl(const std::string &remoteName, const std::string &serviceName,
StringBuilder &sb) const;
void EmitProxyGetRemoteService(const std::string &remoteName,
const std::string &serviceName, StringBuilder &sb, const std::string &prefix) const;
void EmitProxySetInterfaceDesc(const std::string &remoteName, const std::string &recycleFuncName,
StringBuilder &sb, const std::string &prefix) const;
void EmitProxyCreateProxyObject(const std::string &clientObjName, const std::string &remoteName,
const std::string &recycleFuncName, StringBuilder &sb, const std::string &prefix) const;
void EmitProxyCheckVersion(const std::string &clientObjName, const std::string &serMajorName,
const std::string &serMinorName, StringBuilder &sb, const std::string &prefix) const;
// the release metod for releasing driver client obj
void EmitProxyReleaseMethodImpl(StringBuilder &sb) const;
void EmitProxyReleaseInstanceMethodImpl(const std::string &serviceName, const std::string &remoteName,
const std::string &recycleFuncName, StringBuilder &sb);
void EmitProxyLoadOrUnLoadHdiImpl(const std::string &serviceName, bool isLoad, StringBuilder &sb,
const std::string &prefix) const;
void EmitUtilMethods(StringBuilder &sb, bool isDecl) override;
std::vector<std::string> freeObjStatements_;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_HDI_C_CLIENT_PROXY_CODE_EMITTER_H

View File

@ -0,0 +1,537 @@
/*
* Copyright (c) 2024 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 "c_custom_types_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
#include "util/options.h"
namespace OHOS {
namespace Idl {
bool CCustomTypesCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() != ASTFileType::AST_TYPES) {
return false;
}
directory_ = GetFileParentPath(targetDirectory);
if (!File::CreateParentDir(directory_)) {
Logger::E("CCustomTypesCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CCustomTypesCodeEmitter::EmitCode()
{
switch (mode_) {
case GenMode::LOW:
case GenMode::PASSTHROUGH: {
EmitPassthroughCustomTypesHeaderFile();
break;
}
case GenMode::IPC:
case GenMode::KERNEL: {
EmitCustomTypesHeaderFile();
EmitCustomTypesSourceFile();
break;
}
default:
break;
}
}
void CCustomTypesCodeEmitter::EmitPassthroughCustomTypesHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, baseName_);
sb.Append("\n");
EmitPassthroughHeaderInclusions(sb);
sb.Append("\n");
EmitHeadExternC(sb);
sb.Append("\n");
EmitCustomTypeDecls(sb);
EmitTailExternC(sb);
sb.Append("\n");
EmitTailMacro(sb, baseName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CCustomTypesCodeEmitter::EmitPassthroughHeaderInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdint");
headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdbool");
GetStdlibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CCustomTypesCodeEmitter::EmitCustomTypesHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, baseName_);
sb.Append("\n");
EmitHeaderInclusions(sb);
sb.Append("\n");
EmitInterfaceBuffSizeMacro(sb);
sb.Append("\n");
EmitHeadExternC(sb);
sb.Append("\n");
EmitForwardDeclaration(sb);
sb.Append("\n");
EmitCustomTypeDecls(sb);
sb.Append("\n");
EmitCustomTypeFuncDecl(sb);
sb.Append("\n");
EmitTailExternC(sb);
sb.Append("\n");
EmitTailMacro(sb, baseName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CCustomTypesCodeEmitter::EmitHeaderInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdint");
headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdbool");
GetStdlibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CCustomTypesCodeEmitter::EmitForwardDeclaration(StringBuilder &sb) const
{
sb.Append("struct HdfSBuf;\n");
}
void CCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder &sb) const
{
for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(ast_->GetTypeDefintion(i));
sb.Append(typeEmitter->EmitCTypeDecl()).Append("\n");
if (i + 1 < ast_->GetTypeDefinitionNumber()) {
sb.Append("\n");
}
}
}
void CCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder &sb) const
{
for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
EmitCustomTypeMarshallFuncDecl(sb, type);
if (i + 1 < ast_->GetTypeDefinitionNumber()) {
sb.Append("\n");
}
}
}
}
void CCustomTypesCodeEmitter::EmitCustomTypeMarshallFuncDecl(StringBuilder &sb, const AutoPtr<ASTType> &type) const
{
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
std::string objName("dataBlock");
sb.AppendFormat("bool %sBlockMarshalling(struct HdfSBuf *data, const %s *%s);\n\n", type->GetName().c_str(),
typeEmitter->EmitCType().c_str(), objName.c_str());
sb.AppendFormat("bool %sBlockUnmarshalling(struct HdfSBuf *data, %s *%s);\n\n", type->GetName().c_str(),
typeEmitter->EmitCType().c_str(), objName.c_str());
sb.AppendFormat("void %sFree(%s *%s, bool freeSelf);\n", type->GetName().c_str(),
typeEmitter->EmitCType().c_str(), objName.c_str());
}
void CCustomTypesCodeEmitter::EmitCustomTypesSourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(baseName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitSoucreInclusions(sb);
sb.Append("\n");
EmitUtilMethods(sb, true);
sb.Append("\n");
EmitUtilMethods(sb, false);
sb.Append("\n");
EmitCustomTypeDataProcess(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CCustomTypesCodeEmitter::EmitSoucreInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(baseName_));
GetSourceOtherLibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CCustomTypesCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_sbuf");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
}
void CCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder &sb)
{
for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
EmitCustomTypeMarshallingImpl(sb, structType);
EmitCustomTypeUnmarshallingImpl(sb, structType);
sb.Append("\n");
EmitCustomTypeFreeImpl(sb, structType);
if (i + 1 < ast_->GetTypeDefinitionNumber()) {
sb.Append("\n");
}
}
}
}
void CCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
{
std::string typeName = GetTypeEmitter(type.Get())->EmitCType();
std::string objName("dataBlock");
sb.AppendFormat("bool %sBlockMarshalling(struct HdfSBuf *data, const %s *%s)\n", type->GetName().c_str(),
typeName.c_str(), objName.c_str());
sb.Append("{\n");
EmitMarshallingVarDecl(type, objName, sb, TAB);
EmitParamCheck(objName, sb, TAB);
sb.Append("\n");
if (type->IsPod()) {
if (Options::GetInstance().DoGenerateKernelCode()) {
sb.Append(TAB).AppendFormat("if (!HdfSbufWriteBuffer(data, (const void *)%s, sizeof(%s))) {\n",
objName.c_str(), typeName.c_str());
} else {
sb.Append(TAB).AppendFormat("if (!HdfSbufWriteUnpadBuffer(data, (const uint8_t *)%s, sizeof(%s))) {\n",
objName.c_str(), typeName.c_str());
}
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: failed to write buffer data\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return false;\n");
sb.Append(TAB).Append("}\n");
} else {
for (size_t i = 0; i < type->GetMemberNumber(); i++) {
std::string memberName = type->GetMemberName(i);
std::string name = StringHelper::Format("%s->%s", objName.c_str(), memberName.c_str());
GetTypeEmitter(type->GetMemberType(i))->EmitCMarshalling(name, sb, TAB);
sb.Append("\n");
}
}
sb.Append(TAB).Append("return true;\n");
sb.Append("}\n\n");
}
void CCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type)
{
std::string typeName = GetTypeEmitter(type.Get())->EmitCType();
std::string objName("dataBlock");
freeObjStatements_.clear();
sb.AppendFormat("bool %sBlockUnmarshalling(struct HdfSBuf *data, %s *%s)\n", type->GetName().c_str(),
typeName.c_str(), objName.c_str());
sb.Append("{\n");
EmitUnmarshallingVarDecl(type, objName, sb, TAB);
EmitParamCheck(objName, sb, TAB);
sb.Append("\n");
if (type->IsPod()) {
EmitPodTypeUnmarshalling(typeName, objName, sb, TAB);
} else {
for (size_t i = 0; i < type->GetMemberNumber(); i++) {
AutoPtr<ASTType> memberType = type->GetMemberType(i);
EmitMemberUnmarshalling(memberType, objName, type->GetMemberName(i), sb, TAB);
}
}
sb.Append(TAB).Append("return true;\n");
sb.AppendFormat("%s:\n", errorsLabel_ );
EmitCustomTypeMemoryRecycle(type, objName, sb, TAB);
sb.Append(TAB).Append("return false;\n");
sb.Append("}\n");
}
void CCustomTypesCodeEmitter::EmitMarshallingVarDecl(const AutoPtr<ASTStructType> &type,
const std::string &name, StringBuilder &sb, const std::string &prefix) const
{
(void)name;
if (!Options::GetInstance().DoGenerateKernelCode()) {
return;
}
for (size_t i = 0; i < type->GetMemberNumber(); i++) {
if (EmitNeedLoopVar(type->GetMemberType(i), true, false)) {
sb.Append(prefix).Append("uint32_t i = 0;\n");
break;
}
}
}
void CCustomTypesCodeEmitter::EmitUnmarshallingVarDecl(
const AutoPtr<ASTStructType> &type, const std::string &name, StringBuilder &sb, const std::string &prefix) const
{
if (!Options::GetInstance().DoGenerateKernelCode()) {
return;
}
if (type->IsPod()) {
sb.Append(prefix).AppendFormat("%s *%sPtr = NULL;\n",
GetTypeEmitter(type.Get())->EmitCType().c_str(), name.c_str());
sb.Append(prefix).AppendFormat("uint32_t %sLen = 0;\n\n", name.c_str());
return;
}
for (size_t i = 0; i < type->GetMemberNumber(); i++) {
if (EmitNeedLoopVar(type->GetMemberType(i), true, true)) {
sb.Append(prefix).Append("uint32_t i = 0;\n");
break;
}
}
}
void CCustomTypesCodeEmitter::EmitParamCheck(
const std::string &name, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).Append("if (data == NULL) {\n");
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: invalid sbuf\", __func__);\n");
sb.Append(prefix + TAB).Append("return false;\n");
sb.Append(prefix).Append("}\n\n");
sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", name.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: invalid data block\", __func__);\n");
sb.Append(prefix + TAB).Append("return false;\n");
sb.Append(prefix).Append("}\n");
}
void CCustomTypesCodeEmitter::EmitPodTypeUnmarshalling(
const std::string &typeName, const std::string &name, StringBuilder &sb, const std::string &prefix) const
{
std::string objPtrName = StringHelper::Format("%sPtr", name.c_str());
if (Options::GetInstance().DoGenerateKernelCode()) {
std::string lenName = StringHelper::Format("%sLen", name.c_str());
sb.Append(prefix).AppendFormat(
"if (!HdfSbufReadBuffer(data, (const void**)&%s, &%s)) {\n", objPtrName.c_str(), lenName.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to read buffer data\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", errorsLabel_ );
sb.Append(prefix).Append("}\n\n");
sb.Append(prefix).AppendFormat(
"if (%s == NULL || %s != sizeof(%s)) {\n", objPtrName.c_str(), lenName.c_str(), typeName.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: invalid data from reading buffer\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", errorsLabel_ );
sb.Append(prefix).Append("}\n");
} else {
sb.Append(prefix).AppendFormat("const %s *%s = (const %s *)HdfSbufReadUnpadBuffer(data, sizeof(%s));\n",
typeName.c_str(), objPtrName.c_str(), typeName.c_str(), typeName.c_str());
sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", objPtrName.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to read buffer data\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", errorsLabel_ );
sb.Append(prefix).Append("}\n\n");
}
sb.Append(prefix).AppendFormat("if (memcpy_s(%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n", name.c_str(),
typeName.c_str(), objPtrName.c_str(), typeName.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to memcpy data\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", errorsLabel_ );
sb.Append(prefix).Append("}\n\n");
}
void CCustomTypesCodeEmitter::EmitMemberUnmarshalling(const AutoPtr<ASTType> &type, const std::string &name,
const std::string &memberName, StringBuilder &sb, const std::string &prefix)
{
std::string varName = StringHelper::Format("%s->%s", name.c_str(), memberName.c_str());
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
switch (type->GetTypeKind()) {
case TypeKind::TYPE_STRING: {
EmitStringMemberUnmarshalling(typeEmitter, memberName, varName, sb, prefix);
break;
}
case TypeKind::TYPE_STRUCT: {
std::string paramName = StringHelper::Format("&%s", varName.c_str());
typeEmitter->EmitCUnMarshalling(paramName, errorsLabel_, sb, prefix, freeObjStatements_);
sb.Append("\n");
break;
}
case TypeKind::TYPE_UNION: {
std::string tmpName = StringHelper::Format("%sCp", memberName.c_str());
typeEmitter->EmitCUnMarshalling(tmpName, errorsLabel_, sb, prefix, freeObjStatements_);
sb.Append(prefix).AppendFormat("if (memcpy_s(&%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n", varName.c_str(),
typeEmitter->EmitCType().c_str(), tmpName.c_str(), typeEmitter->EmitCType().c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: failed to memcpy data\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", errorsLabel_ );
sb.Append(prefix).Append("}\n");
break;
}
case TypeKind::TYPE_ARRAY:
case TypeKind::TYPE_LIST: {
EmitArrayMemberUnmarshalling(type, memberName, varName, sb, prefix);
sb.Append("\n");
break;
}
default: {
typeEmitter->EmitCUnMarshalling(varName, errorsLabel_, sb, prefix, freeObjStatements_);
sb.Append("\n");
}
}
}
void CCustomTypesCodeEmitter::EmitStringMemberUnmarshalling(const AutoPtr<HdiTypeEmitter> &typeEmitter,
const std::string &memberName, const std::string &varName, StringBuilder &sb, const std::string &prefix)
{
std::string tmpName = StringHelper::Format("%sCp", memberName.c_str());
sb.Append(prefix).Append("{\n");
typeEmitter->EmitCUnMarshalling(tmpName, errorsLabel_, sb, prefix + TAB, freeObjStatements_);
if (Options::GetInstance().DoGenerateKernelCode()) {
sb.Append(prefix + TAB)
.AppendFormat("%s = (char*)OsalMemCalloc(strlen(%s) + 1);\n", varName.c_str(), tmpName.c_str());
sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", varName.c_str());
sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", errorsLabel_ );
sb.Append(prefix + TAB).Append("}\n");
sb.Append(prefix + TAB).AppendFormat("if (strcpy_s(%s, (strlen(%s) + 1), %s) != EOK) {\n",
varName.c_str(), tmpName.c_str(), tmpName.c_str());
sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", errorsLabel_ );
sb.Append(prefix + TAB).Append("}\n");
} else {
sb.Append(prefix + TAB).AppendFormat("%s = strdup(%s);\n", varName.c_str(), tmpName.c_str());
}
sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", varName.c_str());
sb.Append(prefix + TAB + TAB).AppendFormat("goto %s;\n", errorsLabel_ );
sb.Append(prefix + TAB).Append("}\n");
sb.Append(prefix).Append("}\n");
sb.Append("\n");
}
void CCustomTypesCodeEmitter::EmitArrayMemberUnmarshalling(const AutoPtr<ASTType> &type, const std::string &memberName,
const std::string &varName, StringBuilder &sb, const std::string &prefix)
{
std::string tmpName = StringHelper::Format("%sCp", memberName.c_str());
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
AutoPtr<ASTType> elementType = nullptr;
if (type->GetTypeKind() == TypeKind::TYPE_ARRAY) {
AutoPtr<ASTArrayType> arrayType = dynamic_cast<ASTArrayType *>(type.Get());
elementType = arrayType->GetElementType();
} else {
AutoPtr<ASTListType> listType = dynamic_cast<ASTListType *>(type.Get());
elementType = listType->GetElementType();
}
if (elementType->IsStringType()) {
typeEmitter->EmitCUnMarshalling(varName, errorsLabel_, sb, prefix, freeObjStatements_);
return;
}
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("%s* %s = NULL;\n",
GetTypeEmitter(elementType)->EmitCType().c_str(), tmpName.c_str());
sb.Append(prefix + TAB).AppendFormat("uint32_t %sLen = 0;\n", tmpName.c_str());
typeEmitter->EmitCUnMarshalling(tmpName, errorsLabel_, sb, prefix + TAB, freeObjStatements_);
sb.Append(prefix + TAB).AppendFormat("%s = %s;\n", varName.c_str(), tmpName.c_str());
sb.Append(prefix + TAB).AppendFormat("%sLen = %sLen;\n", varName.c_str(), tmpName.c_str());
sb.Append(prefix).Append("}\n");
}
void CCustomTypesCodeEmitter::EmitCustomTypeFreeImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type) const
{
std::string objName("dataBlock");
sb.AppendFormat("void %sFree(%s *%s, bool freeSelf)\n", type->GetName().c_str(),
GetTypeEmitter(type.Get())->EmitCType().c_str(), objName.c_str());
sb.Append("{\n");
if (mode_ == GenMode::KERNEL) {
for (size_t i = 0; i < type->GetMemberNumber(); i++) {
AutoPtr<ASTType> memberType = type->GetMemberType(i);
if (EmitNeedLoopVar(memberType, false, true)) {
sb.Append(TAB).Append("uint32_t i = 0;\n");
break;
}
}
}
sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n");
sb.Append("\n");
EmitCustomTypeMemoryRecycle(type, objName, sb, TAB);
sb.Append(TAB).Append("if (freeSelf) {\n");
sb.Append(TAB).Append(TAB).Append("OsalMemFree(dataBlock);\n");
sb.Append(TAB).Append("}\n");
sb.Append("}\n");
}
void CCustomTypesCodeEmitter::EmitCustomTypeMemoryRecycle(
const AutoPtr<ASTStructType> &type, const std::string &name, StringBuilder &sb, const std::string &prefix) const
{
for (size_t i = 0; i < type->GetMemberNumber(); i++) {
AutoPtr<ASTType> memberType = type->GetMemberType(i);
std::string memberName = type->GetMemberName(i);
std::string varName = StringHelper::Format("%s->%s", name.c_str(), memberName.c_str());
switch (memberType->GetTypeKind()) {
case TypeKind::TYPE_STRING:
case TypeKind::TYPE_STRUCT:
case TypeKind::TYPE_ARRAY:
case TypeKind::TYPE_LIST:
GetTypeEmitter(memberType)->EmitMemoryRecycle(varName, false, sb, prefix);
sb.Append("\n");
break;
default:
break;
}
}
}
void CCustomTypesCodeEmitter::EmitUtilMethods(StringBuilder &sb, bool isDecl)
{
UtilMethodMap methods;
for (const auto &typePair : ast_->GetTypes()) {
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(typePair.second);
typeEmitter->EmitCWriteMethods(methods, "", "", isDecl);
typeEmitter->EmitCStubReadMethods(methods, "", "", isDecl);
}
EmitUtilMethodMap(sb, methods);
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2024 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_IDL_HDI_C_CUSTOM_TYPES_CODE_EMITTER_H
#define OHOS_IDL_HDI_C_CUSTOM_TYPES_CODE_EMITTER_H
#include <vector>
#include "hdi_c_code_emitter.h"
namespace OHOS {
namespace Idl {
class CCustomTypesCodeEmitter : public HDICCodeEmitter {
public:
CCustomTypesCodeEmitter() : HDICCodeEmitter() {}
~CCustomTypesCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitPassthroughCustomTypesHeaderFile();
void EmitPassthroughHeaderInclusions(StringBuilder &sb);
void EmitCustomTypesHeaderFile();
void EmitHeaderInclusions(StringBuilder &sb);
void EmitForwardDeclaration(StringBuilder &sb) const;
void EmitCustomTypeDecls(StringBuilder &sb) const;
void EmitCustomTypeFuncDecl(StringBuilder &sb) const;
void EmitCustomTypeMarshallFuncDecl(StringBuilder &sb, const AutoPtr<ASTType> &type) const;
void EmitCustomTypesSourceFile();
void EmitSoucreInclusions(StringBuilder &sb);
void GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitCustomTypeDataProcess(StringBuilder &sb);
void EmitCustomTypeMarshallingImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type);
void EmitCustomTypeUnmarshallingImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type);
void EmitMarshallingVarDecl(const AutoPtr<ASTStructType> &type,
const std::string &name, StringBuilder &sb, const std::string &prefix) const;
void EmitUnmarshallingVarDecl(const AutoPtr<ASTStructType> &type,
const std::string &name, StringBuilder &sb, const std::string &prefix) const;
void EmitParamCheck(const std::string &name, StringBuilder &sb, const std::string &prefix) const;
void EmitPodTypeUnmarshalling(const std::string &typeName,
const std::string &name, StringBuilder &sb, const std::string &prefix) const;
void EmitMemberUnmarshalling(const AutoPtr<ASTType> &type, const std::string &name, const std::string &memberName,
StringBuilder &sb, const std::string &prefix);
void EmitStringMemberUnmarshalling(const AutoPtr<HdiTypeEmitter> &type, const std::string &memberName,
const std::string &varName, StringBuilder &sb, const std::string &prefix);
void EmitArrayMemberUnmarshalling(const AutoPtr<ASTType> &type, const std::string &memberName,
const std::string &varName, StringBuilder &sb, const std::string &prefix);
void EmitCustomTypeFreeImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type) const;
bool NeedEmitInitVar(const AutoPtr<ASTType> &type, bool needFree);
void EmitCustomTypeMemoryRecycle(const AutoPtr<ASTStructType> &type,
const std::string &name, StringBuilder &sb, const std::string &prefix) const;
void EmitUtilMethods(StringBuilder &sb, bool isDecl) override;
std::vector<std::string> freeObjStatements_;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_HDI_C_CUSTOM_TYPES_CODE_EMITTER_H

View File

@ -0,0 +1,291 @@
/*
* Copyright (c) 2024 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 "c_interface_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
bool CInterfaceCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
directory_ = GetFileParentPath(targetDirectory);
} else {
return false;
}
if (!File::CreateParentDir(directory_)) {
Logger::E("CInterfaceCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CInterfaceCodeEmitter::EmitCode()
{
switch (mode_) {
case GenMode::LOW: {
EmitLowModeInterfaceHeaderFile();
break;
}
case GenMode::PASSTHROUGH:
case GenMode::IPC:
case GenMode::KERNEL: {
EmitInterfaceHeaderFile();
break;
}
default:
break;
}
}
void CInterfaceCodeEmitter::EmitLowModeInterfaceHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(interfaceName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, interfaceFullName_);
sb.Append("\n");
EmitImportInclusions(sb);
sb.Append("\n");
EmitHeadExternC(sb);
sb.Append("\n");
EmitInterfaceVersionMacro(sb);
if (!interface_->IsSerializable()) {
sb.Append("\n");
EmitPreDeclaration(sb);
}
sb.Append("\n");
EmitInterfaceDefinition(sb);
if (!interface_->IsSerializable()) {
sb.Append("\n");
EmitLowModeExternalMethod(sb);
}
sb.Append("\n");
EmitTailExternC(sb);
sb.Append("\n");
EmitTailMacro(sb, interfaceFullName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CInterfaceCodeEmitter::EmitLowModeExternalMethod(StringBuilder &sb) const
{
sb.AppendFormat(
"inline struct %s *%sGet(const char *serviceName)\n", interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat(
"return (struct %s *)DevSvcManagerClntGetService(serviceName);\n", interfaceName_.c_str());
sb.Append("}\n");
}
void CInterfaceCodeEmitter::EmitInterfaceHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(interfaceName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, interfaceFullName_);
sb.Append("\n");
EmitImportInclusions(sb);
sb.Append("\n");
EmitHeadExternC(sb);
if (!Options::GetInstance().DoPassthrough()) {
sb.Append("\n");
EmitPreDeclaration(sb);
}
sb.Append("\n");
EmitInterfaceDesc(sb);
sb.Append("\n");
EmitInterfaceVersionMacro(sb);
if (!Options::GetInstance().DoPassthrough()) {
sb.Append("\n");
EmitInterfaceBuffSizeMacro(sb);
sb.Append("\n");
EmitInterfaceMethodCommands(sb, "");
}
sb.Append("\n");
EmitInterfaceDefinition(sb);
EmitExternalMethod(sb);
EmitTailExternC(sb);
sb.Append("\n");
EmitTailMacro(sb, interfaceFullName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CInterfaceCodeEmitter::EmitImportInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
GetStdlibInclusions(headerFiles);
GetImportInclusions(headerFiles);
GetHeaderOtherLibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CInterfaceCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
if (!Options::GetInstance().DoGenerateKernelCode()) {
headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdint");
headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdbool");
}
}
void CInterfaceCodeEmitter::EmitPreDeclaration(StringBuilder &sb) const
{
sb.Append("struct HdfRemoteService;\n");
}
void CInterfaceCodeEmitter::EmitInterfaceDesc(StringBuilder &sb) const
{
sb.AppendFormat("#define %s \"%s\"\n", EmitDescMacroName().c_str(), interfaceFullName_.c_str());
}
void CInterfaceCodeEmitter::EmitInterfaceVersionMacro(StringBuilder &sb) const
{
sb.AppendFormat("#define %s %u\n", majorVerName_.c_str(), ast_->GetMajorVer());
sb.AppendFormat("#define %s %u\n", minorVerName_.c_str(), ast_->GetMinorVer());
}
void CInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder &sb)
{
sb.AppendFormat("struct %s {\n", interfaceName_.c_str());
if (mode_ == GenMode::LOW && !interface_->IsSerializable()) {
sb.Append(TAB).Append("struct HdfRemoteService *service;\n\n");
}
EmitInterfaceMethods(sb, TAB);
sb.Append("};\n");
}
void CInterfaceCodeEmitter::EmitInterfaceMethods(StringBuilder &sb, const std::string &prefix) const
{
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitInterfaceMethod(method, sb, prefix);
sb.Append("\n");
}
EmitInterfaceMethod(interface_->GetVersionMethod(), sb, prefix);
if (mode_ == GenMode::IPC) {
sb.Append("\n");
EmitAsObjectMethod(sb, TAB);
}
}
void CInterfaceCodeEmitter::EmitInterfaceMethod(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat(
"int32_t (*%s)(struct %s *self);\n", method->GetName().c_str(), interfaceName_.c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat(
"int32_t (*%s)(struct %s *self, ", method->GetName().c_str(), interfaceName_.c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
if (i + 1 < method->GetParameterNumber()) {
paramStr.Append(", ");
}
}
paramStr.Append(");");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
}
void CInterfaceCodeEmitter::EmitAsObjectMethod(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("struct HdfRemoteService* (*AsObject)(struct %s *self);\n", interfaceName_.c_str());
}
void CInterfaceCodeEmitter::EmitExternalMethod(StringBuilder &sb) const
{
if (Options::GetInstance().DoPassthrough() && interface_->IsSerializable()) {
return;
}
sb.Append("\n");
EmitInterfaceGetMethodDecl(sb);
sb.Append("\n");
EmitInterfaceReleaseMethodDecl(sb);
}
void CInterfaceCodeEmitter::EmitInterfaceGetMethodDecl(StringBuilder &sb) const
{
if (mode_ == GenMode::KERNEL) {
sb.AppendFormat("struct %s *%sGet(void);\n", interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("\n");
sb.AppendFormat(
"struct %s *%sGetInstance(const char *instanceName);\n", interfaceName_.c_str(), interfaceName_.c_str());
return;
}
if (interface_->IsSerializable()) {
sb.Append("// no external method used to create client object, it only support ipc mode\n");
sb.AppendFormat("struct %s *%sGet(struct HdfRemoteService *remote);\n", interfaceName_.c_str(),
interfaceName_.c_str());
} else {
sb.Append("// external method used to create client object, it support ipc and passthrought mode\n");
sb.AppendFormat("struct %s *%sGet(bool isStub);\n", interfaceName_.c_str(), interfaceName_.c_str());
sb.AppendFormat("struct %s *%sGetInstance(const char *serviceName, bool isStub);\n", interfaceName_.c_str(),
interfaceName_.c_str());
}
}
void CInterfaceCodeEmitter::EmitInterfaceReleaseMethodDecl(StringBuilder &sb) const
{
if (mode_ == GenMode::KERNEL) {
sb.AppendFormat("void %sRelease(struct %s *instance);\n", interfaceName_.c_str(), interfaceName_.c_str());
return;
}
if (interface_->IsCallback()) {
sb.Append("// external method used to release client object, it support ipc and passthrought mode\n");
sb.AppendFormat("void %sRelease(struct %s *instance);\n", interfaceName_.c_str(),
interfaceName_.c_str());
} else if (interface_->IsSerializable()) {
sb.Append("// external method used to release client object, it support ipc and passthrought mode\n");
sb.AppendFormat("void %sRelease(struct %s *instance, bool isStub);\n", interfaceName_.c_str(),
interfaceName_.c_str());
} else {
sb.Append("// external method used to create release object, it support ipc and passthrought mode\n");
sb.AppendFormat("void %sRelease(struct %s *instance, bool isStub);\n", interfaceName_.c_str(),
interfaceName_.c_str());
sb.AppendFormat("void %sReleaseInstance(const char *serviceName, struct %s *instance, bool isStub);\n",
interfaceName_.c_str(), interfaceName_.c_str());
}
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2024 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_IDL_HDI_C_CLIENT_INTERFACE_CODE_EMITTER_H
#define OHOS_IDL_HDI_C_CLIENT_INTERFACE_CODE_EMITTER_H
#include "hdi_c_code_emitter.h"
namespace OHOS {
namespace Idl {
class CInterfaceCodeEmitter : public HDICCodeEmitter {
public:
CInterfaceCodeEmitter() : HDICCodeEmitter() {}
~CInterfaceCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitLowModeInterfaceHeaderFile();
void EmitLowModeExternalMethod(StringBuilder &sb) const;
void EmitInterfaceHeaderFile();
void EmitImportInclusions(StringBuilder &sb);
void GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitPreDeclaration(StringBuilder &sb) const;
void EmitInterfaceDesc(StringBuilder &sb) const;
void EmitInterfaceVersionMacro(StringBuilder &sb) const;
void EmitInterfaceDefinition(StringBuilder &sb);
void EmitInterfaceMethods(StringBuilder &sb, const std::string &prefix) const;
void EmitInterfaceMethod(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitAsObjectMethod(StringBuilder &sb, const std::string &prefix) const;
void EmitExternalMethod(StringBuilder &sb) const;
void EmitInterfaceGetMethodDecl(StringBuilder &sb) const;
void EmitInterfaceReleaseMethodDecl(StringBuilder &sb) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_HDI_C_CLIENT_INTERFACE_CODE_EMITTER_H

View File

@ -0,0 +1,403 @@
/*
* Copyright (c) 2024 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 "c_service_driver_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
#include "util/options.h"
namespace OHOS {
namespace Idl {
CServiceDriverCodeEmitter::CServiceDriverCodeEmitter() : HDICCodeEmitter(), hostName_("host")
{
}
bool CServiceDriverCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() != ASTFileType::AST_IFACE) {
return false;
}
directory_ = GetFileParentPath(targetDirectory);
if (!File::CreateParentDir(directory_)) {
Logger::E("CServiceDriverCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CServiceDriverCodeEmitter::EmitCode()
{
switch (mode_) {
case GenMode::LOW: {
EmitLowDriverSourceFile();
break;
}
case GenMode::IPC: {
if (!interface_->IsSerializable()) {
EmitDriverSourceFile();
}
break;
}
case GenMode::KERNEL: {
EmitDriverSourceFile();
break;
}
default:
break;
}
}
void CServiceDriverCodeEmitter::EmitLowDriverSourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(baseName_ + "Driver").c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
sb.Append("\n");
EmitLowDriverInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(baseName_ + "Driver"));
sb.Append("\n");
EmitLowDriverBind(sb);
sb.Append("\n");
EmitDriverInit(sb);
sb.Append("\n");
EmitLowDriverRelease(sb);
sb.Append("\n");
EmitDriverEntryDefinition(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CServiceDriverCodeEmitter::EmitLowDriverInclusions(StringBuilder &sb) const
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(implName_));
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_device_desc");
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CServiceDriverCodeEmitter::EmitLowDriverBind(StringBuilder &sb) const
{
sb.AppendFormat("static int Hdf%sDriverBind(struct HdfDeviceObject *deviceObject)\n", baseName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("HDF_LOGI(\"%s: driver bind start\", __func__);\n");
sb.Append(TAB).AppendFormat("struct %s *serviceImpl = %sGet();\n", implName_.c_str(), implName_.c_str());
sb.Append(TAB).Append("if (serviceImpl == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%s: failed to get service impl\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).Append("deviceObject->service = &serviceImpl->super.service;\n");
sb.Append(TAB).Append("return HDF_SUCCESS;\n");
sb.Append("}\n");
}
void CServiceDriverCodeEmitter::EmitLowDriverRelease(StringBuilder &sb) const
{
sb.AppendFormat("static void Hdf%sDriverRelease(struct HdfDeviceObject *deviceObject)\n", baseName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("HDF_LOGI(\"%s: driver release start\", __func__);\n");
sb.Append(TAB).Append("if (deviceObject == NULL || deviceObject->service == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%s: invalid device object\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat(
"struct %s *serviceImpl = (struct %s *)deviceObject->service;\n", implName_.c_str(), implName_.c_str());
sb.Append(TAB).Append("if (serviceImpl != NULL) {\n");
sb.Append(TAB).Append(TAB).AppendFormat("%sRelease(serviceImpl);\n", implName_.c_str());
sb.Append(TAB).Append("}\n");
sb.Append("}\n");
}
void CServiceDriverCodeEmitter::EmitDriverSourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(baseName_ + "Driver").c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitDriverInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(baseName_ + "Driver"));
sb.Append("\n");
EmitDriverServiceDecl(sb);
sb.Append("\n");
if (mode_ == GenMode::KERNEL) {
EmitKernelDriverDispatch(sb);
sb.Append("\n");
EmitDriverInit(sb);
sb.Append("\n");
EmitKernelDriverBind(sb);
sb.Append("\n");
EmitKernelDriverRelease(sb);
} else {
EmitDriverDispatch(sb);
sb.Append("\n");
EmitDriverInit(sb);
sb.Append("\n");
EmitDriverBind(sb);
sb.Append("\n");
EmitDriverRelease(sb);
}
sb.Append("\n");
EmitDriverEntryDefinition(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CServiceDriverCodeEmitter::EmitDriverInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
if (mode_ == GenMode::KERNEL) {
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(implName_));
} else {
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
}
GetDriverSourceOtherLibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CServiceDriverCodeEmitter::GetDriverSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_device_desc");
if (mode_ != GenMode::KERNEL) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_device_object");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_remote_service");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "stub_collector");
}
}
void CServiceDriverCodeEmitter::EmitDriverServiceDecl(StringBuilder &sb) const
{
sb.AppendFormat("struct Hdf%sHost {\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("struct IDeviceIoService ioService;\n");
if (mode_ == GenMode::KERNEL) {
sb.Append(TAB).AppendFormat("struct %s *service;\n", implName_.c_str());
} else {
sb.Append(TAB).AppendFormat("struct %s *service;\n", interfaceName_.c_str());
sb.Append(TAB).Append("struct HdfRemoteService **stubObject;\n");
}
sb.Append("};\n");
}
void CServiceDriverCodeEmitter::EmitKernelDriverDispatch(StringBuilder &sb)
{
sb.AppendFormat(
"static int32_t %sDriverDispatch(struct HdfDeviceIoClient *client, int cmdId,\n", baseName_.c_str());
sb.Append(TAB).Append("struct HdfSBuf *data, struct HdfSBuf *reply)\n");
sb.Append("{\n");
sb.Append(TAB).AppendFormat("struct Hdf%sHost *%s = CONTAINER_OF(\n", baseName_.c_str(), hostName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat(
"client->device->service, struct Hdf%sHost, ioService);\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("if (%s->service == NULL || %s->service->stub.OnRemoteRequest == NULL) {\n",
hostName_.c_str(), hostName_.c_str());
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: invalid service obj\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("return %s->service->stub.OnRemoteRequest(", hostName_.c_str());
sb.AppendFormat("&%s->service->stub.interface, cmdId, data, reply);\n", hostName_.c_str());
sb.Append("}\n");
}
void CServiceDriverCodeEmitter::EmitDriverDispatch(StringBuilder &sb)
{
sb.AppendFormat(
"static int32_t %sDriverDispatch(struct HdfDeviceIoClient *client, int cmdId,\n", baseName_.c_str());
sb.Append(TAB).Append("struct HdfSBuf *data, struct HdfSBuf *reply)\n");
sb.Append("{\n");
sb.Append(TAB).AppendFormat("struct Hdf%sHost *%s = CONTAINER_OF(", baseName_.c_str(), hostName_.c_str());
sb.AppendFormat("client->device->service, struct Hdf%sHost, ioService);\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("if (%s->service == NULL || %s->stubObject == NULL) {\n",
hostName_.c_str(), hostName_.c_str());
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: invalid service obj\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("struct HdfRemoteService *stubObj = *%s->stubObject;\n", hostName_.c_str());
sb.Append(TAB).AppendFormat("if (stubObj == NULL || stubObj->dispatcher == NULL || ");
sb.Append("stubObj->dispatcher->Dispatch == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).Append("return stubObj->dispatcher->Dispatch(");
sb.Append("(struct HdfRemoteService *)stubObj->target, cmdId, data, reply);\n");
sb.Append("}\n");
}
void CServiceDriverCodeEmitter::EmitDriverInit(StringBuilder &sb) const
{
sb.AppendFormat("static int Hdf%sDriverInit(struct HdfDeviceObject *deviceObject)\n", baseName_.c_str());
sb.Append("{\n");
if (mode_ == GenMode::LOW) {
sb.Append(TAB).Append("HDF_LOGI(\"%s: driver init start\", __func__);\n");
} else {
sb.Append(TAB).Append("HDF_LOGI(\"%{public}s: driver init start\", __func__);\n");
}
sb.Append(TAB).Append("return HDF_SUCCESS;\n");
sb.Append("}\n");
}
void CServiceDriverCodeEmitter::EmitKernelDriverBind(StringBuilder &sb)
{
sb.AppendFormat("static int Hdf%sDriverBind(struct HdfDeviceObject *deviceObject)\n", baseName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("HDF_LOGI(\"%{public}s: driver bind start\", __func__);\n");
sb.Append("\n");
sb.Append(TAB).AppendFormat("struct Hdf%sHost *%s = (struct Hdf%sHost *)OsalMemCalloc(", baseName_.c_str(),
hostName_.c_str(), baseName_.c_str());
sb.AppendFormat("sizeof(struct Hdf%sHost));\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", hostName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat(
"HDF_LOGE(\"Hdf%sDriverBind create Hdf%sHost object failed!\");\n", baseName_.c_str(), baseName_.c_str());
sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n");
sb.Append(TAB).Append("}\n");
sb.Append("\n");
sb.Append(TAB).AppendFormat("%s->ioService.Dispatch = %sDriverDispatch;\n", hostName_.c_str(), baseName_.c_str());
sb.Append(TAB).AppendFormat("%s->ioService.Open = NULL;\n", hostName_.c_str());
sb.Append(TAB).AppendFormat("%s->ioService.Release = NULL;\n", hostName_.c_str());
sb.Append(TAB).AppendFormat("%s->service = %sServiceGet();\n", hostName_.c_str(), baseName_.c_str());
sb.Append(TAB).AppendFormat("if (%s->service == NULL) {\n", hostName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(%s);\n", hostName_.c_str());
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: failed to get service object\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n");
sb.Append(TAB).Append("}\n");
sb.Append("\n");
sb.Append(TAB).AppendFormat("deviceObject->service = &%s->ioService;\n", hostName_.c_str());
sb.Append(TAB).Append("return HDF_SUCCESS;\n");
sb.Append("}\n");
}
void CServiceDriverCodeEmitter::EmitDriverBind(StringBuilder &sb)
{
sb.AppendFormat("static int Hdf%sDriverBind(struct HdfDeviceObject *deviceObject)\n", baseName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("HDF_LOGI(\"%{public}s: driver bind start\", __func__);\n");
sb.Append(TAB).AppendFormat("int32_t ret = HdfDeviceObjectSetInterfaceDesc(deviceObject, %s);\n",
EmitDescMacroName().c_str());
sb.Append(TAB).Append("if (ret != HDF_SUCCESS) {\n");
sb.Append(TAB).Append(TAB).Append(
"HDF_LOGE(\"%{public}s: failed to set interface descriptor of device object\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return ret;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("struct Hdf%sHost *%s = (struct Hdf%sHost *)OsalMemCalloc(", baseName_.c_str(),
hostName_.c_str(), baseName_.c_str());
sb.AppendFormat("sizeof(struct Hdf%sHost));\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", hostName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("HDF_LOGE(\"%%{public}s: create Hdf%sHost object failed!\", __func__);\n",
baseName_.c_str());
sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("struct %s *serviceImpl = %sGet(true);\n", interfaceName_.c_str(),
interfaceName_.c_str());
sb.Append(TAB).Append("if (serviceImpl == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: create serviceImpl failed!\", __func__);\n");
sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(%s);\n", hostName_.c_str());
sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("struct HdfRemoteService **stubObj = StubCollectorGetOrNewObject(");
sb.AppendFormat("%s, serviceImpl);\n", EmitDescMacroName().c_str());
sb.Append(TAB).Append("if (stubObj == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: failed to get stub object\", __func__);\n");
sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(%s);\n", hostName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("%sRelease(serviceImpl, true);\n", interfaceName_.c_str());
sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("%s->ioService.Dispatch = %sDriverDispatch;\n", hostName_.c_str(), baseName_.c_str());
sb.Append(TAB).AppendFormat("%s->ioService.Open = NULL;\n", hostName_.c_str());
sb.Append(TAB).AppendFormat("%s->ioService.Release = NULL;\n", hostName_.c_str());
sb.Append(TAB).AppendFormat("%s->service = serviceImpl;\n", hostName_.c_str());
sb.Append(TAB).AppendFormat("%s->stubObject = stubObj;\n", hostName_.c_str());
sb.Append(TAB).AppendFormat("deviceObject->service = &%s->ioService;\n", hostName_.c_str());
sb.Append(TAB).Append("return HDF_SUCCESS;\n");
sb.Append("}\n");
}
void CServiceDriverCodeEmitter::EmitKernelDriverRelease(StringBuilder &sb)
{
sb.AppendFormat("static void Hdf%sDriverRelease(struct HdfDeviceObject *deviceObject)\n", baseName_.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat("HDF_LOGI(\"Hdf%sDriverRelease enter.\");\n", baseName_.c_str());
sb.Append(TAB).Append("HDF_LOGI(\"%{public}s: driver release start\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("struct Hdf%sHost *%s = CONTAINER_OF(", baseName_.c_str(), hostName_.c_str());
sb.AppendFormat("deviceObject->service, struct Hdf%sHost, ioService);\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("if (%s != NULL) {\n", hostName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("%sServiceRelease(%s->service);\n", baseName_.c_str(), hostName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(%s);\n", hostName_.c_str());
sb.Append(TAB).Append("}\n");
sb.Append("}\n");
}
void CServiceDriverCodeEmitter::EmitDriverRelease(StringBuilder &sb)
{
sb.AppendFormat("static void Hdf%sDriverRelease(struct HdfDeviceObject *deviceObject)\n", baseName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("HDF_LOGI(\"%{public}s: driver release start\", __func__);\n");
sb.Append(TAB).Append("if (deviceObject->service == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("struct Hdf%sHost *%s = CONTAINER_OF(", baseName_.c_str(), hostName_.c_str());
sb.AppendFormat("deviceObject->service, struct Hdf%sHost, ioService);\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("if (%s != NULL) {\n", hostName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("StubCollectorRemoveObject(%s, %s->service);\n",
EmitDescMacroName().c_str(), hostName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("%sRelease(%s->service, true);\n", interfaceName_.c_str(),
hostName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(%s);\n", hostName_.c_str());
sb.Append(TAB).Append("}\n");
sb.Append("}\n");
}
void CServiceDriverCodeEmitter::EmitDriverEntryDefinition(StringBuilder &sb) const
{
sb.AppendFormat("struct HdfDriverEntry g_%sDriverEntry = {\n", StringHelper::StrToLower(baseName_).c_str());
sb.Append(TAB).Append(".moduleVersion = 1,\n");
sb.Append(TAB).AppendFormat(".moduleName = \"%s\",\n", Options::GetInstance().GetPackage().c_str());
sb.Append(TAB).AppendFormat(".Bind = Hdf%sDriverBind,\n", baseName_.c_str());
sb.Append(TAB).AppendFormat(".Init = Hdf%sDriverInit,\n", baseName_.c_str());
sb.Append(TAB).AppendFormat(".Release = Hdf%sDriverRelease,\n", baseName_.c_str());
sb.Append("};\n\n");
sb.AppendFormat("HDF_INIT(g_%sDriverEntry);\n", StringHelper::StrToLower(baseName_).c_str());
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2024 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_IDL_HDI_C_SERVICE_DRIVER_CODE_EMITTER_H
#define OHOS_IDL_HDI_C_SERVICE_DRIVER_CODE_EMITTER_H
#include "hdi_c_code_emitter.h"
namespace OHOS {
namespace Idl {
class CServiceDriverCodeEmitter : public HDICCodeEmitter {
public:
CServiceDriverCodeEmitter();
~CServiceDriverCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitLowDriverSourceFile();
void EmitLowDriverInclusions(StringBuilder &sb) const;
void EmitLowDriverBind(StringBuilder &sb) const;
void EmitLowDriverRelease(StringBuilder &sb) const;
void EmitDriverSourceFile();
void EmitDriverInclusions(StringBuilder &sb);
void GetDriverSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitDriverServiceDecl(StringBuilder &sb) const;
void EmitKernelDriverDispatch(StringBuilder &sb);
void EmitDriverDispatch(StringBuilder &sb);
void EmitDriverInit(StringBuilder &sb) const;
void EmitKernelDriverBind(StringBuilder &sb);
void EmitDriverBind(StringBuilder &sb);
void EmitKernelDriverRelease(StringBuilder &sb);
void EmitDriverRelease(StringBuilder &sb);
void EmitDriverEntryDefinition(StringBuilder &sb) const;
private:
std::string hostName_;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_HDI_C_SERVICE_DRIVER_CODE_EMITTER_H

View File

@ -0,0 +1,442 @@
/*
* Copyright (c) 2024 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 "c_service_impl_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
bool CServiceImplCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
directory_ = GetFileParentPath(targetDirectory);
} else {
return false;
}
if (!File::CreateParentDir(directory_)) {
Logger::E("CServiceImplCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CServiceImplCodeEmitter::EmitCode()
{
switch (mode_) {
case GenMode::LOW: {
EmitLowServiceImplHeaderFile();
EmitLowServiceImplSourceFile();
break;
}
case GenMode::PASSTHROUGH:
case GenMode::IPC: {
if (interface_->IsSerializable()) {
EmitServiceImplHeaderFile();
}
EmitServiceImplSourceFile();
break;
}
case GenMode::KERNEL: {
EmitServiceImplHeaderFile();
EmitServiceImplSourceFile();
break;
}
default:
break;
}
}
void CServiceImplCodeEmitter::EmitLowServiceImplHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(implName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
sb.Append("\n");
EmitLicense(sb);
EmitHeadMacro(sb, implFullName_);
EmitLowServiceImplInclusions(sb);
sb.Append("\n");
EmitHeadExternC(sb);
sb.Append("\n");
EmitLowServiceImplDefinition(sb);
sb.Append("\n");
EmitServiceImplExternalMethodsDecl(sb);
sb.Append("\n");
EmitTailExternC(sb);
sb.Append("\n");
EmitTailMacro(sb, implFullName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CServiceImplCodeEmitter::EmitLowServiceImplInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CServiceImplCodeEmitter::EmitLowServiceImplDefinition(StringBuilder &sb)
{
sb.AppendFormat("struct %s {\n", implName_.c_str());
sb.Append(TAB).AppendFormat("struct %s super;\n", interfaceName_.c_str());
sb.Append(TAB).Append("// please add private data here\n");
sb.Append("};\n");
}
void CServiceImplCodeEmitter::EmitLowServiceImplSourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(implName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitServiceImplSourceInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(implName_));
sb.Append("\n");
EmitServiceImplMethodImpls(sb, "");
sb.Append("\n");
EmitLowServiceImplGetMethod(sb);
sb.Append("\n");
EmitServiceImplReleaseMethod(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CServiceImplCodeEmitter::EmitLowServiceImplGetMethod(StringBuilder &sb)
{
sb.AppendFormat("struct %s *%sServiceGet(void)\n", implName_.c_str(), baseName_.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat("struct %s *service = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
implName_.c_str(), implName_.c_str(), implName_.c_str());
sb.Append(TAB).Append("if (service == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%s: failed to malloc service object\", __func__);\n");
sb.Append(TAB).Append("}\n");
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
sb.Append(TAB).AppendFormat("service->super.%s = %s%s;\n", method->GetName().c_str(),
baseName_.c_str(), method->GetName().c_str());
}
AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
sb.Append(TAB).AppendFormat("service->super.%s = %s%s;\n", method->GetName().c_str(),
baseName_.c_str(), method->GetName().c_str());
sb.Append(TAB).Append("return service;\n");
sb.Append("}\n");
}
void CServiceImplCodeEmitter::EmitServiceImplHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_ + "Service").c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, implFullName_);
sb.Append("\n");
EmitServiceImplHeaderInclusions(sb);
sb.Append("\n");
EmitHeadExternC(sb);
if (mode_ == GenMode::KERNEL) {
sb.Append("\n");
EmitKernelServiceImplDef(sb);
} else if (interface_->IsSerializable()) {
sb.Append("\n");
EmitServiceImplDef(sb);
}
sb.Append("\n");
EmitServiceImplExternalMethodsDecl(sb);
sb.Append("\n");
EmitTailExternC(sb);
sb.Append("\n");
EmitTailMacro(sb, implFullName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CServiceImplCodeEmitter::EmitServiceImplHeaderInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
if (mode_ == GenMode::KERNEL) {
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(stubName_));
} else {
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
}
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CServiceImplCodeEmitter::EmitServiceImplExternalMethodsDecl(StringBuilder &sb) const
{
std::string instTypeName;
if (mode_ == GenMode::LOW || mode_ == GenMode::KERNEL) {
instTypeName = implName_;
} else {
instTypeName = interface_->IsSerializable() ? interfaceName_ : implName_;
}
sb.AppendFormat("struct %s *%sServiceGet(void);\n\n", instTypeName.c_str(), baseName_.c_str());
sb.AppendFormat("void %sServiceRelease(struct %s *instance);\n", baseName_.c_str(), instTypeName.c_str());
}
void CServiceImplCodeEmitter::EmitServiceImplSourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(implName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitServiceImplSourceInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(implName_));
if (mode_ != GenMode::KERNEL && !interface_->IsSerializable()) {
sb.Append("\n");
EmitServiceImplDef(sb);
}
sb.Append("\n");
EmitServiceImplMethodImpls(sb, "");
if (mode_ == GenMode::KERNEL) {
sb.Append("\n");
EmitKernelServiceImplGetMethod(sb);
sb.Append("\n");
EmitKernelServiceImplReleaseMethod(sb);
} else {
sb.Append("\n");
EmitServiceImplGetMethod(sb);
sb.Append("\n");
EmitServiceImplReleaseMethod(sb);
}
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CServiceImplCodeEmitter::EmitServiceImplSourceInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
if (mode_ == GenMode::KERNEL || mode_ == GenMode::LOW || interface_->IsSerializable()) {
headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(implName_));
} else {
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
}
GetSourceOtherLibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CServiceImplCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
}
void CServiceImplCodeEmitter::EmitKernelServiceImplDef(StringBuilder &sb) const
{
sb.AppendFormat("struct %sService {\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("struct %sStub stub;\n\n", baseName_.c_str());
sb.Append(TAB).Append("// please add private data here\n");
sb.Append("};\n");
}
void CServiceImplCodeEmitter::EmitServiceImplDef(StringBuilder &sb) const
{
sb.AppendFormat("struct %sService {\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("struct %s interface;\n", interfaceName_.c_str());
sb.Append("};\n");
}
void CServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix) const
{
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitServiceImplMethodImpl(method, sb, prefix);
sb.Append("\n");
}
EmitServiceImplGetVersionMethod(sb, prefix);
}
void CServiceImplCodeEmitter::EmitServiceImplMethodImpl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self)\n", baseName_.c_str(),
method->GetName().c_str(), interfaceName_.c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self, ", baseName_.c_str(),
method->GetName().c_str(), interfaceName_.c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
if (i + 1 < method->GetParameterNumber()) {
paramStr.Append(", ");
}
}
paramStr.Append(")");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
sb.Append(prefix).Append("}\n");
}
void CServiceImplCodeEmitter::EmitServiceImplGetVersionMethod(StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
sb.Append(prefix).AppendFormat("static int32_t %s%s(struct %s *self, ", baseName_.c_str(),
method->GetName().c_str(), interfaceName_.c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, sb, "");
if (i + 1 < method->GetParameterNumber()) {
sb.Append(", ");
}
}
sb.Append(")\n");
sb.Append(prefix).Append("{\n");
AutoPtr<ASTParameter> majorParam = method->GetParameter(0);
sb.Append(prefix + TAB).AppendFormat("*%s = %s;\n", majorParam->GetName().c_str(), majorVerName_.c_str());
AutoPtr<ASTParameter> minorParam = method->GetParameter(1);
sb.Append(prefix + TAB).AppendFormat("*%s = %s;\n", minorParam->GetName().c_str(), minorVerName_.c_str());
sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
sb.Append(prefix).Append("}\n");
}
void CServiceImplCodeEmitter::EmitKernelServiceImplGetMethod(StringBuilder &sb) const
{
std::string objName = "service";
sb.AppendFormat("struct %s *%sGet(void)\n", implName_.c_str(), implName_.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
implName_.c_str(), objName.c_str(), implName_.c_str(), implName_.c_str());
sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat(
"HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n", implName_.c_str());
sb.Append(TAB).Append(TAB).Append("return NULL;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("if (!%sStubConstruct(&%s->stub)) {\n", baseName_.c_str(), objName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat(
"HDF_LOGE(\"%%{public}s: construct %sStub obj failed!\", __func__);\n", baseName_.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("OsalMemFree(%s);\n", objName.c_str());
sb.Append(TAB).Append(TAB).Append("return NULL;\n");
sb.Append(TAB).Append("}\n\n");
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
sb.Append(TAB).AppendFormat("%s->stub.interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
baseName_.c_str(), method->GetName().c_str());
}
sb.Append(TAB).AppendFormat("return service;\n", objName.c_str());
sb.Append("}\n");
}
void CServiceImplCodeEmitter::EmitServiceImplGetMethod(StringBuilder &sb) const
{
std::string objName = "service";
if (interface_->IsSerializable()) {
sb.AppendFormat("struct %s *%sServiceGet(void)\n", interfaceName_.c_str(), baseName_.c_str());
} else {
sb.AppendFormat("struct %s *%sImplGetInstance(void)\n", interfaceName_.c_str(), baseName_.c_str());
}
sb.Append("{\n");
sb.Append(TAB).AppendFormat("struct %s *%s = (struct %s *)OsalMemCalloc(sizeof(struct %s));\n",
implName_.c_str(), objName.c_str(), implName_.c_str(), implName_.c_str());
sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat(
"HDF_LOGE(\"%%{public}s: malloc %s obj failed!\", __func__);\n", implName_.c_str());
sb.Append(TAB).Append(TAB).Append("return NULL;\n");
sb.Append(TAB).Append("}\n\n");
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
sb.Append(TAB).AppendFormat("%s->interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
baseName_.c_str(), method->GetName().c_str());
}
AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
sb.Append(TAB).AppendFormat("%s->interface.%s = %s%s;\n", objName.c_str(), method->GetName().c_str(),
baseName_.c_str(), method->GetName().c_str());
sb.Append(TAB).AppendFormat("return &%s->interface;\n", objName.c_str());
sb.Append("}\n");
}
void CServiceImplCodeEmitter::EmitKernelServiceImplReleaseMethod(StringBuilder &sb) const
{
std::string instName = "instance";
sb.AppendFormat(
"void %sRelease(struct %s *%s)\n", implName_.c_str(), implName_.c_str(), instName.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", instName.c_str());
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("OsalMemFree(%s);\n", instName.c_str());
sb.Append("}\n");
}
void CServiceImplCodeEmitter::EmitServiceImplReleaseMethod(StringBuilder &sb) const
{
if (mode_ == GenMode::LOW || mode_ == GenMode::KERNEL) {
sb.AppendFormat("void %sRelease(struct %s *instance)\n", implName_.c_str(), implName_.c_str());
} else {
if (interface_->IsSerializable()) {
sb.AppendFormat("void %sServiceRelease(struct %s *instance)\n", baseName_.c_str(), interfaceName_.c_str());
} else {
sb.AppendFormat("void %sImplRelease(struct %s *instance)\n", baseName_.c_str(), interfaceName_.c_str());
}
}
sb.Append("{\n");
sb.Append(TAB).Append("if (instance == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).Append("OsalMemFree(instance);\n");
sb.Append("}\n");
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2024 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_IDL_HDI_C_SERVICE_IMPL_CODE_EMITTER_H
#define OHOS_IDL_HDI_C_SERVICE_IMPL_CODE_EMITTER_H
#include "hdi_c_code_emitter.h"
namespace OHOS {
namespace Idl {
class CServiceImplCodeEmitter : public HDICCodeEmitter {
public:
CServiceImplCodeEmitter() : HDICCodeEmitter() {}
~CServiceImplCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
// generate service header file of low mode
void EmitLowServiceImplHeaderFile();
void EmitLowServiceImplInclusions(StringBuilder &sb);
void EmitLowServiceImplDefinition(StringBuilder &sb);
// generate service source file of low mode
void EmitLowServiceImplSourceFile();
void EmitLowServiceImplGetMethod(StringBuilder &sb);
// generate service header file of ipc, passthrough, kernel mode
void EmitServiceImplHeaderFile();
void EmitServiceImplHeaderInclusions(StringBuilder &sb);
void EmitServiceImplExternalMethodsDecl(StringBuilder &sb) const;
void EmitServiceImplSourceFile();
void EmitServiceImplSourceInclusions(StringBuilder &sb);
void GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitKernelServiceImplDef(StringBuilder &sb) const;
void EmitServiceImplDef(StringBuilder &sb) const;
void EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix) const;
void EmitServiceImplMethodImpl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitKernelServiceImplGetMethod(StringBuilder &sb) const;
void EmitServiceImplGetVersionMethod(StringBuilder &sb, const std::string &prefix) const;
void EmitServiceImplGetMethod(StringBuilder &sb) const;
void EmitKernelServiceImplReleaseMethod(StringBuilder &sb) const;
void EmitServiceImplReleaseMethod(StringBuilder &sb) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_HDI_C_SERVICE_IMPL_CODE_EMITTER_H

View File

@ -0,0 +1,811 @@
/*
* Copyright (c) 2024 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 "c_service_stub_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
bool CServiceStubCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
directory_ = GetFileParentPath(targetDirectory);
} else {
return false;
}
if (!File::CreateParentDir(directory_)) {
Logger::E("CServiceStubCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CServiceStubCodeEmitter::EmitCode()
{
switch (mode_) {
case GenMode::IPC:
case GenMode::KERNEL: {
EmitServiceStubHeaderFile();
EmitServiceStubSourceFile();
break;
}
default:
break;
}
}
void CServiceStubCodeEmitter::EmitServiceStubHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(stubName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, stubFullName_);
sb.Append("\n");
EmitStubHeaderInclusions(sb);
sb.Append("\n");
EmitHeadExternC(sb);
sb.Append("\n");
EmitCbServiceStubDef(sb);
if (mode_ == GenMode::KERNEL) {
sb.Append("\n");
EmitCbServiceStubMethodsDcl(sb);
}
sb.Append("\n");
EmitTailExternC(sb);
sb.Append("\n");
EmitTailMacro(sb, stubFullName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CServiceStubCodeEmitter::EmitStubHeaderInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_sbuf");
if (mode_ != GenMode::KERNEL) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_remote_service");
}
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CServiceStubCodeEmitter::EmitCbServiceStubDef(StringBuilder &sb) const
{
sb.AppendFormat("struct %sStub {\n", baseName_.c_str());
if (mode_ == GenMode::KERNEL) {
sb.Append(TAB).AppendFormat("struct %s interface;\n", interfaceName_.c_str());
sb.Append(TAB).AppendFormat("int32_t (*OnRemoteRequest)(struct %s *serviceImpl, ", interfaceName_.c_str());
sb.Append("int code, struct HdfSBuf *data, struct HdfSBuf *reply);\n");
} else {
sb.Append(TAB).Append("struct HdfRemoteService *remote;\n");
sb.Append(TAB).AppendFormat("struct %s *interface;\n", interfaceName_.c_str());
sb.Append(TAB).Append("struct HdfRemoteDispatcher dispatcher;\n");
}
sb.Append("};\n");
}
void CServiceStubCodeEmitter::EmitCbServiceStubMethodsDcl(StringBuilder &sb) const
{
sb.AppendFormat("bool %sStubConstruct(struct %sStub *stub);\n", baseName_.c_str(), baseName_.c_str());
}
void CServiceStubCodeEmitter::EmitServiceStubSourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.c", directory_.c_str(), FileName(stubName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitStubSourceInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(stubName_));
if (mode_ != GenMode::KERNEL && !interface_->IsSerializable()) {
sb.Append("\n");
EmitExternalMethodImpl(sb);
}
sb.Append("\n");
EmitUtilMethods(sb, true);
sb.Append("\n");
EmitUtilMethods(sb, false);
EmitServiceStubMethodImpls(sb, "");
if (mode_ == GenMode::KERNEL) {
sb.Append("\n");
EmitKernelStubOnRequestMethodImpl(sb, "");
sb.Append("\n");
EmitKernelStubConstruct(sb);
} else {
sb.Append("\n");
EmitStubOnRequestMethodImpl(sb, "");
if (!interface_->IsSerializable()) {
sb.Append("\n");
EmitStubRemoteDispatcher(sb);
}
sb.Append("\n");
EmitStubNewInstance(sb);
sb.Append("\n");
EmitStubReleaseMethod(sb);
sb.Append("\n");
EmitStubConstructor(sb);
sb.Append("\n");
EmitStubRegAndUnreg(sb);
}
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CServiceStubCodeEmitter::EmitStubSourceInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(stubName_));
GetSourceOtherLibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CServiceStubCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
if (mode_ != GenMode::KERNEL) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_dlist");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "stub_collector");
if (!interface_->IsSerializable()) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
}
} else {
const AST::TypeStringMap &types = ast_->GetTypes();
for (const auto &pair : types) {
AutoPtr<ASTType> type = pair.second;
if (type->GetTypeKind() == TypeKind::TYPE_STRING || type->GetTypeKind() == TypeKind::TYPE_UNION) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
break;
}
}
}
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "osal_mem");
}
void CServiceStubCodeEmitter::EmitExternalMethodImpl(StringBuilder &sb)
{
EmitGetMethodImpl(sb);
sb.Append("\n");
EmitGetInstanceMehtodImpl(sb);
sb.Append("\n");
EmitReleaseMethodImpl(sb);
sb.Append("\n");
EmitReleaseInstanceMethodImpl(sb);
}
void CServiceStubCodeEmitter::EmitGetMethodImpl(StringBuilder &sb) const
{
sb.AppendFormat("struct %s *%sGet(bool isStub)\n", interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat(
"return %sGetInstance(\"%s\", isStub);\n", interfaceName_.c_str(), FileName(implName_).c_str());
sb.Append("}\n");
}
void CServiceStubCodeEmitter::EmitGetInstanceMehtodImpl(StringBuilder &sb) const
{
sb.AppendFormat("struct %s *%sGetInstance(const char *serviceName, bool isStub)\n", interfaceName_.c_str(),
interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("if (!isStub) {\n");
sb.Append(TAB).Append(TAB).Append("return NULL;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("const char *instName = serviceName;\n");
sb.Append(TAB).AppendFormat("if (strcmp(serviceName, \"%s\") == 0) {\n", FileName(implName_).c_str());
sb.Append(TAB).Append(TAB).Append("instName = \"service\";\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).AppendFormat("return (struct %s *)LoadHdiImpl(%s, instName);\n",
interfaceName_.c_str(), EmitDescMacroName().c_str());
sb.Append("}\n");
}
void CServiceStubCodeEmitter::EmitReleaseMethodImpl(StringBuilder &sb) const
{
sb.AppendFormat(
"void %sRelease(struct %s *instance, bool isStub)\n", interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat(
"%sReleaseInstance(\"%s\", instance, isStub);\n", interfaceName_.c_str(), FileName(implName_).c_str());
sb.Append("}\n");
}
void CServiceStubCodeEmitter::EmitReleaseInstanceMethodImpl(StringBuilder &sb) const
{
sb.AppendFormat("void %sReleaseInstance(const char *serviceName, struct %s *instance, bool isStub)\n",
interfaceName_.c_str(), interfaceName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("if (serviceName == NULL || !isStub || instance == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).Append("const char *instName = serviceName;\n");
sb.Append(TAB).AppendFormat("if (strcmp(serviceName, \"%s\") == 0) {\n", FileName(implName_).c_str());
sb.Append(TAB).Append(TAB).Append("instName = \"service\";\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).AppendFormat("UnloadHdiImpl(%s, instName, instance);\n", EmitDescMacroName().c_str());
sb.Append("}\n");
}
void CServiceStubCodeEmitter::EmitServiceStubMethodImpls(StringBuilder &sb, const std::string &prefix)
{
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitServiceStubMethodImpl(method, sb, prefix);
sb.Append("\n");
}
EmitStubGetVerMethodImpl(interface_->GetVersionMethod(), sb, prefix);
if (mode_ != GenMode::KERNEL) {
sb.Append("\n");
EmitStubAsObjectMethodImpl(sb, prefix);
}
}
void CServiceStubCodeEmitter::EmitServiceStubMethodImpl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat(
"static int32_t SerStub%s(struct %s *serviceImpl, struct HdfSBuf *%s, struct HdfSBuf *%s)\n",
method->GetName().c_str(), interfaceName_.c_str(), HdiTypeEmitter::dataParcelName_.c_str(),
HdiTypeEmitter::replyParcelName_.c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("int32_t %s = HDF_FAILURE;\n", HdiTypeEmitter::errorCodeName_.c_str());
bool readFlag = NeedFlag(method);
if (readFlag) {
sb.Append(prefix + TAB).AppendFormat("bool %s = false;\n", flagOfSetMemName_.c_str());
}
// Local variable definitions must precede all execution statements.
EmitMethodNeedLoopVar(method, true, true, sb, prefix + TAB);
if (method->GetParameterNumber() > 0) {
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitStubLocalVariable(param, sb, prefix + TAB);
}
sb.Append("\n");
EmitReadFlagVariable(readFlag, sb, prefix + TAB);
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
EmitReadStubMethodParameter(param, finishedLabel_, sb, prefix + TAB);
sb.Append("\n");
} else {
EmitOutVarMemInitialize(param, finishedLabel_, sb, prefix + TAB);
}
}
}
EmitStubCallMethod(method, finishedLabel_, sb, prefix + TAB);
sb.Append("\n");
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
if (param->GetAttribute() == ASTParamAttr::PARAM_OUT) {
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
typeEmitter->EmitCWriteVar(TypeMode::PARAM_OUT, param->GetName(), finishedLabel_, sb, prefix + TAB);
sb.Append("\n");
}
}
EmitErrorHandle(method, sb, prefix);
sb.Append(prefix + TAB).AppendFormat("return %s;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix).Append("}\n");
}
void CServiceStubCodeEmitter::EmitErrorHandle(const AutoPtr<ASTMethod> &method,
StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("%s:\n", finishedLabel_);
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
typeEmitter->EmitMemoryRecycle(param->GetName(), true, sb, prefix + TAB);
}
}
void CServiceStubCodeEmitter::EmitReadFlagVariable(bool readFlag, StringBuilder &sb, const std::string &prefix) const
{
if (!readFlag) {
return;
}
sb.Append(prefix).AppendFormat("if (!HdfSbufReadUint8(%s, (uint8_t *)&%s)) {\n",
HdiTypeEmitter::dataParcelName_.c_str(), flagOfSetMemName_.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: read flag of memory setting failed!\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabel_);
sb.Append(prefix).Append("}\n\n");
}
void CServiceStubCodeEmitter::EmitStubLocalVariable(
const AutoPtr<ASTParameter> &param, StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTType> type = param->GetType();
EmitParamLocalVar(param, sb, prefix);
if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST ||
(type->GetTypeKind() == TypeKind::TYPE_STRING && (param->GetAttribute() == ASTParamAttr::PARAM_OUT))) {
sb.Append(prefix).AppendFormat("uint32_t %sLen = 0;\n", param->GetName().c_str());
}
}
void CServiceStubCodeEmitter::EmitParamLocalVar(const AutoPtr<ASTParameter> &param, StringBuilder &sb,
const std::string &prefix) const
{
AutoPtr<ASTType> type = param->GetType();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
sb.Append(prefix).AppendFormat("%s %s", typeEmitter->EmitCType(TypeMode::LOCAL_VAR).c_str(),
param->GetName().c_str());
switch (type->GetTypeKind()) {
case TypeKind::TYPE_BOOLEAN:
sb.Append(" = false");
break;
case TypeKind::TYPE_BYTE:
case TypeKind::TYPE_SHORT:
case TypeKind::TYPE_INT:
case TypeKind::TYPE_LONG:
case TypeKind::TYPE_UCHAR:
case TypeKind::TYPE_USHORT:
case TypeKind::TYPE_UINT:
case TypeKind::TYPE_ULONG:
case TypeKind::TYPE_FLOAT:
case TypeKind::TYPE_DOUBLE:
sb.Append(" = 0");
break;
case TypeKind::TYPE_STRING:
case TypeKind::TYPE_ARRAY:
case TypeKind::TYPE_LIST:
case TypeKind::TYPE_STRUCT:
case TypeKind::TYPE_UNION:
case TypeKind::TYPE_INTERFACE:
case TypeKind::TYPE_NATIVE_BUFFER:
sb.Append(" = NULL");
break;
case TypeKind::TYPE_FILEDESCRIPTOR:
sb.Append(" = -1");
break;
default:
break;
}
sb.Append(";\n");
}
void CServiceStubCodeEmitter::EmitReadStubMethodParameter(const AutoPtr<ASTParameter> &param,
const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTType> type = param->GetType();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
if (type->GetTypeKind() == TypeKind::TYPE_STRING) {
EmitReadCStringStubMethodParameter(param, gotoLabel, sb, prefix, typeEmitter);
} else if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s));\n", param->GetName().c_str(),
typeEmitter->EmitCType().c_str(), typeEmitter->EmitCType().c_str());
sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().c_str());
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s failed\", __func__);\n", param->GetName().c_str());
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabel_);
sb.Append(prefix).Append("}\n");
typeEmitter->EmitCStubReadVar(param->GetName(), gotoLabel, sb, prefix);
} else if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
std::string cpName = StringHelper::Format("%sCp", param->GetName().c_str());
typeEmitter->EmitCStubReadVar(cpName, gotoLabel, sb, prefix);
sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s));\n", param->GetName().c_str(),
typeEmitter->EmitCType().c_str(), typeEmitter->EmitCType().c_str());
sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().c_str());
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s failed\", __func__);\n", param->GetName().c_str());
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", finishedLabel_);
sb.Append(prefix).Append("}\n");
sb.Append(prefix).AppendFormat("if (memcpy_s(%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n",
param->GetName().c_str(), typeEmitter->EmitCType().c_str(), cpName.c_str(),
typeEmitter->EmitCType().c_str());
sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: failed to memcpy %s\", __func__);\n",
param->GetName().c_str());
sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix).Append("}\n");
} else if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST ||
type->GetTypeKind() == TypeKind::TYPE_FILEDESCRIPTOR ||
type->GetTypeKind() == TypeKind::TYPE_NATIVE_BUFFER || type->GetTypeKind() == TypeKind::TYPE_ENUM ||
type->GetTypeKind() == TypeKind::TYPE_INTERFACE) {
typeEmitter->EmitCStubReadVar(param->GetName(), gotoLabel, sb, prefix);
} else {
std::string name = StringHelper::Format("&%s", param->GetName().c_str());
typeEmitter->EmitCStubReadVar(name, gotoLabel, sb, prefix);
}
}
void CServiceStubCodeEmitter::EmitReadCStringStubMethodParameter(const AutoPtr<ASTParameter> &param,
const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix,
AutoPtr<HdiTypeEmitter> &typeEmitter) const
{
std::string cloneName = StringHelper::Format("%sCp", param->GetName().c_str());
typeEmitter->EmitCStubReadVar(cloneName, gotoLabel, sb, prefix);
if (mode_ == GenMode::KERNEL) {
sb.Append("\n");
sb.Append(prefix).AppendFormat(
"%s = (char*)OsalMemCalloc(strlen(%s) + 1);\n", param->GetName().c_str(), cloneName.c_str());
sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().c_str());
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s failed\", __func__);\n", param->GetName().c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
sb.Append(prefix).Append("}\n\n");
sb.Append(prefix).AppendFormat("if (strcpy_s(%s, (strlen(%s) + 1), %s) != HDF_SUCCESS) {\n",
param->GetName().c_str(), cloneName.c_str(), cloneName.c_str());
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: read %s failed!\", __func__);\n", param->GetName().c_str());
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_PARAM;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
sb.Append(prefix).Append("}\n");
} else {
sb.Append(prefix).AppendFormat("%s = strdup(%s);\n", param->GetName().c_str(), cloneName.c_str());
}
}
void CServiceStubCodeEmitter::EmitOutVarMemInitialize(const AutoPtr<ASTParameter> &param,
const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTType> type = param->GetType();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
if (type->IsStructType() || type->IsUnionType()) {
sb.Append(prefix).AppendFormat("%s = (%s*)OsalMemCalloc(sizeof(%s));\n", param->GetName().c_str(),
typeEmitter->EmitCType().c_str(), typeEmitter->EmitCType().c_str());
sb.Append(prefix).AppendFormat("if (%s == NULL) {\n", param->GetName().c_str());
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: malloc %s failed\", __func__);\n", param->GetName().c_str());
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_MALLOC_FAIL;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
sb.Append(prefix).Append("}\n\n");
} else if (type->IsStringType() || type->IsArrayType() || type->IsListType()) {
typeEmitter->EmitCStubReadOutVar(flagOfSetMemName_, param->GetName(), gotoLabel, sb, prefix);
sb.Append("\n");
}
}
void CServiceStubCodeEmitter::EmitStubCallMethod(
const AutoPtr<ASTMethod> &method, const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).Append("if (serviceImpl == NULL) {\n");
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s: invalid serviceImpl object\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_INVALID_OBJECT;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
sb.Append(prefix).Append("}\n\n");
sb.Append(prefix).AppendFormat("if (serviceImpl->%s == NULL) {\n", method->GetName().c_str());
sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: invalid interface function %s \", __func__);\n",
method->GetName().c_str());
sb.Append(prefix + TAB).AppendFormat("%s = HDF_ERR_NOT_SUPPORT;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
sb.Append(prefix).Append("}\n\n");
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat(
"%s = serviceImpl->%s(serviceImpl);\n", HdiTypeEmitter::errorCodeName_.c_str(), method->GetName().c_str());
} else {
sb.Append(prefix).AppendFormat(
"%s = serviceImpl->%s(serviceImpl, ", HdiTypeEmitter::errorCodeName_.c_str(), method->GetName().c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitCallParameter(sb, param->GetType(), param->GetAttribute(), param->GetName());
if (i + 1 < method->GetParameterNumber()) {
sb.Append(", ");
}
}
sb.AppendFormat(");\n", method->GetName().c_str());
}
sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s failed, error code is %%{public}d\", __func__, %s);\n",
HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("goto %s;\n", gotoLabel.c_str());
sb.Append(prefix).Append("}\n");
}
void CServiceStubCodeEmitter::EmitCallParameter(
StringBuilder &sb, const AutoPtr<ASTType> &type, ASTParamAttr::ParamAttr attribute, const std::string &name) const
{
if (attribute == ASTParamAttr::PARAM_OUT) {
if (type->GetTypeKind() == TypeKind::TYPE_STRING || type->GetTypeKind() == TypeKind::TYPE_ARRAY ||
type->GetTypeKind() == TypeKind::TYPE_LIST || type->GetTypeKind() == TypeKind::TYPE_STRUCT ||
type->GetTypeKind() == TypeKind::TYPE_UNION) {
sb.AppendFormat("%s", name.c_str());
} else {
sb.AppendFormat("&%s", name.c_str());
}
if (type->GetTypeKind() == TypeKind::TYPE_STRING) {
sb.AppendFormat(", %sLen", name.c_str());
} else if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) {
sb.AppendFormat(", &%sLen", name.c_str());
}
}
if (attribute == ASTParamAttr::PARAM_IN) {
sb.AppendFormat("%s", name.c_str());
if (type->GetTypeKind() == TypeKind::TYPE_ARRAY || type->GetTypeKind() == TypeKind::TYPE_LIST) {
sb.AppendFormat(", %sLen", name.c_str());
}
}
}
void CServiceStubCodeEmitter::EmitStubGetVerMethodImpl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat(
"static int32_t SerStub%s(struct %s *serviceImpl, struct HdfSBuf *%s, struct HdfSBuf *%s)\n",
method->GetName().c_str(), interfaceName_.c_str(), HdiTypeEmitter::dataParcelName_.c_str(),
HdiTypeEmitter::replyParcelName_.c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("int32_t %s = HDF_SUCCESS;\n", HdiTypeEmitter::errorCodeName_.c_str());
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(new ASTUintType());
typeEmitter->EmitCWriteVar(TypeMode::PARAM_OUT, majorVerName_, finishedLabel_, sb, prefix + TAB);
sb.Append("\n");
typeEmitter->EmitCWriteVar(TypeMode::PARAM_OUT, minorVerName_, finishedLabel_, sb, prefix + TAB);
sb.Append("\n");
sb.Append(finishedLabel_).Append(":\n");
sb.Append(prefix + TAB).AppendFormat("return %s;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix).Append("}\n");
}
void CServiceStubCodeEmitter::EmitStubAsObjectMethodImpl(StringBuilder &sb, const std::string &prefix) const
{
std::string objName = "self";
sb.Append(prefix).AppendFormat("static struct HdfRemoteService *%sStubAsObject(struct %s *%s)\n", baseName_.c_str(),
interfaceName_.c_str(), objName.c_str());
sb.Append(prefix).Append("{\n");
if (interface_->IsSerializable()) {
sb.Append(prefix + TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
sb.Append(prefix + TAB + TAB).Append("return NULL;\n");
sb.Append(prefix + TAB).Append("}\n");
sb.Append(prefix + TAB).AppendFormat(
"struct %sStub *stub = CONTAINER_OF(%s, struct %sStub, interface);\n", baseName_.c_str(),
objName.c_str(), baseName_.c_str());
sb.Append(prefix + TAB).Append("return stub->remote;\n");
} else {
sb.Append(prefix + TAB).Append("return NULL;\n");
}
sb.Append(prefix).Append("}\n");
}
void CServiceStubCodeEmitter::EmitKernelStubOnRequestMethodImpl(StringBuilder &sb, const std::string &prefix)
{
std::string implName = "serviceImpl";
std::string codeName = "code";
std::string funcName = StringHelper::Format("%sOnRemoteRequest", baseName_.c_str());
sb.Append(prefix).AppendFormat("static int32_t %s(struct %s *%s, ", funcName.c_str(), interfaceName_.c_str(),
implName.c_str());
sb.AppendFormat("int %s, struct HdfSBuf *data, struct HdfSBuf *reply)\n", codeName.c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("switch (%s) {\n", codeName.c_str());
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(method).c_str());
sb.Append(prefix + TAB + TAB + TAB)
.AppendFormat("return SerStub%s(%s, data, reply);\n", method->GetName().c_str(), implName.c_str());
}
AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(getVerMethod).c_str());
sb.Append(prefix + TAB + TAB + TAB)
.AppendFormat("return SerStub%s(%s, data, reply);\n", getVerMethod->GetName().c_str(), implName.c_str());
sb.Append(prefix + TAB + TAB).Append("default: {\n");
sb.Append(prefix + TAB + TAB + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: not support cmd %%{public}d\", __func__, %s);\n", codeName.c_str());
sb.Append(prefix + TAB + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix + TAB + TAB).Append("}\n");
sb.Append(prefix + TAB).Append("}\n");
sb.Append("}\n");
}
void CServiceStubCodeEmitter::EmitKernelStubConstruct(StringBuilder &sb) const
{
std::string stubTypeName = StringHelper::Format("%sStub", baseName_.c_str());
std::string objName = "stub";
std::string funcName = StringHelper::Format("%sOnRemoteRequest", baseName_.c_str());
sb.AppendFormat(
"bool %sConstruct(struct %s *%s)\n", stubTypeName.c_str(), stubTypeName.c_str(), objName.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objName.c_str());
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: stub is null!\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return false;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("%s->OnRemoteRequest = %s;\n", objName.c_str(), funcName.c_str());
sb.Append(TAB).Append("return true;\n");
sb.Append("}\n");
}
void CServiceStubCodeEmitter::EmitStubOnRequestMethodImpl(StringBuilder &sb, const std::string &prefix)
{
std::string remoteName = "remote";
std::string codeName = "code";
std::string funcName = StringHelper::Format("%sOnRemoteRequest", baseName_.c_str());
sb.Append(prefix).AppendFormat("static int32_t %s(struct HdfRemoteService *%s, ", funcName.c_str(),
remoteName.c_str());
sb.AppendFormat("int %s, struct HdfSBuf *data, struct HdfSBuf *reply)\n", codeName.c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("struct %s *stub = (struct %s*)%s;\n", stubName_.c_str(),
stubName_.c_str(), remoteName.c_str());
sb.Append(prefix + TAB).Append("if (stub == NULL || stub->remote == NULL || stub->interface == NULL) {\n");
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: invalid stub object\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
sb.Append(prefix + TAB).Append("}\n");
sb.Append(prefix + TAB).AppendFormat("if (!HdfRemoteServiceCheckInterfaceToken(stub->%s, data)) {\n",
remoteName.c_str());
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: interface token check failed\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).AppendFormat("switch (%s) {\n", codeName.c_str());
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(method).c_str());
sb.Append(prefix + TAB + TAB + TAB)
.AppendFormat("return SerStub%s(stub->interface, data, reply);\n", method->GetName().c_str());
}
AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(getVerMethod).c_str());
sb.Append(prefix + TAB + TAB + TAB)
.AppendFormat("return SerStub%s(stub->interface, data, reply);\n", getVerMethod->GetName().c_str());
sb.Append(prefix + TAB + TAB).Append("default: {\n");
sb.Append(prefix + TAB + TAB + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: not support cmd %%{public}d\", __func__, %s);\n", codeName.c_str());
sb.Append(prefix + TAB + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix + TAB + TAB).Append("}\n");
sb.Append(prefix + TAB).Append("}\n");
sb.Append("}\n");
}
void CServiceStubCodeEmitter::EmitStubRemoteDispatcher(StringBuilder &sb) const
{
std::string dispatcherName = StringHelper::Format("g_%sDispatcher", StringHelper::StrToLower(baseName_).c_str());
sb.AppendFormat("static struct HdfRemoteDispatcher %s = {\n", dispatcherName.c_str());
sb.Append(TAB).AppendFormat(".Dispatch = %sOnRemoteRequest,\n", baseName_.c_str());
sb.Append(TAB).Append(".DispatchAsync = NULL,\n");
sb.Append("};\n");
}
void CServiceStubCodeEmitter::EmitStubNewInstance(StringBuilder &sb) const
{
std::string dispatcherName = StringHelper::Format("g_%sDispatcher", StringHelper::StrToLower(baseName_).c_str());
sb.AppendFormat("static struct HdfRemoteService **%sNewInstance(void *impl)\n", stubName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("if (impl == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: impl is null\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return NULL;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("struct %s *serviceImpl = (struct %s *)impl;\n", interfaceName_.c_str(),
interfaceName_.c_str());
sb.Append(TAB).AppendFormat("struct %s *stub = OsalMemCalloc(sizeof(struct %s));\n", stubName_.c_str(),
stubName_.c_str());
sb.Append(TAB).Append("if (stub == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: failed to malloc stub object\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return NULL;\n");
sb.Append(TAB).Append("}\n");
if (interface_->IsSerializable()) {
sb.Append(TAB).Append("stub->remote = HdfRemoteServiceObtain((struct HdfObject *)stub, &stub->dispatcher);\n");
} else {
sb.Append(TAB).AppendFormat("stub->remote = HdfRemoteServiceObtain((struct HdfObject *)stub, &%s);\n",
dispatcherName.c_str());
}
sb.Append(TAB).Append("if (stub->remote == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("OsalMemFree(stub);\n");
sb.Append(TAB).Append(TAB).Append("return NULL;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).AppendFormat("(void)HdfRemoteServiceSetInterfaceDesc(stub->remote, %s);\n",
EmitDescMacroName().c_str());
sb.Append(TAB).AppendFormat("stub->dispatcher.Dispatch = %sOnRemoteRequest;\n", baseName_.c_str());
sb.Append(TAB).Append("stub->interface = serviceImpl;\n");
sb.Append(TAB).AppendFormat("stub->interface->AsObject = %sStubAsObject;\n", baseName_.c_str());
sb.Append(TAB).Append("return &stub->remote;\n");
sb.Append("}\n");
}
void CServiceStubCodeEmitter::EmitStubReleaseMethod(StringBuilder &sb) const
{
sb.AppendFormat("static void %sRelease(struct HdfRemoteService **remote)\n", stubName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("if (remote == NULL) {\n");
sb.Append(TAB).Append(TAB).Append("return;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).AppendFormat("struct %s *stub = CONTAINER_OF(remote, struct %s, remote);\n",
stubName_.c_str(), stubName_.c_str());
sb.Append(TAB).Append("HdfRemoteServiceRecycle(stub->remote);\n");
sb.Append(TAB).Append("OsalMemFree(stub);\n");
sb.Append("}\n");
}
void CServiceStubCodeEmitter::EmitStubConstructor(StringBuilder &sb) const
{
std::string constructorName = StringHelper::Format("g_%sConstructor", StringHelper::StrToLower(baseName_).c_str());
sb.AppendFormat("__attribute__((unused)) static struct StubConstructor %s = {\n", constructorName.c_str());
sb.Append(TAB).AppendFormat(".constructor = %sNewInstance,\n", stubName_.c_str());
sb.Append(TAB).AppendFormat(".destructor = %sRelease,\n", stubName_.c_str());
sb.Append("};\n");
}
void CServiceStubCodeEmitter::EmitStubRegAndUnreg(StringBuilder &sb) const
{
std::string constructorName = StringHelper::Format("g_%sConstructor", StringHelper::StrToLower(baseName_).c_str());
sb.AppendFormat("__attribute__((constructor)) static void %sRegister(void)\n", stubName_.c_str());
sb.Append("{\n");
sb.Append(TAB).AppendFormat(
"HDF_LOGI(\"%%{public}s: register stub constructor of '%%{public}s'\", __func__, %s);\n",
EmitDescMacroName().c_str());
sb.Append(TAB).AppendFormat("StubConstructorRegister(%s, &%s);\n", EmitDescMacroName().c_str(),
constructorName.c_str());
sb.Append("}\n");
}
void CServiceStubCodeEmitter::EmitUtilMethods(StringBuilder &sb, bool isDecl)
{
UtilMethodMap methods;
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
typeEmitter->EmitCStubReadMethods(methods, "", "", isDecl);
} else {
typeEmitter->EmitCWriteMethods(methods, "", "", isDecl);
}
}
}
EmitUtilMethodMap(sb, methods);
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2024 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_IDL_HDI_C_SERVICE_STUB_CODEE_MITTER_H
#define OHOS_IDL_HDI_C_SERVICE_STUB_CODEE_MITTER_H
#include "hdi_c_code_emitter.h"
namespace OHOS {
namespace Idl {
class CServiceStubCodeEmitter : public HDICCodeEmitter {
public:
CServiceStubCodeEmitter() : HDICCodeEmitter() {}
~CServiceStubCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitServiceStubHeaderFile();
void EmitStubHeaderInclusions(StringBuilder &sb);
void EmitCbServiceStubDef(StringBuilder &sb) const;
void EmitCbServiceStubMethodsDcl(StringBuilder &sb) const;
void EmitServiceStubSourceFile();
void EmitStubSourceInclusions(StringBuilder &sb);
void GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
// get or release method for driver interface object
void EmitExternalMethodImpl(StringBuilder &sb);
void EmitGetMethodImpl(StringBuilder &sb) const;
void EmitGetInstanceMehtodImpl(StringBuilder &sb) const;
void EmitReleaseMethodImpl(StringBuilder &sb) const;
void EmitReleaseInstanceMethodImpl(StringBuilder &sb) const;
void EmitServiceStubMethodImpls(StringBuilder &sb, const std::string &prefix);
void EmitServiceStubMethodImpl(const AutoPtr<ASTMethod> &method, StringBuilder &sb,
const std::string &prefix) const;
void EmitReadFlagVariable(bool readFlag, StringBuilder &sb, const std::string &prefix) const;
void EmitStubLocalVariable(const AutoPtr<ASTParameter> &param, StringBuilder &sb, const std::string &prefix) const;
void EmitReadStubMethodParameter(const AutoPtr<ASTParameter> &param, const std::string &gotoLabel,
StringBuilder &sb, const std::string &prefix) const;
void EmitReadCStringStubMethodParameter(const AutoPtr<ASTParameter> &param, const std::string &gotoLabel,
StringBuilder &sb, const std::string &prefix, AutoPtr<HdiTypeEmitter> &typeEmitter) const;
void EmitOutVarMemInitialize(const AutoPtr<ASTParameter> &param, const std::string &gotoLabel, StringBuilder &sb,
const std::string &prefix) const;
void EmitStubCallMethod(const AutoPtr<ASTMethod> &method,
const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const;
void EmitCallParameter(StringBuilder &sb, const AutoPtr<ASTType> &type, ASTParamAttr::ParamAttr attribute,
const std::string &name) const;
void EmitStubGetVerMethodImpl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitStubAsObjectMethodImpl(StringBuilder &sb, const std::string &prefix) const;
void EmitKernelStubOnRequestMethodImpl(StringBuilder &sb, const std::string &prefix);
void EmitKernelStubConstruct(StringBuilder &sb) const;
void EmitStubOnRequestMethodImpl(StringBuilder &sb, const std::string &prefix);
void EmitStubRemoteDispatcher(StringBuilder &sb) const;
void EmitStubNewInstance(StringBuilder &sb) const;
void EmitStubReleaseMethod(StringBuilder &sb) const;
void EmitStubConstructor(StringBuilder &sb) const;
void EmitStubRegAndUnreg(StringBuilder &sb) const;
void EmitUtilMethods(StringBuilder &sb, bool isDecl) override;
void EmitParamLocalVar(const AutoPtr<ASTParameter> &param, StringBuilder &sb,
const std::string &prefix) const;
void EmitErrorHandle(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_HDI_C_SERVICE_STUB_CODEE_MITTER_H

View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2024 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 "hdi_c_code_emitter.h"
#include "util/options.h"
namespace OHOS {
namespace Idl {
void HDICCodeEmitter::GetStdlibInclusions(HeaderFile::HeaderFileSet &headerFiles)
{
const AST::TypeStringMap &types = ast_->GetTypes();
for (const auto &pair : types) {
AutoPtr<ASTType> type = pair.second;
if (type->IsNativeBufferType()) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "base/buffer_util");
}
}
}
void HDICCodeEmitter::GetImportInclusions(HeaderFile::HeaderFileSet &headerFiles)
{
for (const auto &importPair : ast_->GetImports()) {
AutoPtr<AST> importAst = importPair.second;
std::string fileName = PackageToFilePath(importAst->GetFullName());
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, fileName);
}
}
void HDICCodeEmitter::EmitInterfaceMethodParameter(
const AutoPtr<ASTParameter> &parameter, StringBuilder &sb, const std::string &prefix) const
{
std::string name = parameter->GetName();
AutoPtr<ASTType> type = parameter->GetType();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
ASTParamAttr::ParamAttr attrAttr = parameter->GetAttribute();
std::string typeName = (attrAttr == ASTParamAttr::PARAM_IN) ?
typeEmitter->EmitCType(TypeMode::PARAM_IN) : typeEmitter->EmitCType(TypeMode::PARAM_OUT);
switch (type->GetTypeKind()) {
case TypeKind::TYPE_BOOLEAN:
case TypeKind::TYPE_BYTE:
case TypeKind::TYPE_SHORT:
case TypeKind::TYPE_INT:
case TypeKind::TYPE_LONG:
case TypeKind::TYPE_UCHAR:
case TypeKind::TYPE_USHORT:
case TypeKind::TYPE_UINT:
case TypeKind::TYPE_ULONG:
case TypeKind::TYPE_FLOAT:
case TypeKind::TYPE_DOUBLE:
case TypeKind::TYPE_ENUM:
case TypeKind::TYPE_FILEDESCRIPTOR:
case TypeKind::TYPE_INTERFACE:
case TypeKind::TYPE_STRING:
case TypeKind::TYPE_STRUCT:
case TypeKind::TYPE_UNION:
case TypeKind::TYPE_NATIVE_BUFFER:
case TypeKind::TYPE_POINTER:
case TypeKind::TYPE_ARRAY:
case TypeKind::TYPE_LIST:
sb.Append(prefix).AppendFormat("%s %s", typeName.c_str(), name.c_str());
if ((type->GetTypeKind() == TypeKind::TYPE_STRING) && (attrAttr == ASTParamAttr::PARAM_OUT)) {
sb.AppendFormat(", uint32_t %sLen", name.c_str());
}
if ((type->GetTypeKind() == TypeKind::TYPE_ARRAY) || (type->GetTypeKind() == TypeKind::TYPE_LIST)) {
sb.AppendFormat(", uint32_t%s %sLen", (attrAttr == ASTParamAttr::PARAM_OUT) ? "*" : "", name.c_str());
}
break;
default:
sb.Append(prefix).AppendFormat("unknow type %s", name.c_str());
break;
}
}
void HDICCodeEmitter::EmitMethodNeedLoopVar(
const AutoPtr<ASTMethod> &method, bool needRW, bool needFree, StringBuilder &sb, const std::string &prefix) const
{
if (mode_ != GenMode::KERNEL) {
return;
}
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
if (EmitNeedLoopVar(param->GetType(), needRW, needFree)) {
sb.Append(prefix).Append("uint32_t i = 0;\n");
break;
}
}
}
bool HDICCodeEmitter::EmitNeedLoopVar(const AutoPtr<ASTType> &type, bool needRW, bool needFree) const
{
if (type == nullptr) {
return false;
}
auto rwNeedLoopVar = [needRW](const AutoPtr<ASTType> &elementType) -> bool {
if (!needRW) {
return false;
}
if (elementType->IsPod()) {
return elementType->IsBooleanType() ? true : false;
}
return elementType->IsStringType() ? false : true;
};
auto freeNeedLoopVar = [needFree](const AutoPtr<ASTType> &elementType) -> bool {
if (!needFree) {
return false;
}
return elementType->IsPod() ? false : true;
};
if (type->IsArrayType()) {
AutoPtr<ASTArrayType> arrType = dynamic_cast<ASTArrayType *>(type.Get());
if (rwNeedLoopVar(arrType->GetElementType()) || freeNeedLoopVar(arrType->GetElementType())) {
return true;
}
} else if (type->IsListType()) {
AutoPtr<ASTListType> listType = dynamic_cast<ASTListType *>(type.Get());
if (rwNeedLoopVar(listType->GetElementType()) || freeNeedLoopVar(listType->GetElementType())) {
return true;
}
}
return false;
}
void HDICCodeEmitter::EmitHeadMacro(StringBuilder &sb, const std::string &fullName) const
{
std::string macroName = MacroName(fullName);
sb.Append("#ifndef ").Append(macroName).Append("\n");
sb.Append("#define ").Append(macroName).Append("\n");
}
void HDICCodeEmitter::EmitTailMacro(StringBuilder &sb, const std::string &fullName) const
{
std::string macroName = MacroName(fullName);
sb.Append("#endif // ").Append(macroName);
}
void HDICCodeEmitter::EmitHeadExternC(StringBuilder &sb) const
{
sb.Append("#ifdef __cplusplus\n");
sb.Append("extern \"C\" {\n");
sb.Append("#endif /* __cplusplus */\n");
}
void HDICCodeEmitter::EmitTailExternC(StringBuilder &sb) const
{
sb.Append("#ifdef __cplusplus\n");
sb.Append("}\n");
sb.Append("#endif /* __cplusplus */\n");
}
std::string HDICCodeEmitter::MacroName(const std::string &name) const
{
if (name.empty()) {
return name;
}
std::string macro = StringHelper::StrToUpper(StringHelper::Replace(name, '.', '_')) + "_H";
return macro;
}
std::string HDICCodeEmitter::SpecificationParam(StringBuilder &paramSb, const std::string &prefix) const
{
size_t maxLineLen = 120;
size_t replaceLen = 2;
std::string paramStr = paramSb.ToString();
size_t preIndex = 0;
size_t curIndex = 0;
std::string insertStr = StringHelper::Format("\n%s", prefix.c_str());
for (; curIndex < paramStr.size(); curIndex++) {
if (curIndex == maxLineLen && preIndex > 0) {
StringHelper::Replace(paramStr, preIndex, replaceLen, ",");
paramStr.insert(preIndex + 1, insertStr);
} else {
if (paramStr[curIndex] == ',') {
preIndex = curIndex;
}
}
}
return paramStr;
}
std::string HDICCodeEmitter::EmitDescMacroName() const
{
return StringHelper::Format("%s_INTERFACE_DESC", StringHelper::StrToUpper(interface_->GetName()).c_str());
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2024 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_IDL_HDI_C_CODE_EMITTER_H
#define OHOS_IDL_HDI_C_CODE_EMITTER_H
#include "codegen/HDI/hdi_code_emitter.h"
namespace OHOS {
namespace Idl {
class HDICCodeEmitter : public HDICodeEmitter {
public:
~HDICCodeEmitter() override = default;
protected:
void GetStdlibInclusions(HeaderFile::HeaderFileSet &headerFiles);
void GetImportInclusions(HeaderFile::HeaderFileSet &headerFiles);
void EmitInterfaceMethodParameter(
const AutoPtr<ASTParameter> &parameter, StringBuilder &sb, const std::string &prefix) const;
void EmitMethodNeedLoopVar(const AutoPtr<ASTMethod> &method,
bool needRW, bool needFree, StringBuilder &sb, const std::string &prefix) const;
bool EmitNeedLoopVar(const AutoPtr<ASTType> &type, bool needRW, bool needFree) const;
void EmitHeadMacro(StringBuilder &sb, const std::string &fullName) const;
void EmitTailMacro(StringBuilder &sb, const std::string &fullName) const;
void EmitHeadExternC(StringBuilder &sb) const;
void EmitTailExternC(StringBuilder &sb) const;
std::string MacroName(const std::string &name) const;
std::string SpecificationParam(StringBuilder &paramSb, const std::string &prefix) const;
std::string EmitDescMacroName() const;
static constexpr const char *errorsLabel_ = "ERRORS";
static constexpr const char *finishedLabel_ = "FINISHED";
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_HDI_C_CODE_EMITTER_H

View File

@ -0,0 +1,872 @@
/*
* Copyright (c) 2024 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 "cpp_client_proxy_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
#include "util/string_helper.h"
namespace OHOS {
namespace Idl {
bool CppClientProxyCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
directory_ = GetFileParentPath(targetDirectory);
} else {
return false;
}
if (!File::CreateParentDir(directory_)) {
Logger::E("CppClientProxyCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CppClientProxyCodeEmitter::EmitCode()
{
switch (mode_) {
case GenMode::PASSTHROUGH: {
if (!interface_->IsSerializable()) {
EmitPassthroughProxySourceFile();
}
break;
}
case GenMode::IPC: {
EmitProxyHeaderFile();
EmitProxySourceFile();
}
default:
break;
}
}
void CppClientProxyCodeEmitter::EmitProxyHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_ + "Proxy").c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, proxyFullName_);
sb.Append("\n");
EmitProxyHeaderInclusions(sb);
sb.Append("\n");
EmitBeginNamespace(sb);
sb.Append("\n");
EmitProxyDecl(sb, "");
sb.Append("\n");
EmitEndNamespace(sb);
sb.Append("\n");
EmitTailMacro(sb, proxyFullName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppClientProxyCodeEmitter::EmitProxyHeaderInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
if (interface_->GetExtendsInterface() != nullptr) {
headerFiles.emplace(
HeaderFileType::OWN_HEADER_FILE, EmitHeaderNameByInterface(interface_->GetExtendsInterface(), proxyName_));
}
GetHeaderOtherLibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppClientProxyCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iproxy_broker");
if (!interface_->IsSerializable() && (!interface_->IsCallback())) {
headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "unistd");
}
}
void CppClientProxyCodeEmitter::EmitProxyDecl(StringBuilder &sb, const std::string &prefix)
{
(void)prefix;
sb.AppendFormat("class %s : public IProxyBroker<%s> {\n", proxyName_.c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append("public:\n");
if (!interface_->IsSerializable() && (!interface_->IsCallback())) {
EmitProxyDevmgrDeathRecipient(sb, TAB);
sb.Append("\n");
}
EmitProxyConstructor(sb, TAB);
sb.Append("\n");
EmitProxyMethodDecls(sb, TAB);
sb.Append("\n");
if (!interface_->IsSerializable() && (!interface_->IsCallback())) {
EmitProxyPublicMembers(sb, TAB);
}
sb.Append("private:\n");
EmitProxyConstants(sb, TAB);
sb.Append("};\n");
}
void CppClientProxyCodeEmitter::EmitProxyDevmgrDeathRecipient(StringBuilder &sb, const std::string &prefix) const
{
std::string doubleTab = prefix + TAB;
sb.Append(prefix).AppendFormat("class %s : public IRemoteObject::DeathRecipient {\n",
devmgrDeathRecipientName_.c_str());
sb.Append(prefix).Append("public:\n");
sb.Append(doubleTab).AppendFormat("%s(wptr<%s> proxy) : proxy_(proxy) {} \n", devmgrDeathRecipientName_.c_str(),
EmitDefinitionByInterface(interface_, proxyName_).c_str());
sb.Append(doubleTab).AppendFormat("~%s() override = default;\n", devmgrDeathRecipientName_.c_str());
EmitProxyDevmgrDeathCallBack(sb, doubleTab);
sb.Append(prefix).Append("private:\n");
sb.Append(doubleTab).AppendFormat("wptr<%s> proxy_;\n",
EmitDefinitionByInterface(interface_, proxyName_).c_str());
sb.Append(prefix).Append("};\n");
}
void CppClientProxyCodeEmitter::EmitProxyDevmgrDeathCallBack(StringBuilder &sb, const std::string &prefix) const
{
std::string trebleTab = prefix + TAB;
sb.Append(prefix).Append("void OnRemoteDied(const wptr<IRemoteObject> &remote) override\n");
sb.Append(prefix).Append("{\n");
sb.Append(trebleTab).Append("int32_t result = HDF_FAILURE;\n");
sb.Append(trebleTab).Append("const int sleepInterval = 500000;\n");
sb.Append(trebleTab).Append("const int waitTimes = 10;\n");
sb.Append(trebleTab).Append("int currentTime = waitTimes;\n");
sb.Append(trebleTab).Append("do {\n");
sb.Append(trebleTab + TAB).Append("usleep(sleepInterval);\n");
sb.Append(trebleTab + TAB).Append("auto proxy = proxy_.promote();\n");
sb.Append(trebleTab + TAB).Append("if (proxy != nullptr) {\n");
sb.Append(trebleTab + TAB + TAB).AppendFormat("result = %s::Reconnect(proxy);\n",
EmitDefinitionByInterface(interface_, proxyName_).c_str());
sb.Append(trebleTab + TAB).Append("}\n");
sb.Append(trebleTab + TAB).Append("--currentTime;\n");
sb.Append(trebleTab).Append("} while (result != HDF_SUCCESS && currentTime >0);\n");
sb.Append(prefix).Append("}\n");
}
void CppClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("explicit %s(const sptr<IRemoteObject>& remote)", proxyName_.c_str());
sb.AppendFormat(
" : IProxyBroker<%s>(remote) {\n", EmitDefinitionByInterface(interface_, interfaceName_).c_str());
if (!interface_->IsSerializable() && (!interface_->IsCallback())) {
sb.Append(prefix + TAB).Append("reconnectRemote_ = nullptr;\n");
sb.Append(prefix + TAB).Append("isReconnected_ = false;\n");
}
sb.Append(prefix).AppendFormat("}\n");
sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", proxyName_.c_str());
}
void CppClientProxyCodeEmitter::EmitProxyMethodDecls(StringBuilder &sb, const std::string &prefix) const
{
EmitProxyIsProxyMethodImpl(sb, prefix);
AutoPtr<ASTInterfaceType> interface = interface_;
while (interface != nullptr) {
for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitProxyMethodDecl(method, sb, prefix);
sb.Append("\n");
}
interface = interface->GetExtendsInterface();
}
EmitProxyMethodDecl(interface_->GetVersionMethod(), sb, prefix);
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
sb.Append("\n");
EmitProxyStaticMethodDecl(method, sb, prefix);
}
if (interface_->GetExtendsInterface() == nullptr) {
sb.Append("\n");
EmitProxyStaticMethodDecl(interface_->GetVersionMethod(), sb, prefix);
}
if (!interface_->IsSerializable() && (!interface_->IsCallback())) {
sb.Append("\n");
EmitProxyReconnectMethodDecl(sb, prefix);
sb.Append("\n");
EmitProxyGetRemoteMethodDecl(sb, prefix);
}
}
void CppClientProxyCodeEmitter::EmitProxyMethodDecl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
if (i + 1 < method->GetParameterNumber()) {
paramStr.Append(", ");
}
}
paramStr.Append(") override;");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
}
void CppClientProxyCodeEmitter::EmitProxyStaticMethodDecl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat(
"static int32_t %s_(const sptr<IRemoteObject> remote);\n", method->GetName().c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat("static int32_t %s_(", method->GetName().c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
paramStr.Append(", ");
}
paramStr.Append("const sptr<IRemoteObject> remote");
paramStr.Append(");");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
}
void CppClientProxyCodeEmitter::EmitProxyReconnectMethodDecl(StringBuilder &sb, const std::string &prefix) const
{
std::string doubleTab = prefix + TAB;
sb.Append(prefix).AppendFormat("static int32_t Reconnect(sptr<%s> proxy);\n",
EmitDefinitionByInterface(interface_, proxyName_).c_str());
}
void CppClientProxyCodeEmitter::EmitProxyGetRemoteMethodDecl(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).Append("sptr<IRemoteObject> GetCurrentRemote() {\n");
sb.Append(prefix + TAB).Append("return isReconnected_ ? reconnectRemote_ : Remote();\n");
sb.Append(prefix).Append("}\n");
}
void CppClientProxyCodeEmitter::EmitProxyPublicMembers(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).Append("bool isReconnected_;\n");
sb.Append(prefix).Append("std::string serviceName_;\n");
sb.Append(prefix).AppendFormat("sptr<IRemoteObject> servMgr_;\n", devmgrVersionName_.c_str());
sb.Append(prefix).Append("sptr<IRemoteObject> reconnectRemote_;\n");
}
void CppClientProxyCodeEmitter::EmitProxyConstants(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat(
"static inline BrokerDelegator<%s> delegator_;\n", EmitDefinitionByInterface(interface_, proxyName_).c_str());
}
void CppClientProxyCodeEmitter::EmitPassthroughProxySourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(proxyName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitPassthroughProxySourceInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(proxyName_));
sb.Append("\n");
EmitBeginNamespace(sb);
EmitGetMethodImpl(sb, "");
sb.Append("\n");
EmitPassthroughGetInstanceMethodImpl(sb, "");
EmitEndNamespace(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppClientProxyCodeEmitter::EmitPassthroughProxySourceInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
if (Options::GetInstance().GetSystemLevel() == SystemLevel::LITE) {
headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "codecvt");
headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "locale");
} else {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "string_ex");
}
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppClientProxyCodeEmitter::EmitPassthroughGetInstanceMethodImpl(StringBuilder &sb,
const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("%s %s::Get(const std::string &serviceName, bool isStub)\n",
GetTypeEmitter(interface_.Get())->EmitCppType().c_str(), interface_->GetName().c_str());
sb.Append(prefix).Append("{\n");
EmitProxyPassthroughtLoadImpl(sb, prefix + TAB);
sb.Append(prefix + TAB).Append("return nullptr;\n");
sb.Append(prefix).Append("}\n");
}
void CppClientProxyCodeEmitter::EmitProxySourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(proxyName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitProxySourceInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(proxyName_));
sb.Append("\n");
EmitBeginNamespace(sb);
sb.Append("\n");
EmitUtilMethods(sb, true);
sb.Append("\n");
if (interface_->GetExtendsInterface() != nullptr) {
EmitProxyCastFromMethodImplTemplate(sb, "");
sb.Append("\n");
}
if (!interface_->IsSerializable()) {
EmitGetMethodImpl(sb, "");
sb.Append("\n");
EmitGetInstanceMethodImpl(sb, "");
sb.Append("\n");
EmitProxyCppReconnectMethodImpl(sb, "");
sb.Append("\n");
}
EmitProxyCastFromMethodImpls(sb, "");
EmitUtilMethods(sb, false);
EmitProxyMethodImpls(sb, "");
sb.Append("\n");
EmitEndNamespace(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppClientProxyCodeEmitter::EmitProxySourceInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(proxyName_));
GetSourceOtherLibInclusions(headerFiles);
GetSourceOtherFileInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppClientProxyCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
if (!interface_->IsSerializable()) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iservmgr_hdi");
}
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_option");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "string_ex");
const AST::TypeStringMap &types = ast_->GetTypes();
for (const auto &pair : types) {
AutoPtr<ASTType> type = pair.second;
if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
break;
}
}
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
AutoPtr<ASTType> paramType = param->GetType();
if ((param->GetAttribute() == ASTParamAttr::PARAM_IN) &&
(paramType->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "object_collector");
}
if ((param->GetAttribute() == ASTParamAttr::PARAM_OUT) &&
(paramType->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iproxy_broker");
}
}
}
}
void CppClientProxyCodeEmitter::GetSourceOtherFileInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
AutoPtr<ASTType> paramType = param->GetType();
if ((param->GetAttribute() == ASTParamAttr::PARAM_OUT) &&
(param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
AutoPtr<ASTInterfaceType> type = dynamic_cast<ASTInterfaceType *>(paramType.Get());
std::string FileName = InterfaceToFilePath(paramType->ToString());
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, FileName);
}
}
}
}
void CppClientProxyCodeEmitter::EmitGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("%s %s::Get(bool isStub)\n", GetTypeEmitter(interface_.Get())->EmitCppType().c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB)
.AppendFormat("return %s::Get(\"%s\", isStub);\n", interfaceName_.c_str(), FileName(implName_).c_str());
sb.Append(prefix).Append("}\n");
}
void CppClientProxyCodeEmitter::EmitGetInstanceMethodImpl(StringBuilder &sb, const std::string &prefix)
{
std::string objName = "proxy";
std::string interfaceNamespace = GetNameSpaceByInterface(interface_, interfaceName_);
sb.Append(prefix).AppendFormat("sptr<%s> %s::Get(const std::string& serviceName, bool isStub)\n",
EmitDefinitionByInterface(interface_, interfaceName_).c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix).Append("{\n");
EmitProxyPassthroughtLoadImpl(sb, prefix + TAB);
sb.Append(prefix + TAB).AppendFormat("using namespace %s;\n", devmgrVersionName_.c_str());
sb.Append(prefix + TAB).Append("auto servMgr = IServiceManager::Get();\n");
sb.Append(prefix + TAB).Append("if (servMgr == nullptr) {\n");
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:get IServiceManager failed!\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).Append("sptr<IRemoteObject> remote = ");
sb.Append("servMgr->GetService(serviceName.c_str());\n");
sb.Append(prefix + TAB).Append("if (remote == nullptr) {\n");
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:get remote object failed!\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).AppendFormat("sptr<%s> %s = new %s(remote);\n",
EmitDefinitionByInterface(interface_, proxyName_).c_str(), objName.c_str(),
(interfaceNamespace +
(StringHelper::StartWith(interfaceName_, "I") ? interfaceName_.substr(1) : interfaceName_) +
"Proxy").c_str());
sb.Append(prefix + TAB).AppendFormat("if (%s == nullptr) {\n", objName.c_str());
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:iface_cast failed!\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
EmitGetInstanceMethodInitProxyImpl(sb, prefix);
}
void CppClientProxyCodeEmitter::EmitGetInstanceMethodInitProxyImpl(StringBuilder &sb, const std::string &prefix) const
{
std::string objName = "proxy";
std::string serMajorName = "serMajorVer";
std::string serMinorName = "serMinorVer";
sb.Append(prefix + TAB).AppendFormat("%s->servMgr_ = ", objName.c_str());
sb.Append("OHOS::HDI::hdi_objcast<IServiceManager>(servMgr);\n");
sb.Append(prefix + TAB).AppendFormat("%s->servMgr_->AddDeathRecipient(\n", objName.c_str());
sb.Append(prefix + TAB + TAB).AppendFormat("new %s::%s(%s));\n",
EmitDefinitionByInterface(interface_, proxyName_).c_str(),
devmgrDeathRecipientName_.c_str(), objName.c_str());
sb.Append(prefix + TAB).AppendFormat("%s->isReconnected_ = false;\n", objName.c_str());
sb.Append(prefix + TAB).AppendFormat("%s->serviceName_ = serviceName;\n", objName.c_str());
sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", serMajorName.c_str());
sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", serMinorName.c_str());
sb.Append(prefix + TAB).AppendFormat("int32_t %s = %s->GetVersion(%s, %s);\n",
HdiTypeEmitter::errorCodeName_.c_str(), objName.c_str(), serMajorName.c_str(), serMinorName.c_str());
sb.Append(prefix + TAB).AppendFormat("if (%s != HDF_SUCCESS) {\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:get version failed!\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).AppendFormat("if (%s != %d) {\n", serMajorName.c_str(), ast_->GetMajorVer());
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:check version failed! ");
sb.Append("version of service:%u.%u");
sb.AppendFormat(", version of client:%d.%d\", __func__, ", ast_->GetMajorVer(), ast_->GetMinorVer());
sb.AppendFormat("%s, %s);\n", serMajorName.c_str(), serMinorName.c_str());
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).AppendFormat("return %s;\n", objName.c_str());
sb.Append(prefix).Append("}\n");
}
void CppClientProxyCodeEmitter::EmitProxyCppReconnectMethodImpl(StringBuilder &sb, const std::string &prefix) const
{
std::string doubleTab = prefix + TAB;
sb.Append(prefix).AppendFormat("int32_t %s::Reconnect(\n",
EmitDefinitionByInterface(interface_, proxyName_).c_str());
sb.Append(doubleTab).AppendFormat("sptr<%s> proxy) \n",
EmitDefinitionByInterface(interface_, proxyName_).c_str());
sb.Append(prefix).Append("{\n");
sb.Append(doubleTab).Append("if (proxy == nullptr) {\n");
sb.Append(doubleTab + TAB).Append("HDF_LOGW(\"Reconnect failed : input proxy is null\");\n");
sb.Append(doubleTab + TAB).Append("return HDF_FAILURE;\n");
sb.Append(doubleTab).Append("}\n");
sb.Append(doubleTab).AppendFormat("using namespace %s;\n", devmgrVersionName_.c_str());
sb.Append(doubleTab).Append("proxy->isReconnected_ = false;\n");
sb.Append(doubleTab).Append("auto iServMgr = IServiceManager::Get();\n");
sb.Append(doubleTab).Append("if (iServMgr == nullptr) {\n");
sb.Append(doubleTab + TAB).Append("HDF_LOGW(\"Reconnect failed : iServMgr is null\");\n");
sb.Append(doubleTab + TAB).Append("return HDF_FAILURE;\n");
sb.Append(doubleTab).Append("};\n");
sb.Append(doubleTab).Append("proxy->reconnectRemote_ = ");
sb.Append("iServMgr->GetService(proxy->serviceName_.c_str());\n");
sb.Append(doubleTab).Append("if (proxy->reconnectRemote_ == nullptr) {\n");
sb.Append(doubleTab + TAB).Append("HDF_LOGW(\"Reconnect failed : reconnectRemote_ is null\");\n");
sb.Append(doubleTab + TAB).Append("return HDF_FAILURE;\n");
sb.Append(doubleTab).Append("}\n");
sb.Append(doubleTab).Append("proxy->servMgr_ = ");
sb.Append("OHOS::HDI::hdi_objcast<IServiceManager>(iServMgr);\n");
sb.Append(doubleTab).Append("if (proxy->servMgr_ == nullptr) {\n");
sb.Append(doubleTab + TAB).Append("HDF_LOGE(\"%{public}s:get IServiceManager failed!\", __func__);\n");
sb.Append(doubleTab + TAB).Append("return HDF_FAILURE;\n");
sb.Append(doubleTab).Append("}\n");
sb.Append(doubleTab).Append("proxy->servMgr_->AddDeathRecipient(\n");
sb.Append(doubleTab + TAB).AppendFormat("new %s::%s(proxy));\n",
EmitDefinitionByInterface(interface_, proxyName_).c_str(), devmgrDeathRecipientName_.c_str());
sb.Append(doubleTab).Append("proxy->isReconnected_ = true;\n");
sb.Append(doubleTab).Append("return HDF_SUCCESS;\n");
sb.Append(prefix).Append("}\n");
}
std::string CppClientProxyCodeEmitter::GetNameSpaceByInterface(AutoPtr<ASTInterfaceType> interface,
const std::string &name)
{
std::string value = EmitDefinitionByInterface(interface, name);
if (value.empty()) {
return "";
}
size_t index = value.rfind(':');
return (index == std::string::npos) ? value.substr(0) : value.substr(0, index + 1);
}
void CppClientProxyCodeEmitter::EmitProxyPassthroughtLoadImpl(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("if (isStub) {\n");
if (Options::GetInstance().GetSystemLevel() == SystemLevel::LITE) {
sb.Append(prefix + TAB).Append("std::string desc = ");
sb.Append("std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.to_bytes(");
sb.AppendFormat("%s::GetDescriptor());\n", EmitDefinitionByInterface(interface_, interfaceName_).c_str());
} else {
sb.Append(prefix + TAB).AppendFormat("std::string desc = Str16ToStr8(%s::GetDescriptor());\n",
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
}
sb.Append(prefix + TAB).Append("void *impl = LoadHdiImpl(desc.c_str(), ");
sb.AppendFormat("serviceName == \"%s\" ? \"service\" : serviceName.c_str());\n", FileName(implName_).c_str());
sb.Append(prefix + TAB).Append("if (impl == nullptr) {\n");
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"failed to load hdi impl %{public}s\", desc.data());\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n");
if (Options::GetInstance().GetSystemLevel() == SystemLevel::LITE) {
sb.Append(prefix + TAB).AppendFormat("return std::shared_ptr<%s>(reinterpret_cast<%s *>(impl));\n",
EmitDefinitionByInterface(interface_, interfaceName_).c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
} else {
sb.Append(prefix + TAB).AppendFormat("return reinterpret_cast<%s *>(impl);\n",
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
}
sb.Append(prefix).Append("}\n\n");
}
void CppClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder &sb, const std::string &prefix)
{
AutoPtr<ASTInterfaceType> interface = interface_;
AutoPtr<ASTInterfaceType> metaInterface = interface_;
while (interface != nullptr) {
for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitProxyMethodImpl(interface, method, sb, prefix);
sb.Append("\n");
}
interface = interface->GetExtendsInterface();
if (interface != nullptr) {
metaInterface = interface;
}
}
AutoPtr<ASTMethod> verMethod = interface_->GetVersionMethod();
EmitProxyMethodImpl(metaInterface, verMethod, sb, prefix);
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
sb.Append("\n");
EmitProxyStaticMethodImpl(method, sb, prefix);
}
if (interface_->GetExtendsInterface() == nullptr) {
sb.Append("\n");
EmitProxyStaticMethodImpl(interface_->GetVersionMethod(), sb, prefix);
}
}
void CppClientProxyCodeEmitter::EmitProxyIsProxyMethodImpl(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).Append("inline bool IsProxy() override\n");
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("return true;\n");
sb.Append(prefix).Append("}\n\n");
}
void CppClientProxyCodeEmitter::EmitProxyCastFromMethodImpls(StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTInterfaceType> interface = interface_->GetExtendsInterface();
while (interface != nullptr) {
EmitProxyCastFromMethodImpl(interface, sb, prefix);
sb.Append(prefix).Append("\n");
interface = interface->GetExtendsInterface();
}
}
void CppClientProxyCodeEmitter::EmitProxyCastFromMethodImpl(const AutoPtr<ASTInterfaceType> interface,
StringBuilder &sb, const std::string &prefix) const
{
std::string currentInterface = EmitDefinitionByInterface(interface_, interfaceName_);
std::string parentInterface = EmitDefinitionByInterface(interface, interfaceName_);
sb.Append(prefix).AppendFormat("sptr<%s> %s::CastFrom(const sptr<%s> &parent)\n",
currentInterface.c_str(), currentInterface.c_str(), parentInterface.c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("return CastFromTemplate<%s, %s>(parent);\n",
currentInterface.c_str(), parentInterface.c_str());
sb.Append(prefix).Append("}\n");
}
void CppClientProxyCodeEmitter::EmitProxyCastFromMethodImplTemplate(StringBuilder &sb, const std::string &prefix) const
{
std::string serMajorName = "serMajorVer";
std::string serMinorName = "serMinorVer";
sb.Append(prefix).Append("template<typename ChildType, typename ParentType>\n");
sb.Append(prefix).Append("static sptr<ChildType> CastFromTemplate(const sptr<ParentType> &parent)\n");
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("if (parent == nullptr) {\n");
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:parent is nullptr!\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).Append("if (!parent->IsProxy()) {\n");
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:not proxy, not support castfrom!\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).AppendFormat("sptr<IRemoteObject> remote = OHOS::HDI::hdi_objcast<ParentType>(parent);\n");
sb.Append(prefix + TAB).Append("if (remote == nullptr) {\n");
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:hdi_objcast failed!\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).AppendFormat("sptr<ChildType> proxy = OHOS::HDI::hdi_facecast<ChildType>(remote);\n");
sb.Append(prefix + TAB).Append("if (proxy == nullptr) {\n");
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:hdi_facecast failed!\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", serMajorName.c_str());
sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", serMinorName.c_str());
sb.Append(prefix + TAB).AppendFormat("int32_t %s = proxy->GetVersion(%s, %s);\n",
HdiTypeEmitter::errorCodeName_.c_str(), serMajorName.c_str(), serMinorName.c_str());
sb.Append(prefix + TAB).AppendFormat("if (%s != HDF_SUCCESS) {\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:get version failed!\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).AppendFormat("if (%s != %d) {\n", serMajorName.c_str(), ast_->GetMajorVer());
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s:check version failed! ");
sb.Append("version of service:%u.%u");
sb.AppendFormat(", version of client:%d.%d\", __func__, ", ast_->GetMajorVer(), ast_->GetMinorVer());
sb.AppendFormat("%s, %s);\n", serMajorName.c_str(), serMinorName.c_str());
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).Append("return proxy;\n");
sb.Append(prefix).Append("}\n");
}
void CppClientProxyCodeEmitter::EmitProxyMethodImpl(const AutoPtr<ASTInterfaceType> interface,
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
{
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat(
"int32_t %s::%s()\n", EmitDefinitionByInterface(interface_, proxyName_).c_str(), method->GetName().c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat(
"int32_t %s::%s(", EmitDefinitionByInterface(interface_, proxyName_).c_str(), method->GetName().c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
if (i + 1 < method->GetParameterNumber()) {
paramStr.Append(", ");
}
}
paramStr.Append(")");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
EmitProxyMethodBody(interface, method, sb, prefix);
}
void CppClientProxyCodeEmitter::EmitProxyStaticMethodImpl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
{
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat("int32_t %s::%s_(const sptr<IRemoteObject> remote)\n",
EmitDefinitionByInterface(interface_, proxyName_).c_str(), method->GetName().c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat(
"int32_t %s::%s_(", EmitDefinitionByInterface(interface_, proxyName_).c_str(), method->GetName().c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
paramStr.Append(", ");
}
paramStr.Append("const sptr<IRemoteObject> remote)");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
EmitProxyStaticMethodBody(method, sb, prefix);
}
void CppClientProxyCodeEmitter::EmitProxyMethodBody(const AutoPtr<ASTInterfaceType> interface,
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
{
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("return %s::%s_(",
EmitDefinitionByInterface(interface, proxyName_).c_str(), method->GetName().c_str());
if (method->GetParameterNumber() > 0) {
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
sb.Append(param->GetName().c_str());
sb.Append(", ");
}
}
if (!interface_->IsSerializable() && (!interface_->IsCallback())) {
sb.Append("GetCurrentRemote());\n");
} else {
sb.Append("Remote());\n");
}
sb.Append(prefix).Append("}\n");
}
void CppClientProxyCodeEmitter::EmitProxyStaticMethodBody(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix)
{
std::string option = method->IsOneWay() ? "MessageOption::TF_ASYNC" : "MessageOption::TF_SYNC";
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("MessageParcel %s;\n", HdiTypeEmitter::dataParcelName_.c_str());
sb.Append(prefix + TAB).AppendFormat("MessageParcel %s;\n", HdiTypeEmitter::replyParcelName_.c_str());
sb.Append(prefix + TAB).AppendFormat("MessageOption %s(%s);\n", optionName_.c_str(), option.c_str());
sb.Append("\n");
// write interface token
EmitWriteInterfaceToken(HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
sb.Append("\n");
EmitWriteFlagOfNeedSetMem(method, HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
if (method->GetParameterNumber() > 0) {
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
EmitWriteMethodParameter(param, HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
sb.Append("\n");
}
}
}
sb.Append(prefix + TAB).AppendFormat("if (remote == nullptr) {\n");
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"%{public}s: invalid remote object!\", __func__);\n");
sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_OBJECT;\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).AppendFormat("int32_t %s = remote->SendRequest(%s, %s, %s, %s);\n",
HdiTypeEmitter::errorCodeName_.c_str(), EmitMethodCmdID(method).c_str(),
HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(), optionName_.c_str());
sb.Append(prefix + TAB).AppendFormat("if (%s != HDF_SUCCESS) {\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB + TAB).AppendFormat(
"HDF_LOGE(\"%%{public}s failed, error code is %%{public}d\", __func__, %s);\n",
HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB + TAB).AppendFormat("return %s;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).Append("}\n");
if (!method->IsOneWay()) {
sb.Append("\n");
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
if (param->GetAttribute() == ASTParamAttr::PARAM_OUT) {
EmitReadMethodParameter(param, TypeMode::PARAM_OUT, sb, prefix + TAB);
sb.Append("\n");
}
}
}
sb.Append(prefix + TAB).AppendFormat("return %s;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix).Append("}\n");
}
void CppClientProxyCodeEmitter::EmitWriteInterfaceToken(
const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("if (!%s.WriteInterfaceToken(%s::GetDescriptor())) {\n", parcelName.c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: failed to write interface descriptor!\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix).Append("}\n");
}
void CppClientProxyCodeEmitter::EmitWriteFlagOfNeedSetMem(const AutoPtr<ASTMethod> &method,
const std::string &dataBufName, StringBuilder &sb, const std::string &prefix) const
{
if (NeedFlag(method)) {
sb.Append(prefix).AppendFormat("if (!%s.WriteBool(false)) {\n", dataBufName.c_str());
sb.Append(prefix + TAB).Append("HDF_LOGE(\"%{public}s:failed to write flag of memory setting!\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix).Append("}\n\n");
}
}
void CppClientProxyCodeEmitter::EmitUtilMethods(StringBuilder &sb, bool isDecl)
{
UtilMethodMap methods;
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
typeEmitter->EmitCppWriteMethods(methods, "", "", isDecl);
} else {
typeEmitter->EmitCppReadMethods(methods, "", "", isDecl);
}
}
}
EmitUtilMethodMap(sb, methods);
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2024 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_IDL_CPP_CLIENT_PROXY_CODE_EMITTER_H
#define OHOS_IDL_CPP_CLIENT_PROXY_CODE_EMITTER_H
#include "hdi_cpp_code_emitter.h"
namespace OHOS {
namespace Idl {
class CppClientProxyCodeEmitter : public HDICppCodeEmitter {
public:
CppClientProxyCodeEmitter() : HDICppCodeEmitter()
{
devmgrDeathRecipientName_ = "IServiceManagerDeathRecipient";
devmgrVersionName_ = "OHOS::HDI::ServiceManager::V1_0";
}
~CppClientProxyCodeEmitter() override = default;
protected:
std::string devmgrDeathRecipientName_;
std::string devmgrVersionName_;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitProxyHeaderFile();
void EmitProxyHeaderInclusions(StringBuilder &sb);
void GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void GetSourceOtherFileInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitProxyDecl(StringBuilder &sb, const std::string &prefix);
void EmitProxyConstructor(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyMethodDecls(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyMethodDecl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitProxyConstants(StringBuilder &sb, const std::string &prefix) const;
void EmitPassthroughProxySourceFile();
void EmitPassthroughProxySourceInclusions(StringBuilder &sb);
void EmitPassthroughGetInstanceMethodImpl(StringBuilder &sb, const std::string &prefix) const;
void EmitProxySourceFile();
void EmitProxySourceInclusions(StringBuilder &sb);
void GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitGetMethodImpl(StringBuilder &sb, const std::string &prefix) const;
void EmitGetInstanceMethodImpl(StringBuilder &sb, const std::string &prefix);
void EmitProxyPassthroughtLoadImpl(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyMethodImpls(StringBuilder &sb, const std::string &prefix);
void EmitProxyMethodImpl(const AutoPtr<ASTInterfaceType> interface, const AutoPtr<ASTMethod> &method,
StringBuilder &sb, const std::string &prefix);
void EmitProxyMethodBody(const AutoPtr<ASTInterfaceType> interface, const AutoPtr<ASTMethod> &method,
StringBuilder &sb, const std::string &prefix);
void EmitWriteInterfaceToken(const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const;
void EmitWriteFlagOfNeedSetMem(const AutoPtr<ASTMethod> &method, const std::string &dataBufName, StringBuilder &sb,
const std::string &prefix) const;
void EmitUtilMethods(StringBuilder &sb, bool isDecl) override;
void EmitProxyStaticMethodDecl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitProxyStaticMethodImpl(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix);
void EmitProxyStaticMethodBody(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix);
void EmitProxyIsProxyMethodImpl(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyCastFromMethodImpls(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyCastFromMethodImpl(const AutoPtr<ASTInterfaceType> interface, StringBuilder &sb,
const std::string &prefix) const;
void EmitProxyCastFromMethodImplTemplate(StringBuilder &sb, const std::string &prefix) const;
std::string GetNameSpaceByInterface(AutoPtr<ASTInterfaceType> interface, const std::string &name);
void EmitProxyDevmgrDeathRecipient(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyPublicMembers(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyDevmgrDeathCallBack(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyReconnectMethodDecl(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyGetRemoteMethodDecl(StringBuilder &sb, const std::string &prefix) const;
void EmitGetInstanceMethodInitProxyImpl(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyCppReconnectMethodImpl(StringBuilder &sb, const std::string &prefix) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_CPP_CLIENT_PROXY_CODE_EMITTER_H

View File

@ -0,0 +1,361 @@
/*
* Copyright (c) 2024 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 "cpp_custom_types_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
bool CppCustomTypesCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() != ASTFileType::AST_TYPES) {
return false;
}
directory_ = GetFileParentPath(targetDirectory);
if (!File::CreateParentDir(directory_)) {
Logger::E("CppCustomTypesCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CppCustomTypesCodeEmitter::EmitCode()
{
switch (mode_) {
case GenMode::PASSTHROUGH: {
EmitPassthroughCustomTypesHeaderFile();
break;
}
case GenMode::IPC: {
EmitCustomTypesHeaderFile();
EmitCustomTypesSourceFile();
}
default:
break;
}
}
void CppCustomTypesCodeEmitter::EmitPassthroughCustomTypesHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
File file(filePath, File::write_);
std::string marcoName = StringHelper::Format("%s.%s", ast_->GetPackageName().c_str(), baseName_.c_str());
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, marcoName);
sb.Append("\n");
EmitPassthroughHeaderFileInclusions(sb);
sb.Append("\n");
EmitBeginNamespace(sb);
sb.Append("\n");
EmitUsingNamespace(sb);
sb.Append("\n");
EmitCustomTypeDecls(sb);
EmitEndNamespace(sb);
sb.Append("\n");
EmitTailMacro(sb, marcoName);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppCustomTypesCodeEmitter::EmitPassthroughHeaderFileInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdbool");
headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdint");
GetStdlibInclusions(headerFiles);
GetImportInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppCustomTypesCodeEmitter::EmitCustomTypesHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(baseName_).c_str()));
File file(filePath, File::write_);
std::string marcoName = StringHelper::Format("%s.%s", ast_->GetPackageName().c_str(), baseName_.c_str());
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, marcoName);
sb.Append("\n");
EmitHeaderFileInclusions(sb);
sb.Append("\n");
EmitInterfaceBuffSizeMacro(sb);
sb.Append("\n");
EmitForwardDeclaration(sb);
sb.Append("\n");
EmitBeginNamespace(sb);
sb.Append("\n");
EmitUsingNamespace(sb);
sb.Append("\n");
EmitCustomTypeDecls(sb);
sb.Append("\n");
EmitCustomTypeFuncDecl(sb);
sb.Append("\n");
EmitEndNamespace(sb);
sb.Append("\n");
EmitTailMacro(sb, marcoName);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppCustomTypesCodeEmitter::EmitHeaderFileInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdbool");
headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "cstdint");
GetStdlibInclusions(headerFiles);
GetImportInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppCustomTypesCodeEmitter::EmitForwardDeclaration(StringBuilder &sb) const
{
sb.Append("namespace OHOS {\n");
sb.Append("class MessageParcel;\n");
sb.Append("}\n");
}
void CppCustomTypesCodeEmitter::EmitUsingNamespace(StringBuilder &sb)
{
sb.Append("using namespace OHOS;\n");
EmitImportUsingNamespace(sb);
}
void CppCustomTypesCodeEmitter::EmitCustomTypeDecls(StringBuilder &sb) const
{
for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(ast_->GetTypeDefintion(i));
sb.Append(typeEmitter->EmitCppTypeDecl()).Append("\n");
if (i + 1 < ast_->GetTypeDefinitionNumber()) {
sb.Append("\n");
}
}
}
void CppCustomTypesCodeEmitter::EmitCustomTypeFuncDecl(StringBuilder &sb) const
{
for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
EmitCustomTypeMarshallFuncDecl(sb, type);
if (i + 1 < ast_->GetTypeDefinitionNumber()) {
sb.Append("\n");
}
}
}
}
void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallFuncDecl(StringBuilder &sb, const AutoPtr<ASTType> &type) const
{
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
std::string objName("dataBlock");
sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel &data, const %s& %s);\n\n", type->GetName().c_str(),
typeEmitter->EmitCppType().c_str(), objName.c_str());
sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel &data, %s& %s);\n", type->GetName().c_str(),
typeEmitter->EmitCppType().c_str(), objName.c_str());
}
void CppCustomTypesCodeEmitter::EmitCustomTypesSourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(baseName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitSourceFileInclusions(sb);
sb.Append("\n");
EmitBeginNamespace(sb);
sb.Append("\n");
EmitUtilMethods(sb, true);
sb.Append("\n");
EmitUtilMethods(sb, false);
sb.Append("\n");
EmitCustomTypeDataProcess(sb);
sb.Append("\n");
EmitEndNamespace(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppCustomTypesCodeEmitter::EmitSourceFileInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(baseName_));
GetSourceOtherLibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppCustomTypesCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel");
}
void CppCustomTypesCodeEmitter::EmitCustomTypeDataProcess(StringBuilder &sb) const
{
for (size_t i = 0; i < ast_->GetTypeDefinitionNumber(); i++) {
AutoPtr<ASTType> type = ast_->GetTypeDefintion(i);
if (type->GetTypeKind() == TypeKind::TYPE_STRUCT) {
AutoPtr<ASTStructType> structType = dynamic_cast<ASTStructType *>(type.Get());
EmitCustomTypeMarshallingImpl(sb, structType);
EmitCustomTypeUnmarshallingImpl(sb, structType);
if (i + 1 < ast_->GetTypeDefinitionNumber()) {
sb.Append("\n");
}
}
}
}
void CppCustomTypesCodeEmitter::EmitCustomTypeMarshallingImpl(
StringBuilder &sb, const AutoPtr<ASTStructType> &type) const
{
std::string typeName = GetTypeEmitter(type.Get())->EmitCppType();
std::string objName("dataBlock");
sb.AppendFormat("bool %sBlockMarshalling(OHOS::MessageParcel& data, const %s& %s)\n", type->GetName().c_str(),
typeName.c_str(), objName.c_str());
sb.Append("{\n");
if (type->IsPod()) {
sb.Append(TAB).AppendFormat("if (!data.WriteUnpadBuffer((const void*)&%s, sizeof(%s))) {\n",
objName.c_str(), typeName.c_str());
sb.Append(TAB).Append(TAB).Append("return false;\n");
sb.Append(TAB).Append("}\n");
} else {
for (size_t i = 0; i < type->GetMemberNumber(); i++) {
std::string memberName = type->GetMemberName(i);
std::string name = StringHelper::Format("%s.%s", objName.c_str(), memberName.c_str());
GetTypeEmitter(type->GetMemberType(i))->EmitCppMarshalling("data", name, sb, TAB);
if (i + 1 < type->GetMemberNumber()) {
sb.Append("\n");
}
}
}
sb.Append(TAB).Append("return true;\n");
sb.Append("}\n\n");
}
void CppCustomTypesCodeEmitter::EmitCustomTypeUnmarshallingImpl(
StringBuilder &sb, const AutoPtr<ASTStructType> &type) const
{
std::string typeName = GetTypeEmitter(type.Get())->EmitCppType();
std::string objName("dataBlock");
sb.AppendFormat("bool %sBlockUnmarshalling(OHOS::MessageParcel& data, %s& %s)\n", type->GetName().c_str(),
typeName.c_str(), objName.c_str());
sb.Append("{\n");
if (type->IsPod()) {
std::string objPtrName = StringHelper::Format("%sPtr", objName.c_str());
sb.Append(TAB).AppendFormat("const %s *%s = reinterpret_cast<const %s*>(data.ReadUnpadBuffer(sizeof(%s)));\n",
typeName.c_str(), objPtrName.c_str(), typeName.c_str(), typeName.c_str());
sb.Append(TAB).AppendFormat("if (%s == NULL) {\n", objPtrName.c_str());
sb.Append(TAB).Append(TAB).Append("return false;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("if (memcpy_s(&%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n", objName.c_str(),
typeName.c_str(), objPtrName.c_str(), typeName.c_str());
sb.Append(TAB).Append(TAB).Append("return false;\n");
sb.Append(TAB).Append("}\n");
} else {
for (size_t i = 0; i < type->GetMemberNumber(); i++) {
AutoPtr<ASTType> memberType = type->GetMemberType(i);
std::string memberName = type->GetMemberName(i);
std::string name = StringHelper::Format("%s.%s", objName.c_str(), memberName.c_str());
if (i > 0) {
sb.Append("\n");
}
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(memberType);
if (memberType->GetTypeKind() == TypeKind::TYPE_UNION) {
std::string cpName = StringHelper::Format("%sCp", memberName.c_str());
typeEmitter->EmitCppUnMarshalling("data", cpName, sb, TAB);
sb.Append(TAB).AppendFormat("if (memcpy_s(&%s, sizeof(%s), %s, sizeof(%s)) != EOK) {\n",
name.c_str(), typeEmitter->EmitCppType().c_str(), cpName.c_str(),
typeEmitter->EmitCppType().c_str());
sb.Append(TAB).Append(TAB).AppendFormat("HDF_LOGE(\"%%{public}s: failed to memcpy %s\", __func__);\n",
name.c_str());
sb.Append(TAB).Append(TAB).Append("return false;\n");
sb.Append(TAB).Append("}\n");
} else if (memberType->GetTypeKind() == TypeKind::TYPE_STRING) {
std::string cpName = StringHelper::Format("%sCp", memberName.c_str());
typeEmitter->EmitCppUnMarshalling("data", cpName, sb, TAB);
sb.Append(TAB).AppendFormat("%s = %s;\n", name.c_str(), cpName.c_str());
} else {
typeEmitter->EmitCppUnMarshalling("data", name, sb, TAB);
}
}
}
sb.Append(TAB).AppendFormat("return true;\n", objName.c_str());
sb.Append("}\n");
}
void CppCustomTypesCodeEmitter::EmitBeginNamespace(StringBuilder &sb)
{
std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(ast_->GetPackageName());
for (const auto &nspace : cppNamespaceVec) {
sb.AppendFormat("namespace %s {\n", nspace.c_str());
}
}
void CppCustomTypesCodeEmitter::EmitEndNamespace(StringBuilder &sb)
{
std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(ast_->GetPackageName());
for (std::vector<std::string>::const_reverse_iterator nspaceIter = cppNamespaceVec.rbegin();
nspaceIter != cppNamespaceVec.rend(); ++nspaceIter) {
sb.AppendFormat("} // %s\n", nspaceIter->c_str());
}
}
void CppCustomTypesCodeEmitter::EmitUtilMethods(StringBuilder &sb, bool isDecl)
{
UtilMethodMap methods;
for (const auto &typePair : ast_->GetTypes()) {
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(typePair.second);
typeEmitter->EmitCppWriteMethods(methods, "", "", isDecl);
typeEmitter->EmitCppReadMethods(methods, "", "", isDecl);
}
EmitUtilMethodMap(sb, methods);
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2024 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_IDL_CPP_CUSTOM_TYPES_CODE_EMITTER_H
#define OHOS_IDL_CPP_CUSTOM_TYPES_CODE_EMITTER_H
#include "hdi_cpp_code_emitter.h"
namespace OHOS {
namespace Idl {
class CppCustomTypesCodeEmitter : public HDICppCodeEmitter {
public:
CppCustomTypesCodeEmitter() : HDICppCodeEmitter() {}
~CppCustomTypesCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitPassthroughCustomTypesHeaderFile();
void EmitPassthroughHeaderFileInclusions(StringBuilder& sb);
void EmitCustomTypesHeaderFile();
void EmitHeaderFileInclusions(StringBuilder &sb);
void EmitForwardDeclaration(StringBuilder &sb) const;
void EmitUsingNamespace(StringBuilder &sb) override;
void EmitCustomTypeDecls(StringBuilder &sb) const;
void EmitCustomTypeFuncDecl(StringBuilder &sb) const;
void EmitCustomTypeMarshallFuncDecl(StringBuilder &sb, const AutoPtr<ASTType> &type) const;
void EmitCustomTypesSourceFile();
void EmitSourceFileInclusions(StringBuilder &sb);
void GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitCustomTypeDataProcess(StringBuilder &sb) const;
void EmitCustomTypeMarshallingImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type) const;
void EmitCustomTypeUnmarshallingImpl(StringBuilder &sb, const AutoPtr<ASTStructType> &type) const;
void EmitBeginNamespace(StringBuilder &sb) override;
void EmitEndNamespace(StringBuilder &sb) override;
void EmitUtilMethods(StringBuilder &sb, bool isDecl) override;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_CPP_CUSTOM_TYPES_CODE_EMITTER_H

View File

@ -0,0 +1,292 @@
/*
* Copyright (c) 2024 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 "cpp_interface_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
bool CppInterfaceCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
directory_ = GetFileParentPath(targetDirectory);
} else {
return false;
}
if (!File::CreateParentDir(directory_)) {
Logger::E("CppInterfaceCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CppInterfaceCodeEmitter::EmitCode()
{
switch (mode_) {
case GenMode::PASSTHROUGH:
case GenMode::IPC: {
EmitInterfaceHeaderFile();
break;
}
default:
break;
}
}
void CppInterfaceCodeEmitter::EmitInterfaceHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(interfaceName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, interfaceFullName_);
sb.Append("\n");
EmitInterfaceInclusions(sb);
if (!Options::GetInstance().DoPassthrough()) {
sb.Append("\n");
EmitInterfaceBuffSizeMacro(sb);
}
sb.Append("\n");
EmitBeginNamespace(sb);
EmitUsingNamespace(sb);
if (!Options::GetInstance().DoPassthrough()) {
sb.Append("\n");
if (interface_->GetExtendsInterface() == nullptr) {
EmitInterfaceMethodCommands(sb, "");
} else {
EmitInterfaceMethodCommandsWithExtends(sb, "");
}
}
sb.Append("\n");
EmitInterfaceDefinition(sb);
EmitEndNamespace(sb);
sb.Append("\n");
EmitTailMacro(sb, interfaceFullName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppInterfaceCodeEmitter::EmitInterfaceInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
GetStdlibInclusions(headerFiles);
GetImportInclusions(headerFiles);
GetHeaderOtherLibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppInterfaceCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
headerFiles.emplace(HeaderFileType::C_STD_HEADER_FILE, "stdint");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_base");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
}
void CppInterfaceCodeEmitter::EmitInterfaceVersionMacro(StringBuilder &sb) const
{
sb.AppendFormat("#define %s %u\n", majorVerName_.c_str(), ast_->GetMajorVer());
sb.AppendFormat("#define %s %u\n", minorVerName_.c_str(), ast_->GetMinorVer());
}
void CppInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder &sb)
{
AutoPtr<ASTInterfaceType> interface = interface_->GetExtendsInterface();
if (interface != nullptr) {
sb.AppendFormat("class %s : public %s {\n", interfaceName_.c_str(),
EmitDefinitionByInterface(interface, interfaceName_).c_str());
} else {
sb.AppendFormat("class %s : public HdiBase {\n", interfaceName_.c_str());
}
sb.Append("public:\n");
EmitInterfaceDescriptor(sb, TAB);
sb.Append("\n");
EmitInterfaceDestruction(sb, TAB);
sb.Append("\n");
if (!interface_->IsSerializable()) {
EmitGetMethodDecl(sb, TAB);
sb.Append("\n");
}
if (interface_->GetExtendsInterface() != nullptr) {
EmitCastFromDecl(sb, TAB);
sb.Append("\n");
}
EmitInterfaceMethodsDecl(sb, TAB);
sb.Append("\n");
EmitGetDescMethod(sb, TAB);
sb.Append("};\n");
}
void CppInterfaceCodeEmitter::EmitGetDescMethod(StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTInterfaceType> interface = interface_->GetExtendsInterface();
if (interface == nullptr) {
sb.Append(prefix).Append("virtual const std::u16string GetDesc()");
} else {
sb.Append(prefix).Append("const std::u16string GetDesc() override");
}
sb.Append("\n");
sb.Append(prefix).Append("{").Append("\n");
sb.Append(prefix + TAB).Append("return metaDescriptor_;\n");
sb.Append(prefix).Append("}\n");
}
void CppInterfaceCodeEmitter::EmitInterfaceDescriptor(StringBuilder &sb, const std::string &prefix) const
{
(void)prefix;
sb.Append(TAB).AppendFormat("DECLARE_HDI_DESCRIPTOR(u\"%s\");\n", interfaceFullName_.c_str());
}
void CppInterfaceCodeEmitter::EmitCastFromDecl(StringBuilder &sb, const std::string &prefix) const
{
std::string currentInterface = EmitDefinitionByInterface(interface_, interfaceName_);
AutoPtr<ASTInterfaceType> interface = interface_->GetExtendsInterface();
while (interface != nullptr) {
std::string parentInterface = EmitDefinitionByInterface(interface, interfaceName_);
sb.Append(prefix).AppendFormat("static sptr<%s> CastFrom(const sptr<%s> &parent);\n",
currentInterface.c_str(), parentInterface.c_str());
interface = interface->GetExtendsInterface();
}
}
void CppInterfaceCodeEmitter::EmitGetMethodDecl(StringBuilder &sb, const std::string &prefix) const
{
std::string typeName = GetTypeEmitter(interface_.Get())->EmitCppType();
sb.Append(prefix).AppendFormat("static %s Get(bool isStub = false);\n", typeName.c_str());
sb.Append(prefix).AppendFormat("static %s Get(const std::string &serviceName, bool isStub = false);\n",
typeName.c_str());
}
void CppInterfaceCodeEmitter::EmitInterfaceDestruction(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", interface_->GetName().c_str());
}
void CppInterfaceCodeEmitter::EmitInterfaceMethodsDecl(StringBuilder &sb, const std::string &prefix)
{
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitInterfaceMethodDecl(method, sb, prefix);
sb.Append("\n");
}
EmitInterfaceGetVersionMethod(sb, prefix);
if (interface_->GetExtendsInterface() == nullptr) {
sb.Append("\n");
EmitInterfaceIsProxyMethod(sb, prefix);
}
}
void CppInterfaceCodeEmitter::EmitInterfaceMethodDecl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
if (interface_->GetExtendsInterface() != nullptr && method->IsOverload()) {
sb.Append(prefix).AppendFormat("using %s::%s;\n",
EmitDefinitionByInterface(interface_->GetExtendsInterface(), interfaceName_).c_str(),
method->GetName().c_str());
}
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat("virtual int32_t %s() = 0;\n", method->GetName().c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat("virtual int32_t %s(", method->GetName().c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
if (i + 1 < method->GetParameterNumber()) {
paramStr.Append(", ");
}
}
paramStr.Append(") = 0;");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
}
void CppInterfaceCodeEmitter::EmitInterfaceGetVersionMethod(StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTMethod> method = interface_->GetVersionMethod();
if (interface_->GetExtendsInterface() == nullptr) {
sb.Append(prefix).AppendFormat("virtual int32_t %s(", method->GetName().c_str());
} else {
sb.Append(prefix).AppendFormat("int32_t %s(", method->GetName().c_str());
}
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, sb, "");
if (i + 1 < method->GetParameterNumber()) {
sb.Append(", ");
}
}
sb.Append(")");
if (interface_->GetExtendsInterface() != nullptr) {
sb.Append(" override");
}
sb.Append("\n");
sb.Append(prefix).Append("{\n");
AutoPtr<ASTParameter> majorParam = method->GetParameter(0);
sb.Append(prefix + TAB).AppendFormat("%s = %d;\n", majorParam->GetName().c_str(), ast_->GetMajorVer());
AutoPtr<ASTParameter> minorParam = method->GetParameter(1);
sb.Append(prefix + TAB).AppendFormat("%s = %d;\n", minorParam->GetName().c_str(), ast_->GetMinorVer());
sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
sb.Append(prefix).Append("}\n");
}
void CppInterfaceCodeEmitter::EmitInterfaceIsProxyMethod(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("virtual bool %s(", "IsProxy");
sb.Append(")\n");
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("return false;\n");
sb.Append(prefix).Append("}\n");
}
void CppInterfaceCodeEmitter::EmitInterfaceMethodCommandsWithExtends(StringBuilder &sb, const std::string &prefix)
{
size_t extendMethods = 0;
AutoPtr<ASTInterfaceType> interface = interface_->GetExtendsInterface();
while (interface != nullptr) {
extendMethods += interface->GetMethodNumber();
interface = interface->GetExtendsInterface();
}
sb.Append(prefix).AppendFormat("enum {\n");
for (size_t i = 0; i < interface_->GetMethodNumber(); i++) {
AutoPtr<ASTMethod> method = interface_->GetMethod(i);
sb.Append(prefix + TAB)
.Append(EmitMethodCmdID(method))
.AppendFormat(" = %d", extendMethods + i + 1)
.Append(",\n");
}
sb.Append(prefix).Append("};\n");
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2024 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_IDL_CPP_INTERFACE_CODE_EMITTER_H
#define OHOS_IDL_CPP_INTERFACE_CODE_EMITTER_H
#include "hdi_cpp_code_emitter.h"
namespace OHOS {
namespace Idl {
class CppInterfaceCodeEmitter : public HDICppCodeEmitter {
public:
CppInterfaceCodeEmitter() : HDICppCodeEmitter() {}
~CppInterfaceCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitInterfaceHeaderFile();
void EmitInterfaceInclusions(StringBuilder &sb);
void GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitInterfaceVersionMacro(StringBuilder &sb) const;
void EmitInterfaceDefinition(StringBuilder &sb);
void EmitInterfaceDescriptor(StringBuilder &sb, const std::string &prefix) const;
void EmitGetMethodDecl(StringBuilder &sb, const std::string &prefix) const;
void EmitInterfaceDestruction(StringBuilder &sb, const std::string &prefix) const;
void EmitInterfaceMethodsDecl(StringBuilder &sb, const std::string &prefix);
void EmitInterfaceMethodDecl(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitInterfaceGetVersionMethod(StringBuilder &sb, const std::string &prefix) const;
void EmitInterfaceIsProxyMethod(StringBuilder &sb, const std::string &prefix) const;
void EmitInterfaceMethodCommandsWithExtends(StringBuilder &sb, const std::string &prefix);
void EmitGetDescMethod(StringBuilder &sb, const std::string &prefix) const;
void EmitCastFromDecl(StringBuilder &sb, const std::string &prefix) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_CPP_INTERFACE_CODE_EMITTER_H

View File

@ -0,0 +1,217 @@
/*
* Copyright (c) 2024 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 "cpp_service_driver_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
#include "util/options.h"
namespace OHOS {
namespace Idl {
bool CppServiceDriverCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() != ASTFileType::AST_IFACE) {
return false;
}
directory_ = GetFileParentPath(targetDirectory);
if (!File::CreateParentDir(directory_)) {
Logger::E("CppServiceDriverCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CppServiceDriverCodeEmitter::EmitCode()
{
if (mode_ == GenMode::IPC) {
if (!interface_->IsSerializable()) {
EmitDriverSourceFile();
}
}
}
void CppServiceDriverCodeEmitter::EmitDriverSourceFile()
{
std::string filePath = File::AdapterPath(
StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(baseName_ + "Driver").c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitDriverInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(baseName_ + "Driver"));
sb.Append("\n");
EmitDriverUsings(sb);
sb.Append("\n");
EmitDriverServiceDecl(sb);
sb.Append("\n");
EmitDriverDispatch(sb);
sb.Append("\n");
EmitDriverInit(sb);
sb.Append("\n");
EmitDriverBind(sb);
sb.Append("\n");
EmitDriverRelease(sb);
sb.Append("\n");
EmitDriverEntryDefinition(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppServiceDriverCodeEmitter::EmitDriverInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_device_desc");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_sbuf_ipc");
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(stubName_));
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppServiceDriverCodeEmitter::EmitDriverUsings(StringBuilder &sb)
{
std::string nspace = EmitPackageToNameSpace(interface_->GetNamespace()->ToString());
sb.AppendFormat("using namespace %s;\n", nspace.c_str());
}
void CppServiceDriverCodeEmitter::EmitDriverServiceDecl(StringBuilder &sb) const
{
sb.AppendFormat("struct Hdf%sHost {\n", baseName_.c_str());
sb.Append(TAB).Append("struct IDeviceIoService ioService;\n");
sb.Append(TAB).Append("OHOS::sptr<OHOS::IRemoteObject> stub;\n");
sb.Append("};\n");
}
void CppServiceDriverCodeEmitter::EmitDriverDispatch(StringBuilder &sb) const
{
std::string objName = StringHelper::Format("hdf%sHost", baseName_.c_str());
sb.AppendFormat("static int32_t %sDriverDispatch(", baseName_.c_str());
sb.Append("struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,\n");
sb.Append(TAB).Append("struct HdfSBuf *reply)\n");
sb.Append("{\n");
sb.Append(TAB).AppendFormat("auto *%s = CONTAINER_OF(", objName.c_str());
sb.AppendFormat("client->device->service, struct Hdf%sHost, ioService);\n\n", baseName_.c_str());
sb.Append(TAB).Append("OHOS::MessageParcel *dataParcel = nullptr;\n");
sb.Append(TAB).Append("OHOS::MessageParcel *replyParcel = nullptr;\n");
sb.Append(TAB).Append("OHOS::MessageOption option;\n\n");
sb.Append(TAB).Append("if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {\n");
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: invalid data sbuf object to dispatch\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(TAB).Append("}\n");
sb.Append(TAB).Append("if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {\n");
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: invalid reply sbuf object to dispatch\", __func__);\n");
sb.Append(TAB).Append(TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat(
"return %s->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);\n", objName.c_str());
sb.Append("}\n");
}
void CppServiceDriverCodeEmitter::EmitDriverInit(StringBuilder &sb) const
{
sb.AppendFormat("static int Hdf%sDriverInit(struct HdfDeviceObject *deviceObject)\n", baseName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("HDF_LOGI(\"%{public}s: driver init start\", __func__);\n");
sb.Append(TAB).Append("return HDF_SUCCESS;\n");
sb.Append("}\n");
}
void CppServiceDriverCodeEmitter::EmitDriverBind(StringBuilder &sb) const
{
std::string objName = StringHelper::Format("hdf%sHost", baseName_.c_str());
sb.AppendFormat("static int Hdf%sDriverBind(struct HdfDeviceObject *deviceObject)\n", baseName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("HDF_LOGI(\"%{public}s: driver bind start\", __func__);\n");
sb.Append(TAB).AppendFormat("auto *%s = new (std::nothrow) Hdf%sHost;\n", objName.c_str(), baseName_.c_str());
sb.Append(TAB).AppendFormat("if (%s == nullptr) {\n", objName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat(
"HDF_LOGE(\"%%{public}s: failed to create create Hdf%sHost object\", __func__);\n", baseName_.c_str());
sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("%s->ioService.Dispatch = %sDriverDispatch;\n", objName.c_str(), baseName_.c_str());
sb.Append(TAB).AppendFormat("%s->ioService.Open = NULL;\n", objName.c_str());
sb.Append(TAB).AppendFormat("%s->ioService.Release = NULL;\n\n", objName.c_str());
sb.Append(TAB).AppendFormat(
"auto serviceImpl = %s::Get(true);\n", EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(TAB).Append("if (serviceImpl == nullptr) {\n");
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: failed to get of implement service\", __func__);\n");
sb.Append(TAB).Append(TAB).AppendFormat("delete %s;\n", objName.c_str());
sb.Append(TAB).Append(TAB).Append("return HDF_FAILURE;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("%s->stub = OHOS::HDI::ObjectCollector::GetInstance().", objName.c_str());
sb.Append("GetOrNewObject(serviceImpl,\n");
sb.Append(TAB).Append(TAB).AppendFormat(
"%s::GetDescriptor());\n", EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(TAB).AppendFormat("if (%s->stub == nullptr) {\n", objName.c_str());
sb.Append(TAB).Append(TAB).Append("HDF_LOGE(\"%{public}s: failed to get stub object\", __func__);\n");
sb.Append(TAB).Append(TAB).AppendFormat("delete %s;\n", objName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("return HDF_FAILURE;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("deviceObject->service = &%s->ioService;\n", objName.c_str());
sb.Append(TAB).Append("return HDF_SUCCESS;\n");
sb.Append("}\n");
}
void CppServiceDriverCodeEmitter::EmitDriverRelease(StringBuilder &sb) const
{
std::string objName = StringHelper::Format("hdf%sHost", baseName_.c_str());
sb.AppendFormat("static void Hdf%sDriverRelease(struct HdfDeviceObject *deviceObject)\n", baseName_.c_str());
sb.Append("{\n");
sb.Append(TAB).Append("HDF_LOGI(\"%{public}s: driver release start\", __func__);\n");
sb.Append(TAB).AppendFormat("if (deviceObject->service == nullptr) {\n");
sb.Append(TAB).Append(TAB).AppendFormat("return;\n");
sb.Append(TAB).Append("}\n\n");
sb.Append(TAB).AppendFormat("auto *%s = CONTAINER_OF(", objName.c_str());
sb.AppendFormat("deviceObject->service, struct Hdf%sHost, ioService);\n", baseName_.c_str());
sb.Append(TAB).AppendFormat("if (%s != nullptr) {\n", objName.c_str());
sb.Append(TAB).Append(TAB).AppendFormat("delete %s;\n", objName.c_str());
sb.Append(TAB).Append("}\n");
sb.Append("}\n");
}
void CppServiceDriverCodeEmitter::EmitDriverEntryDefinition(StringBuilder &sb) const
{
sb.AppendFormat("struct HdfDriverEntry g_%sDriverEntry = {\n", StringHelper::StrToLower(baseName_).c_str());
sb.Append(TAB).Append(".moduleVersion = 1,\n");
sb.Append(TAB).AppendFormat(".moduleName = \"%s\",\n", Options::GetInstance().GetPackage().c_str());
sb.Append(TAB).AppendFormat(".Bind = Hdf%sDriverBind,\n", baseName_.c_str());
sb.Append(TAB).AppendFormat(".Init = Hdf%sDriverInit,\n", baseName_.c_str());
sb.Append(TAB).AppendFormat(".Release = Hdf%sDriverRelease,\n", baseName_.c_str());
sb.Append("};\n\n");
EmitHeadExternC(sb);
sb.AppendFormat("HDF_INIT(g_%sDriverEntry);\n", StringHelper::StrToLower(baseName_).c_str());
EmitTailExternC(sb);
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2024 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_IDL_CPP_SERVICE_DRIVER_CODE_EMITTER_H
#define OHOS_IDL_CPP_SERVICE_DRIVER_CODE_EMITTER_H
#include "hdi_cpp_code_emitter.h"
namespace OHOS {
namespace Idl {
class CppServiceDriverCodeEmitter : public HDICppCodeEmitter {
public:
CppServiceDriverCodeEmitter() : HDICppCodeEmitter() {}
~CppServiceDriverCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitDriverSourceFile();
void EmitDriverInclusions(StringBuilder &sb);
void EmitDriverUsings(StringBuilder &sb);
void EmitDriverServiceDecl(StringBuilder &sb) const;
void EmitDriverDispatch(StringBuilder &sb) const;
void EmitDriverInit(StringBuilder &sb) const;
void EmitDriverBind(StringBuilder &sb) const;
void EmitDriverRelease(StringBuilder &sb) const;
void EmitDriverEntryDefinition(StringBuilder &sb) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_CPP_SERVICE_DRIVER_CODE_EMITTER_H

View File

@ -0,0 +1,233 @@
/*
* Copyright (c) 2024 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 "cpp_service_impl_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
bool CppServiceImplCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
directory_ = GetFileParentPath(targetDirectory);
} else {
return false;
}
if (!File::CreateParentDir(directory_)) {
Logger::E("CppServiceImplCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CppServiceImplCodeEmitter::EmitCode()
{
switch (mode_) {
case GenMode::PASSTHROUGH:
case GenMode::IPC: {
EmitImplHeaderFile();
EmitImplSourceFile();
break;
}
default:
break;
}
}
void CppServiceImplCodeEmitter::EmitImplHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(implName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, implFullName_);
sb.Append("\n");
EmitServiceImplInclusions(sb);
sb.Append("\n");
EmitServiceImplDecl(sb);
sb.Append("\n");
EmitTailMacro(sb, implFullName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppServiceImplCodeEmitter::EmitServiceImplInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppServiceImplCodeEmitter::EmitServiceImplDecl(StringBuilder &sb)
{
EmitBeginNamespace(sb);
sb.AppendFormat("class %sService : public %s {\n", baseName_.c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append("public:\n");
EmitServiceImplBody(sb, TAB);
sb.Append("};\n");
EmitEndNamespace(sb);
}
void CppServiceImplCodeEmitter::EmitServiceImplBody(StringBuilder &sb, const std::string &prefix)
{
(void)prefix;
EmitServiceImplConstructor(sb, TAB);
sb.Append("\n");
EmitServiceImplMethodDecls(sb, TAB);
}
void CppServiceImplCodeEmitter::EmitServiceImplConstructor(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("%s() = default;\n", implName_.c_str());
sb.Append(prefix).AppendFormat("virtual ~%s() = default;\n", implName_.c_str());
}
void CppServiceImplCodeEmitter::EmitServiceImplMethodDecls(StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTInterfaceType> interface = interface_;
while (interface != nullptr) {
for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitServiceImplMethodDecl(method, sb, prefix);
sb.Append("\n");
}
interface = interface->GetExtendsInterface();
}
}
void CppServiceImplCodeEmitter::EmitServiceImplMethodDecl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat("int32_t %s() override;\n", method->GetName().c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat("int32_t %s(", method->GetName().c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
if (i + 1 < method->GetParameterNumber()) {
paramStr.Append(", ");
}
}
paramStr.Append(") override;");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
}
void CppServiceImplCodeEmitter::EmitImplSourceFile()
{
std::string filePath = File::AdapterPath(
StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(implName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitImplSourceInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(implName_));
sb.Append("\n");
EmitBeginNamespace(sb);
EmitServiceImplGetMethodImpl(sb, "");
EmitServiceImplMethodImpls(sb, "");
EmitEndNamespace(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppServiceImplCodeEmitter::EmitImplSourceInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(implName_));
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppServiceImplCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
}
void CppServiceImplCodeEmitter::EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTInterfaceType> interface = interface_;
while (interface != nullptr) {
for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitServiceImplMethodImpl(method, sb, prefix);
sb.Append("\n");
}
interface = interface->GetExtendsInterface();
}
}
void CppServiceImplCodeEmitter::EmitServiceImplMethodImpl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat("int32_t %sService::%s()\n", baseName_.c_str(), method->GetName().c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat("int32_t %sService::%s(", baseName_.c_str(), method->GetName().c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
if (i + 1 < method->GetParameterNumber()) {
paramStr.Append(", ");
}
}
paramStr.AppendFormat(")");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("return HDF_SUCCESS;\n");
sb.Append(prefix).Append("}\n");
}
void CppServiceImplCodeEmitter::EmitServiceImplGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
{
if (!interface_->IsSerializable()) {
sb.Append(prefix).AppendFormat(
"extern \"C\" %s *%sImplGetInstance(void)\n", interfaceName_.c_str(), baseName_.c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("return new (std::nothrow) %s();\n", implName_.c_str());
sb.Append(prefix).Append("}\n\n");
}
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2024 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_IDL_CPP_SERVICE_IMPL_CODE_EMITTER_H
#define OHOS_IDL_CPP_SERVICE_IMPL_CODE_EMITTER_H
#include "hdi_cpp_code_emitter.h"
namespace OHOS {
namespace Idl {
class CppServiceImplCodeEmitter : public HDICppCodeEmitter {
public:
CppServiceImplCodeEmitter() : HDICppCodeEmitter() {}
~CppServiceImplCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitImplHeaderFile();
void EmitServiceImplInclusions(StringBuilder &sb);
void EmitServiceImplDecl(StringBuilder &sb);
void EmitServiceImplBody(StringBuilder &sb, const std::string &prefix);
void EmitServiceImplConstructor(StringBuilder &sb, const std::string &prefix) const;
void EmitServiceImplMethodDecls(StringBuilder &sb, const std::string &prefix) const;
void EmitServiceImplMethodDecl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitImplSourceFile();
void EmitImplSourceInclusions(StringBuilder &sb);
void GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitServiceImplMethodImpls(StringBuilder &sb, const std::string &prefix) const;
void EmitServiceImplMethodImpl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitExternalGetMethodImpl(StringBuilder &sb);
void EmitExternalReleaseMethodImpl(StringBuilder &sb);
void EmitServiceImplGetMethodImpl(StringBuilder &sb, const std::string &prefix) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_CPP_SERVICE_IMPL_CODE_EMITTER_H

View File

@ -0,0 +1,597 @@
/*
* Copyright (c) 2024 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 "cpp_service_stub_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
bool CppServiceStubCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
directory_ = GetFileParentPath(targetDirectory);
} else {
return false;
}
if (!File::CreateParentDir(directory_)) {
Logger::E("CppServiceStubCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void CppServiceStubCodeEmitter::EmitCode()
{
if (mode_ == GenMode::IPC) {
EmitStubHeaderFile();
EmitStubSourceFile();
}
}
void CppServiceStubCodeEmitter::EmitStubHeaderFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.h", directory_.c_str(), FileName(stubName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitHeadMacro(sb, stubFullName_);
sb.Append("\n");
EmitStubHeaderInclusions(sb);
sb.Append("\n");
EmitStubDecl(sb);
sb.Append("\n");
EmitTailMacro(sb, stubFullName_);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppServiceStubCodeEmitter::EmitStubHeaderInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, EmitVersionHeaderName(interfaceName_));
if (interface_->GetExtendsInterface() != nullptr) {
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE,
EmitHeaderNameByInterface(interface_->GetExtendsInterface(), stubName_));
}
GetHeaderOtherLibInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppServiceStubCodeEmitter::GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_parcel");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "message_option");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "ipc_object_stub");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "object_collector");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "refbase");
}
void CppServiceStubCodeEmitter::EmitStubDecl(StringBuilder &sb)
{
EmitBeginNamespace(sb);
sb.Append("\n");
EmitStubUsingNamespace(sb);
sb.AppendFormat("class %s : public IPCObjectStub {\n", stubName_.c_str());
EmitStubBody(sb, TAB);
sb.Append("};\n");
EmitEndNamespace(sb);
}
void CppServiceStubCodeEmitter::EmitStubUsingNamespace(StringBuilder &sb) const
{
sb.Append("using namespace OHOS;\n");
}
void CppServiceStubCodeEmitter::EmitStubBody(StringBuilder &sb, const std::string &prefix) const
{
sb.Append("public:\n");
EmitStubConstructorDecl(sb, prefix);
sb.Append("\n");
EmitStubOnRequestDecl(sb, prefix);
sb.Append("\n");
EmitStubMethodDecls(sb, prefix);
sb.Append("\n");
EmitStubPrivateData(sb, prefix);
}
void CppServiceStubCodeEmitter::EmitStubConstructorDecl(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("explicit %s(const sptr<%s> &impl);\n", stubName_.c_str(), interfaceName_.c_str());
sb.Append(prefix).AppendFormat("virtual ~%s();\n", stubName_.c_str());
}
void CppServiceStubCodeEmitter::EmitStubOnRequestDecl(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).Append("int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, ");
sb.Append("MessageOption &option) override;\n");
}
void CppServiceStubCodeEmitter::EmitStubMethodDecls(StringBuilder &sb, const std::string &prefix) const
{
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitStubStaticMethodDecl(method, sb, prefix);
sb.Append("\n");
}
if (interface_->GetExtendsInterface() == nullptr) {
EmitStubStaticMethodDecl(interface_->GetVersionMethod(), sb, prefix);
sb.Append("\n");
}
sb.Append("private:\n");
AutoPtr<ASTInterfaceType> interface = interface_;
while (interface != nullptr) {
for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitStubMethodDecl(method, sb, prefix);
sb.Append("\n");
}
interface = interface->GetExtendsInterface();
}
EmitStubMethodDecl(interface_->GetVersionMethod(), sb, prefix);
sb.Append("\n");
}
void CppServiceStubCodeEmitter::EmitStubMethodDecl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("int32_t %s%s%s(MessageParcel& %s, MessageParcel& %s, MessageOption& %s);\n",
stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(), optionName_.c_str());
}
void CppServiceStubCodeEmitter::EmitStubStaticMethodDecl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat(
"static int32_t %s%s%s_(MessageParcel& %s, MessageParcel& %s, MessageOption& %s, sptr<%s> impl);\n",
stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(),
optionName_.c_str(), EmitDefinitionByInterface(interface_, interfaceName_).c_str());
}
void CppServiceStubCodeEmitter::EmitStubPrivateData(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("static inline ObjectDelegator<%s, %s> objDelegator_;\n",
EmitDefinitionByInterface(interface_, stubName_).c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix).AppendFormat("sptr<%s> impl_;\n", EmitDefinitionByInterface(interface_, interfaceName_).c_str());
}
void CppServiceStubCodeEmitter::EmitStubSourceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.cpp", directory_.c_str(), FileName(stubName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitStubSourceInclusions(sb);
sb.Append("\n");
EmitLogTagMacro(sb, FileName(stubName_));
sb.Append("\n");
EmitBeginNamespace(sb);
EmitUtilMethods(sb, true);
sb.Append("\n");
EmitUtilMethods(sb, false);
sb.Append("\n");
EmitInterfaceGetMethodImpl(sb, "");
sb.Append("\n");
EmitStubConstructorImpl(sb, "");
sb.Append("\n");
EmitStubOnRequestMethodImpl(sb, "");
sb.Append("\n");
EmitStubMethodImpls(sb, "");
EmitEndNamespace(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void CppServiceStubCodeEmitter::EmitStubSourceInclusions(StringBuilder &sb)
{
HeaderFile::HeaderFileSet headerFiles;
headerFiles.emplace(HeaderFileType::OWN_HEADER_FILE, EmitVersionHeaderName(stubName_));
GetSourceOtherLibInclusions(headerFiles);
GetSourceOtherFileInclusions(headerFiles);
for (const auto &file : headerFiles) {
sb.AppendFormat("%s\n", file.ToString().c_str());
}
}
void CppServiceStubCodeEmitter::GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
if (!interface_->IsSerializable()) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "string_ex");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdi_support");
} else {
const AST::TypeStringMap &types = ast_->GetTypes();
for (const auto &pair : types) {
AutoPtr<ASTType> type = pair.second;
if (type->GetTypeKind() == TypeKind::TYPE_UNION) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "securec");
break;
}
}
}
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
AutoPtr<ASTType> paramType = param->GetType();
if ((param->GetAttribute() == ASTParamAttr::PARAM_IN) &&
(param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "iproxy_broker");
}
if ((param->GetAttribute() == ASTParamAttr::PARAM_OUT) &&
(param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "object_collector");
}
}
}
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_base");
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "hdf_log");
}
void CppServiceStubCodeEmitter::GetSourceOtherFileInclusions(HeaderFile::HeaderFileSet &headerFiles) const
{
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
AutoPtr<ASTType> paramType = param->GetType();
if ((param->GetAttribute() == ASTParamAttr::PARAM_IN) &&
(param->GetType()->IsInterfaceType() || paramType->HasInnerType(TypeKind::TYPE_INTERFACE))) {
AutoPtr<ASTInterfaceType> type = dynamic_cast<ASTInterfaceType *>(paramType.Get());
std::string FileName = InterfaceToFilePath(paramType->ToString());
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, FileName);
}
}
}
}
void CppServiceStubCodeEmitter::EmitInterfaceGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
{
if (!interface_->IsSerializable()) {
EmitGetMethodImpl(sb, prefix);
sb.Append(prefix).Append("\n");
EmitGetInstanceMethodImpl(sb, prefix);
sb.Append(prefix).Append("\n");
}
}
void CppServiceStubCodeEmitter::EmitGetMethodImpl(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("sptr<%s> %s::Get(bool isStub)\n",
EmitDefinitionByInterface(interface_, interfaceName_).c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("return %s::Get(\"%s\", isStub);\n",
EmitDefinitionByInterface(interface_, interfaceName_).c_str(), FileName(implName_).c_str());
sb.Append(prefix).Append("}\n");
}
void CppServiceStubCodeEmitter::EmitGetInstanceMethodImpl(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("sptr<%s> %s::Get(const std::string& serviceName, bool isStub)\n",
EmitDefinitionByInterface(interface_, interfaceName_).c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("if (!isStub) {\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n");
sb.Append(prefix + TAB).AppendFormat("std::string desc = Str16ToStr8(%s::GetDescriptor());\n",
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix + TAB).Append("void *impl = LoadHdiImpl(desc.c_str(), ");
sb.AppendFormat("serviceName == \"%s\" ? \"service\" : serviceName.c_str());\n", FileName(implName_).c_str());
sb.Append(prefix + TAB).Append("if (impl == nullptr) {\n");
sb.Append(prefix + TAB + TAB).Append("HDF_LOGE(\"failed to load hdi impl %{public}s\", desc.c_str());\n");
sb.Append(prefix + TAB + TAB).Append("return nullptr;\n");
sb.Append(prefix + TAB).Append("}\n");
sb.Append(prefix + TAB).AppendFormat("return reinterpret_cast<%s *>(impl);\n",
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix).Append("}\n");
}
void CppServiceStubCodeEmitter::EmitStubConstructorImpl(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("%s::%s(const sptr<%s> &impl)\n",
EmitDefinitionByInterface(interface_, stubName_).c_str(), stubName_.c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix + TAB).AppendFormat(": IPCObjectStub(%s::GetDescriptor()), impl_(impl)\n",
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix).Append("}\n\n");
sb.Append(prefix).AppendFormat(
"%s::~%s()\n", EmitDefinitionByInterface(interface_, stubName_).c_str(), stubName_.c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("ObjectCollector::GetInstance().RemoveObject(impl_);\n");
sb.Append(prefix).Append("}\n");
}
void CppServiceStubCodeEmitter::EmitStubOnRequestMethodImpl(StringBuilder &sb, const std::string &prefix)
{
sb.Append(prefix).AppendFormat(
"int32_t %s::OnRemoteRequest(uint32_t code, ", EmitDefinitionByInterface(interface_, stubName_).c_str());
sb.Append("MessageParcel& data, MessageParcel& reply, MessageOption& option)\n");
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("switch (code) {\n");
AutoPtr<ASTMethod> getVerMethod = interface_->GetVersionMethod();
sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(getVerMethod).c_str());
sb.Append(prefix + TAB + TAB + TAB)
.AppendFormat("return %sStub%s%s(data, reply, option);\n",
baseName_.c_str(), getVerMethod->GetName().c_str(), getVerMethod->GetMethodIdentifier().c_str());
AutoPtr<ASTInterfaceType> interface = interface_;
while (interface != nullptr) {
for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
sb.Append(prefix + TAB + TAB).AppendFormat("case %s:\n", EmitMethodCmdID(method).c_str());
sb.Append(prefix + TAB + TAB + TAB)
.AppendFormat("return %sStub%s%s(data, reply, option);\n",
baseName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str());
}
interface = interface->GetExtendsInterface();
}
sb.Append(prefix + TAB + TAB).Append("default: {\n");
sb.Append(prefix + TAB + TAB + TAB)
.Append("HDF_LOGE(\"%{public}s: cmd %{public}d is not supported\", __func__, code);\n");
sb.Append(prefix + TAB + TAB + TAB).Append("return IPCObjectStub::OnRemoteRequest(code, data, reply, option);\n");
sb.Append(prefix + TAB + TAB).Append("}\n");
sb.Append(prefix + TAB).Append("}\n");
sb.Append("}\n");
}
void CppServiceStubCodeEmitter::EmitStubMethodImpls(StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTInterfaceType> interface = interface_;
AutoPtr<ASTInterfaceType> mataInterface = interface_;
while (interface != nullptr) {
for (const auto &method : interface->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitStubMethodImpl(interface, method, sb, prefix);
sb.Append("\n");
}
interface = interface->GetExtendsInterface();
if (interface != nullptr) {
mataInterface = interface;
}
}
AutoPtr<ASTMethod> verMethod = interface_->GetVersionMethod();
EmitStubMethodImpl(mataInterface, verMethod, sb, prefix);
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
sb.Append("\n");
EmitStubStaticMethodImpl(method, sb, prefix);
}
if (interface_->GetExtendsInterface() == nullptr) {
sb.Append("\n");
EmitStubStaticMethodImpl(verMethod, sb, prefix);
}
return;
}
void CppServiceStubCodeEmitter::EmitStubMethodImpl(AutoPtr<ASTInterfaceType> interface,
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("int32_t %s::%s%s%s(MessageParcel& %s, MessageParcel& %s, MessageOption& %s)\n",
EmitDefinitionByInterface(interface_, stubName_).c_str(),
stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(), optionName_.c_str());
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).AppendFormat("return %s::%s%s%s_(%s, %s, %s, impl_);\n",
EmitDefinitionByInterface(interface, stubName_).c_str(),
stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(),
optionName_.c_str());
sb.Append("}\n");
}
void CppServiceStubCodeEmitter::EmitStubStaticMethodImpl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat(
"int32_t %s::%s%s%s_(MessageParcel& %s, MessageParcel& %s, MessageOption& %s, sptr<%s> impl)\n",
EmitDefinitionByInterface(interface_, stubName_).c_str(),
stubName_.c_str(), method->GetName().c_str(), method->GetMethodIdentifier().c_str(),
HdiTypeEmitter::dataParcelName_.c_str(), HdiTypeEmitter::replyParcelName_.c_str(), optionName_.c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix).Append("{\n");
// read interface token and check it
EmitStubReadInterfaceToken(HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
sb.Append("\n");
EmitStubReadMemFlag(method, HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
EmitReadMethodParameter(param, TypeMode::PARAM_IN, sb, prefix + TAB);
sb.Append("\n");
} else {
EmitLocalVariable(param, HdiTypeEmitter::dataParcelName_, sb, prefix + TAB);
sb.Append("\n");
}
}
EmitStubCallMethod(method, sb, prefix + TAB);
sb.Append("\n");
if (!method->IsOneWay()) {
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
if (param->GetAttribute() == ASTParamAttr::PARAM_OUT) {
EmitWriteMethodParameter(param, HdiTypeEmitter::replyParcelName_, sb, prefix + TAB);
sb.Append("\n");
}
}
}
sb.Append(prefix + TAB).AppendFormat("return %s;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append("}\n");
}
void CppServiceStubCodeEmitter::EmitStubCallMethod(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).Append("if (impl == nullptr) {\n");
sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: impl is nullptr!\", __func__);\n");
sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix).Append("}\n\n");
sb.Append(prefix).AppendFormat("int32_t %s = impl->%s(", HdiTypeEmitter::errorCodeName_.c_str(),
method->GetName().c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
sb.Append(param->GetName());
if (i + 1 < method->GetParameterNumber()) {
sb.Append(", ");
}
}
sb.Append(");\n");
sb.Append(prefix).AppendFormat("if (%s != HDF_SUCCESS) {\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s failed, error code is %%{public}d\", __func__, %s);\n",
HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix + TAB).AppendFormat("return %s;\n", HdiTypeEmitter::errorCodeName_.c_str());
sb.Append(prefix).Append("}\n");
}
void CppServiceStubCodeEmitter::EmitStubReadInterfaceToken(
const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("if (%s.ReadInterfaceToken() != %s::GetDescriptor()) {\n", parcelName.c_str(),
EmitDefinitionByInterface(interface_, interfaceName_).c_str());
sb.Append(prefix + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: interface token check failed!\", __func__);\n");
sb.Append(prefix + TAB).AppendFormat("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix).Append("}\n");
}
void CppServiceStubCodeEmitter::EmitStubReadMemFlag(const AutoPtr<ASTMethod> &method,
const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
{
if (NeedFlag(method)) {
sb.Append(prefix).AppendFormat("bool %s = false;\n", flagOfSetMemName_.c_str());
sb.Append(prefix).AppendFormat("if (!%s.ReadBool(%s)) {\n", parcelName.c_str(), flagOfSetMemName_.c_str());
sb.Append(prefix + TAB)
.AppendFormat("HDF_LOGE(\"%%{public}s: failed to read %s\", __func__);\n", flagOfSetMemName_.c_str());
sb.Append(prefix + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix).Append("}\n");
}
}
void CppServiceStubCodeEmitter::EmitLocalVariable(const AutoPtr<ASTParameter> &param,
const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
{
EmitCppLocalVar(param, sb, prefix);
AutoPtr<ASTType> type = param->GetType();
if (!type->IsStringType() && !type->IsArrayType() && !type->IsListType()) {
return;
}
sb.Append(prefix).AppendFormat("if (%s) {\n", flagOfSetMemName_.c_str());
std::string capacityName = "capacity";
sb.Append(prefix + TAB).AppendFormat("uint32_t %s = 0;\n", capacityName.c_str());
sb.Append(prefix + TAB).AppendFormat("if (!%s.ReadUint32(%s)) {\n", parcelName.c_str(), capacityName.c_str());
sb.Append(prefix + TAB + TAB).AppendFormat("HDF_LOGE(\"%%{public}s: failed to read %s\", __func__);\n",
capacityName.c_str());
sb.Append(prefix + TAB + TAB).Append("return HDF_ERR_INVALID_PARAM;\n");
sb.Append(prefix + TAB).Append("}\n");
if (type->IsStringType()) {
sb.Append(prefix + TAB).AppendFormat("%s(%s, >, %s / sizeof(char), HDF_ERR_INVALID_PARAM);\n",
CHECK_VALUE_RETURN_MACRO, capacityName.c_str(), MAX_BUFF_SIZE_MACRO);
} else {
AutoPtr<ASTArrayType> arrayType = dynamic_cast<ASTArrayType *>(type.Get());
sb.Append(prefix + TAB).AppendFormat("%s(%s, >, %s / sizeof(%s), HDF_ERR_INVALID_PARAM);\n",
CHECK_VALUE_RETURN_MACRO, capacityName.c_str(), MAX_BUFF_SIZE_MACRO,
GetTypeEmitter(arrayType->GetElementType())->EmitCppType().c_str());
}
sb.Append(prefix + TAB).AppendFormat("%s.reserve(%s);\n", param->GetName().c_str(), capacityName.c_str());
sb.Append(prefix).Append("}\n");
}
void CppServiceStubCodeEmitter::EmitCppLocalVar(const AutoPtr<ASTParameter> &param,
StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTType> type = param->GetType();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
sb.Append(prefix).AppendFormat("%s %s", typeEmitter->EmitCppType(TypeMode::LOCAL_VAR).c_str(),
param->GetName().c_str());
switch (type->GetTypeKind()) {
case TypeKind::TYPE_BOOLEAN:
sb.Append(" = false");
break;
case TypeKind::TYPE_BYTE:
case TypeKind::TYPE_SHORT:
case TypeKind::TYPE_INT:
case TypeKind::TYPE_LONG:
case TypeKind::TYPE_UCHAR:
case TypeKind::TYPE_USHORT:
case TypeKind::TYPE_UINT:
case TypeKind::TYPE_ULONG:
case TypeKind::TYPE_FLOAT:
case TypeKind::TYPE_DOUBLE:
sb.Append(" = 0");
break;
case TypeKind::TYPE_FILEDESCRIPTOR:
sb.Append(" = -1");
break;
case TypeKind::TYPE_SEQUENCEABLE:
sb.Append(" = nullptr");
break;
default:
break;
}
sb.Append(";\n");
}
void CppServiceStubCodeEmitter::EmitUtilMethods(StringBuilder &sb, bool isDecl)
{
UtilMethodMap methods;
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
for (size_t paramIndex = 0; paramIndex < method->GetParameterNumber(); paramIndex++) {
AutoPtr<ASTParameter> param = method->GetParameter(paramIndex);
AutoPtr<ASTType> paramType = param->GetType();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
typeEmitter->EmitCppReadMethods(methods, "", "", isDecl);
} else {
typeEmitter->EmitCppWriteMethods(methods, "", "", isDecl);
}
}
}
EmitUtilMethodMap(sb, methods);
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2024 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_IDL_CPP_SERVICE_STUB_CODE_EMITTER_H
#define OHOS_IDL_CPP_SERVICE_STUB_CODE_EMITTER_H
#include "hdi_cpp_code_emitter.h"
namespace OHOS {
namespace Idl {
class CppServiceStubCodeEmitter : public HDICppCodeEmitter {
public:
CppServiceStubCodeEmitter() : HDICppCodeEmitter() {}
~CppServiceStubCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
// ISample.idl -> sample_service_stub.h
void EmitStubHeaderFile();
void EmitStubHeaderInclusions(StringBuilder &sb);
void GetHeaderOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitStubUsingNamespace(StringBuilder &sb) const;
void EmitStubDecl(StringBuilder &sb);
void EmitStubBody(StringBuilder &sb, const std::string &prefix) const;
void EmitStubConstructorDecl(StringBuilder &sb, const std::string &prefix) const;
void EmitStubOnRequestDecl(StringBuilder &sb, const std::string &prefix) const;
void EmitStubMethodDecls(StringBuilder &sb, const std::string &prefix) const;
void EmitStubMethodDecl(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitStubPrivateData(StringBuilder &sb, const std::string &prefix) const;
// ISample.idl -> sample_service_stub.cpp
void EmitStubSourceFile();
void EmitStubSourceInclusions(StringBuilder &sb);
void GetSourceOtherLibInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void GetSourceOtherFileInclusions(HeaderFile::HeaderFileSet &headerFiles) const;
void EmitInterfaceGetMethodImpl(StringBuilder &sb, const std::string &prefix) const;
void EmitGetMethodImpl(StringBuilder &sb, const std::string &prefix) const;
void EmitGetInstanceMethodImpl(StringBuilder &sb, const std::string &prefix) const;
void EmitStubConstructorImpl(StringBuilder &sb, const std::string &prefix) const;
void EmitStubOnRequestMethodImpl(StringBuilder &sb, const std::string &prefix);
void EmitStubMethodImpls(StringBuilder &sb, const std::string &prefix) const;
void EmitStubMethodImpl(AutoPtr<ASTInterfaceType> interface, const AutoPtr<ASTMethod> &method, StringBuilder &sb,
const std::string &prefix) const;
void EmitStubStaticMethodImpl(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitStubCallMethod(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitStubReadInterfaceToken(const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const;
void EmitStubReadMemFlag(const AutoPtr<ASTMethod> &method, const std::string &parcelName, StringBuilder &sb,
const std::string &prefix) const;
void EmitLocalVariable(const AutoPtr<ASTParameter> &param, const std::string &parcelName, StringBuilder &sb,
const std::string &prefix) const;
void EmitUtilMethods(StringBuilder &sb, bool isDecl) override;
void EmitStubStaticMethodDecl(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitCppLocalVar(const AutoPtr<ASTParameter> &param, StringBuilder &sb, const std::string &prefix) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_CPP_SERVICE_STUB_CODE_EMITTER_H

View File

@ -0,0 +1,260 @@
/*
* Copyright (c) 2024 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 "hdi_cpp_code_emitter.h"
#include <regex>
#include <unordered_set>
#include "util/options.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
void HDICppCodeEmitter::GetImportInclusions(HeaderFile::HeaderFileSet &headerFiles)
{
for (const auto &importPair : ast_->GetImports()) {
AutoPtr<AST> importAst = importPair.second;
std::string fileName = (importAst->GetASTFileType() == ASTFileType::AST_SEQUENCEABLE) ?
PackageToFilePath(importAst->GetName()) :
PackageToFilePath(importAst->GetFullName());
headerFiles.emplace(HeaderFileType::OWN_MODULE_HEADER_FILE, fileName);
}
}
void HDICppCodeEmitter::EmitInterfaceMethodParameter(
const AutoPtr<ASTParameter> &param, StringBuilder &sb, const std::string &prefix) const
{
std::string name = param->GetName();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
if (param->GetAttribute() == ASTParamAttr::PARAM_IN) {
sb.Append(prefix).AppendFormat("%s %s", typeEmitter->EmitCppType(TypeMode::PARAM_IN).c_str(), name.c_str());
} else {
sb.Append(prefix).AppendFormat("%s %s", typeEmitter->EmitCppType(TypeMode::PARAM_OUT).c_str(), name.c_str());
}
}
bool HDICppCodeEmitter::IsVersion(const std::string &name) const
{
std::regex rVer("[V|v][0-9]+_[0-9]+");
return std::regex_match(name.c_str(), rVer);
}
std::vector<std::string> HDICppCodeEmitter::EmitCppNameSpaceVec(const std::string &namespaceStr) const
{
std::vector<std::string> result;
std::vector<std::string> namespaceVec = StringHelper::Split(namespaceStr, ".");
bool findVersion = false;
std::string rootPackage = Options::GetInstance().GetRootPackage(namespaceStr);
size_t rootPackageNum = StringHelper::Split(rootPackage, ".").size();
for (size_t i = 0; i < namespaceVec.size(); i++) {
std::string name;
if (i < rootPackageNum) {
name = StringHelper::StrToUpper(namespaceVec[i]);
} else if (!findVersion && IsVersion(namespaceVec[i])) {
name = StringHelper::Replace(namespaceVec[i], 'v', 'V');
findVersion = true;
} else {
if (findVersion) {
name = namespaceVec[i];
} else {
name = PascalName(namespaceVec[i]);
}
}
result.emplace_back(name);
}
return result;
}
std::string HDICppCodeEmitter::EmitPackageToNameSpace(const std::string &packageName) const
{
if (packageName.empty()) {
return packageName;
}
StringBuilder nameSpaceStr;
std::vector<std::string> namespaceVec = EmitCppNameSpaceVec(packageName);
for (auto nameIter = namespaceVec.begin(); nameIter != namespaceVec.end(); nameIter++) {
nameSpaceStr.Append(*nameIter);
if (nameIter != namespaceVec.end() - 1) {
nameSpaceStr.Append("::");
}
}
return nameSpaceStr.ToString();
}
void HDICppCodeEmitter::GetStdlibInclusions(HeaderFile::HeaderFileSet &headerFiles)
{
const AST::TypeStringMap &types = ast_->GetTypes();
for (const auto &pair : types) {
AutoPtr<ASTType> type = pair.second;
switch (type->GetTypeKind()) {
case TypeKind::TYPE_STRING: {
headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "string");
break;
}
case TypeKind::TYPE_ARRAY:
case TypeKind::TYPE_LIST: {
headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "vector");
break;
}
case TypeKind::TYPE_MAP: {
headerFiles.emplace(HeaderFileType::CPP_STD_HEADER_FILE, "map");
break;
}
case TypeKind::TYPE_SMQ: {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "base/hdi_smq");
break;
}
case TypeKind::TYPE_ASHMEM: {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "ashmem");
break;
}
case TypeKind::TYPE_NATIVE_BUFFER: {
headerFiles.emplace(HeaderFileType::OTHER_MODULES_HEADER_FILE, "base/native_buffer");
break;
}
default:
break;
}
}
}
void HDICppCodeEmitter::EmitBeginNamespace(StringBuilder &sb)
{
std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(interface_->GetNamespace()->ToString());
for (const auto &nspace : cppNamespaceVec) {
sb.AppendFormat("namespace %s {\n", nspace.c_str());
}
}
void HDICppCodeEmitter::EmitEndNamespace(StringBuilder &sb)
{
std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(interface_->GetNamespace()->ToString());
for (std::vector<std::string>::const_reverse_iterator nspaceIter = cppNamespaceVec.rbegin();
nspaceIter != cppNamespaceVec.rend(); ++nspaceIter) {
sb.AppendFormat("} // %s\n", nspaceIter->c_str());
}
}
void HDICppCodeEmitter::EmitUsingNamespace(StringBuilder &sb)
{
sb.Append("using namespace OHOS;\n");
sb.Append("using namespace OHOS::HDI;\n");
EmitImportUsingNamespace(sb);
}
std::string HDICppCodeEmitter::EmitNamespace(const std::string &packageName) const
{
if (packageName.empty()) {
return packageName;
}
size_t index = packageName.rfind('.');
return index != std::string::npos ? StringHelper::SubStr(packageName, 0, index) : packageName;
}
void HDICppCodeEmitter::EmitImportUsingNamespace(StringBuilder &sb)
{
using StringSet = std::unordered_set<std::string>;
StringSet namespaceSet;
std::string selfNameSpace = EmitPackageToNameSpace(EmitNamespace(ast_->GetFullName()));
for (const auto &importPair : ast_->GetImports()) {
AutoPtr<AST> import = importPair.second;
std::string nameSpace = EmitPackageToNameSpace(EmitNamespace(import->GetFullName()));
if (nameSpace == selfNameSpace) {
continue;
}
namespaceSet.emplace(nameSpace);
}
const AST::TypeStringMap &types = ast_->GetTypes();
for (const auto &pair : types) {
AutoPtr<ASTType> type = pair.second;
if (type->GetTypeKind() == TypeKind::TYPE_SMQ ||
type->GetTypeKind() == TypeKind::TYPE_NATIVE_BUFFER) {
namespaceSet.emplace("OHOS::HDI::Base");
break;
}
}
for (const auto &nspace : namespaceSet) {
sb.Append("using namespace ").AppendFormat("%s;\n", nspace.c_str());
}
}
void HDICppCodeEmitter::EmitWriteMethodParameter(const AutoPtr<ASTParameter> &param,
const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
typeEmitter->EmitCppWriteVar(parcelName, param->GetName(), sb, prefix);
}
void HDICppCodeEmitter::EmitReadMethodParameter(const AutoPtr<ASTParameter> &param, TypeMode mode,
StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
typeEmitter->EmitCppReadVar(param->GetName(), sb, prefix, mode);
}
std::string HDICppCodeEmitter::SpecificationParam(StringBuilder &paramSb, const std::string &prefix) const
{
size_t maxLineLen = 120;
size_t replaceLen = 2;
std::string paramStr = paramSb.ToString();
size_t preIndex = 0;
size_t curIndex = 0;
std::string insertStr = StringHelper::Format("\n%s", prefix.c_str());
for (; curIndex < paramStr.size(); curIndex++) {
if (curIndex == maxLineLen && preIndex > 0) {
StringHelper::Replace(paramStr, preIndex, replaceLen, ",");
paramStr.insert(preIndex + 1, insertStr);
} else {
if (paramStr[curIndex] == ',') {
preIndex = curIndex;
}
}
}
return paramStr;
}
std::string HDICppCodeEmitter::EmitHeaderNameByInterface(AutoPtr<ASTInterfaceType> interface, const std::string &name)
{
return StringHelper::Format(
"v%u_%u/%s", interface->GetMajorVersion(), interface->GetMinorVersion(), FileName(name).c_str());
}
std::string HDICppCodeEmitter::EmitDefinitionByInterface(
AutoPtr<ASTInterfaceType> interface, const std::string &name) const
{
StringBuilder sb;
std::vector<std::string> cppNamespaceVec = EmitCppNameSpaceVec(interface->GetNamespace()->ToString());
for (const auto &nspace : cppNamespaceVec) {
sb.AppendFormat("%s", nspace.c_str());
sb.Append("::");
}
sb.Append(name.c_str());
return sb.ToString();
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2024 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_IDL_HDI_CPP_CODE_EMITTER_H
#define OHOS_IDL_HDI_CPP_CODE_EMITTER_H
#include "codegen/HDI/hdi_code_emitter.h"
namespace OHOS {
namespace Idl {
class HDICppCodeEmitter : public HDICodeEmitter {
public:
~HDICppCodeEmitter() override = default;
bool OutPut(const AutoPtr<AST> &ast, const std::string &targetDirectory);
protected:
void GetImportInclusions(HeaderFile::HeaderFileSet &headerFiles);
void EmitInterfaceMethodParameter(
const AutoPtr<ASTParameter> &param, StringBuilder &sb, const std::string &prefix) const;
bool IsVersion(const std::string &name) const;
void GetStdlibInclusions(HeaderFile::HeaderFileSet &headerFiles);
std::vector<std::string> EmitCppNameSpaceVec(const std::string &namespaceStr) const;
std::string EmitPackageToNameSpace(const std::string &packageName) const;
virtual void EmitBeginNamespace(StringBuilder &sb);
virtual void EmitEndNamespace(StringBuilder &sb);
virtual void EmitUsingNamespace(StringBuilder &sb);
std::string EmitNamespace(const std::string &packageName) const;
void EmitImportUsingNamespace(StringBuilder &sb);
void EmitWriteMethodParameter(const AutoPtr<ASTParameter> &param, const std::string &parcelName, StringBuilder &sb,
const std::string &prefix) const;
void EmitReadMethodParameter(const AutoPtr<ASTParameter> &param, TypeMode mode, StringBuilder &sb,
const std::string &prefix) const;
std::string SpecificationParam(StringBuilder &paramSb, const std::string &prefix) const;
std::string EmitHeaderNameByInterface(AutoPtr<ASTInterfaceType> interface, const std::string &name);
std::string EmitDefinitionByInterface(AutoPtr<ASTInterfaceType> interface, const std::string &name) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_CPP_CODE_EMITTER_H

View File

@ -0,0 +1,346 @@
/*
* Copyright (c) 2024 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 "hdi_code_emitter.h"
#include "type/hdi_boolean_type_emitter.h"
#include "type/hdi_byte_type_emitter.h"
#include "type/hdi_short_type_emitter.h"
#include "type/hdi_int_type_emitter.h"
#include "type/hdi_long_type_emitter.h"
#include "type/hdi_float_type_emitter.h"
#include "type/hdi_double_type_emitter.h"
#include "type/hdi_uchar_type_emitter.h"
#include "type/hdi_ushort_type_emitter.h"
#include "type/hdi_uint_type_emitter.h"
#include "type/hdi_ulong_type_emitter.h"
#include "type/hdi_string_type_emitter.h"
#include "type/hdi_fd_type_emitter.h"
#include "type/hdi_seq_type_emitter.h"
#include "type/hdi_interface_type_emitter.h"
#include "type/hdi_map_type_emitter.h"
#include "type/hdi_array_type_emitter.h"
#include "type/hdi_enum_type_emitter.h"
#include "type/hdi_struct_type_emitter.h"
#include "type/hdi_union_type_emitter.h"
#include "type/hdi_smq_type_emitter.h"
#include "type/hdi_native_buffer_type_emitter.h"
#include "type/hdi_pointer_type_emitter.h"
#include <cctype>
#include "util/file.h"
#include "util/options.h"
namespace OHOS {
namespace Idl {
HDICodeEmitter::TypeEmitterMap HDICodeEmitter::basicEmitters_ = {
{TypeKind::TYPE_BOOLEAN, new HdiBooleanTypeEmitter() },
{TypeKind::TYPE_BYTE, new HdiByteTypeEmitter() },
{TypeKind::TYPE_SHORT, new HdiShortTypeEmitter() },
{TypeKind::TYPE_INT, new HdiIntTypeEmitter() },
{TypeKind::TYPE_LONG, new HdiLongTypeEmitter() },
{TypeKind::TYPE_FLOAT, new HdiFloatTypeEmitter() },
{TypeKind::TYPE_DOUBLE, new HdiDoubleTypeEmitter() },
{TypeKind::TYPE_UCHAR, new HdiUcharTypeEmitter() },
{TypeKind::TYPE_USHORT, new HdiUshortTypeEmitter() },
{TypeKind::TYPE_UINT, new HdiUintTypeEmitter() },
{TypeKind::TYPE_ULONG, new HdiUlongTypeEmitter() },
{TypeKind::TYPE_STRING, new HdiStringTypeEmitter() },
{TypeKind::TYPE_FILEDESCRIPTOR, new HdiFdTypeEmitter() },
{TypeKind::TYPE_ASHMEM, new HdiAshmemTypeEmitter() },
{TypeKind::TYPE_NATIVE_BUFFER, new HdiNativeBufferTypeEmitter() },
{TypeKind::TYPE_POINTER, new HdiPointerTypeEmitter() },
};
bool HDICodeEmitter::OutPut(const AutoPtr<AST> &ast, const std::string &targetDirectory, GenMode mode)
{
if (!Reset(ast, targetDirectory, mode)) {
return false;
}
EmitCode();
return true;
}
bool HDICodeEmitter::Reset(const AutoPtr<AST> &ast, const std::string &targetDirectory, GenMode mode)
{
if (ast == nullptr || targetDirectory.empty()) {
return false;
}
CleanData();
mode_ = mode;
ast_ = ast;
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
interface_ = ast_->GetInterfaceDef();
interfaceName_ = interface_->GetName();
std::string nameSpace = interface_->GetNamespace()->ToString();
interfaceFullName_ = nameSpace + interfaceName_;
baseName_ = StringHelper::StartWith(interfaceName_, "I") ? interfaceName_.substr(1) : interfaceName_;
proxyName_ = baseName_ + "Proxy";
proxyFullName_ = nameSpace + proxyName_;
stubName_ = baseName_ + "Stub";
stubFullName_ = nameSpace + stubName_;
implName_ = baseName_ + "Service";
implFullName_ = nameSpace + implName_;
} else if (ast_->GetASTFileType() == ASTFileType::AST_TYPES) {
baseName_ = ast_->GetName();
} else if (ast_->GetASTFileType() == ASTFileType::AST_SEQUENCEABLE) {
baseName_ = ast_->GetName();
}
majorVerName_ = StringHelper::Format("%s_MAJOR_VERSION", ConstantName(interfaceName_).c_str());
minorVerName_ = StringHelper::Format("%s_MINOR_VERSION", ConstantName(interfaceName_).c_str());
std::string prefix = StringHelper::Format("%c%s", tolower(baseName_[0]), baseName_.substr(1).c_str());
HdiTypeEmitter::dataParcelName_ = prefix + "Data";
HdiTypeEmitter::replyParcelName_ = prefix + "Reply";
optionName_ = prefix + "Option";
HdiTypeEmitter::errorCodeName_ = prefix + "Ret";
flagOfSetMemName_ = prefix + "MemSet";
if (!ResolveDirectory(targetDirectory)) {
return false;
}
return true;
}
void HDICodeEmitter::CleanData()
{
ast_ = nullptr;
interface_ = nullptr;
directory_ = "";
interfaceName_ = "";
interfaceFullName_ = "";
baseName_ = "";
proxyName_ = "";
proxyFullName_ = "";
stubName_ = "";
stubFullName_ = "";
implName_ = "";
implFullName_ = "";
HdiTypeEmitter::dataParcelName_ = "";
HdiTypeEmitter::replyParcelName_ = "";
optionName_ = "";
HdiTypeEmitter::errorCodeName_ = "";
}
std::string HDICodeEmitter::GetNameWithNamespace(AutoPtr<ASTNamespace> space, std::string name) const
{
std::vector<std::string> namespaceVec = StringHelper::Split(space->ToString(), ".");
std::regex rVer("[V|v][0-9]+_[0-9]+");
std::vector<std::string> result;
bool findVersion = false;
std::string rootPackage = Options::GetInstance().GetRootPackage(space->ToString());
size_t rootPackageNum = StringHelper::Split(rootPackage, ".").size();
for (size_t i = 0; i < namespaceVec.size(); i++) {
std::string ns;
if (i < rootPackageNum) {
ns = StringHelper::StrToUpper(namespaceVec[i]);
} else if (!findVersion && std::regex_match(namespaceVec[i].c_str(), rVer)) {
ns = StringHelper::Replace(namespaceVec[i], 'v', 'V');
findVersion = true;
} else {
if (findVersion) {
ns = namespaceVec[i];
} else {
ns = PascalName(namespaceVec[i]);
}
}
result.emplace_back(ns);
}
StringBuilder sb;
for (const auto &ns : result) {
sb.AppendFormat("%s::", ns.c_str());
}
sb.Append(name);
return sb.ToString();
}
AutoPtr<HdiTypeEmitter> HDICodeEmitter::GetTypeEmitter(AutoPtr<ASTType> astType) const
{
AutoPtr<HdiTypeEmitter> typeEmitter;
auto basicTypePair = basicEmitters_.find(astType->GetTypeKind());
if (basicTypePair != basicEmitters_.end()) {
typeEmitter = (static_cast<HdiTypeEmitter*>(basicTypePair->second.Get()));
}
if (typeEmitter == nullptr) {
typeEmitter = NewTypeEmitter(astType);
}
typeEmitter->SetName(astType->GetName());
typeEmitter->SetPod(astType->IsPod());
if (astType->IsSequenceableType() || astType->IsInterfaceType() ||
astType->IsEnumType() || astType->IsStructType() || astType->IsUnionType()) {
typeEmitter->SetTypeName(GetNameWithNamespace(astType->GetNamespace(), astType->GetName()));
} else {
typeEmitter->SetTypeName(astType->ToString());
}
return typeEmitter;
}
AutoPtr<HdiTypeEmitter> HDICodeEmitter::NewTypeEmitter(AutoPtr<ASTType> astType) const
{
switch (astType->GetTypeKind()) {
case TypeKind::TYPE_MAP:
return NewMapTypeEmitter(astType);
case TypeKind::TYPE_ARRAY:
return NewArrayTypeEmitter(astType);
case TypeKind::TYPE_LIST:
return NewListTypeEmitter(astType);
case TypeKind::TYPE_ENUM:
return NewEnumTypeEmitter(astType);
case TypeKind::TYPE_STRUCT:
return NewStructTypeEmitter(astType);
case TypeKind::TYPE_UNION:
return NewUnionTypeEmitter(astType);
case TypeKind::TYPE_SMQ:
return NewSmqTypeEmitter(astType);
case TypeKind::TYPE_SEQUENCEABLE:
return new HdiSeqTypeEmitter();
case TypeKind::TYPE_INTERFACE:
return new HdiInterfaceTypeEmitter();
default: {
// type not match, new a empty emitter
AutoPtr<HdiTypeEmitter> typeEmitter = new HdiTypeEmitter();
return typeEmitter;
}
}
}
AutoPtr<HdiTypeEmitter> HDICodeEmitter::NewMapTypeEmitter(AutoPtr<ASTType> astType) const
{
AutoPtr<HdiMapTypeEmitter> mapTypeEmitter = new HdiMapTypeEmitter();
AutoPtr<ASTType> keyType = (static_cast<ASTMapType*>(astType.Get()))->GetKeyType();
AutoPtr<ASTType> valueType = (static_cast<ASTMapType*>(astType.Get()))->GetValueType();
AutoPtr<HdiTypeEmitter> keyEmitter = GetTypeEmitter(keyType);
AutoPtr<HdiTypeEmitter> valueEmitter = GetTypeEmitter(valueType);
mapTypeEmitter->SetKeyEmitter(keyEmitter);
mapTypeEmitter->SetValueEmitter(valueEmitter);
return mapTypeEmitter.Get();
}
AutoPtr<HdiTypeEmitter> HDICodeEmitter::NewArrayTypeEmitter(AutoPtr<ASTType> astType) const
{
AutoPtr<HdiArrayTypeEmitter> arrayTypeEmitter = new HdiArrayTypeEmitter();
AutoPtr<ASTType> elemType = (static_cast<ASTArrayType*>(astType.Get()))->GetElementType();
AutoPtr<HdiTypeEmitter> elemEmitter = GetTypeEmitter(elemType);
arrayTypeEmitter->SetElementEmitter(elemEmitter);
return arrayTypeEmitter.Get();
}
AutoPtr<HdiTypeEmitter> HDICodeEmitter::NewListTypeEmitter(AutoPtr<ASTType> astType) const
{
AutoPtr<HdiListTypeEmitter> listTypeEmitter = new HdiListTypeEmitter();
AutoPtr<ASTType> elemType = (static_cast<ASTListType*>(astType.Get()))->GetElementType();
AutoPtr<HdiTypeEmitter> elemEmitter = GetTypeEmitter(elemType);
listTypeEmitter->SetElementEmitter(elemEmitter);
return listTypeEmitter.Get();
}
AutoPtr<HdiTypeEmitter> HDICodeEmitter::NewEnumTypeEmitter(AutoPtr<ASTType> astType) const
{
AutoPtr<HdiEnumTypeEmitter> enumTypeEmitter = new HdiEnumTypeEmitter();
AutoPtr<ASTEnumType> enumType = (static_cast<ASTEnumType*>(astType.Get()));
if (enumType->GetBaseType() != nullptr) {
AutoPtr<HdiTypeEmitter> baseTypeEmitter = GetTypeEmitter(enumType->GetBaseType());
enumTypeEmitter->SetBaseTypeName(baseTypeEmitter->EmitCppType());
}
for (auto it : enumType->GetMembers()) {
if (it->GetExprValue() == nullptr) {
enumTypeEmitter->AddMember(new HdiEnumValueEmitter(it->GetName(), std::string("")));
} else {
enumTypeEmitter->AddMember(new HdiEnumValueEmitter(it->GetName(), it->GetExprValue()->EmitCode()));
}
}
return enumTypeEmitter.Get();
}
AutoPtr<HdiTypeEmitter> HDICodeEmitter::NewStructTypeEmitter(AutoPtr<ASTType> astType) const
{
AutoPtr<HdiStructTypeEmitter> structTypeEmitter = new HdiStructTypeEmitter();
AutoPtr<ASTStructType> structType = (static_cast<ASTStructType*>(astType.Get()));
for (auto it : structType->GetMembers()) {
structTypeEmitter->AddMember(std::get<0>(it), GetTypeEmitter(std::get<1>(it)));
}
return structTypeEmitter.Get();
}
AutoPtr<HdiTypeEmitter> HDICodeEmitter::NewUnionTypeEmitter(AutoPtr<ASTType> astType) const
{
AutoPtr<HdiUnionTypeEmitter> unionTypeEmitter = new HdiUnionTypeEmitter();
AutoPtr<ASTUnionType> unionType = (static_cast<ASTUnionType*>(astType.Get()));
for (size_t i = 0; i < unionType->GetMemberNumber(); i++) {
unionTypeEmitter->AddMember(unionType->GetMemberName(i), GetTypeEmitter(unionType->GetMemberType(i)));
}
return unionTypeEmitter.Get();
}
AutoPtr<HdiTypeEmitter> HDICodeEmitter::NewSmqTypeEmitter(AutoPtr<ASTType> astType) const
{
AutoPtr<HdiSmqTypeEmitter> smqTypeEmitter = new HdiSmqTypeEmitter();
AutoPtr<ASTType> innerType = (static_cast<ASTSmqType*>(astType.Get()))->GetInnerType();
AutoPtr<HdiTypeEmitter> innerTypeEmitter = GetTypeEmitter(innerType);
smqTypeEmitter->SetInnerTypeEmitter(innerTypeEmitter);
return smqTypeEmitter.Get();
}
void HDICodeEmitter::EmitUtilMethods(StringBuilder &sb, bool isDecl)
{
(void)sb;
(void)isDecl;
}
void HDICodeEmitter::EmitUtilMethodMap(StringBuilder &sb, const UtilMethodMap &methods)
{
// generator util methods
for (const auto &methodPair : methods) {
sb.Append(methodPair.second);
}
}
void HDICodeEmitter::EmitInterfaceBuffSizeMacro(StringBuilder &sb) const
{
sb.AppendFormat("#ifndef %s\n", MAX_BUFF_SIZE_MACRO);
sb.AppendFormat("#define %s (%s)\n", MAX_BUFF_SIZE_MACRO, MAX_BUFF_SIZE_VALUE);
sb.Append("#endif\n\n");
sb.AppendFormat("#ifndef %s\n", CHECK_VALUE_RETURN_MACRO);
sb.AppendFormat("#define %s(lv, compare, rv, ret) do { \\\n", CHECK_VALUE_RETURN_MACRO);
sb.Append(TAB).Append("if ((lv) compare (rv)) { \\\n");
sb.Append(TAB).Append(TAB).Append("return ret; \\\n");
sb.Append(TAB).Append("} \\\n");
sb.Append("} while (false)\n");
sb.Append("#endif\n\n");
sb.AppendFormat("#ifndef %s\n", CHECK_VALUE_RET_GOTO_MACRO);
sb.AppendFormat("#define %s(lv, compare, rv, ret, value, table) do { \\\n", CHECK_VALUE_RET_GOTO_MACRO);
sb.Append(TAB).Append("if ((lv) compare (rv)) { \\\n");
sb.Append(TAB).Append(TAB).Append("ret = value; \\\n");
sb.Append(TAB).Append(TAB).Append("goto table; \\\n");
sb.Append(TAB).Append("} \\\n");
sb.Append("} while (false)\n");
sb.Append("#endif\n");
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2024 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_IDL_HDI_CODE_EMITTER_H
#define OHOS_IDL_HDI_CODE_EMITTER_H
#include "codegen/code_emitter.h"
#include "hdi_type_emitter.h"
namespace OHOS {
namespace Idl {
class HDICodeEmitter : public CodeEmitter {
public:
using TypeEmitterMap = std::unordered_map<TypeKind, AutoPtr<HdiTypeEmitter>>;
~HDICodeEmitter() override = default;
bool OutPut(const AutoPtr<AST> &ast, const std::string &targetDirectory, GenMode mode) override;
virtual void EmitUtilMethods(StringBuilder &sb, bool isDecl);
protected:
bool Reset(const AutoPtr<AST> &ast, const std::string &targetDirectory, GenMode mode);
void CleanData();
AutoPtr<HdiTypeEmitter> GetTypeEmitter(AutoPtr<ASTType> astType) const;
void EmitInterfaceBuffSizeMacro(StringBuilder &sb) const;
void EmitUtilMethodMap(StringBuilder &sb, const UtilMethodMap &methods);
GenMode mode_ = GenMode::IPC;
std::string implName_;
std::string implFullName_;
std::string majorVerName_;
std::string minorVerName_;
std::string flagOfSetMemName_;
std::string optionName_;
private:
std::string GetNameWithNamespace(AutoPtr<ASTNamespace> space, std::string name) const;
AutoPtr<HdiTypeEmitter> NewTypeEmitter(AutoPtr<ASTType> astType) const;
AutoPtr<HdiTypeEmitter> NewMapTypeEmitter(AutoPtr<ASTType> astType) const;
AutoPtr<HdiTypeEmitter> NewArrayTypeEmitter(AutoPtr<ASTType> astType) const;
AutoPtr<HdiTypeEmitter> NewListTypeEmitter(AutoPtr<ASTType> astType) const;
AutoPtr<HdiTypeEmitter> NewEnumTypeEmitter(AutoPtr<ASTType> astType) const;
AutoPtr<HdiTypeEmitter> NewStructTypeEmitter(AutoPtr<ASTType> astType) const;
AutoPtr<HdiTypeEmitter> NewUnionTypeEmitter(AutoPtr<ASTType> astType) const;
AutoPtr<HdiTypeEmitter> NewSmqTypeEmitter(AutoPtr<ASTType> astType) const;
static TypeEmitterMap basicEmitters_;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_CODE_EMITTER_H

View File

@ -0,0 +1,339 @@
/*
* Copyright (c) 2024 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 "hdi_code_generator.h"
#include "codegen/HDI/c/c_client_proxy_code_emitter.h"
#include "codegen/HDI/c/c_custom_types_code_emitter.h"
#include "codegen/HDI/c/c_interface_code_emitter.h"
#include "codegen/HDI/c/c_service_driver_code_emitter.h"
#include "codegen/HDI/c/c_service_impl_code_emitter.h"
#include "codegen/HDI/c/c_service_stub_code_emitter.h"
#include "codegen/HDI/cpp/cpp_client_proxy_code_emitter.h"
#include "codegen/HDI/cpp/cpp_custom_types_code_emitter.h"
#include "codegen/HDI/cpp/cpp_interface_code_emitter.h"
#include "codegen/HDI/cpp/cpp_service_driver_code_emitter.h"
#include "codegen/HDI/cpp/cpp_service_impl_code_emitter.h"
#include "codegen/HDI/cpp/cpp_service_stub_code_emitter.h"
#include "codegen/HDI/java/java_client_interface_code_emitter.h"
#include "codegen/HDI/java/java_client_proxy_code_emitter.h"
#include "util/options.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
HDICodeGenerator::GeneratePolicies HDICodeGenerator::policies_ = {
{
SystemLevel::MINI,
{
{
GenMode::LOW,
{
{Language::C, HDICodeGenerator::GenLowCCode}
}
}
}
},
{
SystemLevel::LITE,
{
{
GenMode::KERNEL,
{
{Language::C, HDICodeGenerator::GenKernelCode}
}
},
{
GenMode::PASSTHROUGH,
{
{Language::C, HDICodeGenerator::GenPassthroughCCode},
{Language::CPP, HDICodeGenerator::GenPassthroughCppCode}
}
}
}
},
{
SystemLevel::FULL,
{
{
GenMode::KERNEL,
{
{Language::C, HDICodeGenerator::GenKernelCode}
}
},
{
GenMode::PASSTHROUGH,
{
{Language::C, HDICodeGenerator::GenPassthroughCCode},
{Language::CPP, HDICodeGenerator::GenPassthroughCppCode}
}
},
{
GenMode::IPC,
{
{Language::C, HDICodeGenerator::GenIpcCCode},
{Language::CPP, HDICodeGenerator::GenIpcCppCode},
{Language::JAVA, HDICodeGenerator::GenIpcJavaCode}
}
}
}
}
};
CodeEmitMap HDICodeGenerator::cCodeEmitters_ = {
{"types", new CCustomTypesCodeEmitter() },
{"interface", new CInterfaceCodeEmitter() },
{"proxy", new CClientProxyCodeEmitter() },
{"driver", new CServiceDriverCodeEmitter()},
{"stub", new CServiceStubCodeEmitter() },
{"service", new CServiceImplCodeEmitter() },
};
CodeEmitMap HDICodeGenerator::cppCodeEmitters_ = {
{"types", new CppCustomTypesCodeEmitter() },
{"interface", new CppInterfaceCodeEmitter() },
{"proxy", new CppClientProxyCodeEmitter() },
{"driver", new CppServiceDriverCodeEmitter()},
{"stub", new CppServiceStubCodeEmitter() },
{"service", new CppServiceImplCodeEmitter() },
};
CodeEmitMap HDICodeGenerator::javaCodeEmitters_ = {
{"interface", new JavaClientInterfaceCodeEmitter()},
{"proxy", new JavaClientProxyCodeEmitter() },
};
bool HDICodeGenerator::DoGenerate(const StrAstMap &allAst)
{
auto genCodeFunc = GetCodeGenPoilcy();
if (!genCodeFunc) {
return false;
}
std::string outDir = Options::GetInstance().GetGenerationDirectory();
std::set<std::string> sourceFile = Options::GetInstance().GetSourceFiles();
Language language = Options::GetInstance().GetLanguage();
if (language == Language::CPP) {
for (const auto &ast : allAst) {
if (sourceFile.find(ast.second->GetIdlFilePath()) != sourceFile.end()) {
genCodeFunc(ast.second, outDir);
}
}
} else if (language == Language::C) {
for (const auto &ast : allAst) {
genCodeFunc(ast.second, outDir);
}
}
return true;
}
CodeGenFunc HDICodeGenerator::GetCodeGenPoilcy()
{
auto systemPolicies = policies_.find(Options::GetInstance().GetSystemLevel());
if (systemPolicies == policies_.end()) {
Logger::E(TAG, "the system level is not supported, please check option");
return CodeGenFunc{};
}
auto genModePolicies = systemPolicies->second;
auto genModeIter = genModePolicies.find(Options::GetInstance().GetGenMode());
if (genModeIter == genModePolicies.end()) {
Logger::E(TAG, "the generate mode is not supported, please check option");
return CodeGenFunc{};
}
auto languagePolicies = genModeIter->second;
auto languageIter = languagePolicies.find(Options::GetInstance().GetLanguage());
if (languageIter == languagePolicies.end()) {
Logger::E(TAG, "the language is not supported, please check option");
return CodeGenFunc{};
}
return languageIter->second;
}
void HDICodeGenerator::GenIpcCCode(const AutoPtr<AST> &ast, const std::string &outDir)
{
GenMode mode = GenMode::IPC;
switch (ast->GetASTFileType()) {
case ASTFileType::AST_TYPES: {
cCodeEmitters_["types"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_IFACE: {
cCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cCodeEmitters_["proxy"]->OutPut(ast, outDir, mode);
cCodeEmitters_["driver"]->OutPut(ast, outDir, mode);
cCodeEmitters_["stub"]->OutPut(ast, outDir, mode);
cCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_ICALLBACK: {
cCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cCodeEmitters_["proxy"]->OutPut(ast, outDir, mode);
cCodeEmitters_["stub"]->OutPut(ast, outDir, mode);
cCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
default:
break;
}
}
void HDICodeGenerator::GenIpcCppCode(const AutoPtr<AST> &ast, const std::string &outDir)
{
GenMode mode = GenMode::IPC;
switch (ast->GetASTFileType()) {
case ASTFileType::AST_TYPES: {
cppCodeEmitters_["types"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_IFACE: {
cppCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cppCodeEmitters_["proxy"]->OutPut(ast, outDir, mode);
cppCodeEmitters_["driver"]->OutPut(ast, outDir, mode);
cppCodeEmitters_["stub"]->OutPut(ast, outDir, mode);
cppCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_ICALLBACK: {
cppCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cppCodeEmitters_["proxy"]->OutPut(ast, outDir, mode);
cppCodeEmitters_["stub"]->OutPut(ast, outDir, mode);
cppCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
default:
break;
}
}
void HDICodeGenerator::GenIpcJavaCode(const AutoPtr<AST> &ast, const std::string &outDir)
{
GenMode mode = GenMode::IPC;
switch (ast->GetASTFileType()) {
case ASTFileType::AST_TYPES: {
javaCodeEmitters_["types"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_IFACE:
case ASTFileType::AST_ICALLBACK: {
javaCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
javaCodeEmitters_["proxy"]->OutPut(ast, outDir, mode);
break;
}
default:
break;
}
}
void HDICodeGenerator::GenPassthroughCCode(const AutoPtr<AST> &ast, const std::string &outDir)
{
GenMode mode = GenMode::PASSTHROUGH;
switch (ast->GetASTFileType()) {
case ASTFileType::AST_TYPES: {
cCodeEmitters_["types"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_IFACE: {
cCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cCodeEmitters_["proxy"]->OutPut(ast, outDir, mode);
cCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_ICALLBACK: {
cCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
default:
break;
}
}
void HDICodeGenerator::GenPassthroughCppCode(const AutoPtr<AST> &ast, const std::string &outDir)
{
GenMode mode = GenMode::PASSTHROUGH;
switch (ast->GetASTFileType()) {
case ASTFileType::AST_TYPES: {
cppCodeEmitters_["types"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_IFACE: {
cppCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cppCodeEmitters_["proxy"]->OutPut(ast, outDir, mode);
cppCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_ICALLBACK: {
cppCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cppCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
default:
break;
}
}
void HDICodeGenerator::GenKernelCode(const AutoPtr<AST> &ast, const std::string &outDir)
{
GenMode mode = GenMode::KERNEL;
switch (ast->GetASTFileType()) {
case ASTFileType::AST_TYPES: {
cCodeEmitters_["types"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_IFACE: {
cCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cCodeEmitters_["proxy"]->OutPut(ast, outDir, mode);
cCodeEmitters_["driver"]->OutPut(ast, outDir, mode);
cCodeEmitters_["stub"]->OutPut(ast, outDir, mode);
cCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
default:
break;
}
}
void HDICodeGenerator::GenLowCCode(const AutoPtr<AST> &ast, const std::string &outDir)
{
GenMode mode = GenMode::LOW;
switch (ast->GetASTFileType()) {
case ASTFileType::AST_TYPES: {
cCodeEmitters_["types"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_IFACE: {
cCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cCodeEmitters_["driver"]->OutPut(ast, outDir, mode);
cCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
case ASTFileType::AST_ICALLBACK: {
cCodeEmitters_["interface"]->OutPut(ast, outDir, mode);
cCodeEmitters_["service"]->OutPut(ast, outDir, mode);
break;
}
default:
break;
}
}
void HDICodeGenerator::GeneratorInit()
{
CodegenBuilder::GetInstance().GeneratorRegister(InterfaceType::HDI, new HDICodeGenerator());
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2024 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_IDL_HDI_CODEGENERATOR_H
#define OHOS_IDL_HDI_CODEGENERATOR_H
#include "codegen/code_generator.h"
namespace OHOS {
namespace Idl {
class HDICodeGenerator : public CodeGenerator {
public:
using GeneratePolicies = std::map<SystemLevel, std::map<GenMode, std::map<Language, CodeGenFunc>>>;
bool DoGenerate(const StrAstMap &allAst) override;
private:
static CodeGenFunc GetCodeGenPoilcy();
static void GenIpcCCode(const AutoPtr<AST> &ast, const std::string &outDir);
static void GenIpcCppCode(const AutoPtr<AST> &ast, const std::string &outDir);
static void GenIpcJavaCode(const AutoPtr<AST> &ast, const std::string &outDir);
static void GenPassthroughCCode(const AutoPtr<AST> &ast, const std::string &outDir);
static void GenPassthroughCppCode(const AutoPtr<AST> &ast, const std::string &outDir);
static void GenKernelCode(const AutoPtr<AST> &ast, const std::string &outDir);
static void GenLowCCode(const AutoPtr<AST> &ast, const std::string &outDir);
static void GeneratorInit() __attribute__((constructor));
static GeneratePolicies policies_;
static CodeEmitMap cCodeEmitters_;
static CodeEmitMap cppCodeEmitters_;
static CodeEmitMap javaCodeEmitters_;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_CODEGENERATOR_H

View File

@ -0,0 +1,215 @@
/*
* Copyright (c) 2024 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 "hdi_type_emitter.h"
namespace OHOS {
namespace Idl {
std::string HdiTypeEmitter::dataParcelName_;
std::string HdiTypeEmitter::replyParcelName_;
std::string HdiTypeEmitter::errorCodeName_;
bool HdiTypeEmitter::IsPod() const
{
return isPod_;
}
void HdiTypeEmitter::SetPod(const bool &isPod)
{
isPod_ = isPod;
}
TypeKind HdiTypeEmitter::GetTypeKind()
{
return TypeKind::TYPE_UNKNOWN;
}
void HdiTypeEmitter::SetTypeName(const std::string &name)
{
typeName_ = name;
}
std::string HdiTypeEmitter::GetTypeName()
{
return typeName_;
}
void HdiTypeEmitter::SetName(const std::string &name)
{
name_ = name;
}
std::string HdiTypeEmitter::GetName()
{
return name_;
}
std::string HdiTypeEmitter::EmitCType(TypeMode mode) const
{
return "unknow";
}
std::string HdiTypeEmitter::EmitCppType(TypeMode mode) const
{
return "unknow";
}
std::string HdiTypeEmitter::EmitJavaType(TypeMode mode, bool isInnerType) const
{
return "unknow";
}
std::string HdiTypeEmitter::EmitCTypeDecl() const
{
StringBuilder sb;
return sb.ToString();
}
std::string HdiTypeEmitter::EmitCppTypeDecl() const
{
StringBuilder sb;
return sb.ToString();
}
std::string HdiTypeEmitter::EmitJavaTypeDecl() const
{
StringBuilder sb;
return sb.ToString();
}
void HdiTypeEmitter::EmitCWriteVar(TypeMode mode, const std::string &name,
const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitCProxyWriteOutVar(const std::string &name, const std::string &gotoLabel, StringBuilder &sb,
const std::string &prefix) const
{
}
void HdiTypeEmitter::EmitCProxyReadVar(const std::string &name, bool isInnerType, const std::string &gotoLabel,
StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitCStubReadVar(const std::string &name, const std::string &gotoLabel, StringBuilder &sb,
const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitCStubReadOutVar(const std::string &memFlagName, const std::string &name,
const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitCppWriteVar(const std::string &parcelName, const std::string &name,
StringBuilder &sb, const std::string &prefix, unsigned int innerLevel) const
{
sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitCppReadVar(const std::string &name, StringBuilder &sb, const std::string &prefix,
TypeMode mode, unsigned int innerLevel) const
{
sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitCMarshalling(const std::string &name, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitCUnMarshalling(const std::string &name, const std::string &gotoLabel,
StringBuilder &sb, const std::string &prefix, std::vector<std::string> &freeObjStatements) const
{
sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitFreeStatements(
const std::vector<std::string> &freeObjStatements, StringBuilder &sb, const std::string &prefix) const
{
for (auto it = freeObjStatements.rbegin(); it != freeObjStatements.rend(); it++) {
sb.Append(prefix).Append(*it);
}
}
void HdiTypeEmitter::EmitCppMarshalling(const std::string &parcelName, const std::string &name,
StringBuilder &sb, const std::string &prefix, unsigned int innerLevel) const
{
}
void HdiTypeEmitter::EmitCppUnMarshalling(const std::string &parcelName, const std::string &name,
StringBuilder &sb, const std::string &prefix, unsigned int innerLevel) const
{
}
void HdiTypeEmitter::EmitMemoryRecycle(
const std::string &name, bool ownership, StringBuilder &sb, const std::string &prefix) const
{
// only std::string, Array, List, struct and union type need recycle memory
(void)name;
(void)ownership;
(void)sb;
(void)prefix;
}
void HdiTypeEmitter::EmitJavaWriteVar(const std::string &parcelName, const std::string &name,
StringBuilder &sb, const std::string &prefix, TypeMode mode) const
{
sb.Append(prefix).AppendFormat("//Writing \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitJavaReadVar(
const std::string &parcelName, const std::string &name, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitJavaReadInnerVar(const std::string &parcelName, const std::string &name, bool isInner,
StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("//Reading \"%s\" type of data is not supported\n", name_.c_str());
}
void HdiTypeEmitter::EmitCWriteMethods(UtilMethodMap &methods, const std::string &prefix,
const std::string &methodPrefix, bool isDecl) const
{
}
void HdiTypeEmitter::EmitCReadMethods(UtilMethodMap &methods, const std::string &prefix,
const std::string &methodPrefix, bool isDecl) const
{
}
void HdiTypeEmitter::EmitCStubReadMethods(UtilMethodMap &methods, const std::string &prefix,
const std::string &methodPrefix, bool isDecl) const
{
}
void HdiTypeEmitter::EmitCppWriteMethods(UtilMethodMap &methods, const std::string &prefix,
const std::string &methodPrefix, bool isDecl) const
{
}
void HdiTypeEmitter::EmitCppReadMethods(UtilMethodMap &methods, const std::string &prefix,
const std::string &methodPrefix, bool isDecl) const
{
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2024 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_IDL_HDI_TYPE_EMITTER_H
#define OHOS_IDL_HDI_TYPE_EMITTER_H
#include <map>
#include "ast/ast_type.h"
namespace OHOS {
namespace Idl {
constexpr const char *MAX_BUFF_SIZE_MACRO = "HDI_BUFF_MAX_SIZE";
constexpr const char *MAX_BUFF_SIZE_VALUE = "1024 * 200"; // 200KB
constexpr const char *CHECK_VALUE_RETURN_MACRO = "HDI_CHECK_VALUE_RETURN";
constexpr const char *CHECK_VALUE_RET_GOTO_MACRO = "HDI_CHECK_VALUE_RET_GOTO";
using UtilMethodMap = std::unordered_map<std::string, std::string>;
class HdiTypeEmitter : public LightRefCountBase {
public:
bool IsPod() const;
void SetPod(const bool &isPod);
virtual TypeKind GetTypeKind();
void SetTypeName(const std::string &name);
std::string GetTypeName();
void SetName(const std::string &name);
std::string GetName();
virtual std::string EmitCppType(TypeMode mode = TypeMode::NO_MODE) const;
virtual std::string EmitCType(TypeMode mode = TypeMode::NO_MODE) const;
virtual std::string EmitJavaType(TypeMode mode, bool isInnerType = false) const;
virtual std::string EmitCTypeDecl() const;
virtual std::string EmitCppTypeDecl() const;
virtual std::string EmitJavaTypeDecl() const;
virtual void EmitCWriteVar(TypeMode mode, const std::string &name, const std::string &gotoLabel,
StringBuilder &sb, const std::string &prefix) const;
virtual void EmitCProxyWriteOutVar(const std::string &name, const std::string &gotoLabel, StringBuilder &sb,
const std::string &prefix) const;
virtual void EmitCProxyReadVar(const std::string &name, bool isInnerType, const std::string &gotoLabel,
StringBuilder &sb, const std::string &prefix) const;
virtual void EmitCStubReadVar(const std::string &name, const std::string &gotoLabel, StringBuilder &sb,
const std::string &prefix) const;
virtual void EmitCStubReadOutVar(const std::string &memFlagName, const std::string &name,
const std::string &gotoLabel, StringBuilder &sb, const std::string &prefix) const;
virtual void EmitCppWriteVar(const std::string &parcelName, const std::string &name, StringBuilder &sb,
const std::string &prefix, unsigned int innerLevel = 0) const;
virtual void EmitCppReadVar(const std::string &name, StringBuilder &sb, const std::string &prefix,
TypeMode mode, unsigned int innerLevel = 0) const;
virtual void EmitCMarshalling(const std::string &name, StringBuilder &sb, const std::string &prefix) const;
virtual void EmitCUnMarshalling(const std::string &name, const std::string &gotoLabel, StringBuilder &sb,
const std::string &prefix, std::vector<std::string> &freeObjStatements) const;
virtual void EmitCWriteMethods(UtilMethodMap &methods, const std::string &prefix,
const std::string &methodPrefix, bool isDecl) const;
virtual void EmitCppWriteMethods(UtilMethodMap &methods, const std::string &prefix,
const std::string &methodPrefix, bool isDecl) const;
virtual void EmitCReadMethods(UtilMethodMap &methods, const std::string &prefix,
const std::string &methodPrefix, bool isDecl) const;
virtual void EmitCppReadMethods(UtilMethodMap &methods, const std::string &prefix,
const std::string &methodPrefix, bool isDecl) const;
virtual void EmitCStubReadMethods(UtilMethodMap &methods, const std::string &prefix,
const std::string &methodPrefix, bool isDecl) const;
void EmitFreeStatements(
const std::vector<std::string> &freeObjStatements, StringBuilder &sb, const std::string &prefix) const;
virtual void EmitCppMarshalling(const std::string &parcelName, const std::string &name, StringBuilder &sb,
const std::string &prefix, unsigned int innerLevel = 0) const;
virtual void EmitCppUnMarshalling(const std::string &parcelName, const std::string &name, StringBuilder &sb,
const std::string &prefix, unsigned int innerLevel = 0) const;
virtual void EmitMemoryRecycle(
const std::string &name, bool ownership, StringBuilder &sb, const std::string &prefix) const;
virtual void EmitJavaWriteVar(const std::string &parcelName, const std::string &name, StringBuilder &sb,
const std::string &prefix, TypeMode mode = TypeMode::NO_MODE) const;
virtual void EmitJavaReadVar(
const std::string &parcelName, const std::string &name, StringBuilder &sb, const std::string &prefix) const;
virtual void EmitJavaReadInnerVar(const std::string &parcelName, const std::string &name, bool isInner,
StringBuilder &sb, const std::string &prefix) const;
static std::string dataParcelName_;
static std::string replyParcelName_;
static std::string errorCodeName_;
protected:
bool isPod_;
std::string typeName_;
std::string name_;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_HDI_TYPE_EMITTER_H

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2024 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 "hdi_java_code_emitter.h"
namespace OHOS {
namespace Idl {
void HDIJavaCodeEmitter::EmitPackage(StringBuilder &sb)
{
sb.AppendFormat("package %s;\n", ast_->GetPackageName().c_str());
}
void HDIJavaCodeEmitter::EmitInterfaceMethodCommands(StringBuilder &sb, const std::string &prefix)
{
auto methods = interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel());
for (size_t i = 0; i < methods.size(); i++) {
sb.Append(prefix).AppendFormat("private static final int COMMAND_%s = IRemoteObject.MIN_TRANSACTION_ID + %d;\n",
ConstantName(methods[i]->GetName()).c_str(), i);
}
}
std::string HDIJavaCodeEmitter::MethodName(const std::string &name) const
{
if (name.empty() || islower(name[0])) {
return name;
}
return StringHelper::Format("%c%s", tolower(name[0]), name.substr(1).c_str());
}
std::string HDIJavaCodeEmitter::SpecificationParam(StringBuilder &paramSb, const std::string &prefix) const
{
size_t maxLineLen = 120;
size_t replaceLen = 2;
std::string paramStr = paramSb.ToString();
size_t preIndex = 0;
size_t curIndex = 0;
std::string insertStr = StringHelper::Format("\n%s", prefix.c_str());
for (; curIndex < paramStr.size(); curIndex++) {
if (curIndex == maxLineLen && preIndex > 0) {
StringHelper::Replace(paramStr, preIndex, replaceLen, ",");
paramStr.insert(preIndex + 1, insertStr);
} else {
if (paramStr[curIndex] == ',') {
preIndex = curIndex;
}
}
}
return paramStr;
}
void HDIJavaCodeEmitter::EmitInterfaceMethodParameter(
const AutoPtr<ASTParameter> &param, StringBuilder &sb, const std::string &prefix) const
{
std::string name = param->GetName();
AutoPtr<ASTType> type = param->GetType();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
switch (type->GetTypeKind()) {
case TypeKind::TYPE_BOOLEAN:
case TypeKind::TYPE_BYTE:
case TypeKind::TYPE_SHORT:
case TypeKind::TYPE_INT:
case TypeKind::TYPE_LONG:
case TypeKind::TYPE_UCHAR:
case TypeKind::TYPE_USHORT:
case TypeKind::TYPE_UINT:
case TypeKind::TYPE_ULONG:
case TypeKind::TYPE_FLOAT:
case TypeKind::TYPE_DOUBLE:
case TypeKind::TYPE_ENUM:
case TypeKind::TYPE_FILEDESCRIPTOR:
case TypeKind::TYPE_STRING:
case TypeKind::TYPE_SEQUENCEABLE:
case TypeKind::TYPE_INTERFACE:
case TypeKind::TYPE_STRUCT:
case TypeKind::TYPE_UNION:
case TypeKind::TYPE_POINTER:
case TypeKind::TYPE_ARRAY:
case TypeKind::TYPE_LIST:
case TypeKind::TYPE_MAP: {
sb.Append(prefix).AppendFormat("%s %s", typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str(), name.c_str());
break;
}
default:
sb.Append(prefix).AppendFormat("unknow type %s", name.c_str());
break;
}
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2024 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_IDL_JAVA_CODE_EMITTER_H
#define OHOS_IDL_JAVA_CODE_EMITTER_H
#include <cctype>
#include "codegen/HDI/hdi_code_emitter.h"
namespace OHOS {
namespace Idl {
class HDIJavaCodeEmitter : public HDICodeEmitter {
public:
~HDIJavaCodeEmitter() override = default;
protected:
bool CreateDirectory();
void EmitPackage(StringBuilder &sb);
void EmitInterfaceMethodCommands(StringBuilder &sb, const std::string &prefix) override;
std::string MethodName(const std::string &name) const;
std::string SpecificationParam(StringBuilder &paramSb, const std::string &prefix) const;
void EmitInterfaceMethodParameter(const AutoPtr<ASTParameter> &param, StringBuilder &sb,
const std::string &prefix) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_JAVA_CODE_EMITTER_H

View File

@ -0,0 +1,153 @@
/*
* Copyright (c) 2024 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 "java_client_interface_code_emitter.h"
#include "util/file.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
bool JavaClientInterfaceCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
directory_ = GetFileParentPath(targetDirectory);
} else {
return false;
}
if (!File::CreateParentDir(directory_)) {
Logger::E("JavaClientInterfaceCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void JavaClientInterfaceCodeEmitter::EmitCode()
{
if (mode_ == GenMode::IPC) {
EmitInterfaceFile();
}
}
void JavaClientInterfaceCodeEmitter::EmitInterfaceFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.java", directory_.c_str(), FileName(interfaceName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
printf("%s/%s.java\n", directory_.c_str(), FileName(interfaceName_).c_str());
EmitLicense(sb);
EmitPackage(sb);
sb.Append("\n");
EmitInterfaceImports(sb);
sb.Append("\n");
EmitInterfaceDefinition(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void JavaClientInterfaceCodeEmitter::EmitInterfaceImports(StringBuilder &sb) const
{
EmitInterfaceCorelibImports(sb);
EmitInterfaceSelfDefinedTypeImports(sb);
EmitInterfaceDBinderImports(sb);
}
void JavaClientInterfaceCodeEmitter::EmitInterfaceCorelibImports(StringBuilder &sb) const
{
bool includeList = false;
bool includeMap = false;
const AST::TypeStringMap &types = ast_->GetTypes();
for (const auto &pair : types) {
AutoPtr<ASTType> type = pair.second;
switch (type->GetTypeKind()) {
case TypeKind::TYPE_LIST: {
if (!includeList) {
sb.Append("import java.util.List;\n");
includeList = true;
}
break;
}
case TypeKind::TYPE_MAP: {
if (!includeMap) {
sb.Append("import java.util.Map;\n");
sb.Append("import java.util.HashMap;\n");
includeMap = true;
}
break;
}
default:
break;
}
}
}
void JavaClientInterfaceCodeEmitter::EmitInterfaceDBinderImports(StringBuilder &sb) const
{
sb.Append("import ohos.rpc.IRemoteBroker;\n");
sb.Append("import ohos.rpc.RemoteException;\n");
}
void JavaClientInterfaceCodeEmitter::EmitInterfaceSelfDefinedTypeImports(StringBuilder &sb) const
{
for (const auto &importPair : ast_->GetImports()) {
AutoPtr<AST> import = importPair.second;
sb.AppendFormat("import %s;\n", import->GetFullName().c_str());
}
}
void JavaClientInterfaceCodeEmitter::EmitInterfaceDefinition(StringBuilder &sb)
{
sb.AppendFormat("public interface %s extends IRemoteBroker {\n", interface_->GetName().c_str());
EmitInterfaceMethods(sb, TAB);
sb.Append("}");
}
void JavaClientInterfaceCodeEmitter::EmitInterfaceMethods(StringBuilder &sb, const std::string &prefix) const
{
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitInterfaceMethod(method, sb, prefix);
sb.Append("\n");
}
}
void JavaClientInterfaceCodeEmitter::EmitInterfaceMethod(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat("int %s() throws RemoteException;\n", MethodName(method->GetName()).c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat("int %s(", MethodName(method->GetName()).c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
if (i + 1 < method->GetParameterNumber()) {
paramStr.Append(", ");
}
}
paramStr.Append(") throws RemoteException;");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2024 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_IDL_JAVA_CLIENT_INTERFACE_CODE_EMITTER_H
#define OHOS_IDL_JAVA_CLIENT_INTERFACE_CODE_EMITTER_H
#include "hdi_java_code_emitter.h"
namespace OHOS {
namespace Idl {
class JavaClientInterfaceCodeEmitter : public HDIJavaCodeEmitter {
public:
JavaClientInterfaceCodeEmitter() : HDIJavaCodeEmitter() {}
~JavaClientInterfaceCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitInterfaceFile();
void EmitInterfaceImports(StringBuilder &sb) const;
void EmitInterfaceCorelibImports(StringBuilder &sb) const;
void EmitInterfaceDBinderImports(StringBuilder &sb) const;
void EmitInterfaceSelfDefinedTypeImports(StringBuilder &sb) const;
void EmitInterfaceDefinition(StringBuilder &sb);
void EmitInterfaceMethods(StringBuilder &sb, const std::string &prefix) const;
void EmitInterfaceMethod(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_JAVA_CLIENT_INTERFACE_CODE_EMITTER_H

View File

@ -0,0 +1,262 @@
/*
* Copyright (c) 2024 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 "java_client_proxy_code_emitter.h"
#include "util/logger.h"
namespace OHOS {
namespace Idl {
bool JavaClientProxyCodeEmitter::ResolveDirectory(const std::string &targetDirectory)
{
if (ast_->GetASTFileType() == ASTFileType::AST_IFACE || ast_->GetASTFileType() == ASTFileType::AST_ICALLBACK) {
directory_ = GetFileParentPath(targetDirectory);
} else {
return false;
}
if (!File::CreateParentDir(directory_)) {
Logger::E("CppClientInterfaceCodeEmitter", "Create '%s' failed!", directory_.c_str());
return false;
}
return true;
}
void JavaClientProxyCodeEmitter::EmitCode()
{
if (mode_ == GenMode::IPC) {
EmitProxyFile();
}
}
void JavaClientProxyCodeEmitter::EmitProxyFile()
{
std::string filePath =
File::AdapterPath(StringHelper::Format("%s/%s.java", directory_.c_str(), FileName(proxyName_).c_str()));
File file(filePath, File::write_);
StringBuilder sb;
EmitLicense(sb);
EmitPackage(sb);
sb.Append("\n");
EmitProxyImports(sb);
sb.Append("\n");
EmitProxyImpl(sb);
std::string data = sb.ToString();
file.WriteData(data.c_str(), data.size());
file.Flush();
file.Close();
}
void JavaClientProxyCodeEmitter::EmitProxyImports(StringBuilder &sb) const
{
EmitProxyCorelibImports(sb);
EmitProxySelfDefinedTypeImports(sb);
EmitProxyDBinderImports(sb);
}
void JavaClientProxyCodeEmitter::EmitProxyCorelibImports(StringBuilder &sb) const
{
bool includeList = false;
bool includeMap = false;
const AST::TypeStringMap &types = ast_->GetTypes();
for (const auto &pair : types) {
AutoPtr<ASTType> type = pair.second;
switch (type->GetTypeKind()) {
case TypeKind::TYPE_LIST: {
if (!includeList) {
sb.Append("import java.util.List;\n");
includeList = true;
}
break;
}
case TypeKind::TYPE_MAP: {
if (!includeMap) {
sb.Append("import java.util.Map;\n");
sb.Append("import java.util.HashMap;\n");
includeMap = true;
}
break;
}
default:
break;
}
}
}
void JavaClientProxyCodeEmitter::EmitProxySelfDefinedTypeImports(StringBuilder &sb) const
{
for (const auto &importPair : ast_->GetImports()) {
AutoPtr<AST> import = importPair.second;
sb.AppendFormat("import %s;\n", import->GetFullName().c_str());
}
}
void JavaClientProxyCodeEmitter::EmitProxyDBinderImports(StringBuilder &sb) const
{
sb.Append("import ohos.hiviewdfx.HiLog;\n");
sb.Append("import ohos.hiviewdfx.HiLogLabel;\n");
sb.Append("import ohos.rpc.IRemoteObject;\n");
sb.Append("import ohos.rpc.RemoteException;\n");
sb.Append("import ohos.rpc.MessageParcel;\n");
sb.Append("import ohos.rpc.MessageOption;\n");
}
void JavaClientProxyCodeEmitter::EmitProxyImpl(StringBuilder &sb)
{
sb.AppendFormat("public class %s implements %s {\n", proxyName_.c_str(), interfaceName_.c_str());
EmitProxyConstants(sb, TAB);
sb.Append("\n");
sb.Append(TAB).AppendFormat(
"private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_CORE, 0xD001510, \"%s\");\n",
interfaceFullName_.c_str());
sb.Append(TAB).Append("private final IRemoteObject remote;\n");
sb.Append(TAB).Append("private static final int ERR_OK = 0;\n");
sb.Append("\n");
EmitProxyConstructor(sb, TAB);
sb.Append("\n");
EmitProxyMethodImpls(sb, TAB);
sb.Append("};");
}
void JavaClientProxyCodeEmitter::EmitProxyConstants(StringBuilder &sb, const std::string &prefix)
{
sb.Append(prefix).AppendFormat(
"private static final std::string DESCRIPTOR = \"%s\";\n\n", interfaceFullName_.c_str());
EmitInterfaceMethodCommands(sb, prefix);
}
void JavaClientProxyCodeEmitter::EmitProxyConstructor(StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).AppendFormat("public %s(IRemoteObject remote) {\n", proxyName_.c_str());
sb.Append(prefix + TAB).Append("this.remote = remote;\n");
sb.Append(prefix).Append("}\n");
sb.Append("\n");
sb.Append(prefix).AppendFormat("@Override\n");
sb.Append(prefix).Append("public IRemoteObject asObject() {\n");
sb.Append(prefix + TAB).Append("return remote;\n");
sb.Append(prefix).Append("}\n");
}
void JavaClientProxyCodeEmitter::EmitProxyMethodImpls(StringBuilder &sb, const std::string &prefix) const
{
for (const auto &method : interface_->GetMethodsBySystem(Options::GetInstance().GetSystemLevel())) {
EmitProxyMethodImpl(method, sb, prefix);
sb.Append("\n");
}
}
void JavaClientProxyCodeEmitter::EmitProxyMethodImpl(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).Append("@Override\n");
if (method->GetParameterNumber() == 0) {
sb.Append(prefix).AppendFormat(
"public int %s() throws RemoteException ", MethodName(method->GetName()).c_str());
} else {
StringBuilder paramStr;
paramStr.Append(prefix).AppendFormat("public int %s(", MethodName(method->GetName()).c_str());
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitInterfaceMethodParameter(param, paramStr, "");
if (i + 1 < method->GetParameterNumber()) {
paramStr.Append(", ");
}
}
paramStr.Append(") throws RemoteException");
sb.Append(SpecificationParam(paramStr, prefix + TAB));
sb.Append("\n");
}
EmitProxyMethodBody(method, sb, prefix);
}
void JavaClientProxyCodeEmitter::EmitProxyMethodBody(
const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const
{
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("MessageParcel data = MessageParcel.obtain();\n");
sb.Append(prefix + TAB).Append("MessageParcel reply = MessageParcel.obtain();\n");
sb.Append(prefix + TAB).AppendFormat("MessageOption option = new MessageOption(MessageOption.TF_SYNC);\n");
sb.Append("\n");
sb.Append(prefix).AppendFormat(" data.writeInterfaceToken(DESCRIPTOR);\n");
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
EmitParamWriteVar(param, "data", sb, prefix + TAB);
}
sb.Append("\n");
sb.Append(prefix + TAB).Append("try {\n");
sb.Append(prefix + TAB + TAB).AppendFormat("if (remote.sendRequest(COMMAND_%s, data, reply, option)) {\n",
ConstantName(method->GetName()).c_str());
sb.Append(prefix + TAB + TAB + TAB).Append("return 1;\n");
sb.Append(prefix + TAB + TAB).Append("}\n");
sb.Append(prefix + TAB).Append(" reply.readException();\n");
for (size_t i = 0; i < method->GetParameterNumber(); i++) {
AutoPtr<ASTParameter> param = method->GetParameter(i);
if (param->GetAttribute() == ASTParamAttr::PARAM_OUT) {
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(param->GetType());
typeEmitter->EmitJavaReadVar("reply", param->GetName(), sb, prefix + TAB + TAB);
}
}
sb.Append(prefix + TAB).Append("} finally {\n");
sb.Append(prefix + TAB + TAB).Append("data.reclaim();\n");
sb.Append(prefix + TAB + TAB).Append("reply.reclaim();\n");
sb.Append(prefix + TAB).Append("}\n");
sb.Append(prefix + TAB).Append("return 0;\n");
sb.Append(prefix).Append("}\n");
}
void JavaClientProxyCodeEmitter::EmitParamWriteVar(const AutoPtr<ASTParameter> &param,
const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const
{
ASTParamAttr::ParamAttr attrAttr = param->GetAttribute();
AutoPtr<ASTType> type = param->GetType();
std::string name = param->GetName();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
if (attrAttr == ASTParamAttr::PARAM_IN) {
typeEmitter->EmitJavaWriteVar(parcelName, name, sb, prefix);
}
if (attrAttr == ASTParamAttr::PARAM_OUT) {
if (type->GetTypeKind() == TypeKind::TYPE_ARRAY) {
typeEmitter->EmitJavaWriteVar(parcelName, name, sb, prefix, TypeMode::PARAM_OUT);
}
}
}
void JavaClientProxyCodeEmitter::EmitLocalVariable(
const AutoPtr<ASTParameter> &param, StringBuilder &sb, const std::string &prefix) const
{
AutoPtr<ASTType> type = param->GetType();
AutoPtr<HdiTypeEmitter> typeEmitter = GetTypeEmitter(type);
if (type->IsSequenceableType()) {
sb.Append(prefix).AppendFormat("%s %s = new %s();\n", typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str(),
param->GetName().c_str(), typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str());
} else if (type->IsListType()) {
sb.Append(prefix).AppendFormat("%s %s = new Array%s();\n", typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str(),
param->GetName().c_str(), typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str());
} else if (type->IsMapType()) {
sb.Append(prefix).AppendFormat("%s %s = new Hash%s();\n", typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str(),
param->GetName().c_str(), typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str());
} else {
sb.Append(prefix).AppendFormat(
"%s %s;\n", typeEmitter->EmitJavaType(TypeMode::NO_MODE).c_str(), param->GetName().c_str());
}
}
} // namespace Idl
} // namespace OHOS

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2024 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_IDL_JAVA_CLIENT_PROXY_CODE_EMITTER_H
#define OHOS_IDL_JAVA_CLIENT_PROXY_CODE_EMITTER_H
#include "hdi_java_code_emitter.h"
#include "util/file.h"
namespace OHOS {
namespace Idl {
class JavaClientProxyCodeEmitter : public HDIJavaCodeEmitter {
public:
JavaClientProxyCodeEmitter() : HDIJavaCodeEmitter() {}
~JavaClientProxyCodeEmitter() override = default;
private:
bool ResolveDirectory(const std::string &targetDirectory) override;
void EmitCode() override;
void EmitProxyFile();
void EmitProxyImports(StringBuilder &sb) const;
void EmitProxyCorelibImports(StringBuilder &sb) const;
void EmitProxySelfDefinedTypeImports(StringBuilder &sb) const;
void EmitProxyDBinderImports(StringBuilder &sb) const;
void EmitProxyImpl(StringBuilder &sb);
void EmitProxyConstants(StringBuilder &sb, const std::string &prefix);
void EmitProxyConstructor(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyMethodImpls(StringBuilder &sb, const std::string &prefix) const;
void EmitProxyMethodImpl(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitProxyMethodBody(const AutoPtr<ASTMethod> &method, StringBuilder &sb, const std::string &prefix) const;
void EmitReadOutArrayVariable(const std::string &parcelName, const std::string &name,
const AutoPtr<ASTArrayType> &arrayType, StringBuilder &sb, const std::string &prefix);
void EmitReadOutVariable(const std::string &parcelName, const std::string &name, const AutoPtr<ASTType> &type,
StringBuilder &sb, const std::string &prefix);
void EmitLocalVariable(const AutoPtr<ASTParameter> &param, StringBuilder &sb, const std::string &prefix) const;
void EmitParamWriteVar(const AutoPtr<ASTParameter> &param,
const std::string &parcelName, StringBuilder &sb, const std::string &prefix) const;
};
} // namespace Idl
} // namespace OHOS
#endif // OHOS_IDL_JAVA_CLIENT_PROXY_CODE_EMITTER_H