void CsStubGen::OnInitGen(std::ofstream& stream) {
GenCodeBlock("copyright.cb");
- stream << std::endl;
- stream << "using System;" << std::endl
- << "using System.Collections.Generic;" << std::endl
- << "using System.Runtime.InteropServices;" << std::endl
- << "using Tizen.Applications;" << std::endl << std::endl;
+ stream << NLine(1);
+ stream << "using System;" << NLine(1)
+ << "using System.Collections.Generic;" << NLine(1)
+ << "using System.Runtime.InteropServices;" << NLine(1)
+ << "using Tizen.Applications;" << NLine(2);
GenInterop(stream);
+ stream << NLine(1);
GenNamespace(stream);
}
}
void CsStubGen::GenNamespace(std::ofstream& stream) {
- stream << "namespace RPCPort" << std::endl;
+ stream << "namespace RPCPort" << NLine(1);
GenBrace(stream, 0, [&]() {
GenStructures(stream);
+ stream << Tab(1) << "namespace Stub" << NLine(1);
+ GenBrace(stream, TAB_SIZE, [&]() {
+ GenInterfaces(stream);
+ });
});
}
+void CsStubGen::GenInterfaces(std::ofstream& stream) {
+ for (auto& i : GetDocument().GetBlocks()) {
+ if (i->GetType() != Block::TYPE_INTERFACE)
+ continue;
+ Interface& iface = static_cast<Interface&>(*i);
+ GenInterface(stream, iface);
+ stream << std::endl;
+ }
+}
+
+void CsStubGen::GenInterface(std::ofstream& stream, const Interface& iface) {
+ stream << Tab(2) << "public sealed class " << iface.GetID() << NLine(1);
+ GenBrace(stream, TAB_SIZE * 2, [&]() {
+ GenServiceBase(stream, iface);
+ stream << Tab(3)
+ << "private IntPtr _stub;" << NLine(2);
+ stream << Tab(3)
+ << "private List<ServiceBase> _services = new List<ServiceBase>();"
+ << NLine(2);
+ stream << Tab(3)
+ << "private Type _serviceType;" << NLine(2);
+ GenMethodId(stream, iface);
+ GenSerializer(stream);
+ GenListSerializer(stream);
+ GenReceivedEvent(stream, iface);
+ GenConnectedEvent(stream);
+ GenDisconnectedEvent(stream);
+ GenCtor(stream, iface);
+ GenCommonMethods(stream);
+ });
+}
+
+void CsStubGen::GenServiceBase(std::ofstream& stream, const Interface& iface) {
+ const char cls[] =
+ "public abstract class ServiceBase\n" \
+ "{\n" \
+ " public string Sender\n" \
+ " {\n" \
+ " get; internal set;\n" \
+ " }\n" \
+ "\n" \
+ " protected ServiceBase()\n" \
+ " {\n" \
+ " }\n" \
+ "\n";
+
+ stream << AddIndent(TAB_SIZE * 3, cls);
+ GenDeclarations(stream, iface.GetDeclarations());
+ stream << NLine(1);
+ stream << AddIndent(TAB_SIZE * 3, "}\n");
+ stream << NLine(1);
+}
+
+void CsStubGen::GenDeclarations(std::ofstream& stream,
+ const Declarations& decls) {
+ for (auto& i : decls.GetDecls()) {
+ stream << Tab(4) << "public abstract ";
+ GenDeclaration(stream, *i);
+ stream << NLine(1);
+ }
+}
+
+void CsStubGen::GenDeclaration(std::ofstream& stream, const Declaration& decl) {
+ stream << ConvertTypeToString(decl.GetType()) << " "
+ << decl.GetID() << "(";
+ GenParameters(stream, decl.GetParameters());
+ stream << ");";
+}
+
+void CsStubGen::GenParameters(std::ofstream& stream, const Parameters& ps) {
+ bool first = true;
+ for (auto& i : ps.GetParams()) {
+ if (!first) {
+ stream << ", ";
+ }
+
+ auto dir = i->GetParameterType().GetDirection();
+ if (dir == ParameterType::Direction::OUT) {
+ stream << "out ";
+ } else if (dir == ParameterType::Direction::REF) {
+ stream << "ref ";
+ }
+
+ stream << ConvertTypeToString(i->GetParameterType().GetBaseType()) << " "
+ << i->GetID();
+ first = false;
+ }
+}
+
+void CsStubGen::GenMethodId(std::ofstream& stream, const Interface& iface) {
+ stream << Tab(3) << "private enum MethodId : int" << NLine(1);
+ GenBrace(stream, TAB_SIZE * 3, [&]() {
+ int cnt = 1;
+ for (auto& i : iface.GetDeclarations().GetDecls()) {
+ stream << Tab(4)
+ << i->GetID() << " = " << cnt++ << "," << NLine(1);
+ }
+ });
+ stream << NLine(1);
+}
+
+void CsStubGen::GenWriteBundle(std::ofstream& stream, const std::string& id) {
+ const char block[] =
+ "if (param.$$ != null)\n" \
+ "{\n" \
+ " Interop.LibRPCPort.Parcel.WriteBundle(h, param.$$.SafeBundleHandle.DangerousGetHandle());\n" \
+ "}\n" \
+ "else\n" \
+ "{\n" \
+ " Interop.LibRPCPort.Parcel.WriteBundle(h, new Bundle().SafeBundleHandle.DangerousGetHandle());\n" \
+ "}\n";
+
+ GenTemplate(AddIndent(TAB_SIZE * 4, block), stream,
+ [&]()->std::string {
+ return id;
+ },
+ [&]()->std::string {
+ return id;
+ }
+ );
+}
+
+void CsStubGen::GenSerializer(std::ofstream& stream, const Structure& st) {
+ stream << Tab(3) << "private static void Serialize(IntPtr h, "
+ << st.GetID() << " param)" << NLine(1);
+ GenBrace(stream, TAB_SIZE * 3, [&]() {
+ for (auto& i : st.GetElements().GetElms()) {
+ auto& t = i->GetType();
+ if (!t.IsUserDefinedType() && t.GetMetaType() == nullptr) {
+ if (t.ToString() == "bundle") {
+ GenWriteBundle(stream, i->GetID());
+ } else {
+ stream << Tab(4) << "Interop.LibRPCPort.Parcel.Write"
+ << ConvertTypeToParcelType(t.ToString())
+ << "(h, param."
+ << i->GetID()
+ << ");" << NLine(1);
+ }
+ } else {
+ stream << Tab(4) << "Serialize(h, param." << i->GetID()
+ << ");" << NLine(1);
+ }
+ }
+ });
+ stream << NLine(1);
+
+ stream << Tab(3) << "private static void Deserialize(IntPtr h, "
+ << st.GetID() << " param)" << NLine(1);
+ GenBrace(stream, TAB_SIZE * 3, [&]() {
+ for (auto& i : st.GetElements().GetElms()) {
+ auto& t = i->GetType();
+ if (!t.IsUserDefinedType() && t.GetMetaType() == nullptr) {
+ stream << Tab(4) << "Interop.LibRPCPort.Parcel.Read"
+ << ConvertTypeToParcelType(t.ToString())
+ << "(h, out var "
+ << i->GetID()
+ << ");" << NLine(1);
+ if (t.ToString() == "bundle") {
+ stream << Tab(4) << "param." << i->GetID()
+ << " = new Bundle(new SafeBundleHandle(" << i->GetID()
+ << ", true));" << NLine(1);
+ } else {
+ stream << Tab(4) << "param." << i->GetID() << " = " << i->GetID()
+ << ";" << NLine(1);
+ }
+ } else {
+ stream << Tab(4) << "param." << i->GetID() << " = new "
+ << ConvertTypeToString(t)
+ << "();" << NLine(1);
+ stream << Tab(4) << "Deserialize(h, param." << i->GetID()
+ << ");" << NLine(1);
+ }
+
+ }
+ });
+ stream << NLine(1);
+}
+
+void CsStubGen::GenSerializer(std::ofstream& stream) {
+ for (auto& i : GetDocument().GetBlocks()) {
+ if (i->GetType() == Block::TYPE_STRUCTURE) {
+ const Structure& st = static_cast<const Structure&>(*i);
+ GenSerializer(stream, st);
+ }
+ }
+}
+
+void CsStubGen::AddSerializerList(const BaseType& type) {
+ if (type.GetMetaType() != nullptr) {
+ serializer_list_[ConvertTypeToString(type)] = &type;
+ AddSerializerList(*type.GetMetaType());
+ }
+}
+
+void CsStubGen::GenListSerializer(std::ofstream& stream, const BaseType& type) {
+ stream << Tab(3) << "private static void Serialize(IntPtr h, "
+ << ConvertTypeToString(type) << " param)" << NLine(1);
+ GenBrace(stream, TAB_SIZE * 3, [&]() {
+ stream << Tab(4)
+ << "Interop.LibRPCPort.Parcel.WriteArrayCount(h, param.Count);"
+ << NLine(1);
+ stream << Tab(4) << "foreach (var i in param)" << NLine(1);
+ GenBrace(stream, TAB_SIZE * 4, [&]() {
+ auto& mt = *type.GetMetaType();
+ if (!mt.IsUserDefinedType() && mt.GetMetaType() == nullptr) {
+ stream << Tab(5) << "Interop.LibRPCPort.Parcel.Write"
+ << ConvertTypeToParcelType(mt.ToString())
+ << "(h, i);" << NLine(1);
+ } else {
+ stream << Tab(5) << "Serialize(h, i);" << NLine(1);
+ }
+ });
+ });
+ stream << NLine(1);
+
+ stream << Tab(3) << "private static void Deserialize(IntPtr h, "
+ << ConvertTypeToString(type) << " param)" << NLine(1);
+ GenBrace(stream, TAB_SIZE * 3, [&]() {
+ stream << Tab(4)
+ << "Interop.LibRPCPort.Parcel.ReadArrayCount(h, out int l);"
+ << NLine(1);
+ stream << Tab(4) << "for (int i = 0; i < l; i++)" << NLine(1);
+ GenBrace(stream, TAB_SIZE * 4, [&]() {
+ auto& mt = *type.GetMetaType();
+ if (!mt.IsUserDefinedType() && mt.GetMetaType() == nullptr) {
+ stream << Tab(5) << "Interop.LibRPCPort.Parcel.Read"
+ << ConvertTypeToParcelType(mt.ToString())
+ << "(h, out var v);" << NLine(1);
+ } else {
+ stream << Tab(5) << "var v = new " << ConvertTypeToString(mt)
+ << "();" << NLine(1);
+ stream << Tab(5) << "Deserialize(h, v);" << NLine(1);
+ }
+ stream << Tab(5) << "param.Add(v);" << NLine(1);
+ });
+ });
+ stream << NLine(1);
+}
+
+void CsStubGen::GenListSerializer(std::ofstream& stream) {
+ serializer_list_.clear();
+ for (auto& i : GetDocument().GetBlocks()) {
+ if (i->GetType() == Block::TYPE_STRUCTURE) {
+ const Structure& st = static_cast<const Structure&>(*i);
+ for (auto& j : st.GetElements().GetElms()) {
+ auto& t = j->GetType();
+ AddSerializerList(t);
+ }
+ } else if (i->GetType() == Block::TYPE_INTERFACE) {
+ const Interface& iface = static_cast<const Interface&>(*i);
+ for (auto& j : iface.GetDeclarations().GetDecls()) {
+ auto& t = j->GetType();
+ AddSerializerList(t);
+ for (auto& k : j->GetParameters().GetParams()) {
+ auto& t1 = k->GetParameterType().GetBaseType();
+ AddSerializerList(t1);
+ }
+ }
+ }
+ }
+
+ for (auto& p : serializer_list_) {
+ const BaseType* t = p.second;
+ GenListSerializer(stream, *t);
+ }
+}
+
+void CsStubGen::GenReceivedEvent(std::ofstream& stream, const Interface& iface) {
+ const char method_front[] =
+ "private int OnReceivedEvent(string sender, IntPtr port, IntPtr data)\n" \
+ "{\n" \
+ " int ret = Interop.LibRPCPort.Parcel.CreateFromPort(out IntPtr p, port);\n" \
+ "\n" \
+ " if (ret != 0)\n" \
+ " return ret;\n" \
+ "\n" \
+ " Interop.LibRPCPort.Parcel.Create(out IntPtr result);\n" \
+ " Interop.LibRPCPort.Parcel.ReadInt32(p, out int cmd);\n" \
+ " ServiceBase b = null;\n" \
+ "\n" \
+ " foreach (var i in _services)\n" \
+ " {\n" \
+ " if (i.Sender.Equals(sender))\n" \
+ " {\n" \
+ " b = i;\n" \
+ " break;\n" \
+ " }\n" \
+ " }\n" \
+ "\n" \
+ " if (b == null)\n" \
+ " return -1;\n" \
+ "\n"
+ " switch ((MethodId)cmd)\n" \
+ " {\n";
+
+ const char method_back[] =
+ " default:\n" \
+ " return -1;\n" \
+ " }\n" \
+ "\n" \
+ " Interop.LibRPCPort.Parcel.Destroy(p);\n" \
+ " Interop.LibRPCPort.Parcel.Destroy(result);\n" \
+ "\n" \
+ " return 0;\n" \
+ "}\n";
+
+ stream << AddIndent(TAB_SIZE * 3, method_front);
+ for (auto& i : iface.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+ continue;
+ stream << Tab(5) << "case MethodId." << i->GetID() << ":" << NLine(1);
+ GenBrace(stream, TAB_SIZE * 6, [&]() {
+ GenInvocation(stream, *i);
+ stream << Tab(7) << "break;" << NLine(1);
+ });
+ }
+ stream << AddIndent(TAB_SIZE * 3, method_back) << NLine(1);
+}
+
+void CsStubGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
+ int cnt = 1;
+
+ // Deserialize
+ for (auto& i : decl.GetParameters().GetParams()) {
+ std::string v = "param" + std::to_string(cnt);
+ std::string c = ConvertTypeToDeserializer(i->GetParameterType(), v);
+ if (c != "")
+ stream << AddIndent(TAB_SIZE * 7, c);
+ cnt++;
+ }
+
+ // Invoke
+ cnt = 1;
+ std::string m;
+ bool hasRet = false;
+
+ if (decl.GetType().ToString() != "void") {
+ m += "var retVal = ";
+ hasRet = true;
+ }
+
+ m += "b." + decl.GetID() + "(";
+ for (auto& i : decl.GetParameters().GetParams()) {
+ if (cnt != 1) {
+ m += ", ";
+ }
+
+ std::string v = "param" + std::to_string(cnt);
+ auto& pt = i->GetParameterType();
+ if (pt.GetDirection() == ParameterType::Direction::OUT) {
+ m += "out " + ConvertTypeToString(pt.GetBaseType()) + " ";
+ } else if (pt.GetDirection() == ParameterType::Direction::REF) {
+ m += "ref ";
+ }
+ m += v;
+ cnt++;
+ }
+
+ m += ");\n";
+ stream << AddIndent(TAB_SIZE * 7, m);
+
+ // Serialize
+ if (decl.GetMethodType() == Declaration::MethodType::ASYNC)
+ return;
+
+ cnt = 0;
+ m = "";
+ for (auto& i : decl.GetParameters().GetParams()) {
+ auto& pt = i->GetParameterType();
+ cnt++;
+ if (pt.GetDirection() == ParameterType::Direction::IN)
+ continue;
+ m += ConvertTypeToSerializer(pt.GetBaseType(), "param" + std::to_string(cnt));
+ }
+
+ if (hasRet) {
+ m += ConvertTypeToSerializer(decl.GetType(), "retVal");
+ }
+
+ m += "Interop.LibRPCPort.Parcel.Send(result, port);\n";
+ stream << AddIndent(TAB_SIZE * 7, m);
+}
+
+void CsStubGen::GenConnectedEvent(std::ofstream& stream) {
+ const char method[] =
+ "private void OnConnectedEvent(string sender, IntPtr data)\n" \
+ "{\n" \
+ " ServiceBase s = Activator.CreateInstance(_serviceType) as ServiceBase;\n" \
+ " s.Sender = sender;\n" \
+ " _services.Add(s);\n" \
+ "}\n";
+ stream << AddIndent(TAB_SIZE * 3, method) << NLine(1);
+}
+
+void CsStubGen::GenDisconnectedEvent(std::ofstream& stream) {
+ const char method[] =
+ "private void OnDisconnectedEvent(string sender, IntPtr data)\n" \
+ "{\n" \
+ " foreach (var i in _services)\n" \
+ " {\n" \
+ " if (i.Sender.Equals(sender))\n" \
+ " {\n" \
+ " _services.Remove(i);\n" \
+ " break;\n" \
+ " }\n" \
+ " }\n" \
+ "}\n";
+ stream << AddIndent(TAB_SIZE * 3, method) << NLine(1);
+}
+
+void CsStubGen::GenCtor(std::ofstream& stream, const Interface& iface) {
+ const char ctor[] =
+ "public $$()\n" \
+ "{\n" \
+ " Interop.LibRPCPort.Stub.Create(out _stub, \"$$\");\n" \
+ " Interop.LibRPCPort.Stub.AddReceivedEventCb(_stub, OnReceivedEvent, IntPtr.Zero);\n" \
+ " Interop.LibRPCPort.Stub.AddConnectedEventCb(_stub, OnConnectedEvent, IntPtr.Zero);\n" \
+ " Interop.LibRPCPort.Stub.AddDisconnectedEventCb(_stub, OnDisconnectedEvent, IntPtr.Zero);\n" \
+ "}\n";
+
+ GenTemplate(AddIndent(TAB_SIZE * 3, ctor), stream,
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ }
+ );
+ stream << NLine(1);
+}
+
+void CsStubGen::GenCommonMethods(std::ofstream& stream) {
+ const char method_listen[] =
+ "public void Listen(Type serviceType)\n" \
+ "{\n" \
+ " _serviceType = serviceType;\n" \
+ " Interop.LibRPCPort.Stub.Listen(_stub);\n" \
+ "}\n";
+
+ const char method_get_services[] =
+ "public IEnumerable<ServiceBase> GetServices()\n" \
+ "{\n" \
+ " return _services;\n" \
+ "}\n";
+
+ stream << AddIndent(TAB_SIZE * 3, method_listen) << NLine(1);
+ stream << AddIndent(TAB_SIZE * 3, method_get_services);
+}
+
} // namespace tidl