Files
aafwk_standard/idl/codegen/cpp_code_emitter.cpp
T
njupthan 059db5b172 Fix codex
Signed-off-by: njupthan <hanhaibin@huawei.com>
2022-04-19 10:57:43 +00:00

1079 lines
39 KiB
C++

/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "codegen/cpp_code_emitter.h"
#include "securec.h"
#include "util/file.h"
namespace OHOS {
namespace Idl {
void CppCodeEmitter::EmitInterface()
{
EmitInterfaceHeaderFile();
}
void CppCodeEmitter::EmitInterfaceHeaderFile()
{
String filePath = String::Format("%s/%s.h", directory_.string(), FileName(interfaceName_).string());
File file(filePath, File::WRITE);
StringBuilder sb;
EmitLicense(sb);
sb.Append("\n");
EmitHeadMacro(sb, interfaceFullName_);
sb.Append("\n");
EmitInterfaceInclusions(sb);
sb.Append("\n");
if (EmitInterfaceUsings(sb)) {
sb.Append("\n");
}
EmitInterfaceDefinition(sb);
EmitTailMacro(sb, interfaceFullName_);
String data = sb.ToString();
file.WriteData(data.string(), data.GetLength());
file.Flush();
file.Close();
}
void CppCodeEmitter::EmitInterfaceInclusions(StringBuilder& sb)
{
EmitInterfaceStdlibInclusions(sb);
EmitInterfaceDBinderInclusions(sb);
EmitInterfaceSelfDefinedTypeInclusions(sb);
}
void CppCodeEmitter::EmitInterfaceStdlibInclusions(StringBuilder& sb)
{
bool includeString = false;
bool includeList = false;
bool includeMap = false;
bool includeNum = false;
for (int i = 0; i < metaComponent_->typeNumber_; i++) {
MetaType* mt = metaComponent_->types_[i];
switch(mt->kind_) {
case TypeKind::Byte: {
if (!includeNum) {
sb.Append("#include <cstdint>\n");
includeNum = true;
}
break;
}
case TypeKind::String: {
if (!includeString) {
sb.Append("#include <string_ex.h>\n");
includeString = true;
}
break;
}
case TypeKind::Array:
case TypeKind::List: {
if (!includeList) {
sb.Append("#include <vector>\n");
includeList = true;
}
break;
}
case TypeKind::Map: {
if (!includeMap) {
sb.Append("#include <unordered_map>\n");
includeMap = true;
}
break;
}
default:
break;
}
}
}
void CppCodeEmitter::EmitInterfaceDBinderInclusions(StringBuilder& sb)
{
sb.Append("#include <iremote_broker.h>\n");
}
String CppCodeEmitter::GetFilePath(const String& fpnp)
{
int pos = fpnp.IndexOf("..");
if (pos == -1) {
return String();
}
String res = fpnp.Substring(0, pos + 1);
return res;
}
String CppCodeEmitter::GetNamespace(const String& fpnp)
{
int pos = fpnp.IndexOf("..");
if (pos == -1) {
return fpnp;
}
String res = fpnp.Substring(pos + 2);
return res;
}
void CppCodeEmitter::EmitInterfaceSelfDefinedTypeInclusions(StringBuilder& sb)
{
for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) {
MetaSequenceable* mp = metaComponent_->sequenceables_[i];
String filePath = GetFilePath(String(mp->namespace_));
String fileName = FileName(filePath + mp->name_);
sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string());
}
for (int i = 0; i < metaComponent_->interfaceNumber_; i++) {
MetaInterface* mi = metaComponent_->interfaces_[i];
if (mi->external_) {
String filePath = GetFilePath(String(mi->namespace_));
String fileName = FileName(filePath + mi->name_);
sb.Append("#include ").AppendFormat("\"%s.h\"\n", fileName.string());
}
}
}
bool CppCodeEmitter::EmitInterfaceUsings(StringBuilder& sb)
{
bool ret = false;
for (int i = 0; i < metaComponent_->sequenceableNumber_; i++) {
MetaSequenceable* mp = metaComponent_->sequenceables_[i];
String np = GetNamespace(String(mp->namespace_));
if (np.IsEmpty()) {
continue;
}
String fullName = CppFullName(np + mp->name_);
sb.Append("using ").AppendFormat("%s;\n", fullName.string());
ret = true;
}
for (int i = 0; i < metaComponent_->interfaceNumber_; i++) {
MetaInterface* mi = metaComponent_->interfaces_[i];
if (mi->external_) {
String np = GetNamespace(String(mi->namespace_));
if (np.IsEmpty()) {
continue;
}
String fullName = CppFullName(np + mi->name_);
sb.Append("using ").AppendFormat("%s;\n", fullName.string());
ret = true;
}
}
return ret;
}
void CppCodeEmitter::EmitInterfaceDefinition(StringBuilder& sb)
{
EmitBeginNamespace(sb);
sb.AppendFormat("class %s : public IRemoteBroker {\n", metaInterface_->name_);
sb.Append("public:\n");
EmitInterfaceBody(sb, TAB);
sb.Append("};\n");
EmitEndNamespace(sb);
}
void CppCodeEmitter::EmitInterfaceBody(StringBuilder& sb, const String& prefix)
{
String nameWithoutPath = GetNamespace(interfaceFullName_);
sb.Append(TAB).AppendFormat("DECLARE_INTERFACE_DESCRIPTOR(u\"%s\");\n", nameWithoutPath.string());
sb.Append("\n");
EmitInterfaceMethods(sb, TAB);
}
void CppCodeEmitter::EmitInterfaceMethods(StringBuilder& sb, const String& prefix)
{
if (metaInterface_->methodNumber_ > 0) {
for (int i = 0; i < metaInterface_->methodNumber_; i++) {
MetaMethod* mm = metaInterface_->methods_[i];
EmitInterfaceMethod(mm, sb, prefix);
if (i != metaInterface_->methodNumber_ - 1) {
sb.Append("\n");
}
}
}
}
void CppCodeEmitter::EmitInterfaceMethod(MetaMethod* mm, StringBuilder& sb, const String& prefix)
{
MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_];
if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) {
sb.Append(prefix).AppendFormat("virtual ErrCode %s() = 0;\n", mm->name_);
} else {
sb.Append(prefix).AppendFormat("virtual ErrCode %s(\n", mm->name_);
for (int i = 0; i < mm->parameterNumber_; i++) {
MetaParameter* mp = mm->parameters_[i];
EmitInterfaceMethodParameter(mp, sb, prefix + TAB);
if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) {
sb.Append(",\n");
}
}
if (returnType->kind_ != TypeKind::Void) {
EmitInterfaceMethodReturn(returnType, sb, prefix + TAB);
}
sb.Append(") = 0;\n");
}
}
void CppCodeEmitter::EmitInterfaceMethodParameter(MetaParameter* mp, StringBuilder& sb, const String& prefix)
{
if ((mp->attributes_ & ATTR_MASK) == (ATTR_IN | ATTR_OUT)) {
sb.Append(prefix).Append("/* [in, out] */ ");
} else if (mp->attributes_ & ATTR_IN) {
sb.Append(prefix).Append("/* [in] */ ");
} else {
sb.Append(prefix).Append("/* [out] */ ");
}
MetaType* mt = metaComponent_->types_[mp->typeIndex_];
const std::string name = UnderlineAdded(mp->name_);
sb.AppendFormat("%s %s", EmitType(mt, mp->attributes_, false).string(), name.c_str());
}
void CppCodeEmitter::EmitInterfaceMethodReturn(MetaType* mt, StringBuilder& sb, const String& prefix)
{
sb.Append(prefix).AppendFormat("/* [out] */ %s result", EmitType(mt, ATTR_OUT, false).string());
}
void CppCodeEmitter::EmitInterfaceProxy()
{
EmitInterfaceProxyHeaderFile();
EmitInterfaceProxyCppFile();
}
void CppCodeEmitter::EmitInterfaceProxyHeaderFile()
{
String filePath = String::Format("%s/%s.h", directory_.string(), FileName(proxyName_).string());
File file(filePath, File::WRITE);
StringBuilder sb;
EmitLicense(sb);
sb.Append("\n");
EmitHeadMacro(sb, proxyFullName_);
sb.Append("\n");
sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string());
sb.Append("#include <iremote_proxy.h>\n");
sb.Append("\n");
EmitInterfaceProxyInHeaderFile(sb);
EmitTailMacro(sb, proxyFullName_);
String data = sb.ToString();
file.WriteData(data.string(), data.GetLength());
file.Flush();
file.Close();
}
void CppCodeEmitter::EmitInterfaceProxyInHeaderFile(StringBuilder& sb)
{
EmitBeginNamespace(sb);
sb.AppendFormat("class %s : public IRemoteProxy<%s> {\n", proxyName_.string(), interfaceName_.string());
sb.Append("public:\n");
EmitInterfaceProxyConstructor(sb, TAB);
sb.Append("\n");
EmitInterfaceProxyMethodDecls(sb, TAB);
sb.Append("\n");
sb.Append("private:\n");
EmitInterfaceProxyConstants(sb, TAB);
sb.Append("};\n");
EmitEndNamespace(sb);
}
void CppCodeEmitter::EmitInterfaceProxyConstructor(StringBuilder& sb, const String& prefix)
{
sb.Append(prefix).AppendFormat("explicit %s(\n", proxyName_.string());
sb.Append(prefix + TAB).Append("/* [in] */ const sptr<IRemoteObject>& remote)\n");
sb.Append(prefix + TAB).AppendFormat(": IRemoteProxy<%s>(remote)\n", interfaceName_.string());
sb.Append(prefix).Append("{}\n");
sb.Append("\n");
sb.Append(prefix).AppendFormat("virtual ~%s()\n", proxyName_.string());
sb.Append(prefix).Append("{}\n");
}
void CppCodeEmitter::EmitInterfaceProxyMethodDecls(StringBuilder& sb, const String& prefix)
{
if (metaInterface_->methodNumber_ > 0) {
for (int i = 0; i < metaInterface_->methodNumber_; i++) {
MetaMethod* mm = metaInterface_->methods_[i];
EmitInterfaceProxyMethodDecl(mm, sb, prefix);
if (i != metaInterface_->methodNumber_ - 1) {
sb.Append("\n");
}
}
}
}
void CppCodeEmitter::EmitInterfaceProxyMethodDecl(MetaMethod* mm, StringBuilder& sb, const String& prefix)
{
MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_];
if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) {
sb.Append(prefix).AppendFormat("ErrCode %s() override;\n", mm->name_);
} else {
sb.Append(prefix).AppendFormat("ErrCode %s(\n", mm->name_);
for (int i = 0; i < mm->parameterNumber_; i++) {
MetaParameter* mp = mm->parameters_[i];
EmitInterfaceMethodParameter(mp, sb, prefix + TAB);
if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) {
sb.Append(",\n");
}
}
if (returnType->kind_ != TypeKind::Void) {
EmitInterfaceMethodReturn(returnType, sb, prefix + TAB);
}
sb.Append(") override;\n");
}
}
void CppCodeEmitter::EmitInterfaceProxyConstants(StringBuilder& sb, const String& prefix)
{
EmitInterfaceMethodCommands(sb, prefix);
sb.Append("\n");
sb.Append(prefix).AppendFormat("static inline BrokerDelegator<%s> delegator_;\n", proxyName_.string());
}
void CppCodeEmitter::EmitInterfaceProxyCppFile()
{
String filePath = String::Format("%s/%s.cpp", directory_.string(), FileName(proxyName_).string());
File file(filePath, File::WRITE);
StringBuilder sb;
EmitLicense(sb);
sb.Append("\n");
sb.AppendFormat("#include \"%s.h\"\n", FileName(proxyName_).string());
sb.Append("\n");
EmitBeginNamespace(sb);
EmitInterfaceProxyMethodImpls(sb, "");
EmitEndNamespace(sb);
String data = sb.ToString();
file.WriteData(data.string(), data.GetLength());
file.Flush();
file.Close();
}
void CppCodeEmitter::EmitInterfaceProxyMethodImpls(StringBuilder& sb, const String& prefix)
{
if (metaInterface_->methodNumber_ > 0) {
for (int i = 0; i < metaInterface_->methodNumber_; i++) {
MetaMethod* mm = metaInterface_->methods_[i];
EmitInterfaceProxyMethodImpl(mm, sb, prefix);
if (i != metaInterface_->methodNumber_ - 1) {
sb.Append("\n");
}
}
}
}
void CppCodeEmitter::EmitInterfaceProxyMethodImpl(MetaMethod* mm, StringBuilder& sb, const String& prefix)
{
MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_];
if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) {
sb.Append(prefix).AppendFormat("ErrCode %s::%s()\n", proxyName_.string(), mm->name_);
} else {
sb.Append(prefix).AppendFormat("ErrCode %s::%s(\n", proxyName_.string(), mm->name_);
for (int i = 0; i < mm->parameterNumber_; i++) {
MetaParameter* mp = mm->parameters_[i];
EmitInterfaceMethodParameter(mp, sb, prefix + TAB);
if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) {
sb.Append(",\n");
}
}
if (returnType->kind_ != TypeKind::Void) {
EmitInterfaceMethodReturn(returnType, sb, prefix + TAB);
}
sb.Append(")\n");
}
EmitInterfaceProxyMethodBody(mm, sb, prefix);
}
void CppCodeEmitter::EmitInterfaceProxyMethodBody(MetaMethod* mm, StringBuilder& sb, const String& prefix)
{
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("MessageParcel data;\n");
sb.Append(prefix + TAB).Append("MessageParcel reply;\n");
sb.Append(prefix + TAB).AppendFormat("MessageOption option(%s);\n",
(mm->properties_ & METHOD_PROPERTY_ONEWAY) != 0 ? "MessageOption::TF_ASYNC" : "MessageOption::TF_SYNC");
sb.Append("\n");
for (int i = 0; i < mm->parameterNumber_; i++) {
MetaParameter* mp = mm->parameters_[i];
if ((mp->attributes_ & ATTR_IN) != 0) {
EmitWriteMethodParameter(mp, "data.", sb, prefix + TAB);
}
}
sb.Append("\n");
sb.Append(prefix + TAB).AppendFormat("int32_t st = Remote()->SendRequest(COMMAND_%s, data, reply, option);\n",
ConstantName(mm->name_).string());
sb.Append(prefix + TAB).Append("if (st != ERR_NONE) {\n");
sb.Append(prefix + TAB).Append(" return st;\n");
sb.Append(prefix + TAB).Append("}\n");
if ((mm->properties_ & METHOD_PROPERTY_ONEWAY) == 0) {
sb.Append("\n");
sb.Append(prefix + TAB).Append("ErrCode ec = reply.ReadInt32();\n");
sb.Append(prefix + TAB).Append("if (FAILED(ec)) {\n");
sb.Append(prefix + TAB).Append(" return ec;\n");
sb.Append(prefix + TAB).Append("}\n");
sb.Append("\n");
for (int i = 0; i < mm->parameterNumber_; i++) {
MetaParameter* mp = mm->parameters_[i];
if ((mp->attributes_ & ATTR_OUT) != 0) {
EmitReadMethodParameter(mp, "reply.", sb, prefix + TAB);
}
}
MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_];
if (returnType->kind_ != TypeKind::Void) {
EmitReadVariable("reply.", "result", returnType, sb, prefix + TAB, false);
}
}
sb.Append(prefix + TAB).Append("return ERR_OK;\n");
sb.Append(prefix).Append("}\n");
}
void CppCodeEmitter::EmitWriteMethodParameter(MetaParameter* mp, const String& parcelName, StringBuilder& sb,
const String& prefix)
{
MetaType* mt = metaComponent_->types_[mp->typeIndex_];
const std::string name = UnderlineAdded(mp->name_);
EmitWriteVariable(parcelName, name, mt, sb, prefix);
}
void CppCodeEmitter::EmitReadMethodParameter(MetaParameter* mp, const String& parcelName, StringBuilder& sb,
const String& prefix)
{
MetaType* mt = metaComponent_->types_[mp->typeIndex_];
const std::string name = UnderlineAdded(mp->name_);
EmitReadVariable(parcelName, name, mt, sb, prefix, false);
}
void CppCodeEmitter::EmitInterfaceStub()
{
EmitInterfaceStubHeaderFile();
EmitInterfaceStubCppFile();
}
void CppCodeEmitter::EmitInterfaceStubHeaderFile()
{
String filePath = String::Format("%s/%s.h", directory_.string(), FileName(stubName_).string());
File file(filePath, File::WRITE);
StringBuilder sb;
EmitLicense(sb);
sb.Append("\n");
EmitHeadMacro(sb, stubFullName_);
sb.Append("\n");
sb.AppendFormat("#include \"%s.h\"\n", FileName(interfaceName_).string());
sb.Append("#include <iremote_stub.h>\n");
sb.Append("\n");
EmitInterfaceStubInHeaderFile(sb);
EmitTailMacro(sb, stubFullName_);
String data = sb.ToString();
file.WriteData(data.string(), data.GetLength());
file.Flush();
file.Close();
}
void CppCodeEmitter::EmitInterfaceStubInHeaderFile(StringBuilder& sb)
{
EmitBeginNamespace(sb);
sb.AppendFormat("class %s : public IRemoteStub<%s> {\n", stubName_.string(), interfaceName_.string());
sb.Append("public:\n");
EmitInterfaceStubMethodDecls(sb, TAB);
sb.Append("\n");
sb.Append("private:\n");
EmitInterfaceStubConstants(sb, TAB);
sb.Append("};\n");
EmitEndNamespace(sb);
}
void CppCodeEmitter::EmitInterfaceStubMethodDecls(StringBuilder& sb, const String& prefix)
{
sb.Append(prefix).Append("int OnRemoteRequest(\n");
sb.Append(prefix + TAB).Append("/* [in] */ uint32_t code,\n");
sb.Append(prefix + TAB).Append("/* [in] */ MessageParcel& data,\n");
sb.Append(prefix + TAB).Append("/* [out] */ MessageParcel& reply,\n");
sb.Append(prefix + TAB).Append("/* [in] */ MessageOption& option) override;\n");
}
void CppCodeEmitter::EmitInterfaceStubConstants(StringBuilder& sb, const String& prefix)
{
EmitInterfaceMethodCommands(sb, prefix);
}
void CppCodeEmitter::EmitInterfaceStubCppFile()
{
String filePath = String::Format("%s/%s.cpp", directory_.string(), FileName(stubName_).string());
File file(filePath, File::WRITE);
StringBuilder sb;
EmitLicense(sb);
sb.Append("\n");
sb.AppendFormat("#include \"%s.h\"\n", FileName(stubName_).string());
sb.Append("\n");
EmitBeginNamespace(sb);
EmitInterfaceStubMethodImpls(sb, "");
EmitEndNamespace(sb);
String data = sb.ToString();
file.WriteData(data.string(), data.GetLength());
file.Flush();
file.Close();
}
void CppCodeEmitter::EmitInterfaceStubMethodImpls(StringBuilder& sb, const String& prefix)
{
sb.Append(prefix).AppendFormat("int %s::OnRemoteRequest(\n", stubName_.string());
sb.Append(prefix + TAB).Append("/* [in] */ uint32_t code,\n");
sb.Append(prefix + TAB).Append("/* [in] */ MessageParcel& data,\n");
sb.Append(prefix + TAB).Append("/* [out] */ MessageParcel& reply,\n");
sb.Append(prefix + TAB).Append("/* [in] */ MessageOption& option)\n");
sb.Append(prefix).Append("{\n");
sb.Append(prefix + TAB).Append("switch (code) {\n");
for (int i = 0; i < metaInterface_->methodNumber_; i++) {
MetaMethod* mm = metaInterface_->methods_[i];
EmitInterfaceStubMethodImpl(mm, sb, prefix + TAB + TAB);
}
sb.Append(prefix + TAB).Append(TAB).Append("default:\n");
sb.Append(prefix + TAB).Append(TAB).Append(TAB).Append(
"return IPCObjectStub::OnRemoteRequest(code, data, reply, option);\n");
sb.Append(prefix + TAB).Append("}\n\n");
sb.Append(prefix + TAB).Append("return ERR_TRANSACTION_FAILED;\n");
sb.Append(prefix).Append("}\n");
}
void CppCodeEmitter::EmitInterfaceStubMethodImpl(MetaMethod* mm, StringBuilder& sb, const String& prefix)
{
sb.Append(prefix).AppendFormat("case COMMAND_%s: {\n", ConstantName(mm->name_).string());
for (int i = 0; i < mm->parameterNumber_; i++) {
MetaParameter* mp = mm->parameters_[i];
if ((mp->attributes_ & ATTR_IN) != 0) {
MetaType* mt = metaComponent_->types_[mp->typeIndex_];
const std::string name = UnderlineAdded(mp->name_);
EmitReadVariable("data.", name, mt, sb, prefix + TAB);
} else if ((mp->attributes_ & ATTR_OUT) != 0) {
EmitLocalVariable(mp, sb, prefix + TAB);
}
}
MetaType* returnType = metaComponent_->types_[mm->returnTypeIndex_];
if (returnType->kind_ != TypeKind::Void) {
if ((returnType->kind_ == TypeKind::Sequenceable) || (returnType->kind_ == TypeKind::Interface)) {
sb.Append(prefix + TAB).AppendFormat("%s result = nullptr;\n",
EmitType(returnType, ATTR_IN, true).string());
} else {
sb.Append(prefix + TAB).AppendFormat("%s result;\n", EmitType(returnType, ATTR_IN, true).string());
}
}
if (mm->parameterNumber_ == 0 && returnType->kind_ == TypeKind::Void) {
sb.Append(prefix + TAB).AppendFormat("ErrCode ec = %s();\n", mm->name_);
} else {
sb.Append(prefix + TAB).AppendFormat("ErrCode ec = %s(", mm->name_);
for (int i = 0; i < mm->parameterNumber_; i++) {
MetaParameter* mp = mm->parameters_[i];
const std::string name = UnderlineAdded(mp->name_);
sb.Append(name.c_str());
if (i != mm->parameterNumber_ - 1 || returnType->kind_ != TypeKind::Void) {
sb.Append(", ");
}
}
if (returnType->kind_ != TypeKind::Void) {
EmitReturnParameter("result", returnType, sb);
}
sb.AppendFormat(");\n", mm->name_);
}
sb.Append(prefix + TAB).Append("reply.WriteInt32(ec);\n");
bool hasOutParameter = false;
for (int i = 0; i < mm->parameterNumber_; i++) {
MetaParameter* mp = mm->parameters_[i];
if ((mp->attributes_ & ATTR_OUT) != 0) {
hasOutParameter = true;
}
}
if (hasOutParameter || returnType->kind_ != TypeKind::Void) {
sb.Append(prefix + TAB).Append("if (SUCCEEDED(ec)) {\n");
for (int i = 0; i < mm->parameterNumber_; i++) {
MetaParameter* mp = mm->parameters_[i];
if ((mp->attributes_ & ATTR_OUT) != 0) {
EmitWriteMethodParameter(mp, "reply.", sb, prefix + TAB + TAB);
}
}
if (returnType->kind_ != TypeKind::Void) {
EmitWriteVariable("reply.", "result", returnType, sb, prefix + TAB + TAB);
}
sb.Append(prefix + TAB).Append("}\n");
}
sb.Append(prefix + TAB).Append("return ERR_NONE;\n");
sb.Append(prefix).Append("}\n");
}
void CppCodeEmitter::EmitInterfaceMethodCommands(StringBuilder& sb, const String& prefix)
{
for (int i = 0; i < metaInterface_->methodNumber_; i++) {
MetaMethod* mm = metaInterface_->methods_[i];
sb.Append(prefix).AppendFormat("static constexpr int COMMAND_%s = MIN_TRANSACTION_ID + %d;\n",
ConstantName(mm->name_).string(), i);
}
}
void CppCodeEmitter::EmitLicense(StringBuilder& sb)
{
sb.Append(metaInterface_->license_).Append("\n");
}
void CppCodeEmitter::EmitHeadMacro(StringBuilder& sb, const String& fullName)
{
String macroName = MacroName(fullName);
sb.Append("#ifndef ").Append(macroName).Append("\n");
sb.Append("#define ").Append(macroName).Append("\n");
}
void CppCodeEmitter::EmitTailMacro(StringBuilder& sb, const String& fullName)
{
String macroName = MacroName(fullName);
sb.Append("#endif // ").Append(macroName).Append("\n\n");
}
void CppCodeEmitter::EmitBeginNamespace(StringBuilder& sb)
{
String nspace = GetNamespace(metaInterface_->namespace_);
int index = nspace.IndexOf('.');
while (index != -1) {
sb.AppendFormat("namespace %s {\n", nspace.Substring(0, index).string());
nspace = nspace.Substring(index + 1);
index = nspace.IndexOf('.');
}
}
void CppCodeEmitter::EmitEndNamespace(StringBuilder& sb)
{
String nspace = GetNamespace(metaInterface_->namespace_);
nspace = nspace.Substring(0, nspace.GetLength() - 1);
while (!nspace.IsEmpty()) {
int index = nspace.LastIndexOf('.');
sb.AppendFormat("} // namespace %s\n", index != -1 ?
nspace.Substring(index + 1, nspace.GetLength()).string() : nspace.string());
nspace = nspace.Substring(0, index);
}
}
void CppCodeEmitter::EmitWriteVariable(const String& parcelName, const std::string& name, MetaType* mt,
StringBuilder& sb, const String& prefix)
{
switch (mt->kind_) {
case TypeKind::Boolean:
sb.Append(prefix).AppendFormat("%sWriteInt32(%s ? 1 : 0);\n", parcelName.string(), name.c_str());
break;
case TypeKind::Char:
case TypeKind::Byte:
case TypeKind::Short:
case TypeKind::Integer:
sb.Append(prefix).AppendFormat("%sWriteInt32(%s);\n", parcelName.string(), name.c_str());
break;
case TypeKind::Long:
sb.Append(prefix).AppendFormat("%sWriteInt64(%s);\n", parcelName.string(), name.c_str());
break;
case TypeKind::Float:
sb.Append(prefix).AppendFormat("%sWriteFloat(%s);\n", parcelName.string(), name.c_str());
break;
case TypeKind::Double:
sb.Append(prefix).AppendFormat("%sWriteDouble(%s);\n", parcelName.string(), name.c_str());
break;
case TypeKind::String:
sb.Append(prefix).AppendFormat("%sWriteString16(Str8ToStr16(%s));\n", parcelName.string(), name.c_str());
break;
case TypeKind::Sequenceable:
sb.Append(prefix).AppendFormat("%sWriteParcelable(%s);\n", parcelName.string(), name.c_str());
break;
case TypeKind::Interface:
sb.Append(prefix).AppendFormat("%sWriteRemoteObject(%s->AsObject());\n", parcelName.string(), name.c_str());
break;
case TypeKind::Array:
case TypeKind::List: {
sb.Append(prefix).AppendFormat("%sWriteInt32(%s.size());\n", parcelName.string(), name.c_str());
sb.Append(prefix).AppendFormat("for (auto it = %s.begin(); it != %s.end(); ++it) {\n",
name.c_str(), name.c_str());
MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
EmitWriteVariable(parcelName, "(*it)", innerType, sb, prefix + TAB);
sb.Append(prefix).Append("}\n");
break;
}
case TypeKind::Map: {
sb.Append(prefix).AppendFormat("%sWriteInt32(%s.size());\n", parcelName.string(), name.c_str());
sb.Append(prefix).AppendFormat("for (auto it = %s.begin(); it != %s.end(); ++it) {\n",
name.c_str(), name.c_str());
MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
EmitWriteVariable(parcelName, "(it->first)", keyType, sb, prefix + TAB);
EmitWriteVariable(parcelName, "(it->second)", valueType, sb, prefix + TAB);
sb.Append(prefix).Append("}\n");
break;
}
default:
break;
}
}
void CppCodeEmitter::EmitReadVariable(const String& parcelName, const std::string& name, MetaType* mt,
StringBuilder& sb, const String& prefix, bool emitType)
{
switch (mt->kind_) {
case TypeKind::Boolean:
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s = %sReadInt32() == 1 ? true : false;\n",
EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
} else {
sb.Append(prefix).AppendFormat("%s = %sReadInt32() == 1 ? true : false;\n",
name.c_str(), parcelName.string());
}
break;
case TypeKind::Char:
case TypeKind::Byte:
case TypeKind::Short:
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s = (%s)%sReadInt32();\n", EmitType(mt, ATTR_IN, true).string(),
name.c_str(), EmitType(mt, ATTR_IN, true).string(), parcelName.string());
} else {
sb.Append(prefix).AppendFormat("%s = (%s)%sReadInt32();\n", name.c_str(),
EmitType(mt, ATTR_IN, true).string(), parcelName.string());
}
break;
case TypeKind::Integer:
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s = %sReadInt32();\n",
EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
} else {
sb.Append(prefix).AppendFormat("%s = %sReadInt32();\n", name.c_str(), parcelName.string());
}
break;
case TypeKind::Long:
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s = %sReadInt64();\n",
EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
} else {
sb.Append(prefix).AppendFormat("%s = %sReadInt64();\n", name.c_str(), parcelName.string());
}
break;
case TypeKind::Float:
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s = %sReadFloat();\n",
EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
} else {
sb.Append(prefix).AppendFormat("%s = %sReadFloat();\n", name.c_str(), parcelName.string());
}
break;
case TypeKind::Double:
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s = %sReadDouble();\n",
EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
} else {
sb.Append(prefix).AppendFormat("%s = %sReadDouble();\n", name.c_str(), parcelName.string());
}
break;
case TypeKind::String:
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s = Str16ToStr8(%sReadString16());\n",
EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string());
} else {
sb.Append(prefix).AppendFormat("%s = Str16ToStr8(%sReadString16());\n",
name.c_str(), parcelName.string());
}
break;
case TypeKind::Sequenceable: {
MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_];
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s = %sReadParcelable<%s>();\n",
EmitType(mt, ATTR_IN, true).string(), name.c_str(), parcelName.string(), mp->name_);
} else {
sb.Append(prefix).AppendFormat("%s = %sReadParcelable<%s>();\n",
name.c_str(), parcelName.string(), mp->name_);
}
break;
}
case TypeKind::Interface: {
MetaInterface* mi = metaComponent_->interfaces_[mt->index_];
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s = iface_cast<%s>(%sReadRemoteObject());\n",
EmitType(mt, ATTR_IN, true).string(), name.c_str(), mi->name_, parcelName.string());
} else {
sb.Append(prefix).AppendFormat("%s = iface_cast<%s>(%sReadRemoteObject());\n",
name.c_str(), mi->name_, parcelName.string());
}
break;
}
case TypeKind::Array:
case TypeKind::List: {
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str());
}
sb.Append(prefix).AppendFormat("int %sSize = %sReadInt32();\n", name.c_str(), parcelName.string());
sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str());
MetaType* innerType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
EmitReadVariable(parcelName, "value", innerType, sb, prefix + TAB);
sb.Append(prefix + TAB).AppendFormat("%s.push_back(value);\n", name.c_str());
sb.Append(prefix).Append("}\n");
break;
}
case TypeKind::Map: {
if (emitType) {
sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str());
}
sb.Append(prefix).AppendFormat("int %sSize = %sReadInt32();\n", name.c_str(), parcelName.string());
sb.Append(prefix).AppendFormat("for (int i = 0; i < %sSize; ++i) {\n", name.c_str());
MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
EmitReadVariable(parcelName, "key", keyType, sb, prefix + TAB);
EmitReadVariable(parcelName, "value", valueType, sb, prefix + TAB);
sb.Append(prefix + TAB).AppendFormat("%s[key] = value;\n", name.c_str());
sb.Append(prefix).Append("}\n");
break;
}
default:
break;
}
}
void CppCodeEmitter::EmitLocalVariable(MetaParameter* mp, StringBuilder& sb, const String& prefix)
{
MetaType* mt = metaComponent_->types_[mp->typeIndex_];
const std::string name = UnderlineAdded(mp->name_);
if ((mt->kind_ == TypeKind::Sequenceable) || (mt->kind_ == TypeKind::Interface)) {
sb.Append(prefix).AppendFormat("%s %s = nullptr;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str());
} else {
sb.Append(prefix).AppendFormat("%s %s;\n", EmitType(mt, ATTR_IN, true).string(), name.c_str());
}
}
void CppCodeEmitter::EmitReturnParameter(const String& name, MetaType* mt, StringBuilder& sb)
{
switch (mt->kind_) {
case TypeKind::Char:
case TypeKind::Boolean:
case TypeKind::Byte:
case TypeKind::Short:
case TypeKind::Integer:
case TypeKind::Long:
case TypeKind::Float:
case TypeKind::Double:
case TypeKind::String:
case TypeKind::Sequenceable:
case TypeKind::Interface:
case TypeKind::List:
case TypeKind::Map:
case TypeKind::Array:
sb.Append(name);
break;
default:
break;
}
}
String CppCodeEmitter::EmitType(MetaType* mt, unsigned int attributes, bool isInnerType)
{
switch(mt->kind_) {
case TypeKind::Char:
if (attributes & ATTR_IN) {
return "zchar";
} else {
return "zchar&";
}
case TypeKind::Boolean:
if (attributes & ATTR_IN) {
return "bool";
} else {
return "bool&";
}
case TypeKind::Byte:
if (attributes & ATTR_IN) {
return "int8_t";
} else {
return "int8_t&";
}
case TypeKind::Short:
if (attributes & ATTR_IN) {
return "short";
} else {
return "short&";
}
case TypeKind::Integer:
if (attributes & ATTR_IN) {
return "int";
} else {
return "int&";
}
case TypeKind::Long:
if (attributes & ATTR_IN) {
return "long";
} else {
return "long&";
}
case TypeKind::Float:
if (attributes & ATTR_IN) {
return "float";
} else {
return "float&";
}
case TypeKind::Double:
if (attributes & ATTR_IN) {
return "double";
} else {
return "double&";
}
case TypeKind::String:
if (attributes & ATTR_IN) {
if (!isInnerType) {
return "const std::string&";
} else {
return "std::string";
}
} else {
return "std::string&";
}
case TypeKind::Void:
return "void";
case TypeKind::Sequenceable: {
MetaSequenceable* mp = metaComponent_->sequenceables_[mt->index_];
if ((attributes & ATTR_MASK) == (ATTR_IN | ATTR_OUT)) {
return String::Format("%s*", mp->name_);
} else if (attributes & ATTR_IN) {
return String::Format("%s*", mp->name_);
} else {
return String::Format("%s*", mp->name_);
}
}
case TypeKind::Interface: {
MetaInterface* mi = metaComponent_->interfaces_[mt->index_];
if (attributes & ATTR_IN) {
if (!isInnerType) {
return String::Format("sptr<%s>", mi->name_);
} else {
return String::Format("sptr<%s>", mi->name_);
}
} else {
return String::Format("sptr<%s>&", mi->name_);
}
}
case TypeKind::Array:
case TypeKind::List: {
MetaType* elementType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
if (attributes & ATTR_OUT) {
return String::Format("std::vector<%s>&",
EmitType(elementType, ATTR_IN, true).string());
} else {
if (!isInnerType) {
return String::Format("const std::vector<%s>&",
EmitType(elementType, ATTR_IN, true).string());
} else {
return String::Format("std::vector<%s>",
EmitType(elementType, ATTR_IN, true).string());
}
}
}
case TypeKind::Map: {
MetaType* keyType = metaComponent_->types_[mt->nestedTypeIndexes_[0]];
MetaType* valueType = metaComponent_->types_[mt->nestedTypeIndexes_[1]];
if (attributes & ATTR_OUT) {
return String::Format("std::unordered_map<%s, %s>&",
EmitType(keyType, ATTR_IN, true).string(), EmitType(valueType, ATTR_IN, true).string());
} else {
if (!isInnerType) {
return String::Format("const std::unordered_map<%s, %s>&",
EmitType(keyType, ATTR_IN, true).string(), EmitType(valueType, ATTR_IN, true).string());
} else {
return String::Format("std::unordered_map<%s, %s>",
EmitType(keyType, ATTR_IN, true).string(), EmitType(valueType, ATTR_IN, true).string());
}
}
break;
}
default:
return "unknown type";
}
}
String CppCodeEmitter::CppFullName(const String& name)
{
if (name.IsEmpty()) {
return name;
}
return name.Replace(".", "::");
}
String CppCodeEmitter::FileName(const String& name)
{
if (name.IsEmpty()) {
return name;
}
StringBuilder sb;
for (int i = 0; i < name.GetLength(); i++) {
char c = name[i];
if (isupper(c) != 0) {
// 2->Index of the last char array.
if (i > 1 && name[i - 1] != '.' && name[i - 2] != '.') {
sb.Append('_');
}
sb.Append(tolower(c));
} else {
sb.Append(c);
}
}
return sb.ToString().Replace('.', '/');
}
String CppCodeEmitter::MacroName(const String& name)
{
if (name.IsEmpty()) {
return name;
}
String macro = name.Replace('.', '_').ToUpperCase() + "_H";
return macro;
}
String CppCodeEmitter::ConstantName(const String& name)
{
if (name.IsEmpty()) {
return name;
}
StringBuilder sb;
for (int i = 0; i < name.GetLength(); i++) {
char c = name[i];
if (isupper(c) != 0) {
if (i > 1) {
sb.Append('_');
}
sb.Append(c);
} else {
sb.Append(toupper(c));
}
}
return sb.ToString();
}
const std::string CppCodeEmitter::UnderlineAdded(const String& originName)
{
std::string underline("_");
return underline + std::string(originName.string());
}
}
}