void CBodyGeneratorBase::GenStructures(std::ofstream& stream) {
for (auto& i : GetDocument().GetBlocks()) {
- if (i->GetType() != Block::TYPE_STRUCTURE)
- continue;
-
- const Structure &st = static_cast<const Structure&>(*i);
- GenStructure(stream, st);
- for (auto& j : st.GetElements().GetElms()) {
- auto& t = j->GetType();
- AddStructureFromType(t);
+ if (i->GetType() == Block::TYPE_STRUCTURE) {
+ const Structure &st = static_cast<const Structure&>(*i);
+ GenStructure(stream, st);
+ for (auto& j : st.GetElements().GetElms()) {
+ auto& t = j->GetType();
+ AddStructureFromType(t);
+ }
+ } else {
+ const Interface &inf = static_cast<const Interface&>(*i);
+ for (auto& d : inf.GetDeclarations().GetDecls()) {
+ for (auto& p : d->GetParameters().GetParams()) {
+ if (TypeIsDelegator(inf, p->GetParameterType().GetBaseType()))
+ continue;
+ AddStructureFromType(p->GetParameterType().GetBaseType());
+ }
+ }
}
}
);
}
-std::string CBodyGeneratorBase::GetParcelTypeString(const BaseType& type) {
+std::string CBodyGeneratorBase::GetParcelTypeString(const BaseType& type,
+ bool meta_type) {
if (type.IsUserDefinedType())
return "";
if (type.ToString() == "char")
if (type.ToString() == "long long")
return "int64";
if (type.ToString() == "list" ||
- type.ToString() == "array")
+ type.ToString() == "array") {
+ if (meta_type)
+ return "";
return "array_count";
+ }
return type.ToString();
}
}
std::string CBodyGeneratorBase::GetParcelWriteFunctionString(
- const BaseType& type) {
+ const BaseType& type, bool meta_type) {
std::string str = "rpc_port_parcel_write";
- std::string parcel_type = GetParcelTypeString(type);
+ std::string parcel_type = GetParcelTypeString(type, meta_type);
if (parcel_type != "")
str += "_" + parcel_type;
[&]()->std::string {
return GenTemplateString(parcel,
[&]()->std::string {
- return GetParcelWriteFunctionString(type);
+ return GetParcelWriteFunctionString(*type.GetMetaType(), true);
},
[&]()->std::string {
if (type.GetMetaType()->IsUserDefinedType() ||
}
std::string CBodyGeneratorBase::GetParcelReadFunctionString(
- const BaseType& type) {
+ const BaseType& type, bool meta_type) {
std::string str = "rpc_port_parcel_read";
- std::string parcel_type = GetParcelTypeString(type);
+ std::string parcel_type = GetParcelTypeString(type, meta_type);
if (parcel_type != "")
str += "_" + parcel_type;
std::string CBodyGeneratorBase::GetParcelReadString(const std::string& id,
const BaseType& type) {
std::string str;
- const char parcel[] = "$$(parcel, $$)\n";
+ const char parcel[] = "$$(parcel, $$);\n";
const char if_statement_with_braces[] =
"if ($$) {\n" \
" $$" \
s += NLine(1);
s += GenTemplateString(parcel,
[&]()->std::string {
- return GetParcelReadFunctionString(*type.GetMetaType());
+ return GetParcelReadFunctionString(*type.GetMetaType(), true);
},
[&]()->std::string {
return "&value->parcelable, value";
return "value";
},
[&]()->std::string {
- return GetDestructorString(*type.GetMetaType(), "value");
+ return GetDestructorString(*type.GetMetaType(), "value", true);
}
);
},
}
std::string CBodyGeneratorBase::GetDestructorString(const BaseType& type,
- const std::string& value) {
+ const std::string& value,
+ bool container_value) {
std::string str;
if (type.IsUserDefinedType() ||
"(" + value + ");" + NLine(1);
} else if (type.ToString() == "bundle") {
str += "bundle_free(" + value + ");" + NLine(1);
- } else {
+ } else if (type.ToString() == "string" || container_value) {
str += "free(" + value + ");" + NLine(1);
}
);
}
+void CBodyGeneratorBase::GenInterfaceEnumerations(std::ofstream& stream,
+ const Interface& inf) {
+ GenInterfaceMethodEnumeration(stream, inf);
+ GenInterfaceDelegateEnumeration(stream, inf);
+}
+
+void CBodyGeneratorBase::GenInterfaceDelegateEnumeration(
+ std::ofstream& stream, const Interface& inf) {
+ const char enum_format[] = "$$_DELEGATE_$$ = $$,\n";
+ const char format[] =
+ "enum $$_delegate_e {\n" \
+ "$$" \
+ "};\n";
+ int count = 1;
+
+ stream << NLine(1);
+ stream << SmartIndent(GenTemplateString(format,
+ [&]()->std::string {
+ return inf.GetID();
+ },
+ [&]()->std::string {
+ std::string str;
+ for (auto& i : inf.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+ continue;
+
+ str += GenTemplateString(enum_format,
+ [&]()->std::string {
+ return inf.GetID();
+ },
+ [&]()->std::string {
+ return i->GetID();
+ },
+ [&]()->std::string {
+ return std::to_string(count++);
+ }
+ );
+ }
+ return str;
+ }
+ )
+ );
+}
+
+void CBodyGeneratorBase::GenInterfaceMethodEnumeration(
+ std::ofstream& stream, const Interface& inf) {
+ const char enum_format[] = "$$_METHOD_$$,\n";
+ const char block[] =
+ "enum $$_method_e {\n" \
+ " $$_METHOD_Result,\n" \
+ " $$_METHOD_Callback,\n"
+ "$$" \
+ "};\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(GenTemplateString(block,
+ [&]()->std::string {
+ return inf.GetID();
+ },
+ [&]()->std::string {
+ return inf.GetID();
+ },
+ [&]()->std::string {
+ return inf.GetID();
+ },
+ [&]()->std::string {
+ std::string str;
+ for (auto& i : inf.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+ continue;
+ str += GenTemplateString(enum_format,
+ [&]()->std::string {
+ return inf.GetID();
+ },
+ [&]()->std::string {
+ return i->GetID();
+ }
+ );
+ }
+ return str;
+ }
+ )
+ );
+}
+
+void CBodyGeneratorBase::GenTypedefStubMethod(std::ofstream& stream) {
+ const char format[] =
+ "typedef int (*stub_method)(rpc_port_h, rpc_port_parcel_h, void* data);\n";
+
+ stream << NLine(1);
+ stream << std::string(format);
+}
+
} // namespace tidl
GenIncludeDefaultHeaders(stream);
GenIncludeHeader(stream);
GenLogTag(stream, std::string("RPC_PORT_STUB"));
+ GenTypedefStubMethod(stream);
GenStructures(stream);
+ GenInterfaces(stream);
}
void CStubBodyGen::OnFiniGen(std::ofstream& stream) {}
+void CStubBodyGen::GenInterfaces(std::ofstream& stream) {
+ for (auto& i : GetDocument().GetBlocks()) {
+ if (i->GetType() != Block::TYPE_INTERFACE)
+ continue;
+
+ const Interface &inf = static_cast<const Interface&>(*i);
+ GenInterface(stream, inf);
+ }
+}
+
+void CStubBodyGen::GenInterface(std::ofstream& stream, const Interface& inf) {
+ GenInterfaceEnumerations(stream, inf);
+ GenInterfaceGlobalVariables(stream, inf);
+ GenInterfaceContext(stream, inf);
+ GenInterfaceDelegators(stream, inf);
+ GenInterfaceMethods(stream, inf);
+ GenInterfaceMethodTable(stream, inf);
+ GenInterfaceOnConnectedEventCB(stream, inf);
+ GenInterfaceOnDisconnectedEventCB(stream, inf);
+ GenInterfaceOnReceivedEventCB(stream, inf);
+ GenInterfaceRegister(stream, inf);
+ GenInterfaceUnregister(stream, inf);
+}
+
+void CStubBodyGen::GenInterfaceMethods(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "static int __$$_method_$$(rpc_port_h port, rpc_port_parcel_h parcel, void* data)\n" \
+ "{\n" \
+ " rpc_port_stub_$$_context_h context = data;\n" \
+ "$$" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+
+ for (auto& i : inf.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+ continue;
+
+ stream << NLine(1);
+ stream << SmartIndent(GenTemplateString(block,
+ [&]()->std::string {
+ return inf.GetID();
+ },
+ [&]()->std::string {
+ return i->GetID();
+ },
+ [&]()->std::string {
+ return inf.GetID();
+ },
+ [&]()->std::string {
+ return GetMethodString(inf, *i);
+ }
+ )
+ );
+ }
+}
+
+void CStubBodyGen::GenInterfaceMethodTable(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "static stub_method __$$_method_table[] = {\n" \
+ "$$" \
+ "};\n";
+ const char method_format[] = "[$$] = $$,\n";
+ std::string str;
+ int cnt = 0;
+
+ for (auto& i : inf.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+ continue;
+ str += GenTemplateString(method_format,
+ [&]()->std::string {
+ return inf.GetID() + "_METHOD_" + i->GetID();
+ },
+ [&]()->std::string {
+ return "__" + inf.GetID() + "_method_" + i->GetID();
+ }
+ );
+ cnt++;
+ }
+
+ if (cnt == 0)
+ return;
+
+ stream << NLine(1);
+ stream << SmartIndent(GenTemplateString(block,
+ [&]()->std::string {
+ return inf.GetID();
+ },
+ [&]()->std::string {
+ return str;
+ }
+ )
+ );
+}
+
+void CStubBodyGen::GenInterfaceOnConnectedEventCB(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "static void __##_on_connected(const char* sender, const char* instance, void* data)\n" \
+ "{\n" \
+ " rpc_port_stub_##_context_h context;\n" \
+ "\n" \
+ " LOGI(\"[__RPC_PORT__] sender(%s), instance(%s)\", sender, instance);\n" \
+ " context = __create_##_context(sender, instance);\n" \
+ " if (!context)\n" \
+ " return;\n" \
+ "\n" \
+ " if (context->callback.create)\n" \
+ " context->callback.create(context, context->user_data);\n" \
+ " __##_contexts = g_list_append(__##_contexts, context);\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceOnDisconnectedEventCB(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "static void __##_on_disconnected(const char* sender, const char* instance, void* data)\n" \
+ "{\n" \
+ " rpc_port_stub_##_context_h context;\n" \
+ "\n" \
+ " LOGI(\"[__RPC_PORT__] sender(%s), instance(%s)\", sender, instance);\n" \
+ " context = __find_##_context(instance);\n" \
+ " if (!context)\n" \
+ " return;\n" \
+ "\n" \
+ " if (context->callback.terminate)\n" \
+ " context->callback.terminate(context, context->user_data);\n" \
+ " __##_contexts = g_list_remove(__##_contexts, context);\n" \
+ " __destroy_##_context(context);\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceOnReceivedEventCB(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "static int __##_on_received(const char* sender, const char* instance, rpc_port_h port, void* data)\n" \
+ "{\n" \
+ " rpc_port_stub_##_context_h context;\n" \
+ " rpc_port_parcel_h parcel;\n" \
+ " int cmd = -1;\n" \
+ " int r;\n" \
+ "\n" \
+ " LOGI(\"[__RPC_PORT__] sender(%s), instance(%s)\", sender, instance);\n" \
+ " context = __find_##_context(instance);\n" \
+ " if (!context) {\n" \
+ " LOGE(\"Failed to find ## context(%s)\", instance);\n" \
+ " return -1;\n" \
+ " }\n" \
+ " context->port = port;\n" \
+ "\n" \
+ " r = rpc_port_parcel_create_from_port(&parcel, port);\n" \
+ " if (r != 0) {\n" \
+ " LOGE(\"Failed to create parcel from port\");\n" \
+ " return r;\n" \
+ " }\n" \
+ "\n" \
+ " rpc_port_parcel_read_int32(parcel, &cmd);\n" \
+ " if (cmd > 1 && cmd < (sizeof(__##_method_table) / sizeof(__##_method_table[0]))) {\n" \
+ " if (__##_method_table[cmd])\n"
+ " r = __##_method_table[cmd](port, parcel, context);\n" \
+ " } else {\n" \
+ " LOGE(\"Unknown Command(%d)\", cmd);\n" \
+ " r = -1;\n" \
+ " }\n"
+ "\n" \
+ " rpc_port_parcel_destroy(parcel);\n" \
+ "\n" \
+ " return r;\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceRegister(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "int rpc_port_stub_##_register(rpc_port_stub_##_callback_s* callback, void* user_data)\n" \
+ "{\n" \
+ " int r;\n" \
+ "\n" \
+ " if (__##_stub) {\n" \
+ " LOGW(\"Already exists\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " if (!callback) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " __##_callback = *callback;\n" \
+ " __##_user_data = user_data;\n" \
+ " r = rpc_port_stub_create(&__##_stub, \"##\");\n" \
+ " if (r != 0) {\n" \
+ " LOGE(\"Failed to create stub handle\");\n" \
+ " return r;\n" \
+ " }\n" \
+ "\n" \
+ " r = rpc_port_stub_add_received_event_cb(__##_stub, __##_on_received, NULL);\n" \
+ " if (r != 0) {\n" \
+ " LOGE(\"Failed to add received event callback\");\n" \
+ " rpc_port_stub_destroy(__##_stub);\n" \
+ " __##_stub = NULL;\n" \
+ " return r;\n" \
+ " }\n" \
+ "\n" \
+ " r = rpc_port_stub_add_connected_event_cb(__##_stub, __##_on_connected, NULL);\n" \
+ " if (r != 0) {\n" \
+ " LOGE(\"Failed to add connected event callback\");\n" \
+ " rpc_port_stub_destroy(__##_stub);\n" \
+ " __##_stub = NULL;\n" \
+ " return r;\n" \
+ " }\n" \
+ "\n" \
+ " r = rpc_port_stub_add_disconnected_event_cb(__##_stub, __##_on_disconnected, NULL);\n" \
+ " if (r != 0) {\n" \
+ " LOGE(\"Failed to add disconnected event callback\");\n" \
+ " rpc_port_stub_destroy(__##_stub);\n" \
+ " __##_stub = NULL;\n" \
+ " return r;\n" \
+ " }\n" \
+ "\n" \
+ "$$" \
+ "\n" \
+ " r = rpc_port_stub_listen(__##_stub);\n" \
+ " if (r != 0) {\n" \
+ " LOGE(\"Failed to listen stub\");\n" \
+ " rpc_port_stub_destroy(__##_stub);\n" \
+ " __##_stub = NULL;\n" \
+ " return r;\n" \
+ " }\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(GenTemplateString(
+ ReplaceAll(block, "##", inf.GetID()),
+ [&]()->std::string {
+ std::string str;
+ for (auto& a : inf.GetAttributes().GetAttrs()) {
+ if (a->GetKey() != "privilege")
+ continue;
+ str += NLine(1);
+ str += GetAddPrivilegeString(inf.GetID(), *a);
+ }
+ return str;
+ }
+ )
+ );
+}
+
+void CStubBodyGen::GenInterfaceUnregister(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "int rpc_port_stub_##_unregister(void)\n" \
+ "{\n" \
+ " int r;\n" \
+ "\n" \
+ " if (!__##_stub)\n" \
+ " return -1;\n" \
+ "\n" \
+ " if (__##_contexts) {\n" \
+ " g_list_free_full(__##_contexts, __destroy_##_context);\n" \
+ " __##_contexts = NULL;\n" \
+ " }\n" \
+ "\n" \
+ " r = rpc_port_stub_destroy(__##_stub);\n" \
+ " __##_stub = NULL;\n" \
+ " return r;\n"
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceGlobalVariables(std::ofstream& stream,
+ const Interface& inf) {
+ const char format[] =
+ "static rpc_port_stub_h __##_stub;\n" \
+ "static rpc_port_stub_##_callback_s __##_callback;\n" \
+ "static void* __##_user_data;\n" \
+ "static GList* __##_contexts;\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(format, "##", inf.GetID()));
+}
+
+std::string CStubBodyGen::GetMethodString(const Interface& inf,
+ const Declaration& decl) {
+ std::string str;
+ const char port_setter[] = "rpc_port_set_$$_port($$, port);\n";
+ const char parcel[] = "$$(parcel, $$);\n";
+ const char do_while_block[] =
+ "do {\n" \
+ " rpc_port_parcel_h result;\n" \
+ " rpc_port_parcel_create(&result);\n" \
+ " rpc_port_parcel_write_int32(result, $$_METHOD_Result);\n" \
+ " $$(result, result_value);\n" \
+ " rpc_port_parcel_send(result, port);\n" \
+ " rpc_port_parcel_destroy(result);\n" \
+ "} while (0);\n";
+ int cnt = 0;
+ for (auto& i : decl.GetParameters().GetParams()) {
+ str += GetParcelParamTypeString(i->GetParameterType().GetBaseType()) +
+ " " + i->GetID() + ";" + NLine(1);
+ cnt++;
+ }
+ 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());
+ if (TypeIsDelegator(inf, i->GetParameterType().GetBaseType())) {
+ str += GenTemplateString(port_setter,
+ [&]()->std::string {
+ return i->GetParameterType().GetBaseType().ToString();
+ },
+ [&]()->std::string {
+ return 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();
+ }
+ );
+ }
+
+ if (cnt > 0)
+ str += NLine(1);
+
+ if (decl.GetMethodType() == Declaration::MethodType::SYNC &&
+ decl.GetType().ToString() != "void") {
+ str += GetReturnTypeString(decl.GetType()) + " result_value = ";
+ }
+
+ str += "context->callback." + decl.GetID() + "(context";
+ for (auto& i: decl.GetParameters().GetParams()) {
+ str += ", " + i->GetID();
+ }
+ str += ", context->user_data);" + NLine(1);
+ if (decl.GetMethodType() == Declaration::MethodType::SYNC &&
+ decl.GetType().ToString() != "void") {
+ str += GenTemplateString(do_while_block,
+ [&]()->std::string {
+ return inf.GetID();
+ },
+ [&]()->std::string {
+ return GetParcelWriteFunctionString(decl.GetType(), true);
+ }
+ );
+ }
+
+ for (auto& i: decl.GetParameters().GetParams()) {
+ str += GetDestructorString(i->GetParameterType().GetBaseType(),
+ i->GetID());
+ }
+
+ return str;
+}
+
+std::string CStubBodyGen::GetAddPrivilegeString(const std::string& id,
+ const Attribute& attr) {
+ const char format[] =
+ "r = $$;\n" \
+ "if (r != 0) {\n" \
+ " LOGE(\"$$\");\n" \
+ " rpc_port_stub_destroy(__$$_stub);\n" \
+ " __$$_stub = NULL;\n" \
+ " return r;\n" \
+ "}\n";
+ std::string str;
+
+ str += GenTemplateString(format,
+ [&]()->std::string {
+ return "rpc_port_stub_add_privilege(__" + id +
+ "_stub, \"" + attr.GetValue() + "\")";
+ },
+ [&]()->std::string {
+ return "Failed to add privilege";
+ },
+ [&]()->std::string {
+ return id;
+ },
+ [&]()->std::string {
+ return id;
+ }
+ );
+ return str;
+}
+
+void CStubBodyGen::GenInterfaceDelegators(std::ofstream& stream,
+ const Interface& inf) {
+ for (auto& i : inf.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+ continue;
+ GenInterfaceDelegator(stream, inf.GetID(), *i);
+ }
+}
+
+void CStubBodyGen::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);
+ GenInterfaceDelegatorDestructor(stream, id, decl);
+ GenInterfaceDelegatorCloner(stream, id, decl);
+ GenInterfaceDelegatorInvoker(stream, id, decl);
+ GenInterfaceDelegatorPortSetter(stream, id, decl);
+}
+
+void CStubBodyGen::GenInterfaceDelegatorDeclaration(std::ofstream& stream,
+ const std::string& id,
+ const Declaration& decl) {
+ const char block[] =
+ "struct $$_s {\n" \
+ " rpc_port_parcelable_t parcelable;\n" \
+ " rpc_port_h port;\n" \
+ " int id;\n" \
+ " int seq_id;\n" \
+ "};\n";
+ stream << NLine(1);
+ stream << SmartIndent(GenTemplateString(block,
+ [&]()->std::string {
+ return decl.GetID();
+ }
+ )
+ );
+}
+
+void CStubBodyGen::GenInterfaceDelegatorConstructor(std::ofstream& stream,
+ const std::string& id,
+ const Declaration& decl) {
+ const char block[] =
+ "int rpc_port_create_##(rpc_port_##_h* h)\n" \
+ "{\n" \
+ " struct ##_s* handle;\n" \
+ " static int seq_num;\n" \
+ "\n" \
+ " if (!h) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " handle = calloc(1, sizeof(struct ##_s));\n" \
+ " if (!handle) {\n" \
+ " LOGE(\"Out of memory\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " handle->parcelable.to = __##_to;\n" \
+ " handle->parcelable.from = __##_from;\n" \
+ " handle->id = $$_DELEGATE_##;\n" \
+ " handle->seq_id = seq_num++;\n" \
+ "\n" \
+ " *h = handle;\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(GenTemplateString(
+ ReplaceAll(block, "##", decl.GetID()),
+ [&]()->std::string {
+ return id;
+ }
+ )
+ );
+}
+
+void CStubBodyGen::GenInterfaceDelegatorDestructor(std::ofstream& stream,
+ const std::string& id,
+ const Declaration& decl) {
+ const char block[] =
+ "int rpc_port_destroy_##(rpc_port_##_h h)\n" \
+ "{\n" \
+ " if (!h) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " free(h);\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", decl.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceDelegatorSerializer(std::ofstream& stream,
+ const std::string& id,
+ const Declaration& decl) {
+ const char block[] =
+ "static void __##_to(rpc_port_parcel_h parcel, void* data)\n" \
+ "{\n" \
+ " rpc_port_##_h handle = data;\n" \
+ "\n" \
+ " if (!handle) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return;\n" \
+ " }\n" \
+ "\n" \
+ " rpc_port_parcel_write_int32(parcel, handle->id);\n" \
+ " rpc_port_parcel_write_int32(parcel, handle->seq_id);\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", decl.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceDelegatorDeserializer(std::ofstream& stream,
+ const std::string& id,
+ const Declaration& decl) {
+ const char block[] =
+ "static void __##_from(rpc_port_parcel_h parcel, void* data)\n" \
+ "{\n" \
+ " rpc_port_##_h handle = data;\n" \
+ "\n" \
+ " if (!handle) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return;\n" \
+ " }\n" \
+ "\n" \
+ " rpc_port_parcel_read_int32(parcel, &handle->id);\n" \
+ " rpc_port_parcel_read_int32(parcel, &handle->seq_id);\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", decl.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceDelegatorCloner(std::ofstream& stream,
+ const std::string& id,
+ const Declaration& decl) {
+ const char block[] =
+ "int rpc_port_clone_##(rpc_port_##_h h, rpc_port_##_h* clone)\n" \
+ "{\n" \
+ " rpc_port_##_h handle;\n" \
+ "\n" \
+ " if (!h || !clone) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " handle = calloc(1, sizeof(struct ##_s));\n" \
+ " if (!handle) {\n" \
+ " LOGE(\"Out of memory\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " handle->parcelable = h->parcelable;\n" \
+ " handle->port = h->port;\n" \
+ " handle->id = h->id;\n" \
+ " handle->seq_id = h->seq_id;\n" \
+ "\n" \
+ " *clone = handle;\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", decl.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceDelegatorInvoker(std::ofstream& stream,
+ const std::string& id,
+ const Declaration& decl) {
+ const char parcel[] = "$$(parcel, $$);\n";
+ const char block[] =
+ "int rpc_port_invoke_$$($$)\n" \
+ "{\n" \
+ " rpc_port_parcel_h parcel = NULL;\n" \
+ "\n" \
+ " if (!h || !h->port) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " if (!__$$_context_port_exist(h->port)) {\n" \
+ " LOGE(\"Port doesn't exist\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " rpc_port_parcel_create(&parcel);\n" \
+ " if (!parcel) {\n" \
+ " LOGE(\"Failed to create parcel\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " rpc_port_parcel_write_int32(parcel, $$_METHOD_Callback);\n" \
+ " rpc_port_parcel_write(parcel, &h->parcelable, h);\n" \
+ "$$" \
+ " rpc_port_parcel_send(parcel, h->port);\n" \
+ " rpc_port_parcel_destroy(parcel);\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(GenTemplateString(block,
+ [&]()->std::string {
+ return decl.GetID();
+ },
+ [&]()->std::string {
+ std::string str;
+ str += "rpc_port_" + decl.GetID() + "_h h";
+ for (auto& i : decl.GetParameters().GetParams()) {
+ str += ", ";
+ str += ConvertTypeToString(i->GetParameterType().GetDirection(),
+ i->GetParameterType().GetBaseType()) + " " + i->GetID();
+ }
+ return str;
+ },
+ [&]()->std::string {
+ return id;
+ },
+ [&]()->std::string {
+ return id;
+ },
+ [&]()->std::string {
+ std::string str;
+ for (auto& i : decl.GetParameters().GetParams()) {
+ str += GenTemplateString(parcel,
+ [&]()->std::string {
+ return GetParcelWriteFunctionString(
+ i->GetParameterType().GetBaseType());
+ },
+ [&]()->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;
+ }
+ )
+ );
+}
+
+void CStubBodyGen::GenInterfaceDelegatorPortSetter(std::ofstream& stream,
+ const std::string& id,
+ const Declaration& decl) {
+ const char block[] =
+ "int rpc_port_set_##_port(rpc_port_##_h h, rpc_port_h port)\n" \
+ "{\n" \
+ " if (!h || !port) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " h->port = port;\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", decl.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContext(std::ofstream& stream,
+ const Interface& inf) {
+ GenInterfaceContextDeclaration(stream, inf);
+ GenInterfaceContextConstructor(stream, inf);
+ GenInterfaceContextDestructor(stream, inf);
+ GenInterfaceContextFinder(stream, inf);
+ GenInterfaceContextTagSetter(stream, inf);
+ GenInterfaceContextTagGetter(stream, inf);
+ GenInterfaceContextSenderGetter(stream, inf);
+ GenInterfaceContextPortExist(stream, inf);
+}
+
+void CStubBodyGen::GenInterfaceContextDeclaration(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "struct ##_context_s {\n" \
+ " char* sender;\n" \
+ " char* instance;\n" \
+ " rpc_port_h port;\n" \
+ " void* tag;\n" \
+ " rpc_port_stub_##_callback_s callback;\n" \
+ " void* user_data;\n" \
+ "};\n";
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextConstructor(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "static struct ##_context_s* __create_##_context(const char* sender, const char* instance)\n" \
+ "{\n" \
+ " struct ##_context_s* handle;\n" \
+ "\n"
+ " handle = calloc(1, sizeof(struct ##_context_s));\n" \
+ " if (!handle) {\n" \
+ " LOGE(\"Out of memory\");\n" \
+ " return NULL;\n" \
+ " }\n" \
+ "\n" \
+ " handle->sender = strdup(sender);\n" \
+ " if (!handle->sender) {\n" \
+ " LOGE(\"Out of memory\");\n" \
+ " free(handle);\n" \
+ " return NULL;\n" \
+ " }\n" \
+ "\n" \
+ " handle->instance = strdup(instance);\n" \
+ " if (!handle->instance) {\n" \
+ " LOGE(\"Out of memory\");\n" \
+ " free(handle->sender);\n" \
+ " free(handle);\n" \
+ " return NULL;\n" \
+ " }\n" \
+ "\n" \
+ " handle->callback = __##_callback;\n"\
+ " handle->user_data = __##_user_data;\n" \
+ "\n" \
+ " return handle;\n" \
+ "}\n";
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextDestructor(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "static void __destroy_##_context(gpointer data)\n" \
+ "{\n" \
+ " struct ##_context_s* handle = data;\n" \
+ "\n" \
+ " if (!handle) {\n" \
+ " LOGE(\"Critical error!\");\n" \
+ " return;\n" \
+ " }\n" \
+ "\n" \
+ " free(handle->instance);\n" \
+ " free(handle->sender);\n" \
+ " free(handle);\n" \
+ "}\n";
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextFinder(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "static struct ##_context_s* __find_##_context(const char* instance)\n" \
+ "{\n" \
+ " struct ##_context_s* handle;\n" \
+ " GList* iter;\n" \
+ "\n" \
+ " iter = __##_contexts;\n" \
+ " while (iter) {\n" \
+ " handle = (struct ##_context_s*)iter->data;\n" \
+ " if (!strcmp(handle->instance, instance))\n" \
+ " return handle;\n" \
+ " iter = g_list_next(iter);\n" \
+ " }\n" \
+ "\n" \
+ " return NULL;\n" \
+ "}\n";
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextTagSetter(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "int rpc_port_stub_##_context_set_tag(rpc_port_stub_##_context_h ctx, void* tag)\n" \
+ "{\n" \
+ " if (!ctx) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " ctx->tag = tag;\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextTagGetter(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "int rpc_port_stub_##_context_get_tag(rpc_port_stub_##_context_h ctx, void** tag)\n" \
+ "{\n" \
+ " if (!ctx || !tag) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " *tag = ctx->tag;\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextSenderGetter(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "int rpc_port_stub_##_context_get_sender(rpc_port_stub_##_context_h ctx, char** sender)\n" \
+ "{\n" \
+ " if (!ctx || !sender) {\n" \
+ " LOGE(\"Invalid parameter\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " *sender = strdup(ctx->sender);\n" \
+ " if (*sender == NULL) {\n" \
+ " LOGE(\"Out of memory\");\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
+void CStubBodyGen::GenInterfaceContextPortExist(std::ofstream& stream,
+ const Interface& inf) {
+ const char block[] =
+ "static bool __##_context_port_exist(rpc_port_h port)\n" \
+ "{\n" \
+ " struct ##_context_s* handle;\n" \
+ " GList* iter;\n" \
+ "\n" \
+ " iter = __##_contexts;\n" \
+ " while (iter) {\n" \
+ " handle = (struct ##_context_s*)iter->data;\n" \
+ " if (handle->port == port)\n" \
+ " return true;\n" \
+ " iter = g_list_next(iter);\n" \
+ " }\n" \
+ "\n" \
+ " return false;\n" \
+ "}\n";
+ stream << NLine(1);
+ stream << SmartIndent(ReplaceAll(block, "##", inf.GetID()));
+}
+
} // namespace tidl
GenIncludeDefaultHeaders(stream, false);
GenExplicitLinkageOpen(stream);
GenStructures(stream);
+ GenInterfaces(stream);
}
void CStubHeaderGen::OnFiniGen(std::ofstream& stream) {
GenExplicitLinkageClose(stream);
}
+void CStubHeaderGen::GenInterfaces(std::ofstream& stream) {
+ for (auto& i : GetDocument().GetBlocks()) {
+ if (i->GetType() != Block::TYPE_INTERFACE)
+ continue;
+
+ const Interface &inf = static_cast<const Interface&>(*i);
+ GenInterface(stream, inf);
+ }
+}
+
+void CStubHeaderGen::GenInterface(std::ofstream& stream,
+ const Interface& inf) {
+ GenInterfaceContext(stream, inf);
+ GenInterfaceDelegators(stream, inf);
+ GenInterfaceDeclaration(stream, inf);
+ GenInterfaceRegister(stream, inf);
+ GenInterfaceUnregister(stream, inf);
+}
+
+void CStubHeaderGen::GenInterfaceDeclaration(std::ofstream& stream,
+ const Interface& inf) {
+ const char callback[] = "$$ (*$$)(rpc_port_stub_Message_context_h context, $$void *user_data);\n";
+ const char block[] =
+ "typedef struct {\n" \
+ " void (*create)(rpc_port_stub_##_context_h context, void* user_data);\n" \
+ " void (*terminate)(rpc_port_stub_##_context_h context, void* user_data);\n" \
+ " $$" \
+ "} rpc_port_stub_##_callback_s;\n";
+ stream << NLine(1);
+ stream << SmartIndent(GenTemplateString(ReplaceAll(block, "##", inf.GetID()),
+ [&]()->std::string {
+ std::string str;
+ for (auto& i: inf.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+ continue;
+ str += GenTemplateString(callback,
+ [&]()->std::string {
+ return GetReturnTypeString(i->GetType());
+ },
+ [&]()->std::string {
+ return i->GetID();
+ },
+ [&]()->std::string {
+ std::string s;
+ for (auto& p : i->GetParameters().GetParams()) {
+ if (TypeIsDelegator(inf, p->GetParameterType().GetBaseType())) {
+ s += GetParcelParamTypeString(p->GetParameterType().GetBaseType()) +
+ " " + p->GetID();
+ } else {
+ s += GetParamTypeString(p->GetParameterType().GetDirection(),
+ p->GetParameterType().GetBaseType()) + " " + p->GetID();
+ }
+ s += ", ";
+ }
+ return s;
+ }
+ );
+ }
+ return str;
+ }
+ )
+ );
+}
+
+void CStubHeaderGen::GenInterfaceContext(std::ofstream& stream,
+ const Interface& inf) {
+ GenInterfaceContextDeclaration(stream, inf);
+ GenInterfaceContextTagSetter(stream, inf);
+ GenInterfaceContextTagGetter(stream, inf);
+ GenInterfaceContextSenderGetter(stream, inf);
+}
+
+void CStubHeaderGen::GenInterfaceContextDeclaration(
+ std::ofstream& stream, const Interface& inf) {
+ const char format[] = "typedef struct ##_context_s* rpc_port_stub_##_context_h;\n";
+ stream << NLine(1);
+ stream << ReplaceAll(format, "##", inf.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceContextTagSetter(
+ std::ofstream& stream, const Interface& inf) {
+ const char format[] =
+ "int rpc_port_stub_##_context_set_tag(rpc_port_stub_##_context_h ctx, void* tag);\n";
+ stream << NLine(1);
+ stream << ReplaceAll(format, "##", inf.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceContextTagGetter(
+ std::ofstream& stream, const Interface& inf) {
+ const char format[] =
+ "int rpc_port_stub_##_context_get_tag(rpc_port_stub_##_context_h ctx, void** tag);\n";
+ stream << NLine(1);
+ stream << ReplaceAll(format, "##", inf.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceContextSenderGetter(
+ std::ofstream& stream, const Interface& inf) {
+ const char format[] =
+ "int rpc_port_stub_##_context_get_sender(rpc_port_stub_##_context_h ctx, char** sender);\n";
+ stream << NLine(1);
+ stream << ReplaceAll(format, "##", inf.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceDelegators(std::ofstream& stream,
+ const Interface& inf) {
+ for (auto& i : inf.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+ continue;
+ GenInterfaceDelegator(stream, inf.GetID(), *i);
+ }
+}
+
+void CStubHeaderGen::GenInterfaceDelegator(std::ofstream& stream,
+ const std::string& id,
+ const Declaration& decl) {
+ GenInterfaceDelegatorDeclaration(stream, id, decl);
+ GenInterfaceDelegatorDestructor(stream, id, decl);
+ GenInterfaceDelegatorCloner(stream, id, decl);
+ GenInterfaceDelegatorInvoker(stream, id, decl);
+}
+
+void CStubHeaderGen::GenInterfaceDelegatorDeclaration(
+ std::ofstream& stream, const std::string& id, const Declaration& decl) {
+ const char format[] = "typedef struct ##_s* rpc_port_##_h;\n";
+ stream << NLine(1);
+ stream << ReplaceAll(format, "##", decl.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceDelegatorDestructor(
+ std::ofstream& stream, const std::string& id, const Declaration& decl) {
+ const char format[] =
+ "int rpc_port_destroy_##(rpc_port_##_h h);\n";
+ stream << NLine(1);
+ stream << ReplaceAll(format, "##", decl.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceDelegatorCloner(
+ std::ofstream& stream, const std::string& id, const Declaration& decl) {
+ const char format[] =
+ "int rpc_port_clone_##(rpc_port_##_h h, rpc_port_##_h* clone);\n";
+ stream << NLine(1);
+ stream << ReplaceAll(format, "##", decl.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceDelegatorInvoker(
+ std::ofstream& stream, const std::string& id, const Declaration& decl) {
+ const char format[] =
+ "int rpc_port_invoke_##(rpc_port_##_h h$$);\n";
+ stream << NLine(1);
+ stream << GenTemplateString(ReplaceAll(format, "##", decl.GetID()),
+ [&]()->std::string {
+ std::string str;
+ for (auto& i : decl.GetParameters().GetParams()) {
+ str += ", ";
+ str += GetParamTypeString(i->GetParameterType().GetDirection(),
+ i->GetParameterType().GetBaseType()) + " " + i->GetID();
+ }
+ return str;
+ }
+ );
+}
+
+void CStubHeaderGen::GenInterfaceRegister(std::ofstream& stream,
+ const Interface& inf) {
+ const char format[] =
+ "int rpc_port_stub_##_register(rpc_port_stub_##_callback_s* callback, void* user_data);\n";
+ stream << NLine(1);
+ stream << ReplaceAll(format, "##", inf.GetID());
+}
+
+void CStubHeaderGen::GenInterfaceUnregister(std::ofstream& stream,
+ const Interface& inf) {
+ const char format[] = "int rpc_port_stub_##_unregister(void);\n";
+ stream << NLine(1);
+ stream << ReplaceAll(format, "##", inf.GetID());
+}
+
} // namespace tidl