#include "idlc/cpp_gen/cpp_gen_base.h"
+namespace {
+#include "cpp_gen_base_cb.h"
+}
+
namespace tidl {
CppGeneratorBase::CppGeneratorBase(std::shared_ptr<Document> doc)
}
void CppGeneratorBase::GenStructuresForHeader(std::ofstream& stream) {
- const char* cls = R"__cls_bundle(class Bundle final {
- public:
- Bundle() {
- raw_ = bundle_create();
- }
-
- Bundle(bundle* b) {
- raw_ = b;
- }
-
- ~Bundle() {
- if (raw_)
- bundle_free(raw_);
- }
-
- Bundle(Bundle&& b) : raw_(b.raw_) {
- b.raw_ = nullptr;
- }
-
- Bundle& operator = (Bundle&& b) {
- raw_ = b.raw_;
- b.raw_ = nullptr;
- return *this;
- }
-
- Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
-
- Bundle& operator = (const Bundle& b) {
- raw_ = bundle_dup(b.GetHandle());
- return *this;
- }
-
- bundle* GetHandle() const {
- return raw_;
- }
-
- private:
- bundle* raw_;
-};
-
-)__cls_bundle";
-
- stream << cls;
+ stream << CB_BUNDLE;
for (auto& i : GetDocument().GetBlocks()) {
if (i->GetType() != Block::TYPE_STRUCTURE)
continue;
}
}
-void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream, const Structure& st) {
- std::vector<std::string> p;
- std::vector<std::string> v;
- std::vector<std::string> lv;
+void CppGeneratorBase::GenStructureForHeader(std::ofstream& stream,
+ const Structure& st) {
const char ctor[] = " $$();\n" \
" $$($$);\n";
const char variable[] = "$$\n";
stream << "class " << st.GetID() << " final ";
- for (auto& i : st.GetElements().GetElms()) {
- if (i->GetType().GetMetaType() != nullptr) {
- lv.push_back(ConvertTypeToString(i->GetType()) + " " + i->GetID());
- }
- else {
- if (i->GetType().IsUserDefinedType())
- p.push_back(i->GetType().ToString() + " " + i->GetID());
- else
- p.push_back(ConvertTypeToString(i->GetType()) + " " + i->GetID());
-
- v.push_back(ConvertTypeToString(i->GetType()) + " " + i->GetID());
- }
- }
-
GenBrace(stream, 0, [&]() {
stream << " public:" << NLine(1);
GenTemplate(ctor, stream,
},
[&]()->std::string {
std::string str;
- for (auto& i : p) {
- str += i;
-
- if (i != p.back())
+ int n = 1;
+ for (auto& i : st.GetElements().GetElms()) {
+ if (n != 1)
str += ", ";
+ str += ConvertTypeToString(i->GetType()) + " " + i->GetID();
+ n++;
}
return str;
}
GenTemplate(variable, stream,
[&]()->std::string {
std::string str;
- for (auto& i : v) {
- str += "\n" + Tab(1) + i + "_;";
- }
- for (auto& i : lv) {
- str += "\n" + Tab(1) + i + "_;";
+ for (auto& i : st.GetElements().GetElms()) {
+ str += NLine(1) + Tab(1)
+ + ConvertTypeToString(i->GetType()) + " "
+ + i->GetID() + "_;";
}
+ str += NLine(1);
return str;
}
);
" : $$ {}";
for (auto& i : st.GetElements().GetElms()) {
- if (i->GetType().GetMetaType() == nullptr) {
- std::pair<std::string, std::string> p;
- if (i->GetType().IsUserDefinedType()) {
- p.first = i->GetType().ToString();
- p.second = i->GetID();
- }
- else {
- p.first = ConvertTypeToString(i->GetType());
- p.second = i->GetID();
- }
- v.push_back(p);
- }
+ std::pair<std::string, std::string> p;
+
+ p.first = ConvertTypeToString(i->GetType());
+ p.second = i->GetID();
+ v.push_back(p);
}
GenTemplate(ctor, stream,
stream << " ";
GenBrace(stream, 0, [&]() {
for (auto& i : st.GetElements().GetElms()) {
- if (i->GetType().ToString() == "string") {
- stream << Tab(1) << "rpc_port_parcel_write_"
- << parcel_type_map_[i->GetType().ToString()]
- << "(h, param.Get" << i->GetID() << "().c_str());"
- << NLine(1);
- } else if (i->GetType().ToString() == "bundle") {
- stream << Tab(1) << "rpc_port_parcel_write_bundle(h, param.Get"
- << i->GetID() << "().GetHandle());" << NLine(1);
- } else if (i->GetType().GetMetaType() ||
- i->GetType().IsUserDefinedType()) {
- stream << Tab(1) << "h << param.Get" << i->GetID() << "();"
- << NLine(1);
- } else {
- stream << Tab(1) << "rpc_port_parcel_write_"
- << parcel_type_map_[i->GetType().ToString()]
- << "(h, param.Get" << i->GetID() << "());"
- << NLine(1);
- }
- stream << NLine(1);
+ stream << AddIndent(TAB_SIZE,
+ ConvertTypeToSerializer(i->GetType(),
+ "param.Get" + i->GetID() + "()", "h"));
}
stream << Tab(1) << "return h;" << NLine(1);
}, false);
stream << " ";
GenBrace(stream, 0, [&]() {
for (auto& i : st.GetElements().GetElms()) {
- if (i->GetType().ToString() == "string") {
- stream << Tab(1) << "char* " << i->GetID() << " = nullptr;" << NLine(1);
- stream << Tab(1) << "rpc_port_parcel_read_"
- << parcel_type_map_[i->GetType().ToString()]
- << "(h, &" << i->GetID() << ");"
- << NLine(1);
- stream << Tab(1) << "param.Set" << i->GetID() << "(" << i->GetID() << ");"
- << NLine(1);
- stream << Tab(1) << "free(" << i->GetID() << ");"
- << NLine(1);
- } else if (i->GetType().ToString() == "bundle") {
- stream << Tab(1) << "bundle* " << i->GetID() << " = nullptr;" << NLine(1);
- stream << Tab(1) << "rpc_port_parcel_read_"
- << parcel_type_map_[i->GetType().ToString()]
- << "(h, &" << i->GetID() << ");"
- << NLine(1);
- stream << Tab(1) << "param.Set" << i->GetID() << "(Bundle(" << i->GetID() << "));"
- << NLine(1);
- } else if (i->GetType().GetMetaType() != nullptr ||
- i->GetType().IsUserDefinedType()) {
- stream << Tab(1) << ConvertTypeToString(i->GetType())
- << " " << i->GetID() << ";" << NLine(1);
- stream << Tab(1) << "h >> " << i->GetID() << ";"
- << NLine(1);
- stream << Tab(1) << "param.Set" << i->GetID() << "(std::move(" << i->GetID() << "));"
- << NLine(1);
- } else {
- stream << Tab(1) << ConvertTypeToString(i->GetType())
- << " " << i->GetID() << ";" << NLine(1);
- stream << Tab(1) << "rpc_port_parcel_read_"
- << parcel_type_map_[i->GetType().ToString()]
- << "(h, &" << i->GetID() << ");"
- << NLine(1);
- stream << Tab(1) << "param.Set" << i->GetID() << "(" << i->GetID() << ");"
- << NLine(1);
- }
- stream << NLine(1);
+ stream << AddIndent(TAB_SIZE,
+ ConvertTypeToDeserializer(i->GetType(), i->GetID(), "h"));
+ stream << Tab(1) << "param.Set" << i->GetID() << "(std::move(" << i->GetID() << "));"
+ << NLine(2);
}
stream << Tab(1) << "return h;" << NLine(1);
}, false);
}
}
+void CppGeneratorBase::GenMethodId(std::ofstream& stream,
+ const Interface& iface) {
+ stream << Tab(1) << "enum class MethodId : int ";
+ GenBrace(stream, TAB_SIZE, [&]() {
+ int cnt = 2;
+ stream << Tab(2) << "Result = 0," << NLine(1);
+ stream << Tab(2) << "Callback = 1," << NLine(1);
+ for (auto& i : iface.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+ continue;
+ stream << Tab(2)
+ << i->GetID() << " = " << cnt++ << "," << NLine(1);
+ }
+ }, false, false);
+ stream << ";" << NLine(2);
+}
+
+void CppGeneratorBase::GenDelegateId(std::ofstream& stream,
+ const Interface& iface) {
+ stream << Tab(1) << "enum class DelegateId : int ";
+ GenBrace(stream, TAB_SIZE, [&]() {
+ int cnt = 1;
+ for (auto& i : iface.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+ continue;
+ stream << Tab(2)
+ << i->GetID() << " = " << cnt++ << "," << NLine(1);
+ }
+ }, false, false);
+ stream << ";" << NLine(2);
+}
+
+void CppGeneratorBase::GenParameters(std::ofstream& stream,
+ const Parameters& ps) {
+ bool first = true;
+ for (auto& i : ps.GetParams()) {
+ if (!first) {
+ stream << ", ";
+ }
+
+ std::string ref;
+ auto dir = i->GetParameterType().GetDirection();
+ if (dir == ParameterType::Direction::OUT ||
+ dir == ParameterType::Direction::REF) {
+ ref = "&";
+ }
+
+ stream << ConvertTypeToString(i->GetParameterType().GetBaseType())
+ << ref << " " << i->GetID();
+ first = false;
+ }
+}
+
+void CppGeneratorBase::GenDeclaration(std::ofstream& stream,
+ const Interface& iface,
+ const Declaration& decl) {
+ stream << ConvertTypeToString(decl.GetType()) << " " << iface.GetID() << "::"
+ << decl.GetID() << "(";
+ GenParameters(stream, decl.GetParameters());
+ stream << ") ";
+}
+
+std::string CppGeneratorBase::ConvertTypeToSerializer(
+ const BaseType& type, std::string id, std::string parcel) {
+ std::string ret;
+
+ if (type.ToString() == "string") {
+ ret += "rpc_port_parcel_write_"
+ + parcel_type_map_[type.ToString()]
+ + "(" + parcel + ", " + id + ".c_str());\n";
+ } else if (type.ToString() == "bundle") {
+ ret += "rpc_port_parcel_write_bundle(" + parcel + ", "
+ + id + ".GetHandle());\n";
+ } else if (type.GetMetaType() || type.IsUserDefinedType()) {
+ ret += parcel + " << " + id + ";\n";
+ } else {
+ ret += "rpc_port_parcel_write_"
+ + parcel_type_map_[type.ToString()]
+ + "(" + parcel + ", " + id + ");\n";
+ }
+
+ return ret;
+}
+
+std::string CppGeneratorBase::ConvertTypeToDeserializer(
+ const BaseType& type, std::string id, std::string parcel,
+ bool make_new_type) {
+ std::string ret;
+
+ if (type.ToString() == "string") {
+ ret += "char* " + id + "_raw = nullptr;\n";
+ ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()]
+ + "(" + parcel + ", &" + id + "_raw);\n";
+ if (make_new_type) {
+ ret += "std::string " + id + "(" + id + "_raw);\n";
+ } else {
+ ret += id + " = " + id + "_raw;\n";
+ }
+ ret += "free(" + id + "_raw);\n";
+ } else if (type.ToString() == "bundle") {
+ ret += "bundle* " + id + "_raw = nullptr;\n";
+ ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()]
+ + "(" + parcel + ", &" + id + "_raw);\n";
+ if (make_new_type) {
+ ret += "Bundle " + id + "(" + id + "_raw);\n";
+ } else {
+ ret += id + " = " + id + "_raw;\n"
+ + "bundle_free(" + id + "_raw);\n";
+ }
+ } else if (type.GetMetaType() != nullptr || type.IsUserDefinedType()) {
+ std::string n;
+
+ if (type.GetMetaType() != nullptr)
+ n = ConvertTypeToString(type);
+ else
+ n = type.ToString();
+
+ if (make_new_type) {
+ ret += n + " ";
+ if (IsDelegateType(type.ToString())) {
+ ret += id + "(port, std::weak_ptr<ServiceBase>(b));\n"
+ + "CallbackBase.";
+ } else {
+ ret += id + ";\n";
+ }
+ }
+ ret += parcel + " >> " + id + ";\n";
+ } else {
+ if (make_new_type)
+ ret += ConvertTypeToString(type) + " " + id + ";\n";
+ ret += "rpc_port_parcel_read_" + parcel_type_map_[type.ToString()]
+ + "(" + parcel + ", &" + id + ");\n";
+ }
+
+ return ret;
+}
+
+void CppGeneratorBase::GenBodyCallbacks(std::ofstream& stream,
+ const Interface& iface, bool is_proxy) {
+ GenTemplate(CB_CALLBACK_BASE, stream,
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ }
+ );
+
+ for (auto& i : iface.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+ continue;
+ stream << NLine(1);
+ GenBodyCallback(stream, iface, *i, is_proxy);
+ }
+}
+
+void CppGeneratorBase::GenBodyCallback(std::ofstream& stream,
+ const Interface& iface, const Declaration& decl, bool is_proxy) {
+ if (!is_proxy) {
+ const char method[] = "void $$::$$::Invoke()";
+
+ GenTemplate(method, stream,
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return decl.GetID();
+ }
+ );
+ GenParameters(stream, decl.GetParameters());
+ stream << ") ";
+ GenBrace(stream, 0, [&]() {
+ //TODO
+
+ }, false);
+ } else {
+ const char cb[] = "void $$::$$::OnReceivedEvent(rpc_port_parcel_h parcel) ";
+
+ GenTemplate(cb, stream,
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return decl.GetID();
+ }
+ );
+ GenBrace(stream, 0, [&]() {
+ int cnt = 1;
+ for (auto& i : decl.GetParameters().GetParams()) {
+ std::string v = "param" + std::to_string(cnt);
+ std::string c = ConvertTypeToDeserializer(
+ i->GetParameterType().GetBaseType(), v, "parcel");
+ stream << AddIndent(TAB_SIZE, c) << NLine(1);
+ cnt++;
+ }
+
+ cnt = 1;
+ stream << Tab(1) << "OnReceived(";
+ for (int i = 0; i < decl.GetParameters().GetParams().size(); i++) {
+ if (cnt != 1) {
+ stream << ", ";
+ }
+ stream << "std::move(param" << std::to_string(cnt) << ")";
+ cnt++;
+ }
+ stream << ");" << NLine(1);
+ }, false);
+ }
+}
+
+void CppGeneratorBase::GenHeaderCallbacks(std::ofstream& stream,
+ const Interface& iface,
+ bool is_proxy) {
+ const char block1[] =
+ "class CallbackBase {\n" \
+ " public:\n" \
+ " CallbackBase(int delegate_id);\n" \
+ " virtual ~CallbackBase() = default;\n" \
+ "\n";
+
+ const char block2[] =
+ " int GetId() const;\n" \
+ " int GetSeqId() const;\n" \
+ "\n" \
+ " private:\n" \
+ " friend rpc_port_parcel_h operator << (rpc_port_parcel_h h, const CallbackBase& cb);\n" \
+ " friend rpc_port_parcel_h operator >> (rpc_port_parcel_h h, CallbackBase& cb);\n" \
+ "\n" \
+ " static int seq_num_;\n" \
+ " int id_;\n" \
+ " int seq_id_;\n" \
+ "};\n";
+
+ stream << AddIndent(TAB_SIZE, block1) << NLine(1);
+ if (is_proxy) {
+ stream << Tab(1) << " virtual void OnReceivedEvent(rpc_port_parcel_h port) = 0;"
+ << NLine(1);
+ }
+ stream << AddIndent(TAB_SIZE, block2) << NLine(1);
+
+ for (auto& i : iface.GetDeclarations().GetDecls()) {
+ if (i->GetMethodType() != Declaration::MethodType::DELEGATE)
+ continue;
+ GenHeaderCallback(stream, *i, is_proxy);
+ }
+}
+
+void CppGeneratorBase::GenHeaderCallback(std::ofstream& stream,
+ const Declaration& decl,
+ bool is_proxy) {
+ stream << Tab(1) << "class " << decl.GetID()
+ << " : public CallbackBase ";
+ GenBrace(stream, TAB_SIZE, [&]() {
+ const char ctor1[] =
+ "$$(rpc_port_parcel_h port, std::weak_ptr<ServiceBase> service)\n" \
+ " : CallbackBase(static_cast<int>(DelegateId::$$)) {\n" \
+ " port_ = port;\n" \
+ " service_ = std::move(service);\n" \
+ "}\n";
+ const char ctor2[] =
+ "$$()\n" \
+ " : CallbackBase(static_cast<int>(DelegateId::$$)) {}\n";
+
+ stream << Tab(1) << " public:" << NLine(1);
+ if (!is_proxy) {
+ GenTemplate(AddIndent(TAB_SIZE * 2, ctor1), stream,
+ [&]()->std::string {
+ return decl.GetID();
+ },
+ [&]()->std::string {
+ return decl.GetID();
+ }
+ );
+ } else {
+ GenTemplate(AddIndent(TAB_SIZE * 2, ctor2), stream,
+ [&]()->std::string {
+ return decl.GetID();
+ },
+ [&]()->std::string {
+ return decl.GetID();
+ }
+ );
+ }
+ stream << NLine(1);
+ if (is_proxy) {
+ stream << Tab(2) << "virtual void OnReceived(";
+ GenParameters(stream, decl.GetParameters());
+ stream << ") {}" << NLine(1);
+ } else {
+ stream << Tab(2) << "void Invoke(";
+ GenParameters(stream, decl.GetParameters());
+ stream << ");" << NLine(2);
+ }
+
+ stream << Tab(1) << " private:" << NLine(1);
+ if (is_proxy) {
+ stream << Tab(2) << "void OnReceivedEvent(rpc_port_parcel_h port) override;"
+ << NLine(1);
+ }
+ stream << Tab(2) << "rpc_port_parcel_h port_;" << NLine(1);
+ if (!is_proxy)
+ stream << Tab(2) << "weak_ptr<ServiceBase> service_;" << NLine(1);
+ }, false, false);
+ stream << ";" << NLine(2);
+}
+
+bool CppGeneratorBase::IsDelegateType(const std::string type_name) {
+ for (auto& i : GetDocument().GetBlocks()) {
+ if (i->GetType() != Block::TYPE_INTERFACE)
+ continue;
+ Interface& iface = static_cast<Interface&>(*i);
+
+ for (auto& j : iface.GetDeclarations().GetDecls()) {
+ if (j->GetMethodType() == Declaration::MethodType::DELEGATE) {
+ if (j->GetID() == type_name)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
} // namespace tidl
void GenDeSerializer(std::ofstream& stream);
void GenListSerializer(std::ofstream& stream, bool proto = false);
void GenPrototype(std::ofstream& stream);
-
+ void GenMethodId(std::ofstream& stream, const Interface& iface);
+ void GenDelegateId(std::ofstream& stream, const Interface& iface);
+ void GenParameters(std::ofstream& stream, const Parameters& ps);
+ void GenDeclaration(std::ofstream& stream, const Interface& iface,
+ const Declaration& decl);
+ void GenBodyCallbacks(std::ofstream& stream, const Interface& iface,
+ bool is_proxy);
+ void GenHeaderCallbacks(std::ofstream& stream, const Interface& iface,
+ bool is_proxy);
+ bool IsDelegateType(const std::string type_name);
std::string ConvertTypeToString(const BaseType& type);
std::string Tab(int cnt);
std::string NLine(int cnt);
+ std::string ConvertTypeToDeserializer(const BaseType& type,
+ std::string id, std::string parcel,
+ bool make_new_type = true);
+ std::string ConvertTypeToSerializer(const BaseType& type,
+ std::string id, std::string parcel);
private:
void GenSetter(std::ofstream& stream, const Element& ele);
bool proto = false);
void GenStructureForHeader(std::ofstream& stream, const Structure& st);
void GenStructureForBody(std::ofstream& stream, const Structure& st);
+ void GenBodyCallback(std::ofstream& stream, const Interface& iface,
+ const Declaration& decl, bool is_proxy);
+ void GenHeaderCallback(std::ofstream& stream, const Declaration& decl,
+ bool is_proxy);
protected:
const int TAB_SIZE = 2;
--- /dev/null
+const char CB_BUNDLE[] = R"__cls_bundle(class Bundle final {
+ public:
+ Bundle() {
+ raw_ = bundle_create();
+ }
+
+ Bundle(bundle* b) {
+ raw_ = b;
+ }
+
+ ~Bundle() {
+ if (raw_)
+ bundle_free(raw_);
+ }
+
+ Bundle(Bundle&& b) : raw_(b.raw_) {
+ b.raw_ = nullptr;
+ }
+
+ Bundle& operator = (Bundle&& b) {
+ raw_ = b.raw_;
+ b.raw_ = nullptr;
+ return *this;
+ }
+
+ Bundle(const Bundle& b) : raw_(bundle_dup(b.GetHandle())) {}
+
+ Bundle& operator = (const Bundle& b) {
+ raw_ = bundle_dup(b.GetHandle());
+ return *this;
+ }
+
+ bundle* GetHandle() const {
+ return raw_;
+ }
+
+ private:
+ bundle* raw_;
+};
+
+)__cls_bundle";
+
+const char CB_CALLBACK_BASE[] =
+R"__cpp_cb(
+int $$::CallbackBase::seq_num_ = 0;
+
+$$::CallbackBase::CallbackBase(int delegate_id)
+ : id_(delegate_id) {
+ seq_id_ = seq_num_++;
+}
+
+int $$::CallbackBase::GetId() const {
+ return id_;
+}
+
+int $$::CallbackBase::GetSeqId() const {
+ return seq_id_;
+}
+
+rpc_port_parcel_h operator << (rpc_port_parcel_h h, const $$::CallbackBase& cb) {
+ rpc_port_parcel_write_int32(h, cb.id_);
+ rpc_port_parcel_write_int32(h, cb.seq_id_);
+
+ return h;
+}
+
+rpc_port_parcel_h operator >> (rpc_port_parcel_h h, $$::CallbackBase& cb) {
+ rpc_port_parcel_read_int32(h, &cb.id_);
+ rpc_port_parcel_read_int32(h, &cb.seq_id_);
+
+ return h;
+}
+
+)__cpp_cb";
\ No newline at end of file
#include "idlc/cpp_gen/cpp_proxy_body_gen.h"
+namespace {
+#include "cpp_proxy_body_gen_cb.h"
+}
+
namespace tidl {
CppProxyBodyGen::CppProxyBodyGen(std::shared_ptr<Document> doc)
stream << "#include <stdlib.h>" << NLine(1)
<< "#include <assert.h>" << NLine(1)
<< NLine(1)
- << "#include <rpc-port-parcel.h>" << NLine(1)
- << "#include <rpc-port.h>" << NLine(1)
- << NLine(1)
<< "#include \"" << header_file << "\"" << NLine(2);
GenNamespace(stream);
}
stream << "namespace rpc_port ";
GenBrace(stream, 0, [&]() {
stream << NLine(1);
- GenPrototype(stream);
GenStructuresForBody(stream);
- GenSerializer(stream);
- GenDeSerializer(stream);
- GenListSerializer(stream);
stream << "namespace proxy ";
GenBrace(stream, 0, [&]() {
-// GenInterfaces(stream);
+ GenPrototype(stream);
+ GenSerializer(stream);
+ GenDeSerializer(stream);
+ GenListSerializer(stream);
+ GenInterfaces(stream);
}, false);
}, false);
}
-void CppProxyBodyGen::GenConstructor(std::ofstream& stream) {
+void CppProxyBodyGen::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);
+ }
+}
+
+void CppProxyBodyGen::GenInterface(std::ofstream& stream,
+ const Interface& iface) {
+ GenBodyCallbacks(stream, iface, true);
+ GenConstructor(stream, iface);
+ GenDestructor(stream, iface);
+ GenHelperMethods(stream, iface);
+ GenMethods(stream, iface);
+}
+
+void CppProxyBodyGen::GenConstructor(std::ofstream& stream,
+ const Interface& iface) {
+ GenTemplate(CB_PROXY_INTERFACE_CTOR, stream,
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ }
+ );
+}
+
+void CppProxyBodyGen::GenDestructor(std::ofstream& stream,
+ const Interface& iface) {
+ const char cb[] =
+ "$$::~$$() {\n" \
+ " if (proxy_)\n" \
+ " rpc_port_proxy_destroy(proxy_);\n" \
+ "}\n";
+
+ GenTemplate(cb, stream,
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ }
+ );
+}
+
+void CppProxyBodyGen::GenHelperMethods(std::ofstream& stream,
+ const Interface& iface) {
+
+ GenTemplate(CB_PROXY_HELPER_METHODS, stream,
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); },
+ [&]()->std::string { return iface.GetID(); }
+ );
+ stream << NLine(1);
+}
+
+void CppProxyBodyGen::GenMethods(std::ofstream& stream,
+ const Interface& iface) {
+ auto& decls = iface.GetDeclarations();
+ for (auto& i : decls.GetDecls()) {
+ if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+ continue;
+
+ GenDeclaration(stream, iface, *i);
+ GenBrace(stream, 0, [&]() {
+ GenInvocation(stream, *i);
+ }, false);
+ stream << NLine(1);
+ }
}
+void CppProxyBodyGen::GenInvocation(std::ofstream& stream, const Declaration& decl) {
+ const char* pre =
+ "if (port_ == nullptr)\n" \
+ " throw NotConnectedSocketException();\n" \
+ "\n" \
+ "rpc_port_parcel_h p;\n" \
+ "rpc_port_parcel_create(&p);\n";
+
+ const char* mid =
+ "// Send\n" \
+ "rpc_port_parcel_send(p, port_);\n";
+
+ stream << AddIndent(TAB_SIZE, pre);
+
+ // Serialize
+ stream << Tab(1)
+ << "rpc_port_parcel_write_int32(p, static_cast<int>(MethodId::"
+ << decl.GetID() << "));" << NLine(1);
+ std::string m;
+ std::string l;
+ for (auto& i : decl.GetParameters().GetParams()) {
+ auto& pt = i->GetParameterType();
+ if (pt.GetDirection() == ParameterType::Direction::OUT)
+ continue;
+ m += ConvertTypeToSerializer(pt.GetBaseType(), i->GetID(), "p");
+ if (IsDelegateType(pt.GetBaseType().ToString()))
+ l += "delegate_list_.emplace_back(new " + pt.GetBaseType().ToString()
+ + "(" + i->GetID() + "));\n";
+ }
+ stream << AddIndent(TAB_SIZE, m) << NLine(1);
+
+ if (decl.GetMethodType() == Declaration::MethodType::SYNC)
+ stream << Tab(1) << "rpc_port_parcel_h parcel_received;" << NLine(1);
+ stream << Tab(1) << "do ";
+ GenBrace(stream, TAB_SIZE, [&]() {
+ stream << Tab(2) << "std::lock_guard<std::recursive_mutex> lock(mutex_);"
+ << NLine(2);
+ if (!l.empty())
+ stream << AddIndent(TAB_SIZE * 2, l) << NLine(1);
+ stream << AddIndent(TAB_SIZE * 2, mid) << NLine(1);
+ if (decl.GetMethodType() == Declaration::MethodType::SYNC) {
+ stream << Tab(2) << "// Receive" << NLine(1);
+ stream << Tab(2)
+ << "ConsumeCommand(&parcel_received, port_);" << NLine(1);
+ }
+ }, false, false);
+ stream << " while (false);" << NLine(2);
+
+ // Deserialize
+ if (decl.GetMethodType() == Declaration::MethodType::ASYNC) {
+ stream << Tab(1) << "rpc_port_parcel_destroy(p);"
+ << NLine(1);
+ return;
+ }
+
+ const char* receive_block =
+ "if (parcel_received == nullptr) {\n" \
+ " throw InvalidProtocolException();\n" \
+ "}\n";
+ stream << AddIndent(TAB_SIZE, receive_block) << NLine(1);
+
+ for (auto& i : decl.GetParameters().GetParams()) {
+ if (i->GetParameterType().GetDirection() == ParameterType::Direction::IN) {
+ continue;
+ }
+
+ std::string c = ConvertTypeToDeserializer(
+ i->GetParameterType().GetBaseType(),
+ i->GetID(), "parcel_received", false);
+ if (c != "")
+ stream << AddIndent(TAB_SIZE, c);
+ }
+
+ if (decl.GetType().ToString() != "void") {
+ stream << AddIndent(TAB_SIZE,
+ ConvertTypeToDeserializer(decl.GetType(),
+ "ret", "parcel_received"));
+ }
+
+ stream << Tab(1) << "rpc_port_parcel_destroy(p);"
+ << NLine(1);
+ stream << Tab(1) << "rpc_port_parcel_destroy(parcel_received);"
+ << NLine(1);
+
+ stream << Tab(1) << "return ret;" << NLine(1);
+}
} // namespace tidl
private:
void GenNamespace(std::ofstream& stream);
void GenStructures(std::ofstream& stream);
- void GenConstructor(std::ofstream& stream);
- void GenDestructor(std::ofstream& stream);
+ void GenInterfaces(std::ofstream& stream);
+ void GenInterface(std::ofstream& stream, const Interface& iface);
+ void GenConstructor(std::ofstream& stream, const Interface& iface);
+ void GenDestructor(std::ofstream& stream, const Interface& iface);
+ void GenHelperMethods(std::ofstream& stream, const Interface& iface);
+ void GenMethods(std::ofstream& stream, const Interface& iface);
+ void GenInvocation(std::ofstream& stream, const Declaration& decl);
};
} // namespace tidl
--- /dev/null
+const char CB_PROXY_HELPER_METHODS[] =
+R"__cpp_cb(
+int $$::Connect() {
+ return rpc_port_proxy_connect(proxy_, target_appid_.c_str(), "$$");
+}
+
+void $$::ProcessReceivedEvent(rpc_port_parcel_h parcel) {
+ int id = 0;
+ int seqId = 0;
+
+ rpc_port_parcel_read_int32(parcel, &id);
+ rpc_port_parcel_read_int32(parcel, &seqId);
+
+ for (auto& i : delegate_list_) {
+ if (i->GetId() == id && i->GetSeqId() == seqId) {
+ i->OnReceivedEvent(parcel);
+ break;
+ }
+ }
+}
+
+void $$::ConsumeCommand(rpc_port_parcel_h* parcel, rpc_port_h port) {
+ do {
+ rpc_port_parcel_h p;
+ int ret = rpc_port_parcel_create_from_port(&p, port);
+ int cmd;
+
+ if (ret != 0)
+ break;
+ rpc_port_parcel_read_int32(p, &cmd);
+ if (cmd == static_cast<int>(MethodId::Result)) {
+ *parcel = p;
+ return;
+ }
+
+ ProcessReceivedEvent(p);
+ rpc_port_parcel_destroy(p);
+ *parcel = nullptr;
+ } while (true);
+ *parcel = nullptr;
+}
+
+void $$::OnConnectedCB(const char *ep, const char *port_name, rpc_port_h port, void *data) {
+ $$* l = static_cast<$$*>(data);
+ l->port_ = port;
+ l->listener_->OnConnected();
+}
+
+void $$::OnDisconnectedCB(const char *ep, const char *port_name, void *data) {
+ $$* l = static_cast<$$*>(data);
+ l->listener_->OnDisconnected();
+}
+
+void $$::OnRejectedCB(const char *ep, const char *port_name, void *data) {
+ $$* l = static_cast<$$*>(data);
+ l->listener_->OnRejected();
+}
+
+void $$::OnReceivedCB(const char *ep, const char *port_name, void *data) {
+ $$* l = static_cast<$$*>(data);
+ int cmd;
+ rpc_port_parcel_h parcel_received;
+
+ do {
+ std::lock_guard<std::recursive_mutex> lock(l->mutex_);
+ if (rpc_port_parcel_create_from_port(&parcel_received, l->port_) != 0)
+ return;
+ } while (false);
+
+ rpc_port_parcel_read_int32(parcel_received, &cmd);
+ if (cmd != static_cast<int>(MethodId::Callback)) {
+ rpc_port_parcel_destroy(parcel_received);
+ throw InvalidProtocolException();
+ }
+
+ l->ProcessReceivedEvent(parcel_received);
+ rpc_port_parcel_destroy(parcel_received);
+}
+)__cpp_cb";
+
+const char CB_PROXY_INTERFACE_CTOR[] =
+R"__cpp_cb(
+$$::$$(IEventListener* listener, const std::string& target_appid)
+ : port_(nullptr), proxy_(nullptr), listener_(listener),
+ target_appid_(target_appid) {
+ rpc_port_proxy_create(&proxy_);
+ rpc_port_proxy_add_connected_event_cb(proxy_, OnConnectedCB, this);
+ rpc_port_proxy_add_disconnected_event_cb(proxy_, OnDisconnectedCB, this);
+ rpc_port_proxy_add_rejected_event_cb(proxy_, OnRejectedCB, this);
+ rpc_port_proxy_add_received_event_cb(proxy_, OnReceivedCB, this);
+}
+)__cpp_cb";
stream << "#pragma once" << NLine(1)
<< NLine(1)
<< "#include <bundle.h>" << NLine(1)
+ << "#include <rpc-port-parcel.h>" << NLine(1)
+ << "#include <rpc-port.h>" << NLine(2)
<< NLine(1)
<< "#include <string>" << NLine(1)
<< "#include <vector>" << NLine(1)
+ << "#include <memory>" << NLine(1)
+ << "#include <mutex>" << NLine(1)
<< "#include <list>" << NLine(2);
GenNamespace(stream);
}
GenStructuresForHeader(stream);
stream << "namespace proxy ";
GenBrace(stream, 0, [&]() {
-// GenInterfaces(stream);
+ GenExceptions(stream);
+ GenInterfaces(stream);
}, false);
}, false);
}
+void CppProxyHeaderGen::GenExceptions(std::ofstream& stream) {
+ const char cb[] =
+R"__cpp_cb(
+class Exception {};
+class NotConnectedSocketException : public Exception {};
+class InvalidProtocolException : public Exception {};
+)__cpp_cb";
+ stream << cb << NLine(1);
+}
+
+void CppProxyHeaderGen::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);
+ }
+}
+
+void CppProxyHeaderGen::GenInterface(std::ofstream& stream,
+ const Interface& iface) {
+ const char* pub =
+ "class IEventListener {\n" \
+ " public:\n" \
+ " virtual void OnConnected() = 0;\n" \
+ " virtual void OnDisconnected() = 0;\n" \
+ " virtual void OnRejected() = 0;\n" \
+ "};\n"
+ "\n" \
+ "$$(IEventListener* listener, const std::string& target_appid);\n" \
+ "virtual ~$$();\n" \
+ "\n" \
+ "int Connect();\n";
+
+ const char* priv =
+ "static void OnConnectedCB(const char *ep, const char *port_name,\n" \
+ " rpc_port_h port, void *data);\n" \
+ "static void OnDisconnectedCB(const char *ep, const char *port_name,\n" \
+ " void *data);\n" \
+ "static void OnRejectedCB(const char *ep, const char *port_name, void *data);\n" \
+ "static void OnReceivedCB(const char *ep, const char *port_name, void *data);\n" \
+ "\n" \
+ "rpc_port_h port_;\n" \
+ "rpc_port_proxy_h proxy_;\n" \
+ "IEventListener* listener_;\n" \
+ "std::recursive_mutex mutex_;\n" \
+ "std::list<std::unique_ptr<CallbackBase>> delegate_list_;\n" \
+ "std::string target_appid_;\n";
+
+ stream << NLine(1) << "class " << iface.GetID() << " ";
+ GenBrace(stream, 0, [&]() {
+ stream << " public:" << NLine(1);
+ GenHeaderCallbacks(stream, iface, true);
+ GenTemplate(AddIndent(TAB_SIZE, pub), stream,
+ [&]()->std::string {
+ return iface.GetID();
+ },
+ [&]()->std::string {
+ return iface.GetID();
+ }
+ );
+ GenMethods(stream, iface);
+ stream << NLine(1) << " private:" << NLine(1);
+ GenMethodId(stream, iface);
+ GenDelegateId(stream, iface);
+ GenHelperMethods(stream);
+ stream << AddIndent(TAB_SIZE, priv);
+ }, false, false);
+ stream << ";" << NLine(1);
+}
+
+void CppProxyHeaderGen::GenHelperMethods(std::ofstream& stream) {
+ const char* func =
+ "void ProcessReceivedEvent(rpc_port_parcel_h parcel);\n" \
+ "void ConsumeCommand(rpc_port_parcel_h* parcel, rpc_port_h port);\n";
+ stream << AddIndent(TAB_SIZE, func) << NLine(1);
+}
+
+void CppProxyHeaderGen::GenMethods(std::ofstream& stream,
+ const Interface& iface) {
+ auto& decls = iface.GetDeclarations();
+
+ for (auto& i : decls.GetDecls()) {
+ if (i->GetMethodType() == Declaration::MethodType::DELEGATE)
+ continue;
+
+ GenDeclaration(stream, *i);
+ }
+}
+
+void CppProxyHeaderGen::GenDeclaration(std::ofstream& stream,
+ const Declaration& decl) {
+ stream << Tab(1) << ConvertTypeToString(decl.GetType()) << " "
+ << decl.GetID() << "(";
+ GenParameters(stream, decl.GetParameters());
+ stream << ");" << NLine(1);
+}
} // namespace tidl
private:
void GenNamespace(std::ofstream& stream);
+ void GenExceptions(std::ofstream& stream);
+ void GenInterfaces(std::ofstream& stream);
+ void GenInterface(std::ofstream& stream, const Interface& iface);
+ void GenMethods(std::ofstream& stream, const Interface& iface);
+ void GenDeclaration(std::ofstream& stream, const Declaration& decl);
+ void GenHelperMethods(std::ofstream& stream);
};
} // namespace tidl
stream << "#include <stdlib.h>" << NLine(1)
<< "#include <assert.h>" << NLine(1)
<< NLine(1)
- << "#include <rpc-port-parcel.h>" << NLine(1)
- << "#include <rpc-port.h>" << NLine(1)
- << NLine(1)
<< "#include \"" << header_file << "\"" << NLine(2);
GenNamespace(stream);
}
stream << "#pragma once" << NLine(1)
<< NLine(1)
<< "#include <bundle.h>" << NLine(1)
+ << "#include <rpc-port-parcel.h>" << NLine(1)
+ << "#include <rpc-port.h>" << NLine(1)
<< NLine(1)
<< "#include <string>" << NLine(1)
<< "#include <vector>" << NLine(1)