📄 rpcgen.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: rpcgen.cpp,v $ * PRODUCTION Revision 1000.3 2004/06/01 19:43:40 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13 * PRODUCTION * =========================================================================== *//* $Id: rpcgen.cpp,v 1000.3 2004/06/01 19:43:40 gouriano Exp $* ===========================================================================** PUBLIC DOMAIN NOTICE* National Center for Biotechnology Information** This software/database is a "United States Government Work" under the* terms of the United States Copyright Act. It was written as part of* the author's official duties as a United States Government employee and* thus cannot be copyrighted. This software/database is freely available* to the public for use. The National Library of Medicine and the U.S.* Government have not placed any restriction on its use or reproduction.** Although all reasonable efforts have been taken to ensure the accuracy* and reliability of the software and data, the NLM and the U.S.* Government do not and cannot warrant the performance or results that* may be obtained by using this software or data. The NLM and the U.S.* Government disclaim all warranties, express or implied, including* warranties of performance, merchantability or fitness for any particular* purpose.** Please cite the author in any work or product based on this material.** ===========================================================================** Author: Aaron Ucko, NCBI** File Description:* ASN.1/XML RPC client generator** ===========================================================================*/#include <ncbi_pch.hpp>#include <serial/datatool/exceptions.hpp>#include <serial/datatool/rpcgen.hpp>#include <serial/datatool/choicetype.hpp>#include <serial/datatool/classstr.hpp>#include <serial/datatool/code.hpp>#include <serial/datatool/generate.hpp>#include <serial/datatool/srcutil.hpp>#include <serial/datatool/statictype.hpp>#include <serial/datatool/stdstr.hpp>BEGIN_NCBI_SCOPE// Does all the actual workclass CClientPseudoTypeStrings : public CClassTypeStrings{public: CClientPseudoTypeStrings(const CClientPseudoDataType& source); void GenerateClassCode(CClassCode& code, CNcbiOstream& getters, const string& methodPrefix, bool haveUserClass, const string& classPrefix) const;private: const CClientPseudoDataType& m_Source;};static void s_SplitName(const string& name, string& type, string& field){ for (SIZE_TYPE pos = name.find('.'); pos != NPOS; pos = name.find('.', pos + 1)) { if (islower(name[pos + 1])) { type.assign(name, 0, pos); field.assign(name, pos + 1, NPOS); return; } } type.assign(name); field.erase();}static const CChoiceDataType* s_ChoiceType(const CDataType* dtype, const string& element){ vector<string> v; if ( !element.empty() ) { NStr::Tokenize(element, ".", v); } ITERATE (vector<string>, subelement, v) { const CDataMemberContainerType* dct = dynamic_cast<const CDataMemberContainerType*>(dtype); if ( !dct ) { NCBI_THROW(CDatatoolException, eInvalidData, dtype->GlobalName() + " is not a container type"); } bool found = false; ITERATE (CDataMemberContainerType::TMembers, it, dct->GetMembers()) { if ((*it)->GetName() == *subelement) { found = true; dtype = (*it)->GetType()->Resolve(); break; } } if (!found) { NCBI_THROW(CDatatoolException, eInvalidData, dtype->GlobalName() + " has no element " + *subelement); } } const CChoiceDataType* choicetype = dynamic_cast<const CChoiceDataType*>(dtype); if ( !choicetype ) { NCBI_THROW(CDatatoolException, eInvalidData, dtype->GlobalName() + " is not a choice type"); } return choicetype;}static string s_SetterName(const string& element) { if (element.empty()) { return kEmptyStr; } SIZE_TYPE start = 0, dot; string result; do { dot = element.find('.', start); result += ".Set" + Identifier(element.substr(start, dot - start)) + "()"; start = dot + 1; } while (dot != NPOS); return result;}CClientPseudoDataType::CClientPseudoDataType(const CCodeGenerator& generator, const string& section_name, const string& class_name) : m_Generator(generator), m_SectionName(section_name), m_ClassName(class_name){ // Just take the first potential module; should normally give sane // results. SetParent(generator.GetMainModules().GetModuleSets().front() ->GetModules().front().get(), class_name); s_SplitName(generator.GetConfig().Get(m_SectionName, "request"), m_RequestType, m_RequestElement); s_SplitName(generator.GetConfig().Get(m_SectionName, "reply"), m_ReplyType, m_ReplyElement); if (m_RequestType.empty()) { NCBI_THROW(CDatatoolException, eInvalidData, "No request type supplied for " + m_ClassName); } else if (m_ReplyType.empty()) { NCBI_THROW(CDatatoolException, eInvalidData, "No reply type supplied for " + m_ClassName); } m_RequestDataType = m_Generator.ResolveMain(m_RequestType); m_ReplyDataType = m_Generator.ResolveMain(m_ReplyType); _ASSERT(m_RequestDataType && m_ReplyDataType); m_RequestChoiceType = s_ChoiceType(m_RequestDataType, m_RequestElement); m_ReplyChoiceType = s_ChoiceType(m_ReplyDataType, m_ReplyElement);}AutoPtr<CTypeStrings>CClientPseudoDataType::GenerateCode(void) const{ return new CClientPseudoTypeStrings(*this);}CClientPseudoTypeStrings::CClientPseudoTypeStrings(const CClientPseudoDataType& source) : CClassTypeStrings(kEmptyStr, source.m_ClassName), m_Source(source){ // SetClassNamespace(generator.GetNamespace()); // not defined(!) SetParentClass("CRPCClient<" + source.m_RequestDataType->ClassName() + ", " + source.m_ReplyDataType->ClassName() + '>', CNamespace::KNCBINamespace, "serial/rpcbase"); SetObject(true); SetHaveUserClass(true); SetHaveTypeInfo(false);}static string s_QualClassName(const CDataType* dt){ _ASSERT(dt); string result; const CDataType* parent = dt->GetParentType(); if (parent) { result = s_QualClassName(parent) + "::"; } result += dt->ClassName(); return result;}void CClientPseudoTypeStrings::GenerateClassCode(CClassCode& code, CNcbiOstream& /* getters */, const string& /* methodPfx */, bool /* haveUserClass */, const string& /* classPfx */) const{ const string& sect_name = m_Source.m_SectionName; const string& class_name = m_Source.m_ClassName; string class_base = class_name + "_Base"; const CCodeGenerator& generator = m_Source.m_Generator; string treq = class_base + "::TRequest"; string trep = class_base + "::TReply"; const CNamespace& ns = code.GetNamespace(); // Pull in the relevant headers, and add corresponding typedefs code.HPPIncludes().insert(m_Source.m_RequestDataType->FileName()); code.ClassPublic() << " typedef " << m_Source.m_RequestDataType->ClassName() << " TRequest;\n"; code.HPPIncludes().insert(m_Source.m_ReplyDataType->FileName()); code.ClassPublic() << " typedef " << m_Source.m_ReplyDataType->ClassName() << " TReply;\n"; if ( !m_Source.m_RequestElement.empty() ) { code.HPPIncludes().insert(m_Source.m_RequestChoiceType->FileName()); code.ClassPublic() << " typedef " << s_QualClassName(m_Source.m_RequestChoiceType) << " TRequestChoice;\n"; code.ClassPrivate() << " TRequest m_DefaultRequest;\n\n"; } else { code.ClassPublic() << " typedef TRequest TRequestChoice;\n"; } {{ if ( !m_Source.m_ReplyElement.empty() ) { code.HPPIncludes().insert(m_Source.m_ReplyChoiceType->FileName()); code.ClassPublic() << " typedef " << s_QualClassName(m_Source.m_ReplyChoiceType) << " TReplyChoice;\n\n"; } else { code.ClassPublic() << " typedef TReply TReplyChoice;\n\n"; } code.ClassPrivate() << " TReplyChoice& x_Choice(TReply& reply);\n"; code.MethodStart(true) << trep << "Choice& " << class_base << "::x_Choice(" << trep << "& reply)\n" << "{\n return reply" << s_SetterName(m_Source.m_ReplyElement) << ";\n}\n\n"; }} {{ // Figure out arguments to parent's constructor string service = generator.GetConfig().Get(sect_name, "service"); string format = generator.GetConfig().Get(sect_name, "serialformat"); string args; if (service.empty()) { ERR_POST(Warning << "No service name provided for " << class_name); args = "kEmptyStr"; } else { args = '\"' + NStr::PrintableString(service) + '\"'; } if ( !format.empty() ) { args += ", eSerial_" + format; } code.AddInitializer("Tparent", args); }} // This should just be a simple using-declaration, but that breaks // on GCC 2.9x at least, even with a full parent class name :-/ code.ClassPublic() // << " using Tparent::Ask;\n" << " virtual void Ask(const TRequest& request, TReply& reply);\n" << " virtual void Ask(const TRequest& request, TReply& reply,\n" << " TReplyChoice::E_Choice wanted);\n\n"; // second version defined further down code.MethodStart(true) << "void " << class_base << "::Ask(const " << treq << "& request, " << trep << "& reply)\n" << "{\n Tparent::Ask(request, reply);\n}\n\n\n"; // Add appropriate infrastructure if TRequest is not itself the choice // (m_DefaultRequest declared earlier to reduce ugliness) if ( !m_Source.m_RequestElement.empty() ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -