📄 rpcgen.cpp
字号:
string setter = s_SetterName(m_Source.m_RequestElement); code.ClassPublic() << "\n" << " virtual const TRequest& GetDefaultRequest(void) const;\n" << " virtual TRequest& SetDefaultRequest(void);\n" << " virtual void SetDefaultRequest(const TRequest& request);\n" << "\n" << " virtual void Ask(const TRequestChoice& req, TReply& reply);\n" << " virtual void Ask(const TRequestChoice& req, TReply& reply,\n" << " TReplyChoice::E_Choice wanted);\n\n"; // inline methods code.MethodStart(true) << "const " << treq << "& " << class_base << "::GetDefaultRequest(void) const\n" << "{\n return m_DefaultRequest;\n}\n\n"; code.MethodStart(true) << treq << "& " << class_base << "::SetDefaultRequest(void)\n" << "{\n return m_DefaultRequest;\n}\n\n"; code.MethodStart(true) << "void " << class_base << "::SetDefaultRequest(const " << treq << "& request)\n" << "{\n m_DefaultRequest.Assign(request);\n}\n\n\n"; code.MethodStart(false) << "void " << class_base << "::Ask(const " << treq << "Choice& req, " << trep << "& reply)\n" << "{\n" << " TRequest request;\n" << " request.Assign(m_DefaultRequest);\n" // We have to copy req because SetXxx() wants a non-const ref. << " request" << setter << ".Assign(req);\n" << " Ask(request, reply);\n" << "}\n\n\n"; code.MethodStart(false) << "void " << class_base << "::Ask(const " << treq << "Choice& req, " << trep << "& reply, " << trep << "Choice::E_Choice wanted)\n" << "{\n" << " TRequest request;\n" << " request.Assign(m_DefaultRequest);\n" // We have to copy req because SetXxx() wants a non-const ref. << " request" << setter << ".Assign(req);\n" << " Ask(request, reply, wanted);\n" << "}\n\n\n"; } // Scan choice types for interesting elements typedef CChoiceDataType::TMembers TChoices; typedef map<string, const CDataMember*> TChoiceMap; const TChoices& choices = m_Source.m_RequestChoiceType->GetMembers(); TChoiceMap reply_map; bool has_init = false, has_fini = false, has_error = false; ITERATE (TChoices, it, choices) { const string& name = (*it)->GetName(); if (name == "init") { if (dynamic_cast<const CNullDataType*>((*it)->GetType())) { has_init = true; } else { CNcbiOstrstream oss; (*it)->GetType()->PrintASN(oss, 0); string type = CNcbiOstrstreamToString(oss); _ASSERT(type != "NULL"); ERR_POST(Warning << "Ignoring non-null init (type " << type << ") in " << m_Source.m_RequestChoiceType); } } else if (name == "fini") { if (dynamic_cast<const CNullDataType*>((*it)->GetType())) { has_fini = true; } else { CNcbiOstrstream oss; (*it)->GetType()->PrintASN(oss, 0); string type = CNcbiOstrstreamToString(oss); _ASSERT(type != "NULL"); ERR_POST(Warning << "Ignoring non-null fini (type " << type << ") in " << m_Source.m_RequestChoiceType); } } } ITERATE (TChoices, it, m_Source.m_ReplyChoiceType->GetMembers()) { const string& name = (*it)->GetName(); reply_map[name] = it->get(); if (name == "error") { has_error = true; } } if (has_init) { code.ClassProtected() << " void x_Connect(void);\n"; code.MethodStart(false) << "void " << class_base << "::x_Connect(void)\n" << "{\n" << " Tparent::x_Connect();\n" << " AskInit();\n" << "}\n\n"; } if (has_fini) { code.ClassProtected() << " void x_Disconnect(void);\n"; code.MethodStart(false) << "void " << class_base << "::x_Disconnect(void)\n" << "{\n" << " AskFini();\n" // ignore/downgrade errors? << " Tparent::x_Disconnect();\n" << "}\n\n"; } // Make sure the reply's choice is correct -- rolled into Ask for // maximum flexibility. (Split out methods for the two error cases?) code.MethodStart(false) << "void " << class_base << "::Ask(const " << treq << "& request, " << trep << "& reply, " << trep << "Choice::E_Choice wanted)\n" << "{\n" << " Ask(request, reply);\n" << " TReplyChoice& rc = x_Choice(reply);\n" << " if (rc.Which() == wanted) {\n" << " return; // ok\n"; if (has_error) { code.Methods(false) << " } else if (rc.IsError()) {\n" << " CNcbiOstrstream oss;\n" << " oss << \"" << class_name << ": server error: \" << rc.GetError();\n" << " NCBI_THROW(CException, eUnknown, CNcbiOstrstreamToString(oss));\n"; } code.Methods(false) << " } else {\n" << " rc.ThrowInvalidSelection(wanted);\n" << " }\n" << "}\n\n"; // Finally, generate all the actual Ask* methods.... ITERATE (TChoices, it, choices) { typedef AutoPtr<CTypeStrings> TTypeStr; string name = (*it)->GetName(); string reply = m_Source.m_Generator.GetConfig().Get(sect_name, "reply." + name); if (reply.empty()) { reply = name; } else if (reply == "special") { continue; } TChoiceMap::const_iterator rm = reply_map.find(reply); if (rm == reply_map.end()) { NCBI_THROW(CDatatoolException, eInvalidData, "Invalid reply type " + reply + " for " + name); } string method = "Ask" + Identifier(name); const CDataType* req_type = (*it)->GetType()->Resolve(); string req_class; bool null_req = false; if (dynamic_cast<const CNullDataType*>(req_type)) { req_class = "void"; null_req = true; } else if ( !req_type->GetParentType() ) { req_class = req_type->ClassName(); } else { TTypeStr typestr = req_type->GetFullCType(); typestr->GeneratePointerTypeCode(code); req_class = typestr->GetCType(ns); } const CDataType* rep_type = rm->second->GetType()->Resolve(); string rep_class; bool use_cref = false; bool null_rep = false; if (dynamic_cast<const CNullDataType*>(rep_type)) { rep_class = "void"; null_rep = true; } else if ( !rep_type->GetParentType() && !rep_type->IsStdType() ) { rep_class = ns.GetNamespaceRef(CNamespace::KNCBINamespace) + "CRef<" + rep_type->ClassName() + '>'; use_cref = true; code.CPPIncludes().insert(rep_type->FileName()); } else { TTypeStr typestr = rep_type->GetFullCType(); typestr->GeneratePointerTypeCode(code); rep_class = typestr->GetCType(ns); } code.ClassPublic() << " virtual " << rep_class << ' ' << method << "\n"; if (null_req) { code.ClassPublic() << " (TReply* reply = 0);\n\n"; } else { code.ClassPublic() << " (const " << req_class << "& req, TReply* reply = 0);\n\n"; } code.MethodStart(false) << rep_class << ' ' << class_base << "::" << method; if (null_req) { code.Methods(false) << '(' << trep << "* reply)\n"; } else { code.Methods(false) << "(const " << req_class << "& req, " << trep << "* reply)\n"; } code.Methods(false) << "{\n" << " TRequestChoice request;\n" << " TReply reply0;\n"; if (null_req) { code.Methods(false) << " request.Set" << Identifier(name) << "();\n"; } else { code.Methods(false) << " request.Set" << Identifier(name) << "(const_cast<" << req_class << "&>(req));\n"; } code.Methods(false) << " if ( !reply ) {\n" << " reply = &reply0;\n" << " }\n" << " Ask(request, *reply, TReplyChoice::e_" << Identifier(reply) << ");\n"; if (null_rep) { code.Methods(false) << "}\n\n"; } else if (use_cref) { code.Methods(false) << " return " << rep_class << "(&x_Choice(*reply).Set" << Identifier(reply) << "());\n" << "}\n\n"; } else { code.Methods(false) << " return x_Choice(*reply).Get" << Identifier(reply) << "();\n" << "}\n\n"; } }}END_NCBI_SCOPE/** ===========================================================================** $Log: rpcgen.cpp,v $* Revision 1000.3 2004/06/01 19:43:40 gouriano* PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13** Revision 1.13 2004/05/17 21:03:14 gorelenk* Added include of PCH ncbi_pch.hpp** Revision 1.12 2004/03/25 21:57:13 ucko* Allow request and reply elements to have anonymous (internal) types.** Revision 1.11 2004/02/09 15:10:55 ucko* Make sure to qualify CRef with ncbi:: if necessary.** Revision 1.10 2003/11/20 15:40:53 ucko* Update for new (saner) treatment of ASN.1 NULLs.** Revision 1.9 2003/10/21 13:48:51 grichenk* Redesigned type aliases in serialization library.* Fixed the code (removed CRef-s, added explicit* initializers etc.)** Revision 1.8 2003/04/08 20:40:08 ucko* Get client name(s) from [-]clients rather than hardcoding "client"** Revision 1.7 2003/04/04 19:34:25 ucko* Let request and reply be deeply nested subelements.* Make s_* actually static. (Oops.)** Revision 1.6 2003/03/11 20:06:47 kuznets* iterate -> ITERATE** Revision 1.5 2003/03/10 18:55:19 gouriano* use new structured exceptions (based on CException)** Revision 1.4 2002/11/18 19:48:46 grichenk* Removed "const" from datatool-generated setters** Revision 1.3 2002/11/14 16:36:54 ucko* Rework generated code, rolling x_CheckReply into (an overloaded* version of) Ask for increased flexibility.** Revision 1.2 2002/11/13 19:55:11 ucko* Distinguish between named and anonymous types rather than between* heterogeneous containers and everything else -- fixes handling of aliases.** Revision 1.1 2002/11/13 00:46:08 ucko* Add RPC client generator; CVS logs to end in generate.?pp*** ===========================================================================*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -