/* * Copyright (c) 2017 Samsung Electronics 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 "idlc/c_gen/c_proxy_body_gen.h" namespace { #include "idlc/c_gen/c_proxy_body_gen_cb.h" } namespace tidl { CProxyBodyGen::CProxyBodyGen(std::shared_ptr doc) : CBodyGeneratorBase(doc) {} void CProxyBodyGen::OnInitGen(std::ofstream& stream) { GenLicenseDescription(stream); GenGNUSourceDefinition(stream); GenIncludeDefaultHeaders(stream); GenIncludeHeader(stream); GenLogTag(stream, std::string("RPC_PORT_PROXY")); GenLogDefinition(stream); GenTypedefProxyDelegate(stream); GenStructures(stream); GenInterfaces(stream); } void CProxyBodyGen::OnFiniGen(std::ofstream& stream) { } void CProxyBodyGen::GenTypedefProxyDelegate(std::ofstream& stream) { const char format[] = "typedef void (*proxy_delegate)(GList **list, rpc_port_parcel_h parcel," \ " int seq_id, int id);\n"; stream << NLine(1); stream << std::string(format); } void CProxyBodyGen::GenInterfaces(std::ofstream& stream) { for (auto& i : GetDocument().GetBlocks()) { if (i->GetType() != Block::TYPE_INTERFACE) continue; const Interface &inf = static_cast(*i); GenInterface(stream, inf); } } void CProxyBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) { GenInterfaceEnumerations(stream, inf); GenInterfaceDeclaration(stream, inf); GenInterfaceDelegators(stream, inf); GenInterfaceDelegatorTable(stream, inf); GenInterfaceDelegatorHandler(stream, inf); GenInterfaceConsumeCommand(stream, inf); GenInterfaceOnConnectedEventCB(stream, inf); GenInterfaceOnDisconnectedEventCB(stream, inf); GenInterfaceOnRejectedEventCB(stream, inf); GenInterfaceOnReceivedEventCB(stream, inf); GenInterfaceMethods(stream, inf); GenInterfaceHandleCtor(stream, inf); GenInterfaceHandleDtor(stream, inf); GenInterfaceCtor(stream, inf); GenInterfaceConnect(stream, inf); GenInterfaceDtor(stream, inf); } void CProxyBodyGen::GenInterfaceDeclaration(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_INTERFACE_STRUCT, "##", GetInterfaceIdWithNamespace(inf))); } void CProxyBodyGen::GenInterfaceDelegators(std::ofstream& stream, const Interface& inf) { for (auto& i : inf.GetDeclarations().GetDecls()) { if (i->GetMethodType() != Declaration::MethodType::DELEGATE) continue; GenInterfaceDelegator(stream, GetInterfaceIdWithNamespace(inf), *i); } } void CProxyBodyGen::GenInterfaceDelegator(std::ofstream& stream, const std::string& id, const Declaration& decl) { GenInterfaceDelegatorDeclaration(stream, id, decl); GenInterfaceDelegatorSerializer(stream, id, decl); GenInterfaceDelegatorDeserializer(stream, id, decl); GenInterfaceDelegatorConstructor(stream, id, decl); GenInterfaceDelegatorDisposer(stream, id, decl); GenInterfaceDelegatorInvoker(stream, id, decl); } void CProxyBodyGen::GenInterfaceDelegatorDeclaration( std::ofstream& stream, const std::string& id, const Declaration& decl) { stream << SmartIndent(ReplaceAll( CB_DELEGATE_STRUCT, "##", id + "_" + decl.GetID())); } void CProxyBodyGen::GenInterfaceDelegatorSerializer( std::ofstream& stream, const std::string& id, const Declaration& decl) { stream << SmartIndent( ReplaceAll(CB_DELEGATE_SERIALIZER, "##", id + "_" + decl.GetID())); } void CProxyBodyGen::GenInterfaceDelegatorDeserializer( std::ofstream& stream, const std::string& id, const Declaration& decl) { stream << SmartIndent( ReplaceAll(CB_DELEGATE_DESERIALIZER, "##", id + "_" + decl.GetID())); } void CProxyBodyGen::GenInterfaceDelegatorConstructor( std::ofstream& stream, const std::string& id, const Declaration& decl) { stream << SmartIndent(GenTemplateString( ReplaceAll(CB_DELEGATE_CTOR, "##", id + "_" + decl.GetID()), [&]()->std::string { return id; }, [&]()->std::string { return decl.GetID(); })); } void CProxyBodyGen::GenInterfaceDelegatorDisposer( std::ofstream& stream, const std::string& id, const Declaration& decl) { stream << SmartIndent(GenTemplateString( ReplaceAll(CB_DELEGATE_DISPOSER, "##", id + "_" + decl.GetID()), [&]()->std::string { return id; })); } void CProxyBodyGen::GenInterfaceDelegatorInvoker( std::ofstream& stream, const std::string& id, const Declaration& decl) { const char parcel[] = "$$(parcel, $$);\n"; stream << SmartIndent(GenTemplateString( ReplaceAll(CB_DELEGATE_INVOKER, "##", id + "_" + decl.GetID()), [&]()->std::string { return id; }, [&]()->std::string { return decl.GetID(); }, [&]()->std::string { std::string str; int cnt = 0; for (auto& i : decl.GetParameters().GetParams()) { str += GetParcelParamTypeString( i->GetParameterType().GetBaseType(), false) + i->GetID() + ";" + NLine(1); cnt++; } if (cnt > 0) str += NLine(1); for (auto& i : decl.GetParameters().GetParams()) { if (i->GetParameterType().GetBaseType().IsUserDefinedType() || i->GetParameterType().GetBaseType().ToString() == "list" || i->GetParameterType().GetBaseType().ToString() == "array") { str += GetConstructorString(i->GetParameterType().GetBaseType(), i->GetID()); } str += GenTemplateString(parcel, [&]()->std::string { return GetParcelReadFunctionString( i->GetParameterType().GetBaseType(), true); }, [&]()->std::string { if (i->GetParameterType().GetBaseType().IsUserDefinedType() || i->GetParameterType().GetBaseType() .ToString() == "list" || i->GetParameterType().GetBaseType().ToString() == "array") return "&" + i->GetID() + "->parcelable, " + i->GetID(); return "&" + i->GetID(); }); } return str; }, [&]()->std::string { std::string str; str += "handle->callback(handle->user_data"; for (auto& i : decl.GetParameters().GetParams()) { str += ", "; str += i->GetID(); } str += ");" + NLine(1); return str; }, [&]()->std::string { std::string str; for (auto& i : decl.GetParameters().GetParams()) { str += GetDestructorString(i->GetParameterType().GetBaseType(), i->GetID()); str += NLine(1); } return str; })); } void CProxyBodyGen::GenInterfaceDelegatorTable(std::ofstream& stream, const Interface& inf) { const char block[] = "static proxy_delegate __$$_delegate_table[] = {\n" \ "$$" \ "};\n"; const char delegate_format[] = "[$$] = $$,\n"; std::string str; int cnt = 0; for (auto& i : inf.GetDeclarations().GetDecls()) { if (i->GetMethodType() != Declaration::MethodType::DELEGATE) continue; str += GenTemplateString(delegate_format, [&]()->std::string { return GetInterfaceIdWithNamespace(inf) + "_DELEGATE_" + i->GetID(); }, [&]()->std::string { return "__" + GetInterfaceIdWithNamespace(inf) + "_delegate_" + i->GetID(); }); cnt++; } if (cnt == 0) return; stream << NLine(1); stream << SmartIndent(GenTemplateString(block, [&]()->std::string { return GetInterfaceIdWithNamespace(inf); }, [&]()->std::string { return str; })); } void CProxyBodyGen::GenInterfaceDelegatorHandler(std::ofstream& stream, const Interface& inf) { std::string str; int cnt = 0; for (auto& i : inf.GetDeclarations().GetDecls()) { if (i->GetMethodType() != Declaration::MethodType::DELEGATE) continue; cnt++; } stream << SmartIndent(GenTemplateString( ReplaceAll(CB_PROCESS_RECEIVED_EVENT, "##", GetInterfaceIdWithNamespace(inf)), [&]()->std::string { if (cnt == 0) return str; return ReplaceAll(CB_PROCESS_RECEIVED_EVENT_IMPL, "##", GetInterfaceIdWithNamespace(inf)); })); } void CProxyBodyGen::GenInterfaceConsumeCommand(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_CONSUME_COMMAND, "##", GetInterfaceIdWithNamespace(inf))); } void CProxyBodyGen::GenInterfaceOnConnectedEventCB(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_ON_CONNECTED, "##", GetInterfaceIdWithNamespace(inf))); } void CProxyBodyGen::GenInterfaceOnDisconnectedEventCB(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_ON_DISCONNECTED, "##", GetInterfaceIdWithNamespace(inf))); } void CProxyBodyGen::GenInterfaceOnRejectedEventCB(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_ON_REJECTED, "##", GetInterfaceIdWithNamespace(inf))); } void CProxyBodyGen::GenInterfaceOnReceivedEventCB(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_ON_RECEIVED, "##", GetInterfaceIdWithNamespace(inf))); } void CProxyBodyGen::GenInterfaceMethods(std::ofstream& stream, const Interface& inf) { for (auto& i : inf.GetDeclarations().GetDecls()) { if (i->GetMethodType() == Declaration::MethodType::DELEGATE) continue; stream << SmartIndent(GenTemplateString( ReplaceAll(CB_INTERFACE_METHODS, "##", GetInterfaceIdWithNamespace(inf)), [&]()->std::string { return GetReturnTypeString(i->GetType()); }, [&]()->std::string { return i->GetID(); }, [&]()->std::string { std::string str; for (auto& p : i->GetParameters().GetParams()) { str += ", "; if (IsDelegateType(inf, p->GetParameterType().GetBaseType())) { str += "rpc_port_" + GetInterfaceIdWithNamespace(inf) + "_" + p->GetParameterType().GetBaseType().ToString() + "_h " + p->GetID(); } else { str += GetParamTypeString(p->GetParameterType().GetDirection(), p->GetParameterType().GetBaseType()) + p->GetID(); } } return str; }, [&]()->std::string { if (GetReturnTypeString(i->GetType()) != "void ") return GetReturnTypeString(i->GetType()) + "ret = " + GetErrorValue(i->GetType()) + ";"; return ""; }, [&]()->std::string { std::string str; for (auto& p : i->GetParameters().GetParams()) { if (p->GetParameterType().GetDirection() == ParameterType::Direction::OUT || p->GetParameterType().GetBaseType().IsUserDefinedType() || p->GetParameterType().GetBaseType().ToString() == "list" || p->GetParameterType().GetBaseType().ToString() == "array" || p->GetParameterType().GetBaseType().ToString() == "bundle") str += " || !" + p->GetID(); } return str; }, [&]()->std::string { if (GetReturnTypeString(i->GetType()) != "void ") return " ret"; return ""; }, [&]()->std::string { if (GetReturnTypeString(i->GetType()) != "void ") return " ret"; return ""; }, [&]()->std::string { return i->GetID(); }, [&]()->std::string { return GetMethodWriteString(inf, *i); }, [&]()->std::string { return GetMethodReadString(inf, *i); })); } } void CProxyBodyGen::GenInterfaceHandleCtor(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_INTERFACE_HANDLE_CTOR, "##", GetInterfaceIdWithNamespace(inf))); } void CProxyBodyGen::GenInterfaceHandleDtor(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_INTERFACE_HANDLE_DTOR, "##", GetInterfaceIdWithNamespace(inf))); } void CProxyBodyGen::GenInterfaceCtor(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_INTERFACE_CTOR, "##", GetInterfaceIdWithNamespace(inf))); } void CProxyBodyGen::GenInterfaceConnect(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_INTERFACE_CONNECT, "##", GetInterfaceIdWithNamespace(inf))); } void CProxyBodyGen::GenInterfaceDtor(std::ofstream& stream, const Interface& inf) { stream << SmartIndent(ReplaceAll(CB_INTERFACE_DTOR, "##", GetInterfaceIdWithNamespace(inf))); } std::string CProxyBodyGen::GetMethodWriteString(const Interface& inf, const Declaration& decl) { const char setter[] = "$$($$, $$);\n"; const char ternary_operation[] = "## ? ## : \"\""; std::string str; for (auto& p : decl.GetParameters().GetParams()) { if (p->GetParameterType().GetDirection() == ParameterType::Direction::OUT) continue; if (IsDelegateType(inf, p->GetParameterType().GetBaseType())) { str += GenTemplateString(ReplaceAll(CB_DELEGATE_BLOCK, "##", GetInterfaceIdWithNamespace(inf) + "_" + p->GetParameterType() .GetBaseType().ToString()), [&]()->std::string { return p->GetID(); }); } else { str += GenTemplateString(setter, [&]()->std::string { return GetParcelWriteFunctionString( p->GetParameterType().GetBaseType(), true); }, [&]()->std::string { return "parcel"; }, [&]()->std::string { if (p->GetParameterType().GetBaseType().IsUserDefinedType() || p->GetParameterType().GetBaseType().ToString() == "list" || p->GetParameterType().GetBaseType().ToString() == "array") { if (p->GetParameterType().GetDirection() == ParameterType::Direction::REF) return "&(*" + p->GetID() + ")->parcelable, " + "*" + p->GetID(); else return "&" + p->GetID() + "->parcelable, " + p->GetID(); } else if (p->GetParameterType().GetDirection() == ParameterType::Direction::REF) { if (p->GetParameterType().GetBaseType().ToString() == "string") return ReplaceAll(ternary_operation, "##", "*" + p->GetID()); return "*" + p->GetID(); } else if (p->GetParameterType().GetBaseType().ToString() == "string") { return ReplaceAll(ternary_operation, "##", p->GetID()); } return p->GetID(); }); } } return str; } std::string CProxyBodyGen::GetMethodReadString(const Interface& inf, const Declaration& decl) { const char setter[] = "$$($$, $$);\n"; std::string str; if (decl.GetMethodType() != Declaration::MethodType::SYNC) { str += "set_last_result(r);" + NLine(1); return str; } str += GenTemplateString(CB_RECEIVE_BLOCK, [&]()->std::string { std::string s; for (auto& p : decl.GetParameters().GetParams()) { if (p->GetParameterType().GetDirection() != ParameterType::Direction::OUT) continue; s += GetReturnTypeString(p->GetParameterType().GetBaseType()) + "out_" + p->GetID() + ";" + NLine(1); } return s; }, [&]()->std::string { return GetInterfaceIdWithNamespace(inf); }, [&]()->std::string { std::string s; for (auto& p : decl.GetParameters().GetParams()) { if (p->GetParameterType().GetDirection() != ParameterType::Direction::OUT) continue; if (p->GetParameterType().GetBaseType().IsUserDefinedType() || p->GetParameterType().GetBaseType().ToString() == "list" || p->GetParameterType().GetBaseType().ToString() == "array") { s += GetConstructorString(p->GetParameterType().GetBaseType(), "out_" + p->GetID()); } s += GenTemplateString(setter, [&]()->std::string { return GetParcelReadFunctionString( p->GetParameterType().GetBaseType(), true); }, [&]()->std::string { return "parcel_received"; }, [&]()->std::string { auto& t = p->GetParameterType().GetBaseType(); if (t.IsUserDefinedType() || t.ToString() == "list" || t.ToString() == "array") { return "&out_" + p->GetID() + "->parcelable, out_" + p->GetID(); } return "&out_" + p->GetID(); }); s += "*" + p->GetID() + " = out_" + p->GetID() + ";" + NLine(1); } if (GetReturnTypeString(decl.GetType()) != "void ") { if (decl.GetType().IsUserDefinedType() || decl.GetType().ToString() == "list" || decl.GetType().ToString() == "array") { s += GetConstructorString(decl.GetType(), "ret"); } s += GenTemplateString(setter, [&]()->std::string { return GetParcelReadFunctionString(decl.GetType(), false); }, [&]()->std::string { return "parcel_received"; }, [&]()->std::string { if (decl.GetType().IsUserDefinedType() || decl.GetType().ToString() == "list" || decl.GetType().ToString() == "array") return "&ret->parcelable, ret"; return "&ret"; }); } return s; }); if (GetReturnTypeString(decl.GetType()) != "void ") { str += "set_last_result(r);" + NLine(1); str += NLine(1); str += "return ret;"; } return str; } } // namespace tidl