mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-10-02 23:08:31 +00:00
4910 lines
139 KiB
C++
4910 lines
139 KiB
C++
|
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||
|
// Copyright (C) 2010 Winch Gate Property Limited
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Affero General Public License as
|
||
|
// published by the Free Software Foundation, either version 3 of the
|
||
|
// License, or (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU Affero General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Affero General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
|
||
|
#include "parser.h"
|
||
|
#include "cpp_output.h"
|
||
|
#include "templatizer.h"
|
||
|
|
||
|
#include "parser_rules.h"
|
||
|
|
||
|
#include <nel/misc/path.h>
|
||
|
#include <nel/misc/sha1.h>
|
||
|
|
||
|
using namespace std;
|
||
|
using namespace NLMISC;
|
||
|
//using namespace RY_PDS;
|
||
|
|
||
|
|
||
|
bool GenerateCpp = true;
|
||
|
bool GenerateXmlDescription = true;
|
||
|
bool VerboseMode = false;
|
||
|
bool GenerateDebugMessages = false;
|
||
|
bool GenerateHAuto = false;
|
||
|
bool GenerateOnlyLogs = false;
|
||
|
|
||
|
|
||
|
CTokenizer Tokenizer;
|
||
|
CTemplatizer Templatizer;
|
||
|
CHashKey HashKey;
|
||
|
|
||
|
string CurrentEnum;
|
||
|
CEnumNode *CurrentEnumNode = NULL;
|
||
|
|
||
|
string DbDescriptionVersion("0.0");
|
||
|
|
||
|
string formatDescription(const string &str)
|
||
|
{
|
||
|
string result;
|
||
|
|
||
|
uint pos = 0;
|
||
|
|
||
|
while (pos < str.size() && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\r' || str[pos] == '\n'))
|
||
|
++pos;
|
||
|
|
||
|
bool first = true;
|
||
|
|
||
|
while (pos < str.size())
|
||
|
{
|
||
|
if (!first)
|
||
|
result += "\n";
|
||
|
first = false;
|
||
|
|
||
|
result += "* ";
|
||
|
|
||
|
while (pos < str.size() && str[pos] != '\n')
|
||
|
result += str[pos++];
|
||
|
|
||
|
while (pos < str.size() && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\r' || str[pos] == '\n'))
|
||
|
++pos;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
string strReplace(string str, const string &search, const string &replace)
|
||
|
{
|
||
|
std::string::size_type pos = 0;
|
||
|
while ((pos = str.find(search)) != string::npos)
|
||
|
str.replace(pos, search.size(), replace);
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
string xmlSpecialChars(string str)
|
||
|
{
|
||
|
str = strReplace(str, "&", "&");
|
||
|
str = strReplace(str, "<", "<");
|
||
|
str = strReplace(str, ">", ">");
|
||
|
str = strReplace(str, "\"", """);
|
||
|
str = strReplace(str, "'", "'");
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
string getFullStdPathNoExt(const string &path)
|
||
|
{
|
||
|
string dir = NLMISC::toLower(NLMISC::CFile::getPath(path));
|
||
|
string file = NLMISC::toLower(NLMISC::CFile::getFilenameWithoutExtension(path));
|
||
|
|
||
|
return dir.empty() ? file : NLMISC::CPath::standardizePath(dir)+file;
|
||
|
}
|
||
|
|
||
|
string getFullStdPath(const string &path)
|
||
|
{
|
||
|
string dir = NLMISC::toLower(NLMISC::CFile::getPath(path));
|
||
|
string file = NLMISC::toLower(NLMISC::CFile::getFilename(path));
|
||
|
|
||
|
return dir.empty() ? file : NLMISC::CPath::standardizePath(dir)+file;
|
||
|
}
|
||
|
|
||
|
string appendArg(const std::string& firstArgs, const std::string& nextArg)
|
||
|
{
|
||
|
if (firstArgs.empty())
|
||
|
return nextArg;
|
||
|
return firstArgs + ", " + nextArg;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Start parsing
|
||
|
*/
|
||
|
CParseNode *parse(const string &file)
|
||
|
{
|
||
|
HashKey = getSHA1(file);
|
||
|
|
||
|
Tokenizer.readFile(file);
|
||
|
|
||
|
if (Tokenizer.tokenize())
|
||
|
return parseMain(Tokenizer);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Execute nodes
|
||
|
*/
|
||
|
|
||
|
// DB Node
|
||
|
bool CDbNode::prolog()
|
||
|
{
|
||
|
addTypeNode("CSheetId", "NLMISC::CSheetId", "NLMISC::CSheetId::Unknown");
|
||
|
addTypeNode("CEntityId", "NLMISC::CEntityId", "NLMISC::CEntityId::Unknown");
|
||
|
addTypeNode("double", "double", "0.0");
|
||
|
addTypeNode("float", "float", "0.0f");
|
||
|
addTypeNode("sint64", "sint64", "(sint64)0");
|
||
|
addTypeNode("uint64", "uint64", "(uint64)0");
|
||
|
addTypeNode("sint32", "sint32", "0");
|
||
|
addTypeNode("uint32", "uint32", "0");
|
||
|
addTypeNode("sint16", "sint16", "0");
|
||
|
addTypeNode("uint16", "uint16", "0");
|
||
|
addTypeNode("sint8", "sint8", "0");
|
||
|
addTypeNode("uint8", "uint8", "0");
|
||
|
addTypeNode("ucchar", "ucchar", "0");
|
||
|
addTypeNode("char", "char", "0");
|
||
|
addTypeNode("bool", "bool", "false");
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
bool inlineAccessors = false;
|
||
|
string getFunctionPrefix = "get";
|
||
|
string setFunctionPrefix = "set";
|
||
|
string newFunction = "addTo";
|
||
|
string deleteFunction = "deleteFrom";
|
||
|
|
||
|
string indexVariable = "__i";
|
||
|
string valueVariable = "__v";
|
||
|
string keyVariable = "__k";
|
||
|
string objectVariable = "__o";
|
||
|
|
||
|
bool inlineUserInitDefaultCode = false;
|
||
|
string userInitFunction = "init";
|
||
|
string userReleaseFunction = "release";
|
||
|
|
||
|
bool inlineStaticPublic = false;
|
||
|
string staticCreateFunction = "create";
|
||
|
string staticRemoveFunction = "remove";
|
||
|
string staticSetUserFactoryFunction = "setFactory";
|
||
|
string staticLoadFunction = "load";
|
||
|
string staticUnloadFunction = "unload";
|
||
|
string staticSetLoadCbFunction = "setLoadCallback";
|
||
|
string staticGetFunction = "get";
|
||
|
string staticCastFunction = "cast";
|
||
|
string staticConstCastFunction = "cast";
|
||
|
string staticBeginFunction = "begin";
|
||
|
string staticEndFunction = "end";
|
||
|
|
||
|
bool inlineInternal = false;
|
||
|
string initFunction = "pds__init";
|
||
|
string destroyFunction = "pds__destroy";
|
||
|
string registerFunction = "pds__register";
|
||
|
string registerAttributesFunction = "pds__registerAttributes";
|
||
|
string unregisterFunction = "pds__unregister";
|
||
|
string unregisterAttributesFunction = "pds__unregisterAttributes";
|
||
|
string fetchFunction = "pds__fetch";
|
||
|
string setParentFunction = "pds__setParent";
|
||
|
string setUnnotifiedParentFunction = "pds__setParentUnnotified";
|
||
|
string getTableFunction = "pds__getTable";
|
||
|
string unlinkFunction = "pds__unlink";
|
||
|
string notifyInitFunction = "pds__notifyInit";
|
||
|
string notifyReleaseFunction = "pds__notifyRelease";
|
||
|
|
||
|
string clearFunction = "clear";
|
||
|
string storeFunction = "store";
|
||
|
string applyFunction = "apply";
|
||
|
string declareTokensFunction = "pds__declareTokens";
|
||
|
|
||
|
|
||
|
bool inlineStaticInternal = false;
|
||
|
string staticInitFactoryFunction = "pds_static__setFactory";
|
||
|
string staticFactoryFunction = "pds_static__factory";
|
||
|
string staticFetchFunction = "pds_static__fetch";
|
||
|
string staticInitFunction = "pds_static__init";
|
||
|
string staticNotifyLoadFailure = "pds_static__notifyFailure";
|
||
|
string staticLoadCbAttribute = "__pds__LoadCallback";
|
||
|
|
||
|
bool inlineLog = false;
|
||
|
string logStartFunction = "pds__startLog";
|
||
|
string logStopFunction = "pds__stopLog";
|
||
|
|
||
|
string PDSNamespace = "RY_PDS";
|
||
|
string CPDSLibName = PDSNamespace+"::CPDSLib";
|
||
|
string objectIndexName = PDSNamespace+"::CObjectIndex";
|
||
|
string nullIndexName = PDSNamespace+"::CObjectIndex::null()";
|
||
|
string TTableIndexName = PDSNamespace+"::TTableIndex";
|
||
|
string TRowIndexName = PDSNamespace+"::TRowIndex";
|
||
|
string TColumnIndexName = PDSNamespace+"::TColumnIndex";
|
||
|
string INVALID_TABLE_INDEXName = PDSNamespace+"::INVALID_TABLE_INDEX";
|
||
|
string INVALID_ROW_INDEXName = PDSNamespace+"::INVALID_ROW_INDEX";
|
||
|
string indexAllocatorName = PDSNamespace+"::CIndexAllocator";
|
||
|
string pdBaseDataName = PDSNamespace+"::IPDBaseData";
|
||
|
//string pdBaseInheritDataName = PDSNamespace+"::IPDBaseInheritData";
|
||
|
string CPDataName = PDSNamespace+"::CPData";
|
||
|
string TPDFactoryName = PDSNamespace+"::TPDFactory";
|
||
|
string TPDFetchName = PDSNamespace+"::TPDFetch";
|
||
|
string TPDFetchFailureName = PDSNamespace+"::TPDFetchFailure";
|
||
|
|
||
|
bool inlineLogFunctions = false;
|
||
|
|
||
|
string pdslibFunc(const std::string& func)
|
||
|
{
|
||
|
//return CPDSLibName+"::"+func;
|
||
|
return "PDSLib."+func;
|
||
|
}
|
||
|
|
||
|
bool CDbNode::epilog()
|
||
|
{
|
||
|
uint i;
|
||
|
|
||
|
Env = Templatizer.RootEnv;
|
||
|
setEnv("db", Name);
|
||
|
|
||
|
string fullfile = getFullStdPathNoExt(MainFile.empty() ? Name : MainFile);
|
||
|
string filename = NLMISC::toLower(NLMISC::CFile::getFilenameWithoutExtension(fullfile));
|
||
|
|
||
|
setEnv("filename", filename);
|
||
|
setEnv("fullfilename", fullfile);
|
||
|
setEnv("headerfilename", strReplace(strupr(filename+".h"), ".", "_"));
|
||
|
|
||
|
DbHpp.setFileHeader(filename+".h", "Initialisation of the "+Name+" database, declarations\n"+Description);
|
||
|
DbCpp.setFileHeader(filename+".cpp", "Initialisation of the "+Name+" database, implementation\n"+Description);
|
||
|
DbHppInline.setFileHeader(filename+"_inline.h", "Initialisation of the "+Name+" database, inline implementation\n"+Description);
|
||
|
|
||
|
DbSummary << "\n\n";
|
||
|
DbSummary << "Summary of " << Name << " database classes of database\n";
|
||
|
DbSummary << "-----------------------------------------------------------------------------\n\n";
|
||
|
DbSummary << "This file is automatically generated.\n";
|
||
|
DbSummary << "This is a reminder of all classes generated and methods implemented.\n\n\n";
|
||
|
|
||
|
DbSummary << "Database " << Name << " is managed through 4 functions located in " << fullfile << ".h:\n\n";
|
||
|
|
||
|
DbSummary << Name << "::init():\n";
|
||
|
DbSummary << "Initialises database context and connection towards database server (refered as PDS).\n";
|
||
|
DbSummary << "All user factories must have been set before call to this function.\n";
|
||
|
DbSummary << "Call this function in service init method.\n\n";
|
||
|
|
||
|
DbSummary << Name << "::ready():\n";
|
||
|
DbSummary << "Tells whether the whole database engine is ready to work.\n";
|
||
|
DbSummary << "You must not update any value nor call update() unless ready() is true.\n\n";
|
||
|
|
||
|
DbSummary << Name << "::update():\n";
|
||
|
DbSummary << "Updates the database engine and sends updates to the PDS.\n";
|
||
|
DbSummary << "Call this function each tick, provided ready() returned true.\n\n";
|
||
|
|
||
|
DbSummary << Name << "::release():\n";
|
||
|
DbSummary << "Releases the database engine. Drops all data, closes the connection to the PDS.\n";
|
||
|
DbSummary << "Call this function in service release method.\n\n";
|
||
|
|
||
|
DbSummary << "\n\n";
|
||
|
DbSummary << "Summary of generated classes for " << Name << "\n\n";
|
||
|
|
||
|
DbHpp << "\n#ifndef " << strReplace(strupr(filename+".h"), ".", "_") << "\n";
|
||
|
DbHpp << "#define " << strReplace(strupr(filename+".h"), ".", "_") << "\n";
|
||
|
DbHpp << "\n";
|
||
|
DbHpp << "#include <nel/misc/types_nl.h>\n";
|
||
|
DbHpp << "#include <pd_lib/pd_lib.h>\n";
|
||
|
DbHpp << "\n";
|
||
|
DbHpp << "namespace " << Name << "\n{\n\n";
|
||
|
DbHpp.unindent();
|
||
|
|
||
|
if (!Pch.empty())
|
||
|
{
|
||
|
DbCpp << "\n#include \"" << Pch << "\"\n\n";
|
||
|
}
|
||
|
|
||
|
DbCpp << "#include \"" << filename << ".h\"\n\n";
|
||
|
DbCpp << "namespace " << Name << "\n{\n\n";
|
||
|
DbCpp.unindent();
|
||
|
|
||
|
DbCpp << "RY_PDS::CPDSLib PDSLib;\n";
|
||
|
|
||
|
DbHppInline << "namespace " << Name << "\n{\n\n";
|
||
|
DbHppInline.unindent();
|
||
|
|
||
|
|
||
|
uint maxClassId = 0;
|
||
|
for (i=0; i<ClassNodes.size(); ++i)
|
||
|
{
|
||
|
CClassNode *classnd = ClassNodes[i];
|
||
|
++maxClassId;
|
||
|
}
|
||
|
|
||
|
uint maxTypeId = 0;
|
||
|
for (i=0; i<TypeNodes.size(); ++i)
|
||
|
{
|
||
|
CTypeNode *typend = TypeNodes[i];
|
||
|
++maxTypeId;
|
||
|
}
|
||
|
|
||
|
xmlDescription.clear();
|
||
|
xmlDescription.push_back("<?xml version='1.0'?>");
|
||
|
xmlDescription.push_back("<dbdescription version='"+DbDescriptionVersion+"'>");
|
||
|
//xmlDescription.push_back("<db name='"+Name+"' types='"+toString(maxTypeId)+"' classes='"+toString(maxClassId)+"' hashkey='"+HashKey.toString()+"'>");
|
||
|
xmlDescription.push_back("<db name='"+Name+"' types='"+toString(maxTypeId)+"' classes='"+toString(maxClassId)+"'>");
|
||
|
|
||
|
pass1();
|
||
|
|
||
|
pass2();
|
||
|
|
||
|
pass3();
|
||
|
|
||
|
// Check dependencies order
|
||
|
vector<CClassNode*> classesOrder;
|
||
|
vector<CFileNode*> filesOrder;
|
||
|
buildClassOrder(classesOrder, filesOrder);
|
||
|
|
||
|
// generate all file prologs
|
||
|
for (i=0; i<FileNodes.size(); ++i)
|
||
|
{
|
||
|
CFileNode *child = FileNodes[i];
|
||
|
child->generateProlog();
|
||
|
}
|
||
|
|
||
|
pass4();
|
||
|
|
||
|
//
|
||
|
initDb.init("init");
|
||
|
initDb.IsInline = false;
|
||
|
initDb.Proto = "uint32 overrideDbId";
|
||
|
initDb.Type = "void";
|
||
|
initDb.Description = "Initialise the whole database engine.\nCall this function at service init.";
|
||
|
|
||
|
readyDb.init("ready");
|
||
|
readyDb.IsInline = false;
|
||
|
readyDb.Proto = "";
|
||
|
readyDb.Type = "bool";
|
||
|
readyDb.Description = "Tells if database engine is ready to work.\nEngine may not be ready because PDS is down, not yet ready\nor message queue to PDS is full.";
|
||
|
|
||
|
updateDb.init("update");
|
||
|
updateDb.IsInline = false;
|
||
|
updateDb.Proto = "";
|
||
|
updateDb.Type = "void";
|
||
|
updateDb.Description = "Update the database engine.\nCall this method once per tick, only if engine is ready (see also ready() above).";
|
||
|
|
||
|
logChatDb.init("logChat");
|
||
|
logChatDb.IsInline = false;
|
||
|
logChatDb.Proto = "const ucstring& sentence, const NLMISC::CEntityId& from, const std::vector<NLMISC::CEntityId>& to";
|
||
|
logChatDb.Type = "void";
|
||
|
logChatDb.Description = "Logs chat sentence with sender and receipiants.";
|
||
|
|
||
|
logTellDb.init("logTell");
|
||
|
logTellDb.IsInline = false;
|
||
|
logTellDb.Proto = "const ucstring& sentence, const NLMISC::CEntityId& from, const NLMISC::CEntityId& to";
|
||
|
logTellDb.Type = "void";
|
||
|
logTellDb.Description = "Logs tell sentence with sender and single recipient (might be player or group).";
|
||
|
|
||
|
releaseDb.init("release");
|
||
|
releaseDb.IsInline = false;
|
||
|
releaseDb.Proto = "";
|
||
|
releaseDb.Type = "void";
|
||
|
releaseDb.Description = "Release the whole database engine.\nCall this function at service release.";
|
||
|
|
||
|
//
|
||
|
generateClassesDeclaration();
|
||
|
|
||
|
//
|
||
|
generateClassesContent(classesOrder);
|
||
|
|
||
|
//
|
||
|
generateLogContent();
|
||
|
|
||
|
xmlDescription.push_back("</db>");
|
||
|
xmlDescription.push_back("</dbdescription>");;
|
||
|
|
||
|
initDb.add("std::string\txmlDescription;");
|
||
|
|
||
|
DbXml.setXmlMode();
|
||
|
|
||
|
for (i=0; i<xmlDescription.size(); ++i)
|
||
|
{
|
||
|
initDb.add("xmlDescription += \""+xmlDescription[i]+"\\n\";");
|
||
|
DbXml << xmlDescription[i] << "\n";
|
||
|
}
|
||
|
|
||
|
DbXml.flush(fullfile+".xml");
|
||
|
|
||
|
DbHpp << "/// \\name Public API for " << Name << " database\n";
|
||
|
DbHpp << "// @{\n";
|
||
|
DbHpp.unindent();
|
||
|
|
||
|
initDb.add(pdslibFunc("init")+"(xmlDescription, overrideDbId);");
|
||
|
initDb.flush(DbHpp, DbCpp, DbHppInline);
|
||
|
|
||
|
readyDb.add("return "+pdslibFunc("PDSReady")+"();");
|
||
|
readyDb.flush(DbHpp, DbCpp, DbHppInline);
|
||
|
|
||
|
updateDb.add(pdslibFunc("update")+"();");
|
||
|
updateDb.flush(DbHpp, DbCpp, DbHppInline);
|
||
|
|
||
|
logChatDb.add(pdslibFunc("logChat")+"(sentence, from, to);");
|
||
|
logChatDb.flush(DbHpp, DbCpp, DbHppInline);
|
||
|
|
||
|
logTellDb.add("std::vector<NLMISC::CEntityId>\tids;");
|
||
|
logTellDb.add("ids.push_back(to);");
|
||
|
logTellDb.add(pdslibFunc("logChat")+"(sentence, from, ids);");
|
||
|
logTellDb.flush(DbHpp, DbCpp, DbHppInline);
|
||
|
|
||
|
releaseDb.add(pdslibFunc("release")+"();");
|
||
|
releaseDb.flush(DbHpp, DbCpp, DbHppInline);
|
||
|
|
||
|
DbHpp << "\n// @}\n\n";
|
||
|
|
||
|
DbHpp << "extern RY_PDS::CPDSLib PDSLib;\n";
|
||
|
|
||
|
DbHpp.indent();
|
||
|
DbHpp << "\n} // End of " << Name <<"\n";
|
||
|
|
||
|
generateIncludes(filesOrder);
|
||
|
|
||
|
DbHpp << "\n#include \"" << filename << "_inline.h\"\n\n";
|
||
|
DbHpp << "\n#endif\n";
|
||
|
DbHpp.flush(fullfile+".h");
|
||
|
|
||
|
DbCpp.indent();
|
||
|
DbCpp << "\n} // End of " << Name <<"\n";
|
||
|
DbCpp.flush(fullfile+".cpp");
|
||
|
|
||
|
DbHppInline.indent();
|
||
|
DbHppInline << "\n} // End of " << Name <<"\n";
|
||
|
DbHppInline.flush(fullfile+"_inline.h");
|
||
|
|
||
|
DbSummary.flush(fullfile+"_summary.txt");
|
||
|
|
||
|
for (i=0; i<FileNodes.size(); ++i)
|
||
|
{
|
||
|
CFileNode *child = FileNodes[i];
|
||
|
child->generateEpilog();
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void CDbNode::pass1()
|
||
|
{
|
||
|
/*
|
||
|
* PASS 1
|
||
|
* - all type names and class names are known
|
||
|
* -> look for classes in set or backreferences
|
||
|
*/
|
||
|
|
||
|
uint i;
|
||
|
|
||
|
uint classId = 0;
|
||
|
uint typeId = 0;
|
||
|
|
||
|
for (i=0; i<ClassNodes.size(); ++i)
|
||
|
{
|
||
|
CClassNode *classnd = ClassNodes[i];
|
||
|
classnd->checkClassReferences();
|
||
|
classnd->Id = classId++;
|
||
|
|
||
|
classnd->getFileNode()->IncludeStandard = true;
|
||
|
classnd->getFileNode()->IncludeDbFile = true;
|
||
|
}
|
||
|
|
||
|
for (i=0; i<TypeNodes.size(); ++i)
|
||
|
{
|
||
|
CTypeNode *typend = TypeNodes[i];
|
||
|
|
||
|
typend->Id = typeId++;
|
||
|
|
||
|
uint tsize = 0;
|
||
|
if (typend->StorageType == "bool") tsize = 1;
|
||
|
if (typend->StorageType == "char") tsize = 1;
|
||
|
if (typend->StorageType == "ucchar") tsize = 2;
|
||
|
if (typend->StorageType == "uint8") tsize = 1;
|
||
|
if (typend->StorageType == "sint8") tsize = 1;
|
||
|
if (typend->StorageType == "uint16") tsize = 2;
|
||
|
if (typend->StorageType == "sint16") tsize = 2;
|
||
|
if (typend->StorageType == "uint32") tsize = 4;
|
||
|
if (typend->StorageType == "sint32") tsize = 4;
|
||
|
if (typend->StorageType == "uint64") tsize = 8;
|
||
|
if (typend->StorageType == "sint64") tsize = 8;
|
||
|
if (typend->StorageType == "float") tsize = 4;
|
||
|
if (typend->StorageType == "double") tsize = 8;
|
||
|
if (typend->StorageType == "CEntityId") tsize = 8;
|
||
|
if (typend->StorageType == "CSheetId") tsize = 4;
|
||
|
|
||
|
typend->Size = tsize;
|
||
|
|
||
|
string xmlnode = "<typedef name='"+typend->Name+"' id='"+toString(typend->Id)+"' size='"+toString(tsize)+"' storage='"+typend->StorageType+"'";
|
||
|
|
||
|
if (typend->isEnum())
|
||
|
{
|
||
|
CEnumNode *enumnd = static_cast<CEnumNode*>(typend);
|
||
|
|
||
|
xmlnode += " type='enum'>";
|
||
|
xmlDescription.push_back(xmlnode);
|
||
|
uint j;
|
||
|
for (j=0; j<enumnd->Values.size(); ++j)
|
||
|
xmlDescription.push_back("<enumvalue name='"+enumnd->Values[j].first+"' value='"+toString(enumnd->Values[j].second)+"'/>");
|
||
|
xmlDescription.push_back("</typedef>");
|
||
|
}
|
||
|
else if (typend->isDimension())
|
||
|
{
|
||
|
CDimensionNode *dimnd = static_cast<CDimensionNode*>(typend);
|
||
|
|
||
|
xmlnode += " type='dimension' dimension='"+toString(dimnd->Dimension)+"'/>";
|
||
|
xmlDescription.push_back(xmlnode);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
xmlnode += " type='type'/>";
|
||
|
xmlDescription.push_back(xmlnode);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CDbNode::pass2()
|
||
|
{
|
||
|
/*
|
||
|
* PASS 2
|
||
|
* - class hierarchy, backreferences and in set information are known
|
||
|
* -> fill up attributes
|
||
|
*/
|
||
|
|
||
|
uint i;
|
||
|
|
||
|
for (i=0; i<ClassNodes.size(); ++i)
|
||
|
{
|
||
|
CClassNode *child = ClassNodes[i];
|
||
|
|
||
|
if (!child->Inherited.empty() && child->MappedFlag && !child->HasParent)
|
||
|
child->error("class cannot inherit another class and be mapped. Try to map base class instead.");
|
||
|
|
||
|
if (child->MappedFlag && child->getClassKey() == NULL)
|
||
|
child->error("class is mapped and has no key defined");
|
||
|
|
||
|
child->ForceReference = (child->HasInheritance || child->MappedFlag || child->DerivatedFlag || (child->HasParent && !child->ParentIsHidden));
|
||
|
|
||
|
if (child->ForceReference && child->ParentIsHidden)
|
||
|
child->error("Parent attribute cannot be hidden because class has inheritance, is mapped or is derivated.");
|
||
|
|
||
|
child->getFileNode()->IncludePDSLib = true;
|
||
|
|
||
|
if (!child->Inherited.empty())
|
||
|
{
|
||
|
CClassNode *icln = child;
|
||
|
CClassNode *lastMapped = (child->MappedFlag ? child : NULL);
|
||
|
while (!icln->Inherited.empty())
|
||
|
{
|
||
|
icln = getClassNode(icln->Inherited);
|
||
|
if (icln->MappedFlag)
|
||
|
{
|
||
|
if (lastMapped != NULL)
|
||
|
lastMapped->error("class cannot be remapped since parent "+icln->Name+" is already mapped");
|
||
|
lastMapped = icln;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
if (icln->MappedFlag)
|
||
|
child->MapClass = icln;
|
||
|
*/
|
||
|
child->MapClass = lastMapped;
|
||
|
}
|
||
|
else if (child->MappedFlag)
|
||
|
{
|
||
|
child->MapClass = child;
|
||
|
}
|
||
|
|
||
|
child->fillAttributes();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CDbNode::pass3()
|
||
|
{
|
||
|
/*
|
||
|
* PASS 3
|
||
|
* - attributes are known
|
||
|
* -> fill up backrefs and array/set forwardrefs
|
||
|
*/
|
||
|
|
||
|
uint i;
|
||
|
|
||
|
for (i=0; i<ClassNodes.size(); ++i)
|
||
|
{
|
||
|
CClassNode *child = ClassNodes[i];
|
||
|
child->fillRefs();
|
||
|
}
|
||
|
|
||
|
for (i=0; i<ClassNodes.size(); ++i)
|
||
|
{
|
||
|
CClassNode *child = ClassNodes[i];
|
||
|
child->computeFriends();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CDbNode::pass4()
|
||
|
{
|
||
|
/*
|
||
|
* PASS 4
|
||
|
* - everything is ok in database descriptor
|
||
|
* -> output c++ code
|
||
|
*/
|
||
|
|
||
|
uint i;
|
||
|
|
||
|
for (i=0; i<FileNodes.size(); ++i)
|
||
|
{
|
||
|
CFileNode* file = FileNodes[i];
|
||
|
file->Hpp << "\n\n//\n// Typedefs & Enums\n//\n\n";
|
||
|
}
|
||
|
|
||
|
for (i=0; i<TypeNodes.size(); ++i)
|
||
|
{
|
||
|
CTypeNode *type = TypeNodes[i];
|
||
|
if (type->ExternFlag || type->InternFlag)
|
||
|
continue;
|
||
|
|
||
|
type->generateContent();
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void CDbNode::generateClassesDeclaration()
|
||
|
{
|
||
|
uint i;
|
||
|
|
||
|
DbHpp << "\n//\n";
|
||
|
DbHpp << "// Global Forward Declarations\n";
|
||
|
DbHpp << "//\n\n";
|
||
|
|
||
|
for (i=0; i<ClassNodes.size(); ++i)
|
||
|
{
|
||
|
DbHpp << "class " << ClassNodes[i]->Name << ";\n";
|
||
|
}
|
||
|
|
||
|
DbHpp << "\n";
|
||
|
DbHpp << "//\n\n";
|
||
|
}
|
||
|
|
||
|
void CDbNode::generateIncludes(vector<CFileNode*>& filesOrder)
|
||
|
{
|
||
|
uint i;
|
||
|
|
||
|
DbHpp << "\n//\n";
|
||
|
DbHpp << "// Includes\n";
|
||
|
DbHpp << "//\n\n";
|
||
|
|
||
|
for (i=0; i<filesOrder.size(); ++i)
|
||
|
{
|
||
|
if (!filesOrder[i]->SeparatedFlag)
|
||
|
{
|
||
|
filesOrder[i]->setEnv("as", getFileNoExtPath(filesOrder[i]->IncludeAs));
|
||
|
DbHpp << "#include \"" << getFileNoExtPath(filesOrder[i]->IncludeAs) << ".h\"\n";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DbHpp << "\n";
|
||
|
|
||
|
for (i=0; i<filesOrder.size(); ++i)
|
||
|
{
|
||
|
if (filesOrder[i]->IncludeDbFile && !filesOrder[i]->SeparatedFlag)
|
||
|
{
|
||
|
filesOrder[i]->define("incinline");
|
||
|
DbHpp << "#include \"" << getFileNoExtPath(filesOrder[i]->IncludeAs) << "_inline.h\"\n";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DbHpp << "\n";
|
||
|
DbHpp << "//\n\n";
|
||
|
}
|
||
|
|
||
|
void CDbNode::generateClassesContent(vector<CClassNode*>& classesOrder)
|
||
|
{
|
||
|
uint i;
|
||
|
|
||
|
//
|
||
|
// output classes content
|
||
|
//
|
||
|
for (i=0; i<classesOrder.size(); ++i)
|
||
|
{
|
||
|
CClassNode *cln = classesOrder[i];
|
||
|
|
||
|
initDb.add(pdslibFunc("registerClassMapping")+"("+toString(cln->Id)+", \""+cln->Name+"\");");
|
||
|
cln->generateContent();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CDbNode::buildClassOrder(vector<CClassNode*>& classesOrder, vector<CFileNode*>& filesOrder)
|
||
|
{
|
||
|
set<CClassNode*> checkedClasses;
|
||
|
|
||
|
uint i;
|
||
|
|
||
|
for (i=0; i<ClassNodes.size(); ++i)
|
||
|
{
|
||
|
CClassNode *child = ClassNodes[i];
|
||
|
|
||
|
if (checkedClasses.find(child) != checkedClasses.end())
|
||
|
continue;
|
||
|
|
||
|
set<CClassNode*> beingChecked;
|
||
|
child->checkDependencies(beingChecked, checkedClasses, classesOrder);
|
||
|
}
|
||
|
|
||
|
set<CFileNode*> checkedFiles;
|
||
|
filesOrder.clear();
|
||
|
|
||
|
for (i=0; i<FileNodes.size(); ++i)
|
||
|
{
|
||
|
CFileNode *child = FileNodes[i];
|
||
|
|
||
|
if (checkedFiles.find(child) != checkedFiles.end())
|
||
|
continue;
|
||
|
|
||
|
set<CFileNode*> beingChecked;
|
||
|
child->checkDependencies(beingChecked, checkedFiles, filesOrder);
|
||
|
}
|
||
|
|
||
|
for (i=0; i<filesOrder.size(); ++i)
|
||
|
filesOrder[i]->Env = Env->nextArrayNode("files");
|
||
|
|
||
|
for (i=0; i<classesOrder.size(); ++i)
|
||
|
classesOrder[i]->Env = classesOrder[i]->getFileNode()->Env->nextArrayNode("classes");
|
||
|
}
|
||
|
|
||
|
|
||
|
void CDbNode::generateLogContent()
|
||
|
{
|
||
|
uint logid = 0;
|
||
|
|
||
|
uint i;
|
||
|
|
||
|
for (i=0; i<LogNodes.size(); ++i)
|
||
|
{
|
||
|
CLogMsgNode *child = LogNodes[i];
|
||
|
child->Id = logid;
|
||
|
logid += (uint)child->Logs.size();
|
||
|
|
||
|
child->generateContent();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// get file path from this file
|
||
|
string CDbNode::getFileNoExtPath(const std::string& file)
|
||
|
{
|
||
|
string thisPath = NLMISC::CFile::getPath(NLMISC::toLower(getDbFile()));
|
||
|
string filePath = NLMISC::CFile::getPath(NLMISC::toLower(file));
|
||
|
string fileName = NLMISC::CFile::getFilename(NLMISC::toLower(file));
|
||
|
|
||
|
if (thisPath == filePath)
|
||
|
return CFile::getFilenameWithoutExtension(fileName);
|
||
|
else
|
||
|
return CPath::standardizePath(filePath)+CFile::getFilenameWithoutExtension(NLMISC::toLower(file));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// File Node
|
||
|
bool CFileNode::prolog()
|
||
|
{
|
||
|
CDbNode* db = getDbNode();
|
||
|
db->FileNodes.push_back(this);
|
||
|
|
||
|
if (GenerateOnlyLogs)
|
||
|
Generate = false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CFileNode::epilog()
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CFileNode::generateProlog()
|
||
|
{
|
||
|
CDbNode* db = getDbNode();
|
||
|
|
||
|
if (!db->Description.empty())
|
||
|
Hpp << db->Description << "\n";
|
||
|
|
||
|
string filename = NLMISC::toLower(CFile::getFilenameWithoutExtension(Name));
|
||
|
|
||
|
setEnv("fullfilename", getFullStdPathNoExt(Name));
|
||
|
setEnv("filename", filename);
|
||
|
setEnv("headerfilename", strReplace(strupr(filename+".h"), ".", "_"));
|
||
|
setEnv("description", Description);
|
||
|
|
||
|
Hpp.setFileHeader(filename+".h", Description);
|
||
|
Cpp.setFileHeader(filename+".cpp", Description);
|
||
|
HppInline.setFileHeader(filename+"_inline.h", Description);
|
||
|
|
||
|
Hpp << "\n#ifndef " << strReplace(strupr(filename+".h"), ".", "_") << "\n";
|
||
|
Hpp << "#define " << strReplace(strupr(filename+".h"), ".", "_") << "\n\n";
|
||
|
|
||
|
|
||
|
Hpp << "#include <nel/misc/types_nl.h>\n";
|
||
|
Hpp << "#include <nel/misc/debug.h>\n";
|
||
|
Hpp << "#include <nel/misc/common.h>\n";
|
||
|
|
||
|
if (GenerateHAuto)
|
||
|
{
|
||
|
Hpp << "#include <nel/misc/hierarchical_timer.h>\n";
|
||
|
}
|
||
|
|
||
|
if (IncludeStandard)
|
||
|
{
|
||
|
define("incstd");
|
||
|
Hpp << "#include <nel/misc/entity_id.h>\n";
|
||
|
Hpp << "#include <nel/misc/sheet_id.h>\n";
|
||
|
}
|
||
|
|
||
|
Hpp << "#include <vector>\n";
|
||
|
Hpp << "#include <map>\n";
|
||
|
|
||
|
if (IncludePDSLib)
|
||
|
{
|
||
|
define("incpdslib");
|
||
|
Hpp << "#include <pd_lib/pd_lib.h>\n";
|
||
|
Hpp << "#include <game_share/persistent_data.h>\n";
|
||
|
}
|
||
|
Hpp << "\n";
|
||
|
|
||
|
if (SeparatedFlag)
|
||
|
{
|
||
|
string fullfile = getFullStdPathNoExt(db->MainFile.empty() ? db->Name : db->MainFile);
|
||
|
string filename = NLMISC::toLower(NLMISC::CFile::getFilenameWithoutExtension(fullfile));
|
||
|
Hpp << "#include \"" << filename << ".h\"\n";
|
||
|
Hpp << "\n";
|
||
|
}
|
||
|
|
||
|
Hpp << "// User #includes\n";
|
||
|
uint i;
|
||
|
for (i=0; i<IncludeNodes.size(); ++i)
|
||
|
{
|
||
|
Env->nextArrayNode("incuser")->set("as", IncludeNodes[i]->Name);
|
||
|
Hpp << "#include \"" << IncludeNodes[i]->Name << "\"\n";
|
||
|
}
|
||
|
|
||
|
Hpp << "\nnamespace " << db->Name << "\n{\n\n";
|
||
|
Hpp.unindent();
|
||
|
|
||
|
if (!db->Description.empty())
|
||
|
HppInline << db->Description;
|
||
|
HppInline << "namespace " << db->Name << "\n{\n\n";
|
||
|
HppInline.unindent();
|
||
|
Hpp << "//\n// Forward declarations\n//\n\n";
|
||
|
|
||
|
if (!db->Pch.empty())
|
||
|
{
|
||
|
Cpp << "\n";
|
||
|
Cpp << "#include \""+db->Pch+"\"";
|
||
|
}
|
||
|
|
||
|
Cpp << "\n";
|
||
|
if (SeparatedFlag || !IncludeDbFile)
|
||
|
{
|
||
|
Cpp << "#include \"" << filename << ".h\"\n";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Cpp << "#include \"" << getFileNoExtPath(getDbNode()->getDbFile()) << ".h\"\n";
|
||
|
}
|
||
|
|
||
|
Cpp << "\n";
|
||
|
Cpp << "namespace " << db->Name << "\n{\n\n";
|
||
|
Cpp.unindent();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CFileNode::generateEpilog()
|
||
|
{
|
||
|
CDbNode* db = getDbNode();
|
||
|
|
||
|
string fullfile = getFullStdPathNoExt(Name);
|
||
|
string filename = NLMISC::toLower(CFile::getFilenameWithoutExtension(Name));
|
||
|
|
||
|
Hpp.indent();
|
||
|
Hpp << "\n} // End of " << db->Name <<"\n";
|
||
|
|
||
|
if (!IncludeDbFile || SeparatedFlag)
|
||
|
{
|
||
|
// add inline #include
|
||
|
Hpp << "\n\n//\n// Inline implementations\n//\n\n";
|
||
|
Hpp << "#include \"" << filename << "_inline.h\"\n";
|
||
|
}
|
||
|
|
||
|
Hpp << "\n#endif\n";
|
||
|
|
||
|
HppInline.indent();
|
||
|
HppInline << "\n} // End of " << db->Name <<"\n";
|
||
|
|
||
|
Cpp.indent();
|
||
|
Cpp << "\n} // End of " << db->Name <<"\n";
|
||
|
|
||
|
if (Generate)
|
||
|
writeFile();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
string CFileNode::getFileNoExtPath(const string& file)
|
||
|
{
|
||
|
string thisPath = NLMISC::CFile::getPath(NLMISC::toLower(Name));
|
||
|
string filePath = NLMISC::CFile::getPath(NLMISC::toLower(file));
|
||
|
string fileName = NLMISC::CFile::getFilename(NLMISC::toLower(file));
|
||
|
|
||
|
if (thisPath == filePath)
|
||
|
return CFile::getFilenameWithoutExtension(fileName);
|
||
|
else
|
||
|
return CFile::getFilenameWithoutExtension(NLMISC::toLower(file));
|
||
|
}
|
||
|
|
||
|
void CFileNode::writeFile()
|
||
|
{
|
||
|
string fullfile = getFullStdPathNoExt(Name);
|
||
|
|
||
|
Hpp.flush(fullfile+".h");
|
||
|
Cpp.flush(fullfile+".cpp");
|
||
|
HppInline.flush(fullfile+"_inline.h");
|
||
|
}
|
||
|
|
||
|
void CFileNode::checkDependencies(set<CFileNode*> &beingChecked,
|
||
|
set<CFileNode*> &checkedFiles,
|
||
|
vector<CFileNode*> &filesOrder)
|
||
|
{
|
||
|
if (beingChecked.find(this) != beingChecked.end())
|
||
|
error("circular dependency in file '"+Name+"'");
|
||
|
|
||
|
if (checkedFiles.find(this) != checkedFiles.end())
|
||
|
return;
|
||
|
|
||
|
beingChecked.insert(this);
|
||
|
checkedFiles.insert(this);
|
||
|
|
||
|
set<CFileNode*>::iterator it;
|
||
|
for (it=Dependencies.begin(); it!=Dependencies.end(); ++it)
|
||
|
{
|
||
|
CFileNode *fileNode = *it;
|
||
|
if (fileNode == this)
|
||
|
continue;
|
||
|
|
||
|
fileNode->checkDependencies(beingChecked, checkedFiles, filesOrder);
|
||
|
}
|
||
|
|
||
|
filesOrder.push_back(this);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Type Node
|
||
|
bool CTypeNode::prolog()
|
||
|
{
|
||
|
CDbNode* db = getDbNode();
|
||
|
db->TypeNodes.push_back(this);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CTypeNode::generateContent()
|
||
|
{
|
||
|
hOutput() << "/** " << Name << "\n";
|
||
|
if (!Description.empty())
|
||
|
{
|
||
|
hOutput() << Description << "\n";
|
||
|
}
|
||
|
uint line, col;
|
||
|
string file;
|
||
|
getFileLine(line, col, file);
|
||
|
hOutput() << "defined at " << file << ":" << line << "\n";
|
||
|
hOutput() << "*/\n";
|
||
|
|
||
|
hOutput() << "typedef " << getCppType() << " " << Name << ";\n\n";
|
||
|
|
||
|
|
||
|
if (ToCppType != NULL)
|
||
|
{
|
||
|
CCppCodeNode *tocpp = static_cast<CCppCodeNode*>(ToCppType);
|
||
|
|
||
|
CFunctionGenerator toCppFunc;
|
||
|
|
||
|
toCppFunc.init(storageToCpp());
|
||
|
toCppFunc.setType(getName());
|
||
|
toCppFunc.IsInline = true;
|
||
|
toCppFunc.Proto = StorageType+" _v";
|
||
|
|
||
|
toCppFunc.add(getName()+"\t__res;");
|
||
|
toCppFunc.add(strReplace(strReplace(tocpp->RawCode, "$("+CppType+")", "__res"), "$("+StorageType+")", "_v"));
|
||
|
toCppFunc.add("return __res;");
|
||
|
toCppFunc.flush(hOutput(), cppOutput(), inlineOutput());
|
||
|
}
|
||
|
if (ToStorageType != NULL)
|
||
|
{
|
||
|
CCppCodeNode *tostorage = static_cast<CCppCodeNode*>(ToStorageType);
|
||
|
|
||
|
CFunctionGenerator toStorageFunc;
|
||
|
|
||
|
toStorageFunc.init(cppToStorage());
|
||
|
toStorageFunc.setType(StorageType);
|
||
|
toStorageFunc.IsInline = true;
|
||
|
toStorageFunc.Proto = getName()+" _v";
|
||
|
|
||
|
toStorageFunc.add(StorageType+"\t__res;");
|
||
|
toStorageFunc.add(strReplace(strReplace(tostorage->RawCode, "$("+StorageType+")", "__res"), "$("+CppType+")", "_v"));
|
||
|
toStorageFunc.add("return __res;");
|
||
|
toStorageFunc.flush(hOutput(), cppOutput(), inlineOutput());
|
||
|
}
|
||
|
|
||
|
hOutput() << "\n";
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Include Node
|
||
|
bool CIncludeNode::prolog()
|
||
|
{
|
||
|
CFileNode* file = getFileNode();
|
||
|
file->IncludeNodes.push_back(this);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Include Node
|
||
|
bool CUsePchNode::prolog()
|
||
|
{
|
||
|
CDbNode* db = getDbNode();
|
||
|
db->Pch = Name;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
// CppCode Node
|
||
|
bool CCppCodeNode::prolog()
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Dimension Nodes
|
||
|
bool CDimensionNode::prolog()
|
||
|
{
|
||
|
CDbNode* db = getDbNode();
|
||
|
db->TypeNodes.push_back(this);
|
||
|
|
||
|
if (Dimension < 256)
|
||
|
StorageType = "uint8";
|
||
|
else if (Dimension < 65536)
|
||
|
StorageType = "uint16";
|
||
|
else
|
||
|
StorageType = "uint32";
|
||
|
|
||
|
CppType = "uint32";
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CDimensionNode::epilog()
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CDimensionNode::generateContent()
|
||
|
{
|
||
|
hOutput() << "/** " << Name << "\n";
|
||
|
if (!Description.empty())
|
||
|
{
|
||
|
hOutput() << Description << "\n";
|
||
|
}
|
||
|
uint line, col;
|
||
|
string file;
|
||
|
getFileLine(line, col, file);
|
||
|
hOutput() << "defined at " << file << ":" << line << "\n";
|
||
|
hOutput() << "*/\n";
|
||
|
|
||
|
hOutput() << "typedef " << CppType << " " << Name << ";\n";
|
||
|
hOutput() << "const " << getName() << "\t" << getSizeName() << " = " << Dimension << ";\n\n";
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Enum Nodes
|
||
|
bool CEnumNode::prolog()
|
||
|
{
|
||
|
CDbNode* db = getDbNode();
|
||
|
db->TypeNodes.push_back(this);
|
||
|
|
||
|
if (Name.empty() || Name[0] != 'T')
|
||
|
error("enum name '"+Name+"' is invalid, must begin with a 'T'");
|
||
|
|
||
|
CurrentValue = 0;
|
||
|
CurrentEnum = Name;
|
||
|
CurrentEnumNode = this;
|
||
|
|
||
|
MinValue = 0;
|
||
|
MaxValue = 0;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CEnumNode::epilog()
|
||
|
{
|
||
|
uint i;
|
||
|
|
||
|
for (i=0; i<Nodes.size(); ++i)
|
||
|
{
|
||
|
CEnumNode *nd = dynamic_cast<CEnumNode*>(Nodes[i]);
|
||
|
if (!nd)
|
||
|
continue;
|
||
|
Values.insert(Values.end(), nd->Values.begin(), nd->Values.end());
|
||
|
}
|
||
|
|
||
|
for (i=0; i<Values.size(); ++i)
|
||
|
{
|
||
|
if (MinValue > Values[i].second)
|
||
|
MinValue = Values[i].second;
|
||
|
if (MaxValue < Values[i].second)
|
||
|
MaxValue = Values[i].second;
|
||
|
}
|
||
|
|
||
|
CurrentEnumNode = NULL;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CEnumSimpleValueNode::prolog()
|
||
|
{
|
||
|
CEnumNode *parent = dynamic_cast<CEnumNode*>(Parent);
|
||
|
if (parent != NULL)
|
||
|
{
|
||
|
CurrentValue = parent->CurrentValue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CurrentValue = 0;
|
||
|
}
|
||
|
uint i;
|
||
|
for (i=0; i<Names.size(); ++i)
|
||
|
{
|
||
|
CurrentEnumNode->Values.push_back(make_pair<string, uint32>(Names[i], CurrentValue));
|
||
|
}
|
||
|
if (parent != NULL)
|
||
|
++(parent->CurrentValue);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CEnumSimpleValueNode::epilog()
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CEnumRangeNode::prolog()
|
||
|
{
|
||
|
CEnumNode *parent = dynamic_cast<CEnumNode*>(Parent);
|
||
|
if (parent != NULL)
|
||
|
{
|
||
|
CurrentValue = parent->CurrentValue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CurrentValue = 0;
|
||
|
}
|
||
|
|
||
|
CurrentEnumNode->Values.push_back(make_pair<string, uint32>(Name, CurrentValue));
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CEnumRangeNode::epilog()
|
||
|
{
|
||
|
CEnumNode *parent = dynamic_cast<CEnumNode*>(Parent);
|
||
|
if (parent != NULL)
|
||
|
{
|
||
|
parent->CurrentValue = CurrentValue;
|
||
|
}
|
||
|
|
||
|
uint i;
|
||
|
for (i=0; i<Nodes.size(); ++i)
|
||
|
{
|
||
|
CEnumNode *nd = dynamic_cast<CEnumNode*>(Nodes[i]);
|
||
|
if (!nd)
|
||
|
continue;
|
||
|
Values.insert(Values.end(), nd->Values.begin(), nd->Values.end());
|
||
|
}
|
||
|
|
||
|
if (!EndRange.empty())
|
||
|
{
|
||
|
CurrentEnumNode->Values.push_back(make_pair<string, uint32>(EndRange, CurrentValue));
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool CEnumNode::generateContent()
|
||
|
{
|
||
|
hOutput() << "/** " << Name << "\n";
|
||
|
if (!Description.empty())
|
||
|
{
|
||
|
hOutput() << Description << "\n";
|
||
|
}
|
||
|
uint line, col;
|
||
|
string file;
|
||
|
getFileLine(line, col, file);
|
||
|
hOutput() << "defined at " << file << ":" << line << "\n";
|
||
|
hOutput() << "*/\n";
|
||
|
|
||
|
string enumTruncName = Name.substr(1);
|
||
|
CClassGenerator gen;
|
||
|
gen.init("C"+enumTruncName);
|
||
|
gen.createPublic("enum", "Enum values", "");
|
||
|
gen.createPublic("conv", "Conversion methods", "Use these methods to convert from enum value to string (and vice versa)");
|
||
|
gen.createPrivate("init", "Enum initialisation", "");
|
||
|
|
||
|
uint j;
|
||
|
gen.addOther("enum "+Name+"\n", "enum");
|
||
|
gen.addOther("{\n", "enum");
|
||
|
for (j=0; j<Values.size(); ++j)
|
||
|
gen.addOther(Values[j].first+" = "+toString(Values[j].second)+",\n", "enum");
|
||
|
gen.addOther(getUnscopedUseSize()+" = "+toString(MaxValue-MinValue+1)+",\n", "enum");
|
||
|
gen.addOther(getUnknownValue()+" = "+toString(MaxValue-MinValue+1)+",\n", "enum");
|
||
|
if (!EndRange.empty())
|
||
|
gen.addOther(EndRange+" = "+toString(MaxValue-MinValue+1)+",\n", "enum");
|
||
|
gen.addOther("};\n", "enum");
|
||
|
|
||
|
gen.startMethod("const std::string&", "toString", Name+" v", "conv", false, true, true);
|
||
|
gen.add("if (v < 0 || v >= "+getUnscopedUseSize()+")");
|
||
|
gen.add("{");
|
||
|
gen.add("nlwarning(\""+Name+"::toString(): value '%u' is not matched, \\\"Unknown\\\" string returned\", v);");
|
||
|
gen.add("return _UnknownString;");
|
||
|
gen.add("}");
|
||
|
//gen.add(checkCode("v"));
|
||
|
gen.add("if (!_Initialised)");
|
||
|
gen.add("{");
|
||
|
gen.add("init();");
|
||
|
gen.add("}");
|
||
|
gen.add("return _StrTable[v];");
|
||
|
|
||
|
gen.startMethod(getName(), "fromString", "const std::string& v", "conv", false, true, true);
|
||
|
gen.add("if (!_Initialised)");
|
||
|
gen.add("{");
|
||
|
gen.add("init();");
|
||
|
gen.add("}");
|
||
|
gen.add("if(v==_UnknownString)");
|
||
|
gen.add("{");
|
||
|
gen.add("return Unknown;");
|
||
|
gen.add("}");
|
||
|
gen.add("const std::map<std::string, "+Name+">::const_iterator\tit = _ValueMap.find(NLMISC::toLower(v));");
|
||
|
gen.add("if (it == _ValueMap.end())");
|
||
|
gen.add("{");
|
||
|
gen.add("nlwarning(\""+Name+"::toString(): string '%s' is not matched, 'Unknown' enum value returned\", v.c_str());");
|
||
|
gen.add("return "+getUnknownValue()+";");
|
||
|
gen.add("}");
|
||
|
gen.add("return (*it).second;");
|
||
|
|
||
|
|
||
|
gen.startMethod("void", "init", "", "init", false, false, true);
|
||
|
gen.add("_StrTable.clear();");
|
||
|
gen.add("_ValueMap.clear();");
|
||
|
gen.add("_StrTable.resize("+toString(getSize()+1)+");");
|
||
|
gen.add("uint\ti;");
|
||
|
gen.add("for (i=0; i<"+toString(Values.size())+"; ++i)");
|
||
|
gen.add("{");
|
||
|
gen.add("_StrTable["+Name+"Convert[i].Value] = "+Name+"Convert[i].Name;");
|
||
|
gen.add("_ValueMap[NLMISC::toLower(std::string("+Name+"Convert[i].Name))] = "+Name+"Convert[i].Value;");
|
||
|
gen.add("}");
|
||
|
|
||
|
gen.add("_Initialised = true;");
|
||
|
|
||
|
|
||
|
gen.addAttribute("bool", "_Initialised", "init", true, "false");
|
||
|
gen.addAttribute("std::string", "_UnknownString", "init", true, "\""+getUnknownValue()+"\"");
|
||
|
gen.addAttribute("std::vector<std::string>", "_StrTable", "init", true);
|
||
|
gen.addAttribute("std::map<std::string, "+Name+">", "_ValueMap", "init", true, "", false, "std::map<std::string, "+getName()+">");
|
||
|
|
||
|
cppOutput() << "static const struct { char* Name; " << getName() << " Value; } " << Name << "Convert[] =\n";
|
||
|
cppOutput() << "{\n";
|
||
|
for (j=0; j<Values.size(); ++j)
|
||
|
cppOutput() << "{ \"" << Values[j].first << "\", C"+enumTruncName+"::"+Values[j].first+" },\n";
|
||
|
cppOutput() << "};\n";
|
||
|
|
||
|
gen.flush(hOutput(), cppOutput(), inlineOutput());
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Class Node
|
||
|
bool CClassNode::prolog()
|
||
|
{
|
||
|
CDbNode* db = getDbNode();
|
||
|
db->ClassNodes.push_back(this);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CClassNode::epilog()
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
string CClassNode::getUserCode(const string& name)
|
||
|
{
|
||
|
uint i;
|
||
|
for (i=0; i<Nodes.size(); ++i)
|
||
|
{
|
||
|
CCppCodeNode *code = dynamic_cast<CCppCodeNode*>(Nodes[i]);
|
||
|
if (!code)
|
||
|
continue;
|
||
|
|
||
|
if (code->Name == name)
|
||
|
return code->RawCode;
|
||
|
}
|
||
|
|
||
|
return "";
|
||
|
}
|
||
|
|
||
|
|
||
|
void CClassNode::checkClassReferences()
|
||
|
{
|
||
|
if (!Implements.empty())
|
||
|
{
|
||
|
Gen.Inherit += (HasRowAccess ? string(", ") : string(""))+"public "+Implements;
|
||
|
getDbNode()->Implemented.insert(Implements);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
HasInheritance = true;
|
||
|
CClassNode *nd = getClassNode(Inherited);
|
||
|
nd->HasInheritance = true;
|
||
|
nd->ChildrenClasses.push_back(Name);
|
||
|
|
||
|
Dependencies.insert(nd);
|
||
|
getFileNode()->Dependencies.insert(nd->getFileNode());
|
||
|
}
|
||
|
|
||
|
CClassNode* inherit = this;
|
||
|
while (inherit != NULL)
|
||
|
{
|
||
|
if (MappedFlag)
|
||
|
inherit->PDSMapped = true;
|
||
|
|
||
|
inherit->Legacy.insert(this);
|
||
|
inherit = getClassNode(inherit->Inherited, false);
|
||
|
}
|
||
|
|
||
|
uint i;
|
||
|
uint id = 0;
|
||
|
for (i=0; i<Nodes.size(); ++i)
|
||
|
{
|
||
|
CDeclarationNode *decl = dynamic_cast<CDeclarationNode*>(Nodes[i]);
|
||
|
if (!decl)
|
||
|
continue;
|
||
|
|
||
|
decl->Id = id++;
|
||
|
|
||
|
if (decl->ParentFlag)
|
||
|
{
|
||
|
if (HasParent)
|
||
|
decl->error("class '"+Name+"' already has a parent");
|
||
|
|
||
|
//if (MappedFlag)
|
||
|
// decl->error("class '"+Name+"' can't have a parent and be mapped at the same time");
|
||
|
|
||
|
CClassNode* inherit = this;
|
||
|
while (inherit != NULL)
|
||
|
{
|
||
|
inherit->PDSMapped = false;
|
||
|
inherit = getClassNode(inherit->Inherited, false);
|
||
|
}
|
||
|
|
||
|
ParentClass = decl->ParentClass;
|
||
|
HasParent = true;
|
||
|
|
||
|
ParentIsHidden = decl->HiddenFlag;
|
||
|
|
||
|
decl->getClassNode(decl->ParentClass)->IsBackReferenced = true;
|
||
|
}
|
||
|
else if (decl->SetFlag)
|
||
|
{
|
||
|
decl->getClassNode(decl->Type)->IsInSet = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CClassNode::fillAttributes()
|
||
|
{
|
||
|
if (HasParent && !IsBackReferenced && !HasInheritance && !IsInSet && !DerivatedFlag && !MappedFlag)
|
||
|
error("class '"+Name+"' has a parent whereas it is not backreferenced, has no inherited link and is not mapped");
|
||
|
|
||
|
uint i;
|
||
|
for (i=0; i<Nodes.size(); ++i)
|
||
|
{
|
||
|
CDeclarationNode *decl = dynamic_cast<CDeclarationNode*>(Nodes[i]);
|
||
|
if (!decl)
|
||
|
continue;
|
||
|
|
||
|
uint j;
|
||
|
for (j=0; j<Nodes.size(); ++j)
|
||
|
if (j != i && dynamic_cast<CDeclarationNode*>(Nodes[j]) != NULL && Nodes[j]->Name == decl->Name)
|
||
|
decl->error("attribute '"+decl->Name+"' already defined");
|
||
|
|
||
|
if (decl->ParentFlag)
|
||
|
{
|
||
|
decl->DeclarationType = BackRef;
|
||
|
}
|
||
|
else if (decl->ArrayFlag)
|
||
|
{
|
||
|
CClassNode *classNd = NULL;
|
||
|
CTypeNode *typeNd = NULL;
|
||
|
|
||
|
if ( (classNd = decl->getClassNode(decl->Type, false)) )
|
||
|
{
|
||
|
if (classNd->IsBackReferenced || classNd->ForceReference)
|
||
|
{
|
||
|
if (decl->ForwardRefAttribute.empty())
|
||
|
decl->error("no forward reference to parent in array declaration, class '"+decl->Type+"' is backref'd or has inheritance");
|
||
|
|
||
|
classNd->IsInArrayRef = true;
|
||
|
decl->IsRef = true;
|
||
|
decl->DeclarationType = ArrayRef;
|
||
|
|
||
|
if (classNd->ParentIsHidden)
|
||
|
Dependencies.insert(classNd);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!decl->ForwardRefAttribute.empty())
|
||
|
decl->error("forward reference declared whereas subclass is not backreferenced and has no inheritance link");
|
||
|
|
||
|
Dependencies.insert(classNd);
|
||
|
|
||
|
classNd->IsInArray = true;
|
||
|
decl->IsRef = false;
|
||
|
decl->DeclarationType = ArrayClass;
|
||
|
}
|
||
|
}
|
||
|
else if ( (typeNd = decl->getTypeNode(decl->Type, false)) )
|
||
|
{
|
||
|
decl->DeclarationType = ArrayType;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
decl->error("type or class '"+decl->Type+"' not found");
|
||
|
}
|
||
|
}
|
||
|
else if (decl->SetFlag)
|
||
|
{
|
||
|
decl->IsRef = true;
|
||
|
decl->DeclarationType = Set;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CClassNode *classNd = NULL;
|
||
|
CTypeNode *typeNd = NULL;
|
||
|
|
||
|
if ( (classNd = decl->getClassNode(decl->Type, false)) )
|
||
|
{
|
||
|
if (classNd->IsBackReferenced || classNd->ForceReference)
|
||
|
{
|
||
|
if (decl->ForwardRefAttribute.empty())
|
||
|
decl->error("no forward reference to parent in array declaration, class '"+decl->Type+"' is backref'd or has inheritance");
|
||
|
|
||
|
decl->IsRef = true;
|
||
|
|
||
|
decl->DeclarationType = ForwardRef;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!decl->ForwardRefAttribute.empty())
|
||
|
decl->error("forward reference declared whereas subclass is not backreferenced and has no inheritance link");
|
||
|
|
||
|
Dependencies.insert(classNd);
|
||
|
|
||
|
decl->IsRef = false;
|
||
|
|
||
|
decl->DeclarationType = SimpleClass;
|
||
|
}
|
||
|
}
|
||
|
else if ( (typeNd = decl->getTypeNode(decl->Type, false)) )
|
||
|
{
|
||
|
decl->IsType = true;
|
||
|
|
||
|
decl->DeclarationType = SimpleType;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
decl->error("type or class '"+decl->Type+"' not found");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CDeclarationNode *declNd = getClassKey();
|
||
|
if (declNd != NULL)
|
||
|
{
|
||
|
if (!declNd->IsType)
|
||
|
error("attribute '"+declNd->Name+"' can't be a key, only simple type allowed");
|
||
|
|
||
|
declNd->IsKey = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CClassNode::fillRefs()
|
||
|
{
|
||
|
uint i;
|
||
|
for (i=0; i<Nodes.size(); ++i)
|
||
|
{
|
||
|
CDeclarationNode *decl = dynamic_cast<CDeclarationNode*>(Nodes[i]);
|
||
|
if (!decl)
|
||
|
continue;
|
||
|
|
||
|
switch (decl->DeclarationType)
|
||
|
{
|
||
|
case BackRef:
|
||
|
{
|
||
|
// check parent is a valid class
|
||
|
CClassNode *cln = decl->getClassNode(decl->ParentClass);
|
||
|
CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(cln->getNode(decl->ParentField));
|
||
|
if (!dln) decl->error("attribute '"+decl->ParentField+"' not found in class '"+decl->ParentClass+"'");
|
||
|
|
||
|
if (!dln->ArrayFlag && !dln->SetFlag && !ForceReference)
|
||
|
decl->error("back reference 'parent "+decl->ParentClass+":"+decl->ParentField+" "+decl->Name+"' is not forwarded in class '"+decl->ParentClass+"' with an array or a set");
|
||
|
|
||
|
if (dln->Type != Name || dln->ForwardRefAttribute != decl->Name)
|
||
|
decl->error("back reference 'parent "+decl->ParentClass+":"+decl->ParentField+" "+decl->Name+"' is not correctly forwarded in class '"+decl->ParentClass+"'");
|
||
|
|
||
|
Friends.insert(cln->Name);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case Set:
|
||
|
{
|
||
|
CClassNode *cln = decl->getClassNode(decl->Type);
|
||
|
CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(cln->getNode(decl->ForwardRefAttribute));
|
||
|
if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'");
|
||
|
|
||
|
if (!dln->ParentFlag)
|
||
|
decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not backref'd in class '"+decl->Type+"'");
|
||
|
|
||
|
if (dln->ParentClass != Name || dln->ParentField != decl->Name)
|
||
|
decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'");
|
||
|
|
||
|
if (cln->getClassKey() == NULL)
|
||
|
decl->error("class '"+decl->Type+"' has no key defined, whereas it is used in a set");
|
||
|
|
||
|
cln->Friends.insert(Name);
|
||
|
ForwardFriends.insert(cln->Name);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ArrayRef:
|
||
|
{
|
||
|
if (decl->ForwardRefAttribute.empty())
|
||
|
decl->error("No forward reference defined");
|
||
|
|
||
|
CClassNode *cln = decl->getClassNode(decl->Type);
|
||
|
CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(cln->getNode(decl->ForwardRefAttribute));
|
||
|
CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex);
|
||
|
getFileNode()->Dependencies.insert(tln->getFileNode());
|
||
|
if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'");
|
||
|
|
||
|
if (!dln->ParentFlag)
|
||
|
decl->error("array '"+decl->Type+":"+decl->ForwardRefAttribute+"["+decl->ArrayIndex+"] "+decl->Name+"' is not backref'd in class '"+decl->Type+"'");
|
||
|
|
||
|
if (dln->ParentClass != Name || dln->ParentField != decl->Name)
|
||
|
decl->error("array '"+decl->Type+":"+decl->ForwardRefAttribute+"["+decl->ArrayIndex+"] "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'");
|
||
|
|
||
|
if (cln->getClassKey() == NULL)
|
||
|
decl->error("class '"+decl->Type+"' has no key defined, whereas it is used in an array of ref");
|
||
|
CDeclarationNode *kdn = dynamic_cast<CDeclarationNode*>(cln->getClassKey());
|
||
|
if (!kdn) decl->error("attribute '"+cln->ClassKey+"' not found in class '"+cln->Name+"'");
|
||
|
|
||
|
if (kdn->Type != decl->ArrayIndex)
|
||
|
decl->error("type in array definition mismatch class '"+cln->Name+"' key definition");
|
||
|
|
||
|
cln->Friends.insert(Name);
|
||
|
ForwardFriends.insert(cln->Name);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ForwardRef:
|
||
|
{
|
||
|
if (decl->ForwardRefAttribute.empty())
|
||
|
decl->error("No forward reference defined");
|
||
|
|
||
|
CClassNode *cln = decl->getClassNode(decl->Type);
|
||
|
CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(cln->getNode(decl->ForwardRefAttribute));
|
||
|
if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'");
|
||
|
|
||
|
if (!dln->ParentFlag)
|
||
|
decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not backref'd in class '"+decl->Type+"'");
|
||
|
|
||
|
if (dln->ParentClass != Name || dln->ParentField != decl->Name)
|
||
|
decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'");
|
||
|
|
||
|
cln->Friends.insert(Name);
|
||
|
ForwardFriends.insert(cln->Name);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case ArrayType:
|
||
|
{
|
||
|
CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex);
|
||
|
getFileNode()->Dependencies.insert(tln->getFileNode());
|
||
|
}
|
||
|
case SimpleType:
|
||
|
break;
|
||
|
|
||
|
case ArrayClass:
|
||
|
{
|
||
|
CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex);
|
||
|
getFileNode()->Dependencies.insert(tln->getFileNode());
|
||
|
}
|
||
|
case SimpleClass:
|
||
|
{
|
||
|
CClassNode *cln = decl->getClassNode(decl->Type);
|
||
|
cln->Friends.insert(Name);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
decl->error("Can't decide declaration type");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CClassNode::computeFriends()
|
||
|
{
|
||
|
bool added;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
added = false;
|
||
|
set<string>::iterator itf, itsf;
|
||
|
|
||
|
for (itf=Friends.begin(); !added && itf!=Friends.end(); ++itf)
|
||
|
{
|
||
|
CClassNode* pfriend = getClassNode(*itf);
|
||
|
|
||
|
for (itsf=pfriend->Friends.begin(); !added && itsf!=pfriend->Friends.end(); ++itsf)
|
||
|
{
|
||
|
const string& sfriend = *itsf;
|
||
|
if (Friends.find(*itsf) == Friends.end())
|
||
|
{
|
||
|
Friends.insert(*itsf);
|
||
|
added = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while (added);
|
||
|
}
|
||
|
|
||
|
|
||
|
void CClassNode::checkDependencies(set<CClassNode*> &beingChecked,
|
||
|
set<CClassNode*> &checkedClasses,
|
||
|
vector<CClassNode*> &classesOrder)
|
||
|
{
|
||
|
if (beingChecked.find(this) != beingChecked.end())
|
||
|
error("circular dependency in class '"+Name+"'");
|
||
|
|
||
|
if (checkedClasses.find(this) != checkedClasses.end())
|
||
|
return;
|
||
|
|
||
|
beingChecked.insert(this);
|
||
|
checkedClasses.insert(this);
|
||
|
|
||
|
set<CClassNode*>::iterator it;
|
||
|
for (it=Dependencies.begin(); it!=Dependencies.end(); ++it)
|
||
|
{
|
||
|
CClassNode *classNode = *it;
|
||
|
|
||
|
classNode->checkDependencies(beingChecked, checkedClasses, classesOrder);
|
||
|
}
|
||
|
|
||
|
classesOrder.push_back(this);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
void CClassNode::buildInit()
|
||
|
{
|
||
|
CDbNode *db = getDbNode();
|
||
|
|
||
|
if (!Init.empty())
|
||
|
return;
|
||
|
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
CClassNode *mother = getClassNode(Inherited);
|
||
|
if (mother)
|
||
|
{
|
||
|
mother->buildInit();
|
||
|
Init = mother->Init;
|
||
|
|
||
|
uint i;
|
||
|
for (i=0; i<Init.size(); ++i)
|
||
|
{
|
||
|
if (!InitProto.empty())
|
||
|
InitProto += ", ";
|
||
|
if (!InitCallArgs.empty())
|
||
|
InitCallArgs += ", ";
|
||
|
|
||
|
CTypeNode* typeNode = getTypeNode(Init[i]->Type);
|
||
|
InitProto += "const "+typeNode->getName()+" &"+Init[i]->Name;
|
||
|
InitCallArgs += Init[i]->Name;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!ClassKey.empty())
|
||
|
{
|
||
|
CDeclarationNode *decl = dynamic_cast<CDeclarationNode*>(getNode(ClassKey));
|
||
|
if (decl)
|
||
|
{
|
||
|
Init.push_back(decl);
|
||
|
|
||
|
if (!InitProto.empty())
|
||
|
InitProto += ", ";
|
||
|
|
||
|
CTypeNode* typeNode = getTypeNode(decl->Type);
|
||
|
InitProto += "const "+typeNode->getName()+" &"+decl->Name;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void CClassNode::computeAttributesColumns()
|
||
|
{
|
||
|
if (Columns >= 0)
|
||
|
return;
|
||
|
|
||
|
CDbNode *db = getDbNode();
|
||
|
|
||
|
Columns = 0;
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
CClassNode *mother = getClassNode(Inherited);
|
||
|
mother->computeAttributesColumns();
|
||
|
Columns = mother->Columns;
|
||
|
|
||
|
Attributes = mother->Attributes;
|
||
|
}
|
||
|
|
||
|
uint attribId = (uint)Attributes.size();
|
||
|
uint i;
|
||
|
for (i=0; i<Nodes.size(); ++i)
|
||
|
{
|
||
|
CDeclarationNode *decl = dynamic_cast<CDeclarationNode*>(Nodes[i]);
|
||
|
if (decl == NULL)
|
||
|
continue;
|
||
|
|
||
|
Attributes.push_back(decl);
|
||
|
|
||
|
decl->Column = Columns;
|
||
|
decl->Id = attribId++;
|
||
|
CColumn col;
|
||
|
|
||
|
// All for backref, set, forwardref, type
|
||
|
switch (decl->DeclarationType)
|
||
|
{
|
||
|
case ForwardRef:
|
||
|
decl->Columns = 1;
|
||
|
col.Name = decl->Name;
|
||
|
col.Type = ForwardRef;
|
||
|
col.TypeStr = "forwardref";
|
||
|
col.TypeId = decl->getClassNode(decl->Type)->Id;
|
||
|
col.ByteSize = 8;
|
||
|
decl->ColumnList.push_back(col);
|
||
|
break;
|
||
|
case BackRef:
|
||
|
decl->Columns = 1;
|
||
|
col.Name = decl->Name;
|
||
|
col.Type = BackRef;
|
||
|
col.TypeStr = "backref";
|
||
|
col.TypeId = decl->getClassNode(decl->ParentClass)->Id;
|
||
|
col.ByteSize = 8;
|
||
|
decl->ColumnList.push_back(col);
|
||
|
break;
|
||
|
case SimpleType:
|
||
|
decl->Columns = 1;
|
||
|
col.Name = decl->Name;
|
||
|
col.Type = SimpleType;
|
||
|
col.TypeStr = "type";
|
||
|
col.TypeId = decl->getTypeNode(decl->Type)->Id;
|
||
|
col.ByteSize = decl->getTypeNode(decl->Type)->Size;
|
||
|
decl->ColumnList.push_back(col);
|
||
|
break;
|
||
|
case Set:
|
||
|
decl->Columns = 1;
|
||
|
col.Name = decl->Name;
|
||
|
col.Type = Set;
|
||
|
col.TypeStr = "set";
|
||
|
col.TypeId = decl->getClassNode(decl->Type)->Id;
|
||
|
col.ByteSize = 4;
|
||
|
decl->ColumnList.push_back(col);
|
||
|
break;
|
||
|
case SimpleClass:
|
||
|
{
|
||
|
CClassNode *sub = decl->getClassNode(decl->Type);
|
||
|
sub->computeAttributesColumns();
|
||
|
decl->Columns = sub->Columns;
|
||
|
|
||
|
uint i, j;
|
||
|
for (i=0; i<sub->Attributes.size(); ++i)
|
||
|
{
|
||
|
CDeclarationNode *attrib = sub->Attributes[i];
|
||
|
|
||
|
for (j=0; j<attrib->ColumnList.size(); ++j)
|
||
|
{
|
||
|
col.Name = decl->Name+"."+attrib->ColumnList[j].Name;
|
||
|
col.Type = attrib->ColumnList[j].Type;
|
||
|
col.TypeStr = attrib->ColumnList[j].TypeStr;
|
||
|
col.TypeId = attrib->ColumnList[j].TypeId;
|
||
|
col.ByteSize = attrib->ColumnList[j].ByteSize;
|
||
|
decl->ColumnList.push_back(col);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ArrayRef:
|
||
|
{
|
||
|
CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex);
|
||
|
uint numInEnum = indexNd->getSize();
|
||
|
decl->Columns = numInEnum;
|
||
|
|
||
|
uint i;
|
||
|
for (i=0; i<numInEnum; ++i)
|
||
|
{
|
||
|
col.Name = decl->Name+"["+indexNd->getIndexName(i)+"]";
|
||
|
col.Type = ForwardRef;
|
||
|
col.TypeStr = "forwardref";
|
||
|
col.TypeId = decl->getClassNode(decl->Type)->Id;
|
||
|
col.ByteSize = 8;
|
||
|
decl->ColumnList.push_back(col);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ArrayType:
|
||
|
{
|
||
|
CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex);
|
||
|
uint numInEnum = indexNd->getSize();
|
||
|
decl->Columns = numInEnum;
|
||
|
|
||
|
uint i;
|
||
|
for (i=0; i<numInEnum; ++i)
|
||
|
{
|
||
|
col.Name = decl->Name+"["+indexNd->getIndexName(i)+"]";
|
||
|
col.Type = SimpleType;
|
||
|
col.TypeStr = "type";
|
||
|
col.TypeId = decl->getTypeNode(decl->Type)->Id;
|
||
|
col.ByteSize = decl->getTypeNode(decl->Type)->Size;
|
||
|
decl->ColumnList.push_back(col);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case ArrayClass:
|
||
|
{
|
||
|
CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex);
|
||
|
|
||
|
CClassNode *sub = decl->getClassNode(decl->Type);
|
||
|
sub->computeAttributesColumns();
|
||
|
|
||
|
uint numInEnum = indexNd->getSize();
|
||
|
decl->Columns = numInEnum*sub->Columns;
|
||
|
|
||
|
uint i, j, k;
|
||
|
for (k=0; k<numInEnum; ++k)
|
||
|
{
|
||
|
for (i=0; i<sub->Attributes.size(); ++i)
|
||
|
{
|
||
|
CDeclarationNode *attrib = sub->Attributes[i];
|
||
|
|
||
|
for (j=0; j<attrib->ColumnList.size(); ++j)
|
||
|
{
|
||
|
col.Name = decl->Name+"["+indexNd->getIndexName(k)+"]."+attrib->ColumnList[j].Name;
|
||
|
col.Type = attrib->ColumnList[j].Type;
|
||
|
col.TypeStr = attrib->ColumnList[j].TypeStr;
|
||
|
col.TypeId = attrib->ColumnList[j].TypeId;
|
||
|
col.ByteSize = attrib->ColumnList[j].ByteSize;
|
||
|
decl->ColumnList.push_back(col);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Columns += decl->Columns;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
bool CClassNode::generateContent()
|
||
|
{
|
||
|
nlassert(Env != NULL);
|
||
|
|
||
|
uint line, col;
|
||
|
string file;
|
||
|
getFileLine(line, col, file);
|
||
|
|
||
|
setEnv("name", Name);
|
||
|
if (!Description.empty())
|
||
|
setEnv("description", Description);
|
||
|
setEnv("deffile", file);
|
||
|
setEnv("defline", line);
|
||
|
|
||
|
computeAttributesColumns();
|
||
|
|
||
|
uint j;
|
||
|
|
||
|
//
|
||
|
// generate description
|
||
|
//
|
||
|
hOutput() << "/** " << Name << "\n";
|
||
|
if (!Description.empty())
|
||
|
hOutput() << Description << "\n";
|
||
|
|
||
|
hOutput() << "defined at " << file << ":" << line << "\n";
|
||
|
hOutput() << "*/\n";
|
||
|
|
||
|
CCppOutput& DbSummary = getDbNode()->DbSummary;
|
||
|
DbSummary << "Class " << getDbNode()->Name << "::" << Name << ":\n";
|
||
|
DbSummary << "----------------------------------------------------------\n";
|
||
|
DbSummary << "located in file \"" << getFullStdPathNoExt(getFileNode()->Name) << ".h\"\n";
|
||
|
DbSummary << "defined in file \"" << getFullStdPath(file) << "\"\n";
|
||
|
DbSummary << "The class contains:\n\n";
|
||
|
|
||
|
Gen.init(Name);
|
||
|
Gen.createPublic("methods", "Accessors and Mutators methods", "Use these methods to change a value, add or delete elements.");
|
||
|
Gen.createPublic("map", "Public Management methods", "Use these methods to create, load, unload and get\nan object from database.");
|
||
|
Gen.createPublic("user", "User defined attributes and methods", "This code was verbatim copied from source file");
|
||
|
Gen.createPublic("construct", "Public constructor", "This constructor is public to allow direct instanciation of the class");
|
||
|
Gen.createPublic("persist", "Persistent methods declaration", "");
|
||
|
Gen.createProtected("userinit", "User defined init and release methods", "Overload those methods to implement init and release behaviours");
|
||
|
Gen.createProtected("attributes", "Attributes", "Don't modify those value manually, use accessors and mutators above");
|
||
|
Gen.createProtected("internal", "Internal Management methods");
|
||
|
Gen.createProtected("inherit map");
|
||
|
Gen.createProtected("factories", "Default Factory and Fetch methods");
|
||
|
Gen.createProtected("friends");
|
||
|
|
||
|
// EGS Compat
|
||
|
// -- begin
|
||
|
|
||
|
Gen.startRaw("persist", false);
|
||
|
ApplyId = Gen.startMethod("void", applyFunction, "CPersistentDataRecord &__pdr", "persist", false, inlineInternal, false, false, "", HasInheritance);
|
||
|
StoreId = Gen.startMethod("void", storeFunction, "CPersistentDataRecord &__pdr", "persist", true, inlineInternal, false, false, "", HasInheritance);
|
||
|
|
||
|
ClearId = Gen.startMethod("void", clearFunction, "", "map", false, inlineStaticPublic, false, false, "", HasInheritance);
|
||
|
Gen.setDescription("Clear whole object content but key (delete subobjects if there are, key is left unmodified), default clear value is 0.");
|
||
|
|
||
|
StoreId.add("uint16\t__Tok_MapKey = __pdr.addString(\"__Key__\");");
|
||
|
StoreId.add("uint16\t__Tok_MapVal = __pdr.addString(\"__Val__\");");
|
||
|
StoreId.add("uint16\t__Tok_ClassName = __pdr.addString(\"__Class__\");");
|
||
|
ApplyId.add("uint16\t__Tok_MapKey = __pdr.addString(\"__Key__\");");
|
||
|
ApplyId.add("uint16\t__Tok_MapVal = __pdr.addString(\"__Val__\");");
|
||
|
ApplyId.add("uint16\t__Tok_ClassName = __pdr.addString(\"__Class__\");");
|
||
|
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
StoreId.add("uint16\t__Tok_Parent = __pdr.addString(\"__Parent__\");");
|
||
|
ApplyId.add("uint16\t__Tok_Parent = __pdr.addString(\"__Parent__\");");
|
||
|
}
|
||
|
|
||
|
for (j=0; j<Attributes.size(); ++j)
|
||
|
{
|
||
|
CDeclarationNode* decl = Attributes[j];
|
||
|
if (decl->Parent != this)
|
||
|
continue;
|
||
|
|
||
|
if (decl->DeclarationType == BackRef)
|
||
|
{
|
||
|
ApplyId.add(decl->cppName()+" = NULL;");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StoreId.add("uint16\t"+decl->tokenName()+" = __pdr.addString(\""+decl->Name+"\");");
|
||
|
ApplyId.add("uint16\t"+decl->tokenName()+" = __pdr.addString(\""+decl->Name+"\");");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ApplyId.add("while (!__pdr.isEndOfStruct())");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add( "if (false) {}");
|
||
|
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
StoreId.add("__pdr.pushStructBegin(__Tok_Parent);");
|
||
|
StoreId.add(Inherited+"::store(__pdr);");
|
||
|
StoreId.add("__pdr.pushStructEnd(__Tok_Parent);");
|
||
|
|
||
|
ApplyId.add("else if (__pdr.peekNextToken() == __Tok_Parent)");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add( "__pdr.popStructBegin(__Tok_Parent);");
|
||
|
ApplyId.add( Inherited+"::apply(__pdr);");
|
||
|
ApplyId.add( "__pdr.popStructEnd(__Tok_Parent);");
|
||
|
ApplyId.add("}");
|
||
|
}
|
||
|
|
||
|
// -- end
|
||
|
|
||
|
|
||
|
for (j=0; j<Nodes.size(); ++j)
|
||
|
{
|
||
|
CCppCodeNode* cpp = dynamic_cast<CCppCodeNode*>(Nodes[j]);
|
||
|
if (cpp == NULL || !cpp->Name.empty())
|
||
|
continue;
|
||
|
|
||
|
Gen.addOther(cpp->RawCode, "user");
|
||
|
}
|
||
|
|
||
|
HasRowAccess = false;
|
||
|
HasTableAccess = false;
|
||
|
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
setEnv("inherit", Inherited);
|
||
|
setEnv("inheritclass", Inherited);
|
||
|
|
||
|
Gen.Inherit += "public "+Inherited;
|
||
|
HasRowAccess = true;
|
||
|
HasTableAccess = true;
|
||
|
}
|
||
|
else if (HasInheritance || IsBackReferenced || IsInSet || ForceReference)
|
||
|
{
|
||
|
setEnv("inherit", pdBaseDataName);
|
||
|
|
||
|
Gen.Inherit += "public "+pdBaseDataName;
|
||
|
HasTableAccess = true;
|
||
|
HasRowAccess = true;
|
||
|
}
|
||
|
|
||
|
if (Legacy.size() > 1 && HasTableAccess)
|
||
|
{
|
||
|
CClassGenerator::SMethodId castId = Gen.startMethod(Name+"*", staticCastFunction, pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false);
|
||
|
Gen.setDescription("Cast base object to "+Name);
|
||
|
castId.add("switch (obj->getTable())");
|
||
|
castId.add("{");
|
||
|
std::set<CClassNode*>::iterator itl;
|
||
|
for (itl=Legacy.begin(); itl!=Legacy.end(); ++itl)
|
||
|
{
|
||
|
CClassNode* child = (*itl);
|
||
|
castId.add("case "+toString(child->Id)+":");
|
||
|
}
|
||
|
castId.add("return static_cast<"+Name+"*>(obj);");
|
||
|
castId.add("}");
|
||
|
castId.add("return NULL;");
|
||
|
|
||
|
CClassGenerator::SMethodId constCastId = Gen.startMethod("const "+Name+"*", staticConstCastFunction, "const "+pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false);
|
||
|
Gen.setDescription("Cast base object to const "+Name);
|
||
|
constCastId.add("switch (obj->getTable())");
|
||
|
constCastId.add("{");
|
||
|
for (itl=Legacy.begin(); itl!=Legacy.end(); ++itl)
|
||
|
{
|
||
|
CClassNode* child = (*itl);
|
||
|
constCastId.add("case "+toString(child->Id)+":");
|
||
|
}
|
||
|
constCastId.add("return static_cast<const "+Name+"*>(obj);");
|
||
|
constCastId.add("}");
|
||
|
constCastId.add("return NULL;");
|
||
|
}
|
||
|
else if (Legacy.size() == 1 && HasTableAccess)
|
||
|
{
|
||
|
CClassGenerator::SMethodId castId = Gen.startMethod(Name+"*", staticCastFunction, pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false);
|
||
|
std::set<CClassNode*>::iterator itl = Legacy.begin();
|
||
|
Gen.setDescription("Cast base object to "+Name);
|
||
|
castId.add("return (obj->getTable() == "+toString((*itl)->Id)+") ? static_cast<"+Name+"*>(obj) : NULL;");
|
||
|
|
||
|
CClassGenerator::SMethodId constCastId = Gen.startMethod("const "+Name+"*", staticConstCastFunction, "const "+pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false);
|
||
|
Gen.setDescription("Cast base object to const "+Name);
|
||
|
constCastId.add("return (obj->getTable() == "+toString((*itl)->Id)+") ? static_cast<const "+Name+"*>(obj) : NULL;");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
}
|
||
|
|
||
|
if (HasRowAccess)
|
||
|
define("hasrowaccess");
|
||
|
if (HasTableAccess)
|
||
|
define("hastableaccess");
|
||
|
|
||
|
if (!Implements.empty())
|
||
|
{
|
||
|
setEnv("implements", Implements);
|
||
|
Gen.Inherit += (HasRowAccess ? string(", ") : string(""))+"public "+Implements;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate init method
|
||
|
//
|
||
|
buildInit();
|
||
|
|
||
|
setEnv("initproto", InitProto);
|
||
|
|
||
|
InitId = Gen.startMethod("void", initFunction, InitProto, "internal", false, inlineInternal, false, false, "", HasInheritance);
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
InitId.add(Inherited + "::" + initFunction + "(" + InitCallArgs + ");");
|
||
|
setEnv("initcallargs", InitCallArgs);
|
||
|
}
|
||
|
|
||
|
DestroyId = Gen.startMethod("void", destroyFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
|
||
|
FetchId = Gen.startMethod("void", fetchFunction, CPDataName+" &data", "internal", false, inlineInternal, false, false, "", HasInheritance);
|
||
|
RegisterId = Gen.startMethod("void", registerFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
|
||
|
RegisterAttributesId = Gen.startMethod("void", registerAttributesFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
|
||
|
UnregisterId = Gen.startMethod("void", unregisterFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
|
||
|
UnregisterAttributesId = Gen.startMethod("void", unregisterAttributesFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
|
||
|
SetParentId;
|
||
|
SetUnnotifiedParentId;
|
||
|
if (HasParent)
|
||
|
{
|
||
|
SetParentId = Gen.startMethod("void", setParentFunction, ParentClass+"* __parent", "internal", false, inlineInternal);
|
||
|
SetUnnotifiedParentId = Gen.startMethod("void", setUnnotifiedParentFunction, ParentClass+"* __parent", "internal", false, inlineInternal);
|
||
|
}
|
||
|
|
||
|
if (HasRowAccess && GenerateDebugMessages)
|
||
|
{
|
||
|
DestroyId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": destroy %u:%u\", "+getId()+", __BaseRow);");
|
||
|
FetchId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": fetch %u:%u\", "+getId()+", __BaseRow);");
|
||
|
}
|
||
|
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
FetchId.add(Inherited+"::"+fetchFunction+"(data);");
|
||
|
}
|
||
|
|
||
|
if (DerivatedFlag)
|
||
|
{
|
||
|
UserInitId = Gen.startMethod("void", userInitFunction, "", "userinit", false, inlineUserInitDefaultCode, false, false, "", true);
|
||
|
UserReleaseId = Gen.startMethod("void", userReleaseFunction, "", "userinit", false, inlineUserInitDefaultCode, false, false, "", true);
|
||
|
}
|
||
|
|
||
|
NotifyInitId = Gen.startMethod("void", notifyInitFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
|
||
|
string initUCode = getUserCode("onInit");
|
||
|
if (!Inherited.empty())
|
||
|
Gen.add(Inherited+"::"+notifyInitFunction+"();");
|
||
|
if (DerivatedFlag)
|
||
|
Gen.add(userInitFunction+"();");
|
||
|
if (!initUCode.empty())
|
||
|
{
|
||
|
Gen.add("{");
|
||
|
uint line, col;
|
||
|
string file;
|
||
|
getFileLine(line, col, file);
|
||
|
Gen.add("// "+Name+" init user code, defined at "+file+":"+toString(line));
|
||
|
Gen.add(initUCode);
|
||
|
Gen.add("}");
|
||
|
}
|
||
|
|
||
|
NotifyReleaseId = Gen.startMethod("void", notifyReleaseFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
|
||
|
string releaseUCode = getUserCode("onRelease");
|
||
|
if (!releaseUCode.empty())
|
||
|
{
|
||
|
Gen.add("{");
|
||
|
uint line, col;
|
||
|
string file;
|
||
|
getFileLine(line, col, file);
|
||
|
Gen.add("// "+Name+" release user code, defined at "+file+":"+toString(line));
|
||
|
Gen.add(releaseUCode);
|
||
|
Gen.add("}");
|
||
|
}
|
||
|
if (DerivatedFlag)
|
||
|
Gen.add(userReleaseFunction+"();");
|
||
|
if (!Inherited.empty())
|
||
|
Gen.add(Inherited+"::"+notifyReleaseFunction+"();");
|
||
|
else if (HasRowAccess)
|
||
|
Gen.add(pdslibFunc("release")+"("+getId()+", __BaseRow);");
|
||
|
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
DestroyId.add(Inherited+"::"+destroyFunction+"();");
|
||
|
ClearId.add(Inherited+"::"+clearFunction+"();");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Generate XML description
|
||
|
//
|
||
|
string xmlnode;
|
||
|
xmlnode += "<classdef";
|
||
|
xmlnode += " name='"+Name+"'";
|
||
|
xmlnode += " id='"+toString(Id)+"'";
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
CClassNode *inh = getClassNode(Inherited);
|
||
|
xmlnode += " inherit='"+toString(inh->Id)+"'";
|
||
|
}
|
||
|
CDeclarationNode *dln = getClassKey();
|
||
|
if (dln != NULL)
|
||
|
{
|
||
|
xmlnode += " key='"+toString(dln->Id)+"'";
|
||
|
}
|
||
|
if (MapClass && !MapClass->HasParent)
|
||
|
{
|
||
|
xmlnode += " mapped='"+toString(MapClass->Id)+"'";
|
||
|
}
|
||
|
if (HasRowAccess)
|
||
|
{
|
||
|
/*
|
||
|
if (!Reserve.empty())
|
||
|
{
|
||
|
xmlnode += " allocate='"+(Reserve)+"'";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
xmlnode += " allocate='10000'";
|
||
|
}
|
||
|
*/
|
||
|
}
|
||
|
xmlnode += " columns='"+toString(Columns)+"'";
|
||
|
xmlnode += ">";
|
||
|
getDbNode()->xmlDescription.push_back(xmlnode);
|
||
|
|
||
|
indexUsedInInit = false;
|
||
|
indexUsedInDestroy = false;
|
||
|
indexUsedInFetch = false;
|
||
|
tableAndRowIndicesUsedInFetch = false;
|
||
|
indexUsedInRegister = false;
|
||
|
indexUsedInUnregister = false;
|
||
|
|
||
|
// generate code for init of new index
|
||
|
if (HasRowAccess)
|
||
|
{
|
||
|
RegisterId.add("__BaseRow = _IndexAllocator.allocate();");
|
||
|
if (GenerateDebugMessages)
|
||
|
{
|
||
|
if (MapClass != NULL)
|
||
|
{
|
||
|
CDeclarationNode* key = MapClass->getKey();
|
||
|
RegisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": register %u:%u, key="+key->displayPrintfPrefix()+"\", "+getId()+", __BaseRow, "+key->displayCppCode()+");");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RegisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": register %u:%u\", "+getId()+", __BaseRow);");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
string oeid;
|
||
|
if (useEntityId())
|
||
|
{
|
||
|
oeid = ", "+getClassKey()->cppName();
|
||
|
}
|
||
|
|
||
|
RegisterId.add(pdslibFunc("allocateRow")+"("+getId()+", __BaseRow, "+(PDSMapped ? MapClass->getKey()->toUint64() : "0")+oeid+");");
|
||
|
RegisterId.add(registerAttributesFunction + "();");
|
||
|
|
||
|
RegisterAttributesId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": registerAttributes %u:%u\", "+getId()+", __BaseRow);");
|
||
|
|
||
|
// send key to the pds (if key exists)
|
||
|
if (!ClassKey.empty())
|
||
|
{
|
||
|
CDeclarationNode *keyNode = getKey();
|
||
|
CTypeNode *keyTypeNode = getTypeNode(keyNode->Type);
|
||
|
///// TYPE CAST
|
||
|
RegisterAttributesId.add(pdslibFunc("set")+"("+getId()+", __BaseRow, ("+TColumnIndexName+")("+toString(keyNode->Column)+"), "+keyTypeNode->castToPDS(getKey()->cppName())+");");
|
||
|
}
|
||
|
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
RegisterAttributesId.add(Inherited + "::" + registerAttributesFunction + "();");
|
||
|
}
|
||
|
|
||
|
UnregisterAttributesId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregisterAttributes %u:%u\", "+getId()+", __BaseRow);");
|
||
|
|
||
|
if (!Inherited.empty())
|
||
|
{
|
||
|
UnregisterAttributesId.add(Inherited + "::" + unregisterAttributesFunction + "();");
|
||
|
}
|
||
|
|
||
|
if (HasParent)
|
||
|
{
|
||
|
UnregisterAttributesId.add(setParentFunction+"(NULL);");
|
||
|
}
|
||
|
|
||
|
if (GenerateDebugMessages)
|
||
|
{
|
||
|
if (MapClass != NULL)
|
||
|
{
|
||
|
CDeclarationNode* key = MapClass->getKey();
|
||
|
UnregisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregister %u:%u, key="+key->displayPrintfPrefix()+"\", "+getId()+", __BaseRow, "+key->displayCppCode()+");");
|
||
|
}
|
||
|
else
|
||
|
UnregisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregister %u:%u\", "+getId()+", __BaseRow);");
|
||
|
}
|
||
|
|
||
|
UnregisterId.add(unregisterAttributesFunction + "();");
|
||
|
|
||
|
oeid = "";
|
||
|
if (useEntityId())
|
||
|
{
|
||
|
oeid = ", "+getClassKey()->cppName();
|
||
|
}
|
||
|
|
||
|
UnregisterId.add(pdslibFunc("deallocateRow")+"("+getId()+", __BaseRow"+oeid+");");
|
||
|
UnregisterId.add("_IndexAllocator.deallocate(__BaseRow);");
|
||
|
//UnregisterId.add(destroyFunction+"();");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// add attributes and methods
|
||
|
// - attributes are in private part
|
||
|
// - read accessor are public
|
||
|
// - write accessor are public or delegated in public accessor objects
|
||
|
//
|
||
|
for (j=0; j<Nodes.size(); ++j)
|
||
|
{
|
||
|
CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(Nodes[j]);
|
||
|
if (!dln)
|
||
|
continue;
|
||
|
|
||
|
dln->Env = Env->nextArrayNode("dcl");
|
||
|
|
||
|
dln->generateContent();
|
||
|
|
||
|
}
|
||
|
|
||
|
uint columnId = 0;
|
||
|
|
||
|
for (j=0; j<Attributes.size(); ++j)
|
||
|
{
|
||
|
CDeclarationNode *dln = Attributes[j];
|
||
|
getDbNode()->xmlDescription.push_back("<attribute "+dln->XmlNode+"/>");
|
||
|
|
||
|
uint k;
|
||
|
for (k=0; k<dln->ColumnList.size(); ++k)
|
||
|
{
|
||
|
CColumn &column = dln->ColumnList[k];
|
||
|
//getDbNode()->xmlDescription.push_back("<column id='"+toString(k)+"' name='"+column.Name+"' type='"+column.TypeStr+"' typeid='"+toString(column.TypeId)+"' size='"+toString(column.ByteSize)+"' columnid='"+toString(columnId)+"'/>");
|
||
|
++columnId;
|
||
|
}
|
||
|
|
||
|
//getDbNode()->xmlDescription.push_back("</attribute>");
|
||
|
}
|
||
|
|
||
|
getDbNode()->xmlDescription.push_back("</classdef>");
|
||
|
|
||
|
if (HasTableAccess)
|
||
|
{
|
||
|
Gen.startConstructor("", "construct");
|
||
|
Gen.add("__BaseTable = "+toString(Id)+";");
|
||
|
|
||
|
Gen.startDestructor("construct", true, DerivatedFlag || HasInheritance);
|
||
|
}
|
||
|
|
||
|
// when inited/fetched a mapped class, map id to object
|
||
|
if (MappedFlag)
|
||
|
{
|
||
|
InitId.add("_Map["+getKey()->getFunc()+"()] = this;");
|
||
|
FetchId.add("_Map["+getKey()->getFunc()+"()] = this;");
|
||
|
DestroyId.add("_Map.erase("+getKey()->getFunc()+"());");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate IPDBaseData API
|
||
|
//
|
||
|
|
||
|
if (MappedFlag || DerivatedFlag || HasInheritance || ForceReference)
|
||
|
{
|
||
|
if (DerivatedFlag)
|
||
|
{
|
||
|
Gen.startMethod("void", staticSetUserFactoryFunction, TPDFactoryName+" userFactory", "map", false, inlineStaticPublic, true);
|
||
|
Gen.setDescription("Set user factory for this class (as class is indicated as derived, a home made constructor must be provided)");
|
||
|
Gen.add(staticInitFactoryFunction+"(userFactory);");
|
||
|
}
|
||
|
|
||
|
Gen.startMethod("void", staticInitFactoryFunction, TPDFactoryName+" userFactory", "factories", false, inlineStaticInternal, true);
|
||
|
Gen.add("if (!_FactoryInitialised)");
|
||
|
Gen.add("{");
|
||
|
Gen.add(pdslibFunc("registerClass")+"(" + toString(Id) + ", userFactory, "+staticFetchFunction+", "+((MappedFlag && !HasParent) ? staticNotifyLoadFailure : string("NULL"))+");");
|
||
|
Gen.add("_FactoryInitialised = true;");
|
||
|
Gen.add("}");
|
||
|
|
||
|
Gen.addAttribute("bool", "_FactoryInitialised", "factories", true);
|
||
|
|
||
|
if (MappedFlag || HasInheritance || ForceReference)
|
||
|
{
|
||
|
//
|
||
|
// create: create an object, then init attributes and register
|
||
|
//
|
||
|
|
||
|
Gen.startMethod(Name+"*", staticCreateFunction, InitProto, "map", false, inlineStaticPublic, true);
|
||
|
Gen.setDescription("Create an object of the "+Name+" class, and declare it to the PDS.");
|
||
|
if (GenerateDebugMessages)
|
||
|
{
|
||
|
Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": create\");");
|
||
|
}
|
||
|
if (DerivatedFlag)
|
||
|
{
|
||
|
Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>("+pdslibFunc("create")+"("+toString(Id)+"));");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>("+staticFactoryFunction+"());");
|
||
|
}
|
||
|
|
||
|
string str = objectVariable+"->" + initFunction + "(";
|
||
|
uint i;
|
||
|
for (i=0; i<Init.size(); ++i)
|
||
|
str += (i != 0 ? ", " : "") + Init[i]->Name;
|
||
|
str += ");";
|
||
|
Gen.add(str);
|
||
|
Gen.add(objectVariable+"->" + registerFunction + "();");
|
||
|
/*
|
||
|
if (MappedFlag)
|
||
|
{
|
||
|
Gen.add("_Map["+MapClass->ClassKey+"] = "+objectVariable+";");
|
||
|
}
|
||
|
*/
|
||
|
Gen.add(objectVariable+"->"+notifyInitFunction+"();");
|
||
|
Gen.add("return "+objectVariable+";");
|
||
|
}
|
||
|
|
||
|
if (MappedFlag)
|
||
|
{
|
||
|
CDeclarationNode *dln = (MapClass != NULL ? MapClass->getKey() : NULL);
|
||
|
CTypeNode *keyType = getTypeNode(dln->Type);
|
||
|
|
||
|
// only authorize remove/load/unload for mapped objects that are roots
|
||
|
if (!HasParent)
|
||
|
{
|
||
|
Gen.startMethod("void", staticRemoveFunction, "const "+keyType->getName()+"& "+dln->Name, "map", false, inlineStaticPublic, true);
|
||
|
Gen.setDescription("Destroy an object from the PDS. Caution! Object will no longer exist in database.\nAlso children (that is objects that belong to this object) are also destroyed.");
|
||
|
if (GenerateDebugMessages)
|
||
|
{
|
||
|
Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": remove "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");");
|
||
|
}
|
||
|
Gen.add("std::map<" + keyType->getName() + "," + Name + "*>::iterator\tit = _Map.find("+dln->Name+");");
|
||
|
Gen.add("if (it != _Map.end())");
|
||
|
Gen.add("{");
|
||
|
Gen.add(Name + "*\t__o = (*it).second;");
|
||
|
Gen.add("__o->"+notifyReleaseFunction+"();");
|
||
|
Gen.add("__o->"+unregisterFunction+"();");
|
||
|
Gen.add("__o->"+destroyFunction+"();");
|
||
|
Gen.add("delete __o;");
|
||
|
//Gen.add("_Map.erase(it);");
|
||
|
Gen.add("}");
|
||
|
|
||
|
Gen.startMethod("void", staticLoadFunction, "const "+keyType->getName()+"& "+dln->Name, "map", false, inlineStaticPublic, true);
|
||
|
Gen.setDescription("Retrieve an object from the database.\nData are sent asynchronously, so the load callback is called when data are ready.\nUse get() to access to the loaded object.");
|
||
|
if (GenerateDebugMessages)
|
||
|
{
|
||
|
Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": load "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");");
|
||
|
}
|
||
|
Gen.add(pdslibFunc("load")+"("+toString(Id)+", "+dln->toUint64(dln->Name)+");");
|
||
|
|
||
|
Gen.startMethod("void", staticSetLoadCbFunction, "void (*callback)(const "+keyType->getName()+"& key, "+Name+"* object)", "map", false, inlineStaticPublic, true);
|
||
|
Gen.setDescription("Setup load callback so client is warned that load succeded or failed.");
|
||
|
Gen.add(staticLoadCbAttribute+" = callback;");
|
||
|
|
||
|
Gen.startMethod("void", staticNotifyLoadFailure, "uint64 key", "factories", false, inlineStaticInternal, true);
|
||
|
Gen.add("if ("+staticLoadCbAttribute+" != NULL)");
|
||
|
Gen.add("{");
|
||
|
Gen.add(staticLoadCbAttribute+"("+keyType->castFromUser("key")+", NULL);");
|
||
|
Gen.add("}");
|
||
|
|
||
|
Gen.addAttribute("void", staticLoadCbAttribute, "factories", true, "NULL", true, "const "+keyType->getName()+"& key, "+Name+"* object");
|
||
|
|
||
|
|
||
|
//
|
||
|
Gen.startMethod("void", staticUnloadFunction, "const " + keyType->getName() + " &" + dln->Name, "map", false, inlineStaticPublic, true);
|
||
|
Gen.setDescription("Unload an object from the client memory. Object still exists in database and can be retrieved again using load.");
|
||
|
if (GenerateDebugMessages)
|
||
|
{
|
||
|
Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unload "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");");
|
||
|
}
|
||
|
Gen.add("std::map<" + keyType->getName() + "," + Name + "*>::iterator\tit = _Map.find("+dln->Name+");");
|
||
|
Gen.add("if (it != _Map.end())");
|
||
|
Gen.add("{");
|
||
|
Gen.add(Name + "*\t__o = (*it).second;");
|
||
|
Gen.add("__o->"+notifyReleaseFunction+"();");
|
||
|
Gen.add("__o->"+destroyFunction+"();");
|
||
|
Gen.add("delete __o;");
|
||
|
//Gen.add("_Map.erase(it);");
|
||
|
Gen.add("}");
|
||
|
}
|
||
|
|
||
|
std::string mapType = "std::map<"+keyType->getName()+", "+Name+"*>";
|
||
|
|
||
|
Gen.startMethod(Name+"*", staticGetFunction, "const " + keyType->getName() + " &" + dln->Name, "map", false, inlineStaticPublic, true);
|
||
|
Gen.setDescription("Get an object in client. Object must have been previously loaded from database with a load.");
|
||
|
if (GenerateDebugMessages)
|
||
|
{
|
||
|
Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": get "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");");
|
||
|
}
|
||
|
Gen.add(mapType+"::iterator\t__it = _Map.find("+dln->Name+");");
|
||
|
if (GenerateDebugMessages)
|
||
|
{
|
||
|
Gen.add("if (__it == _Map.end())");
|
||
|
Gen.add("nlwarning(\""+Name+": unable to get %\"NL_I64\"u, not found in map.\", "+dln->toUint64(dln->Name)+");");
|
||
|
}
|
||
|
Gen.add("return (__it != _Map.end()) ? (*__it).second : NULL;");
|
||
|
|
||
|
Gen.startMethod(mapType+"::iterator", staticBeginFunction, "", "map", false, inlineStaticPublic, true);
|
||
|
Gen.setDescription("Return the begin iterator of the global map of "+Name);
|
||
|
Gen.add("return _Map.begin();");
|
||
|
|
||
|
Gen.startMethod(mapType+"::iterator", staticEndFunction, "", "map", false, inlineStaticPublic, true);
|
||
|
Gen.setDescription("Return the end iterator of the global map of "+Name);
|
||
|
Gen.add("return _Map.end();");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// generate internal management functions
|
||
|
//
|
||
|
|
||
|
if (HasRowAccess || MappedFlag)
|
||
|
{
|
||
|
if (MappedFlag)
|
||
|
{
|
||
|
CDeclarationNode *dln = (MappedFlag ? getKey() : NULL);
|
||
|
CTypeNode *keyType = getTypeNode(dln->Type);
|
||
|
Gen.addAttribute("std::map<" + keyType->getName() + "," + Name + "*>", "_Map", "inherit map", true);
|
||
|
}
|
||
|
|
||
|
Gen.addAttribute(indexAllocatorName, "_IndexAllocator", "factories", true);
|
||
|
|
||
|
Gen.startMethod("void", staticInitFunction, "", "internal", false, inlineInternal, true, false, "", false);
|
||
|
Gen.add(pdslibFunc("setIndexAllocator")+"("+toString(Id)+", _IndexAllocator);");
|
||
|
if (MappedFlag || DerivatedFlag || HasInheritance || ForceReference)
|
||
|
{
|
||
|
if (DerivatedFlag)
|
||
|
{
|
||
|
// check factory has been set
|
||
|
Gen.add("nlassertex(_FactoryInitialised, (\"User Factory for class "+Name+" not set!\"));");
|
||
|
Gen.add("// factory must have been set by user before database init called!");
|
||
|
Gen.add("// You must provide a factory for the class "+Name+" as it is marked as derived");
|
||
|
Gen.add("// Call "+getDbNode()->Name+"::"+Name+"::"+staticSetUserFactoryFunction+"() with a factory before any call to "+getDbNode()->Name+"::init()!");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Gen.add(staticInitFactoryFunction+"("+staticFactoryFunction+");");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
getDbNode()->initDb.add(Name+"::"+staticInitFunction+"();");
|
||
|
|
||
|
if (ForceReference)
|
||
|
{
|
||
|
if (!DerivatedFlag) // forbid factory function for derivated classes
|
||
|
{
|
||
|
Gen.startMethod(pdBaseDataName+"*", staticFactoryFunction, "", "factories", false, inlineStaticInternal, true);
|
||
|
Gen.add("return new " + Name + "();");
|
||
|
}
|
||
|
|
||
|
if (Inherited.empty())
|
||
|
{
|
||
|
Gen.startMethod("void", staticFetchFunction, pdBaseDataName+" *object, "+CPDataName+" &data", "factories", false, inlineStaticInternal, true);
|
||
|
Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>(object);");
|
||
|
Gen.add(objectVariable+"->"+fetchFunction+"(data);");
|
||
|
if (MappedFlag)
|
||
|
{
|
||
|
//Gen.add("_Map["+objectVariable+"->"+getKey()->getFunc()+"()] = "+objectVariable+";");
|
||
|
if (!HasParent)
|
||
|
{
|
||
|
Gen.add("if ("+staticLoadCbAttribute+" != NULL)");
|
||
|
Gen.add("{");
|
||
|
Gen.add(staticLoadCbAttribute+"("+objectVariable+"->"+getKey()->getFunc()+"(), "+objectVariable+");");
|
||
|
Gen.add("}");
|
||
|
}
|
||
|
}
|
||
|
Gen.add(objectVariable+"->"+notifyInitFunction+"();");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// EGS Compat
|
||
|
// -- begin
|
||
|
|
||
|
ApplyId.add( "else");
|
||
|
ApplyId.add( "{");
|
||
|
ApplyId.add( "nlwarning(\"Skipping unrecognised token: %s\", __pdr.peekNextTokenName().c_str());");
|
||
|
ApplyId.add( "__pdr.skipData();");
|
||
|
ApplyId.add( "}");
|
||
|
ApplyId.add("}");
|
||
|
|
||
|
if (MappedFlag && !HasParent)
|
||
|
{
|
||
|
ApplyId.add(notifyInitFunction+"();");
|
||
|
}
|
||
|
|
||
|
|
||
|
//EGSImplId.add("\n#include \"game_share/persistent_data_template.h\"");
|
||
|
//EGSImplId.add("#undef PERSISTENT_CLASS");
|
||
|
//EGSImplId.add("#undef PERSISTENT_DATA");
|
||
|
|
||
|
// -- end
|
||
|
|
||
|
set<string>::iterator itf;
|
||
|
for (itf=Friends.begin(); itf!=Friends.end(); ++itf)
|
||
|
if (*itf != Name)
|
||
|
Gen.addOther("friend class "+(*itf)+";\n", "friends");
|
||
|
for (itf=ForwardFriends.begin(); itf!=ForwardFriends.end(); ++itf)
|
||
|
if (*itf != Name)
|
||
|
Gen.addOther("friend class "+(*itf)+";\n", "friends");
|
||
|
Gen.addOther("friend class "+CPDSLibName+";\n", "friends");
|
||
|
CDbNode* dbNode = getDbNode();
|
||
|
Gen.addOther("friend void "+dbNode->Name+"::init(uint32);\n", "friends");
|
||
|
|
||
|
Gen.flush(hOutput(), cppOutput(), inlineOutput());
|
||
|
|
||
|
DbSummary << "\n\n";
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void CClassNode::generateContentInCall(CCallContext *context)
|
||
|
{
|
||
|
uint j;
|
||
|
for (j=0; j<Nodes.size(); ++j)
|
||
|
{
|
||
|
CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(Nodes[j]);
|
||
|
if (!dln)
|
||
|
continue;
|
||
|
|
||
|
dln->generateContent(context);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Declaration Node
|
||
|
bool CDeclarationNode::prolog()
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CDeclarationNode::epilog()
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateContent(CCallContext *context)
|
||
|
{
|
||
|
ClassNode = static_cast<CClassNode*>(Parent);
|
||
|
|
||
|
nlassert(Env != NULL);
|
||
|
|
||
|
setEnv("name", Name);
|
||
|
|
||
|
XmlNode = "name='"+Name+"' id='"+toString(Id)+"' columnid='"+toString(Column)+"' columns='"+toString(Columns)+"'";
|
||
|
|
||
|
if (context == NULL)
|
||
|
{
|
||
|
CCppOutput& DbSummary = getDbNode()->DbSummary;
|
||
|
DbSummary << "Attribute " << Name << ":\n";
|
||
|
}
|
||
|
|
||
|
switch (DeclarationType)
|
||
|
{
|
||
|
case SimpleType:
|
||
|
generateTypeContent(context);
|
||
|
break;
|
||
|
|
||
|
case SimpleClass:
|
||
|
generateClassContent(context);
|
||
|
break;
|
||
|
|
||
|
case BackRef:
|
||
|
generateBackRefContent();
|
||
|
break;
|
||
|
|
||
|
case ForwardRef:
|
||
|
generateForwardRefContent();
|
||
|
break;
|
||
|
|
||
|
case ArrayType:
|
||
|
generateArrayTypeContent(context);
|
||
|
break;
|
||
|
|
||
|
case ArrayClass:
|
||
|
generateArrayClassContent(context);
|
||
|
break;
|
||
|
|
||
|
case ArrayRef:
|
||
|
generateArrayRefContent(context);
|
||
|
break;
|
||
|
|
||
|
case Set:
|
||
|
generateSetContent(context);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
error("Can't decide declaration type");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (context == NULL)
|
||
|
{
|
||
|
ClassNode->Gen.separator("methods");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
std::string CDeclarationNode::getAccessorName(CCallContext *context, const std::string& accessortype, const std::string& sep)
|
||
|
{
|
||
|
return context->getRootCaller()->Name + sep +accessortype + context->getCallString();
|
||
|
}
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateTypeContent(CCallContext *context)
|
||
|
{
|
||
|
CClassGenerator& Gen = ClassNode->Gen;
|
||
|
CCppOutput& DbSummary = getDbNode()->DbSummary;
|
||
|
|
||
|
CClassGenerator::SMethodId &InitId = ClassNode->InitId;
|
||
|
CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
|
||
|
CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
|
||
|
CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
|
||
|
CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
|
||
|
CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
|
||
|
CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
|
||
|
CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
|
||
|
CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
|
||
|
CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
|
||
|
|
||
|
string UCodeContext;
|
||
|
if (context != NULL)
|
||
|
UCodeContext = context->getUserCodeContext();
|
||
|
|
||
|
string onGetUser = getUserCode("onGet", UCodeContext);
|
||
|
string onSetUser = getUserCode("onSet", UCodeContext);
|
||
|
string onChangeUser = getUserCode("onChange", UCodeContext);
|
||
|
|
||
|
CTypeNode *tnd = getTypeNode(Type);
|
||
|
XmlNode += " type='type' typeid='"+toString(tnd->Id)+"'";
|
||
|
|
||
|
setEnv("decltype", "type");
|
||
|
setEnv("type", tnd->getName());
|
||
|
define(IsKey, "iskey");
|
||
|
setEnv("defaultvalue", tnd->getDefaultValue());
|
||
|
setEnv("checkcode", tnd->checkCode(Name));
|
||
|
|
||
|
CCallContext ctx(this);
|
||
|
if (context != NULL)
|
||
|
ctx = context->getSubContext(this);
|
||
|
CClassGenerator &gen = ctx.getRootCaller()->Gen;
|
||
|
|
||
|
// EGS Compat
|
||
|
// -- begin
|
||
|
|
||
|
CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
|
||
|
CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
|
||
|
|
||
|
|
||
|
ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
|
||
|
ApplyId.add("{");
|
||
|
tnd->generateApplyCode(ApplyId, tokenName(), cppName());
|
||
|
ApplyId.add("}");
|
||
|
|
||
|
tnd->generateStoreCode(StoreId, tokenName(), cppName());
|
||
|
|
||
|
// -- end
|
||
|
|
||
|
CTemplatizerEnv* env = ctx.getRootDeclaration()->Env->nextArrayNode("accessors");
|
||
|
|
||
|
env->set("name", Name);
|
||
|
env->set("type", tnd->getName());
|
||
|
env->set("defaultvalue", tnd->getDefaultValue());
|
||
|
env->set("checkcode", tnd->checkCode(Name));
|
||
|
env->define(ctx.getRootCaller()->HasRowAccess, "rowaccess");
|
||
|
env->define(IsKey, "iskey");
|
||
|
env->set("rootcallerid", ctx.getRootCaller()->getId());
|
||
|
env->set("callstr", ctx.getCallString());
|
||
|
env->set("callargs", ctx.getCallArgList());
|
||
|
env->set("callpath", ctx.getCallPath());
|
||
|
env->set("column", ctx.getColumn());
|
||
|
env->set("valuevar", valueVariable);
|
||
|
env->set("castcpp", tnd->castToCpp(valueVariable));
|
||
|
env->set("castpds", tnd->castToPDS(valueVariable));
|
||
|
|
||
|
vector<string> checks = ctx.getCheckCode();
|
||
|
for (uint i=0; i<checks.size(); ++i)
|
||
|
env->nextArrayNode("checks")->set("check", checks[i]);
|
||
|
env->nextArrayNode("checks")->set("check", tnd->checkCode(valueVariable));
|
||
|
|
||
|
if (!onGetUser.empty()) env->set("onget", onGetUser);
|
||
|
if (!onSetUser.empty()) env->set("onset", onSetUser);
|
||
|
if (!onChangeUser.empty()) env->set("onchange", onChangeUser);
|
||
|
|
||
|
//
|
||
|
// generate read accessor
|
||
|
//
|
||
|
if (ctx.getRootCaller()->HasRowAccess)
|
||
|
{
|
||
|
string arglist = ctx.getCallArgList();
|
||
|
|
||
|
gen.startMethod(tnd->getName(), getFunctionPrefix+ctx.getCallString(), arglist, "methods", true, inlineAccessors);
|
||
|
|
||
|
DbSummary << "\t" << getFunctionPrefix+ctx.getCallString() << "\n";
|
||
|
|
||
|
uint i;
|
||
|
vector<string> checks = ctx.getCheckCode();
|
||
|
for (i=0; i<checks.size(); ++i)
|
||
|
{
|
||
|
gen.add(checks[i]);
|
||
|
}
|
||
|
|
||
|
if (!onGetUser.empty())
|
||
|
{
|
||
|
gen.add("{");
|
||
|
gen.add(onGetUser);
|
||
|
gen.add("}");
|
||
|
}
|
||
|
gen.add("return "+ctx.getCallPath()+";");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate write accessor
|
||
|
//
|
||
|
if (ctx.getRootCaller()->HasRowAccess && !IsKey)
|
||
|
{
|
||
|
string arglist = ctx.getCallArgList();
|
||
|
|
||
|
if (!arglist.empty())
|
||
|
arglist += ", ";
|
||
|
arglist += tnd->getName()+" "+valueVariable;
|
||
|
gen.startMethod("void", setFunctionPrefix+ctx.getCallString(), appendArg(arglist, "bool forceWrite=false"), "methods", false, inlineAccessors);
|
||
|
|
||
|
DbSummary << "\t" << setFunctionPrefix << ctx.getCallString() << "\n";
|
||
|
|
||
|
if (GenerateHAuto)
|
||
|
{
|
||
|
gen.add("H_AUTO("+getAccessorName(&ctx, setFunctionPrefix, "_")+")");
|
||
|
}
|
||
|
|
||
|
if (VerboseMode)
|
||
|
{
|
||
|
string verbStr;
|
||
|
string callStr;
|
||
|
|
||
|
verbStr = "nlinfo(\"" + ctx.getRootCaller()->Name + "(%d:%d)::" +setFunctionPrefix + ctx.getCallString() + "(";
|
||
|
|
||
|
callStr = ctx.getDebugCallStringFmt();
|
||
|
if (!callStr.empty())
|
||
|
callStr += ", ";
|
||
|
|
||
|
callStr += valueVariable+"="+tnd->getPrintfFmt();
|
||
|
|
||
|
verbStr += callStr;
|
||
|
verbStr += ")\", __BaseTable, __BaseRow, ";
|
||
|
|
||
|
callStr = ctx.getDebugCallStringVal();
|
||
|
if (!callStr.empty())
|
||
|
callStr += ", ";
|
||
|
|
||
|
callStr += tnd->getPrintfVal(valueVariable);
|
||
|
|
||
|
verbStr += callStr;
|
||
|
verbStr += ");";
|
||
|
|
||
|
gen.add(verbStr);
|
||
|
}
|
||
|
|
||
|
uint i;
|
||
|
vector<string> checks = ctx.getCheckCode();
|
||
|
for (i=0; i<checks.size(); ++i)
|
||
|
{
|
||
|
gen.add(checks[i]);
|
||
|
}
|
||
|
gen.add(tnd->checkCode(valueVariable));
|
||
|
|
||
|
///// TYPE CAST
|
||
|
if (!onChangeUser.empty())
|
||
|
{
|
||
|
gen.add("if ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+")");
|
||
|
gen.add("{");
|
||
|
gen.add(onChangeUser);
|
||
|
gen.add("}");
|
||
|
}
|
||
|
if (!onSetUser.empty())
|
||
|
{
|
||
|
gen.add("{");
|
||
|
gen.add(onSetUser);
|
||
|
gen.add("}");
|
||
|
}
|
||
|
if (WriteTriggerFlag)
|
||
|
{
|
||
|
gen.add("if (forceWrite && ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+"))");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gen.add("if (("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+") || forceWrite)");
|
||
|
}
|
||
|
gen.add("{");
|
||
|
bool useEntityId = ctx.hasRootEntityIdKey();
|
||
|
if (useEntityId)
|
||
|
{
|
||
|
gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+", "+ctx.getRootCaller()->getKey()->cppName()+");");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");");
|
||
|
}
|
||
|
gen.add("}");
|
||
|
gen.add(ctx.getCallPath()+" = "+tnd->castToCpp(valueVariable)+";");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate attribute
|
||
|
//
|
||
|
Gen.addAttribute(tnd->getName(), cppName(), "attributes");
|
||
|
|
||
|
|
||
|
string defaultValue;
|
||
|
if (!DefaultValue.empty())
|
||
|
defaultValue = DefaultValue;
|
||
|
else
|
||
|
defaultValue = tnd->getDefaultValue();
|
||
|
|
||
|
//
|
||
|
// generate init
|
||
|
//
|
||
|
if (!IsKey)
|
||
|
{
|
||
|
InitId.add(cppName()+" = "+defaultValue+";");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InitId.add(tnd->checkCode(Name));
|
||
|
InitId.add(cppName()+" = "+Name+";");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate create code
|
||
|
//
|
||
|
|
||
|
|
||
|
//
|
||
|
// generate fetch code
|
||
|
//
|
||
|
if (tnd->isEnum())
|
||
|
FetchId.add("data.serialEnum("+cppName()+");");
|
||
|
else if (tnd->CppType != tnd->StorageType)
|
||
|
{
|
||
|
FetchId.add("{");
|
||
|
FetchId.add(tnd->StorageType+"\t_v;");
|
||
|
FetchId.add("data.serial(_v);");
|
||
|
FetchId.add(cppName()+" = "+tnd->castToCpp("_v")+";");
|
||
|
FetchId.add("}");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FetchId.add("data.serial("+cppName()+");");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate clear code
|
||
|
//
|
||
|
if (ctx.getRootCaller()->HasRowAccess && !IsKey)
|
||
|
{
|
||
|
ctx.getRootCaller()->ClearId.add(ctx.getCallPath()+" = "+defaultValue+";");
|
||
|
ctx.getRootCaller()->ClearId.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(defaultValue)+");");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateClassContent(CCallContext *context)
|
||
|
{
|
||
|
setEnv("decltype", "class");
|
||
|
|
||
|
CClassGenerator &Gen = ClassNode->Gen;
|
||
|
CCppOutput& DbSummary = getDbNode()->DbSummary;
|
||
|
|
||
|
CClassGenerator::SMethodId &InitId = ClassNode->InitId;
|
||
|
CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
|
||
|
CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
|
||
|
CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
|
||
|
CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
|
||
|
CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
|
||
|
CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
|
||
|
CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
|
||
|
CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
|
||
|
CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
|
||
|
|
||
|
CClassNode *cnd = getClassNode(Type);
|
||
|
XmlNode += " type='class' classid='"+toString(cnd->Id)+"'";
|
||
|
|
||
|
setEnv("type", Type);
|
||
|
|
||
|
// EGS Compat
|
||
|
// -- begin
|
||
|
|
||
|
CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
|
||
|
CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
|
||
|
|
||
|
StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
|
||
|
StoreId.add(cppName()+".store(__pdr);");
|
||
|
StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
|
||
|
|
||
|
ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add("__pdr.popStructBegin("+tokenName()+");");
|
||
|
ApplyId.add(cppName()+".apply(__pdr);");
|
||
|
ApplyId.add("__pdr.popStructEnd("+tokenName()+");");
|
||
|
ApplyId.add("}");
|
||
|
|
||
|
// -- end
|
||
|
|
||
|
|
||
|
//
|
||
|
// export class accessors into root caller
|
||
|
//
|
||
|
CCallContext ctx;
|
||
|
if (context != NULL)
|
||
|
ctx = *context;
|
||
|
ctx.Context.push_back(this);
|
||
|
cnd->generateContentInCall(&ctx);
|
||
|
|
||
|
//
|
||
|
// generate attribute
|
||
|
//
|
||
|
Gen.addAttribute(Type, cppName(), "attributes");
|
||
|
|
||
|
//
|
||
|
// generate init
|
||
|
//
|
||
|
InitId.add(cppName()+"."+initFunction+"();");
|
||
|
|
||
|
//
|
||
|
// generate create code
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate fetch code
|
||
|
//
|
||
|
FetchId.add(cppName()+"."+fetchFunction+"(data);");
|
||
|
|
||
|
//
|
||
|
// generate clear code
|
||
|
//
|
||
|
//ClearId.add(cppName()+"."+clearFunction+"();");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateBackRefContent()
|
||
|
{
|
||
|
setEnv("decltype", "backref");
|
||
|
define(HiddenFlag, "hidden");
|
||
|
|
||
|
CClassGenerator &Gen = ClassNode->Gen;
|
||
|
CCppOutput& DbSummary = getDbNode()->DbSummary;
|
||
|
|
||
|
CClassGenerator::SMethodId &InitId = ClassNode->InitId;
|
||
|
CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
|
||
|
CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
|
||
|
CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
|
||
|
CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
|
||
|
CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
|
||
|
CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
|
||
|
CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
|
||
|
CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
|
||
|
CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
|
||
|
|
||
|
CClassNode *cnd = getClassNode(ParentClass);
|
||
|
CDeclarationNode *dnd = cnd->getDeclarationNode(ParentField);
|
||
|
CDeclarationNode *knd = (ClassNode->ClassKey.empty() ? NULL : ClassNode->getKey());
|
||
|
XmlNode += " type='backref' classid='"+toString(cnd->Id)+"' backreferentid='"+toString(dnd->Id)+"'";
|
||
|
if (knd != NULL)
|
||
|
XmlNode += " key='"+toString(knd->Id)+"'";
|
||
|
|
||
|
setEnv("type", ParentClass);
|
||
|
|
||
|
//
|
||
|
// generate read accessor
|
||
|
//
|
||
|
Gen.startMethod(ParentClass+"*", getFunc(), "", "methods", false, inlineAccessors);
|
||
|
Gen.add("return "+cppName()+";");
|
||
|
|
||
|
Gen.startMethod("const "+ParentClass+"*", getFunc(), "", "methods", true, inlineAccessors);
|
||
|
Gen.add("return "+cppName()+";");
|
||
|
|
||
|
DbSummary << "\t" << getFunc() << "\n";
|
||
|
|
||
|
//
|
||
|
// generate write accessor
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate attribute
|
||
|
//
|
||
|
Gen.addAttribute(ParentClass+"*", cppName(), "attributes");
|
||
|
|
||
|
//
|
||
|
// generate init
|
||
|
//
|
||
|
InitId.add(cppName()+" = NULL;");
|
||
|
|
||
|
//
|
||
|
// generate create code
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate fetch code
|
||
|
//
|
||
|
FetchId.add(cppName()+" = NULL;");
|
||
|
|
||
|
//
|
||
|
// generate set parent code
|
||
|
//
|
||
|
|
||
|
bool useId = ClassNode->useEntityId();
|
||
|
bool parentUseId = cnd->useEntityId();
|
||
|
|
||
|
if (parentUseId)
|
||
|
SetParentId.add("NLMISC::CEntityId\tprevId;");
|
||
|
|
||
|
if (!HiddenFlag)
|
||
|
{
|
||
|
//SetParentId.add(pdslibFunc("set")+"("+ClassNode->getId()+", getRow(), ("+TColumnIndexName+")("+toString(Column)+"), (__parent != NULL ? "+objectIndexName+"("+(cnd->HasInheritance ? toString("__parent->getTable()") : toString(cnd->Id))+", __parent->getRow()) : "+nullIndexName+"));");
|
||
|
|
||
|
SetParentId.add("if ("+cppName()+" != NULL)");
|
||
|
SetParentId.add("{");
|
||
|
|
||
|
if (parentUseId)
|
||
|
SetParentId.add("prevId = "+cppName()+"->"+getFunctionPrefix+cnd->getKey()->Name+"();");
|
||
|
|
||
|
if (ClassNode->getClassKey() == NULL)
|
||
|
{
|
||
|
SetParentId.add(cppName()+"->"+dnd->unlinkFunc()+"();");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetParentId.add(cppName()+"->"+dnd->unlinkFunc()+"("+ClassNode->getKey()->cppName()+");");
|
||
|
}
|
||
|
SetParentId.add("}");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (parentUseId)
|
||
|
{
|
||
|
SetParentId.add("if ("+cppName()+" != NULL)");
|
||
|
SetParentId.add("{");
|
||
|
SetParentId.add("prevId = "+cppName()+"->"+cnd->getKey()->cppName()+";");
|
||
|
SetParentId.add("}");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
string oeid;
|
||
|
string peid;
|
||
|
|
||
|
if (useId)
|
||
|
oeid = ", "+ClassNode->getKey()->cppName();
|
||
|
|
||
|
if (parentUseId)
|
||
|
peid = ", ("+cppName()+" != NULL ? "+cppName()+"->"+getFunctionPrefix+cnd->getKey()->Name+"() : NLMISC::CEntityId::Unknown), prevId";
|
||
|
|
||
|
SetParentId.add(cppName()+" = __parent;");
|
||
|
SetParentId.add(pdslibFunc("setParent")+"("+ClassNode->getId()+", getRow(), ("+TColumnIndexName+")("+toString(Column)+"), (__parent != NULL ? "+objectIndexName+"("+(cnd->HasInheritance ? toString("__parent->getTable()") : toString(cnd->Id))+", __parent->getRow()) : "+nullIndexName+")"+oeid+peid+");");
|
||
|
|
||
|
SetUnnotifiedParentId.add(cppName()+" = __parent;");
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateClassPtrApplyCode(const std::string& value)
|
||
|
{
|
||
|
CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
|
||
|
|
||
|
ApplyId.add(value+" = NULL;");
|
||
|
ApplyId.add("if (__pdr.peekNextToken() == __Tok_ClassName)");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add( "std::string\t__className;");
|
||
|
ApplyId.add( "__pdr.pop(__Tok_ClassName, __className);");
|
||
|
ApplyId.add( value+" = "+Type+"::cast("+pdslibFunc("create")+"(__className));");
|
||
|
ApplyId.add( "if ("+value+" != NULL)");
|
||
|
ApplyId.add( "{");
|
||
|
ApplyId.add( "__pdr.popStructBegin("+tokenName()+");");
|
||
|
ApplyId.add( value+"->apply(__pdr);");
|
||
|
ApplyId.add( value+"->"+setUnnotifiedParentFunction+"(this);");
|
||
|
ApplyId.add( "__pdr.popStructEnd("+tokenName()+");");
|
||
|
ApplyId.add( "}");
|
||
|
ApplyId.add( "else");
|
||
|
ApplyId.add( "{");
|
||
|
ApplyId.add( "__pdr.skipStruct();");
|
||
|
ApplyId.add( "}");
|
||
|
ApplyId.add("}");
|
||
|
}
|
||
|
|
||
|
void CDeclarationNode::generateClassPtrStoreCode(const std::string& value)
|
||
|
{
|
||
|
CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
|
||
|
|
||
|
StoreId.add("if ("+value+" != NULL)");
|
||
|
StoreId.add("{");
|
||
|
StoreId.add( "std::string\t__className = "+pdslibFunc("getClassName")+"("+value+");");
|
||
|
StoreId.add( "__pdr.push(__Tok_ClassName, __className);");
|
||
|
StoreId.add( "__pdr.pushStructBegin("+tokenName()+");");
|
||
|
StoreId.add( value+"->store(__pdr);");
|
||
|
StoreId.add( "__pdr.pushStructEnd("+tokenName()+");");
|
||
|
StoreId.add("}");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateForwardRefContent()
|
||
|
{
|
||
|
setEnv("decltype", "forwardref");
|
||
|
|
||
|
CClassGenerator &Gen = ClassNode->Gen;
|
||
|
CCppOutput& DbSummary = getDbNode()->DbSummary;
|
||
|
|
||
|
CClassGenerator::SMethodId &InitId = ClassNode->InitId;
|
||
|
CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
|
||
|
CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
|
||
|
CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
|
||
|
CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
|
||
|
CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
|
||
|
CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
|
||
|
CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
|
||
|
CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
|
||
|
CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId;
|
||
|
CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId;
|
||
|
|
||
|
CClassNode *cnd = getClassNode(Type);
|
||
|
CDeclarationNode *dnd = cnd->getDeclarationNode(ForwardRefAttribute);
|
||
|
CDeclarationNode *knd = (cnd->ClassKey.empty() ? NULL : cnd->getKey());
|
||
|
XmlNode += " type='forwardref' classid='"+toString(cnd->Id)+"' forwardreferedid='"+toString(dnd->Id)+"'";
|
||
|
if (knd != NULL)
|
||
|
XmlNode += " key='"+toString(knd->Id)+"'";
|
||
|
|
||
|
setEnv("type", Type);
|
||
|
|
||
|
// EGS Compat
|
||
|
// -- begin
|
||
|
|
||
|
CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
|
||
|
CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
|
||
|
|
||
|
StoreId.add("// store "+Name);
|
||
|
StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
|
||
|
generateClassPtrStoreCode(cppName());
|
||
|
StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
|
||
|
|
||
|
ApplyId.add("// apply "+Name);
|
||
|
ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add( "__pdr.popStructBegin("+tokenName()+");");
|
||
|
generateClassPtrApplyCode(cppName());
|
||
|
ApplyId.add( "__pdr.popStructEnd("+tokenName()+");");
|
||
|
ApplyId.add("}");
|
||
|
|
||
|
// -- end
|
||
|
|
||
|
|
||
|
//
|
||
|
// generate read accessor
|
||
|
//
|
||
|
Gen.startMethod(Type+"*", getFunc(), "", "methods", false, inlineAccessors);
|
||
|
Gen.add("return "+cppName()+";");
|
||
|
|
||
|
Gen.startMethod("const "+Type+"*", getFunc(), "", "methods", true, inlineAccessors);
|
||
|
Gen.add("return "+cppName()+";");
|
||
|
|
||
|
DbSummary << "\t" << getFunc() << "\n";
|
||
|
|
||
|
//
|
||
|
// generate write accessor
|
||
|
//
|
||
|
Gen.startMethod("void", setFunc(), Type+"* "+valueVariable, "methods", false, inlineAccessors);
|
||
|
Gen.add("if ("+cppName()+" != NULL)");
|
||
|
Gen.add("{");
|
||
|
Gen.add(cppName()+"->"+setParentFunction+"(NULL);");
|
||
|
Gen.add("}");
|
||
|
Gen.add(valueVariable+"->"+setParentFunction+"(this);");
|
||
|
Gen.add(cppName()+" = "+valueVariable+";");
|
||
|
|
||
|
DbSummary << "\t" << setFunc() << "\n";
|
||
|
|
||
|
//
|
||
|
// generate attribute
|
||
|
//
|
||
|
Gen.addAttribute(Type+"*", cppName(), "attributes");
|
||
|
|
||
|
//
|
||
|
// generate init
|
||
|
//
|
||
|
InitId.add(cppName()+" = NULL;");
|
||
|
|
||
|
//
|
||
|
// generate destroy code
|
||
|
//
|
||
|
DestroyId.add("if ("+cppName()+" != NULL)");
|
||
|
DestroyId.add("{");
|
||
|
DestroyId.add(Type+"*\t__o = "+cppName()+";");
|
||
|
DestroyId.add("__o->"+destroyFunction+"();");
|
||
|
DestroyId.add("delete __o;");
|
||
|
DestroyId.add("}");
|
||
|
|
||
|
//
|
||
|
// generate create code
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate fetch code
|
||
|
//
|
||
|
FetchId.add("// read table and row, create an object, affect to the ref, and fetch it");
|
||
|
if (!ClassNode->tableAndRowIndicesUsedInFetch)
|
||
|
{
|
||
|
FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;");
|
||
|
ClassNode->tableAndRowIndicesUsedInFetch = true;
|
||
|
}
|
||
|
FetchId.add(cppName()+" = NULL;");
|
||
|
FetchId.add("data.serial(tableIndex, rowIndex);");
|
||
|
FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")");
|
||
|
FetchId.add("{");
|
||
|
FetchId.add(cppName()+" = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));");
|
||
|
FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+cppName()+");");
|
||
|
FetchId.add(cppName()+"->"+fetchFunction+"(data);");
|
||
|
FetchId.add(cppName()+"->"+setUnnotifiedParentFunction+"(this);");
|
||
|
FetchId.add("}");
|
||
|
|
||
|
//
|
||
|
// generate register/unregister code
|
||
|
//
|
||
|
|
||
|
UnregisterAttributesId.add("if ("+cppName()+" != NULL)");
|
||
|
UnregisterAttributesId.add("{");
|
||
|
UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = "+cppName()+";");
|
||
|
UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();");
|
||
|
UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();");
|
||
|
UnregisterAttributesId.add("delete "+objectVariable+";");
|
||
|
UnregisterAttributesId.add("}");
|
||
|
|
||
|
//
|
||
|
// generate init/release notification
|
||
|
//
|
||
|
|
||
|
NotifyInitId.add("if ("+cppName()+" != NULL)");
|
||
|
NotifyInitId.add("{");
|
||
|
NotifyInitId.add(cppName()+"->"+notifyInitFunction+"();");
|
||
|
NotifyInitId.add("}");
|
||
|
|
||
|
NotifyReleaseId.add("if ("+cppName()+" != NULL)");
|
||
|
NotifyReleaseId.add("{");
|
||
|
NotifyReleaseId.add(cppName()+"->"+notifyReleaseFunction+"();");
|
||
|
NotifyReleaseId.add("}");
|
||
|
|
||
|
//
|
||
|
// generate unlink code
|
||
|
//
|
||
|
string unlinkProto;
|
||
|
if (cnd->getClassKey() != NULL)
|
||
|
{
|
||
|
CDeclarationNode* kd = cnd->getClassKey();
|
||
|
CTypeNode* keyType = getTypeNode(kd->Type);
|
||
|
unlinkProto = keyType->getName()+" dummy";
|
||
|
}
|
||
|
Gen.startMethod("void", unlinkFunc(), unlinkProto, "internal", false, inlineInternal);
|
||
|
Gen.add("{");
|
||
|
Gen.add(cppName()+" = NULL;");
|
||
|
Gen.add("}");
|
||
|
|
||
|
//
|
||
|
// generate clear code
|
||
|
//
|
||
|
//ClearId.add(cppName()+"->"+setParentFunction+"(NULL);");
|
||
|
ClearId.add(Type+"*\t"+objectVariable+" = "+cppName()+";");
|
||
|
ClearId.add(objectVariable+"->"+unregisterFunction+"();");
|
||
|
ClearId.add(objectVariable+"->"+destroyFunction+"();");
|
||
|
ClearId.add("delete "+objectVariable+";");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateArrayApplyCode()
|
||
|
{
|
||
|
CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
|
||
|
|
||
|
ApplyId.add("// apply "+Name);
|
||
|
ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add( "__pdr.popStructBegin("+tokenName()+");");
|
||
|
ApplyId.add( "uint\tindex = 0;");
|
||
|
ApplyId.add( "while (!__pdr.isEndOfStruct())");
|
||
|
ApplyId.add( "{");
|
||
|
|
||
|
CIndexNode *ind = getIndexNode(ArrayIndex);
|
||
|
if (ind->isEnum())
|
||
|
{
|
||
|
ApplyId.add("std::string\tindexname;");
|
||
|
ApplyId.add("__pdr.pop(__Tok_MapKey, indexname);");
|
||
|
ApplyId.add("index = "+ind->getFromStringCode("indexname")+";");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CDeclarationNode::generateArrayStoreCode()
|
||
|
{
|
||
|
CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
|
||
|
|
||
|
StoreId.add("// store "+Name);
|
||
|
StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
|
||
|
CIndexNode *ind = getIndexNode(ArrayIndex);
|
||
|
|
||
|
StoreId.add("for (uint index=0; index<"+ind->getSizeName()+"; ++index)");
|
||
|
StoreId.add("{");
|
||
|
|
||
|
if (ind->isEnum())
|
||
|
{
|
||
|
StoreId.add("std::string\tindexname = "+ind->getToStringCode(ind->castFromUser("index"))+";");
|
||
|
StoreId.add("__pdr.push(__Tok_MapKey, indexname);");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateArrayEndCode()
|
||
|
{
|
||
|
CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
|
||
|
CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
|
||
|
|
||
|
ApplyId.add( "++index;");
|
||
|
ApplyId.add( "}");
|
||
|
ApplyId.add( "__pdr.popStructEnd("+tokenName()+");");
|
||
|
ApplyId.add("}");
|
||
|
|
||
|
StoreId.add("}");
|
||
|
StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateArrayTypeContent(CCallContext *context)
|
||
|
{
|
||
|
setEnv("decltype", "arraytype");
|
||
|
|
||
|
CClassGenerator &Gen = ClassNode->Gen;
|
||
|
CCppOutput& DbSummary = getDbNode()->DbSummary;
|
||
|
|
||
|
CClassGenerator::SMethodId &InitId = ClassNode->InitId;
|
||
|
CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
|
||
|
CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
|
||
|
CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
|
||
|
CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
|
||
|
CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
|
||
|
CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
|
||
|
CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
|
||
|
CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
|
||
|
CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
|
||
|
|
||
|
string UCodeContext;
|
||
|
if (context != NULL)
|
||
|
UCodeContext = context->getUserCodeContext();
|
||
|
|
||
|
string onGetUser = getUserCode("onGet", UCodeContext);
|
||
|
string onSetUser = getUserCode("onSet", UCodeContext);
|
||
|
string onChangeUser = getUserCode("onChange", UCodeContext);
|
||
|
|
||
|
CTypeNode *tnd = getTypeNode(Type);
|
||
|
CIndexNode *ind = getIndexNode(ArrayIndex);
|
||
|
XmlNode += " type='arraytype' typeid='"+toString(tnd->Id)+"' indexid='"+toString(ind->Id)+"'";
|
||
|
|
||
|
CCallContext ctx(this);
|
||
|
if (context != NULL)
|
||
|
ctx = context->getSubContext(this);
|
||
|
CClassGenerator &gen = ctx.getRootCaller()->Gen;
|
||
|
|
||
|
setEnv("type", tnd->getName());
|
||
|
setEnv("indexsize", ind->getSizeName());
|
||
|
|
||
|
// EGS Compat
|
||
|
// -- begin
|
||
|
|
||
|
CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
|
||
|
CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
|
||
|
|
||
|
generateArrayApplyCode();
|
||
|
generateArrayStoreCode();
|
||
|
|
||
|
ApplyId.add(tnd->getName()+"\tvalue;");
|
||
|
tnd->generateApplyCode(ApplyId, "__Tok_MapVal", "value");
|
||
|
ApplyId.add("if (index != "+toString(ind->getSize())+")");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add( cppName()+"[index] = value;");
|
||
|
ApplyId.add("}");
|
||
|
|
||
|
tnd->generateStoreCode(ApplyId, "__Tok_MapVal", cppName()+"[index]");
|
||
|
|
||
|
generateArrayEndCode();
|
||
|
|
||
|
// -- end
|
||
|
|
||
|
|
||
|
//
|
||
|
// generate read accessor
|
||
|
//
|
||
|
if (ctx.getRootCaller()->HasRowAccess)
|
||
|
{
|
||
|
string arglist = ctx.getCallArgList();
|
||
|
ctx.getRootCaller()->Gen.startMethod(tnd->getName(), getFunctionPrefix+ctx.getCallString(), arglist, "methods", true, inlineAccessors);
|
||
|
|
||
|
DbSummary << "\t" << getFunctionPrefix+ctx.getCallString() << "\n";
|
||
|
|
||
|
uint i;
|
||
|
vector<string> checks = ctx.getCheckCode();
|
||
|
for (i=0; i<checks.size(); ++i)
|
||
|
gen.add(checks[i]);
|
||
|
|
||
|
if (!onGetUser.empty())
|
||
|
{
|
||
|
gen.add("{");
|
||
|
gen.add(onGetUser);
|
||
|
gen.add("}");
|
||
|
}
|
||
|
gen.add("return "+ctx.getCallPath()+";");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate write accessor
|
||
|
//
|
||
|
if (ctx.getRootCaller()->HasRowAccess)
|
||
|
{
|
||
|
string arglist = ctx.getCallArgList();
|
||
|
if (!arglist.empty())
|
||
|
arglist += ", ";
|
||
|
arglist += tnd->getName()+" "+valueVariable;
|
||
|
gen.startMethod("void", setFunctionPrefix+ctx.getCallString(), appendArg(arglist, "bool forceWrite=false"), "methods", false, inlineAccessors);
|
||
|
|
||
|
DbSummary << "\t" << setFunctionPrefix+ctx.getCallString() << "\n";
|
||
|
|
||
|
if (GenerateHAuto)
|
||
|
{
|
||
|
gen.add("H_AUTO("+getAccessorName(&ctx, getFunctionPrefix, "_")+")");
|
||
|
}
|
||
|
|
||
|
if (VerboseMode)
|
||
|
{
|
||
|
string verbStr;
|
||
|
string callStr;
|
||
|
|
||
|
verbStr = "nlinfo(\"" + ctx.getRootCaller()->Name + "(%d:%d)::" +setFunctionPrefix + ctx.getCallString() + "(";
|
||
|
|
||
|
callStr = ctx.getDebugCallStringFmt();
|
||
|
if (!callStr.empty())
|
||
|
callStr += ", ";
|
||
|
|
||
|
callStr += valueVariable+"="+tnd->getPrintfFmt();
|
||
|
|
||
|
verbStr += callStr;
|
||
|
verbStr += ")\", __BaseTable, __BaseRow, ";
|
||
|
|
||
|
callStr = ctx.getDebugCallStringVal();
|
||
|
if (!callStr.empty())
|
||
|
callStr += ", ";
|
||
|
|
||
|
callStr += tnd->getPrintfVal(valueVariable);
|
||
|
|
||
|
verbStr += callStr;
|
||
|
verbStr += ");";
|
||
|
|
||
|
gen.add(verbStr);
|
||
|
}
|
||
|
|
||
|
uint i;
|
||
|
vector<string> checks = ctx.getCheckCode();
|
||
|
for (i=0; i<checks.size(); ++i)
|
||
|
gen.add(checks[i]);
|
||
|
gen.add(tnd->checkCode(valueVariable));
|
||
|
|
||
|
if (!onChangeUser.empty())
|
||
|
{
|
||
|
gen.add("if ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+")");
|
||
|
gen.add("{");
|
||
|
gen.add(onChangeUser);
|
||
|
gen.add("}");
|
||
|
}
|
||
|
if (!onSetUser.empty())
|
||
|
{
|
||
|
gen.add("{");
|
||
|
gen.add(onGetUser);
|
||
|
gen.add("}");
|
||
|
}
|
||
|
if (WriteTriggerFlag)
|
||
|
{
|
||
|
gen.add("if (forceWrite && ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+"))");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gen.add("if (("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+") || forceWrite)");
|
||
|
}
|
||
|
gen.add("{");
|
||
|
bool useEntityId = ctx.hasRootEntityIdKey();
|
||
|
if (useEntityId)
|
||
|
{
|
||
|
gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+", "+ctx.getRootCaller()->getKey()->cppName()+");");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");");
|
||
|
}
|
||
|
//gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");");
|
||
|
gen.add("}");
|
||
|
gen.add(ctx.getCallPath()+" = "+tnd->castToCpp(valueVariable)+";");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate attribute
|
||
|
//
|
||
|
Gen.addAttribute(tnd->getName(), cppName()+"["+ind->getSizeName()+"]", "attributes");
|
||
|
|
||
|
//
|
||
|
// generate init
|
||
|
//
|
||
|
if (!ClassNode->indexUsedInInit)
|
||
|
{
|
||
|
InitId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInInit = true;
|
||
|
}
|
||
|
|
||
|
InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i] = "+tnd->getDefaultValue()+";");
|
||
|
|
||
|
//
|
||
|
// generate create code
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate fetch code
|
||
|
//
|
||
|
if (!ClassNode->indexUsedInFetch)
|
||
|
{
|
||
|
FetchId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInFetch = true;
|
||
|
}
|
||
|
|
||
|
if (tnd->isEnum())
|
||
|
FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\tdata.serialEnum("+cppName()+"[i]);");
|
||
|
else if (tnd->CppType != tnd->StorageType)
|
||
|
{
|
||
|
FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
|
||
|
FetchId.add("{");
|
||
|
FetchId.add(tnd->StorageType+"\t_v;");
|
||
|
FetchId.add("data.serial(_v);");
|
||
|
FetchId.add(cppName()+"[i] = "+tnd->castToCpp("_v")+";");
|
||
|
FetchId.add("}");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\tdata.serial("+cppName()+"[i]);");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate clear code
|
||
|
//
|
||
|
if (ctx.getRootCaller()->HasRowAccess)
|
||
|
{
|
||
|
string forIndex = "__i"+toString(ctx.getContextIndex());
|
||
|
ctx.getRootCaller()->ClearId.add("for (uint "+forIndex+"=0; "+forIndex+"<"+ind->getSizeName()+"; ++"+forIndex+")");
|
||
|
ctx.getRootCaller()->ClearId.add("{");
|
||
|
ctx.getRootCaller()->ClearId.add(ctx.getCallPath()+" = "+tnd->getDefaultValue()+";");
|
||
|
ctx.getRootCaller()->ClearId.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(tnd->getDefaultValue())+");");
|
||
|
ctx.getRootCaller()->ClearId.add("}");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateArrayClassContent(CCallContext *context)
|
||
|
{
|
||
|
setEnv("decltype", "arrayclass");
|
||
|
|
||
|
CClassGenerator &Gen = ClassNode->Gen;
|
||
|
CCppOutput& DbSummary = getDbNode()->DbSummary;
|
||
|
|
||
|
CClassGenerator::SMethodId &InitId = ClassNode->InitId;
|
||
|
CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
|
||
|
CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
|
||
|
CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
|
||
|
CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
|
||
|
CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
|
||
|
CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
|
||
|
CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
|
||
|
CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
|
||
|
CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
|
||
|
|
||
|
CClassNode *sub = getClassNode(Type);
|
||
|
CIndexNode *ind = getIndexNode(ArrayIndex);
|
||
|
XmlNode += " type='arrayclass' classid='"+toString(sub->Id)+"' indexid='"+toString(ind->Id)+"'";
|
||
|
|
||
|
setEnv("type", Type);
|
||
|
setEnv("indexsize", ind->getSizeName());
|
||
|
|
||
|
// EGS Compat
|
||
|
// -- begin
|
||
|
|
||
|
CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
|
||
|
CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
|
||
|
|
||
|
generateArrayApplyCode();
|
||
|
generateArrayStoreCode();
|
||
|
|
||
|
// StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
|
||
|
StoreId.add("__pdr.pushStructBegin(__Tok_MapVal);");
|
||
|
StoreId.add(cppName()+"[index].store(__pdr);");
|
||
|
StoreId.add("__pdr.pushStructEnd(__Tok_MapVal);");
|
||
|
// StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
|
||
|
|
||
|
ApplyId.add("if (index < "+ind->getSizeName()+")");
|
||
|
ApplyId.add("{");
|
||
|
// ApplyId.add("__pdr.popStructBegin("+tokenName()+");");
|
||
|
ApplyId.add("__pdr.popStructBegin(__pdr.peekNextToken());");
|
||
|
ApplyId.add(cppName()+"[index].apply(__pdr);");
|
||
|
ApplyId.add("__pdr.popStructEnd(__pdr.peekNextToken());");
|
||
|
// ApplyId.add("__pdr.popStructEnd("+tokenName()+");");
|
||
|
ApplyId.add("}");
|
||
|
ApplyId.add("else");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add( "__pdr.skipStruct();");
|
||
|
ApplyId.add("}");
|
||
|
|
||
|
generateArrayEndCode();
|
||
|
|
||
|
// -- end
|
||
|
|
||
|
|
||
|
//
|
||
|
// export class accessors into root caller
|
||
|
//
|
||
|
|
||
|
CCallContext ctx;
|
||
|
if (context != NULL)
|
||
|
ctx = *context;
|
||
|
ctx.Context.push_back(this);
|
||
|
|
||
|
if (ctx.getRootCaller()->HasRowAccess)
|
||
|
{
|
||
|
string forIndex = "__i"+toString(ctx.getContextIndex());
|
||
|
ctx.getRootCaller()->ClearId.add("for (uint "+forIndex+"=0; "+forIndex+"<"+ind->getSizeName()+"; ++"+forIndex+")");
|
||
|
ctx.getRootCaller()->ClearId.add("{");
|
||
|
}
|
||
|
|
||
|
sub->generateContentInCall(&ctx);
|
||
|
|
||
|
if (ctx.getRootCaller()->HasRowAccess)
|
||
|
{
|
||
|
ctx.getRootCaller()->ClearId.add("}");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate attribute
|
||
|
//
|
||
|
Gen.addAttribute(Type, cppName()+"["+ind->getSizeName()+"]", "attributes");
|
||
|
|
||
|
//
|
||
|
// generate init
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate create code
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate fetch code
|
||
|
//
|
||
|
if (!ClassNode->indexUsedInFetch)
|
||
|
{
|
||
|
FetchId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInFetch = true;
|
||
|
}
|
||
|
FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i]."+fetchFunction+"(data);");
|
||
|
|
||
|
//
|
||
|
// generate clear code
|
||
|
//
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateArrayRefContent(CCallContext *context)
|
||
|
{
|
||
|
setEnv("decltype", "arrayref");
|
||
|
|
||
|
CClassGenerator &Gen = ClassNode->Gen;
|
||
|
CCppOutput& DbSummary = getDbNode()->DbSummary;
|
||
|
|
||
|
CClassGenerator::SMethodId &InitId = ClassNode->InitId;
|
||
|
CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
|
||
|
CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
|
||
|
CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
|
||
|
CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
|
||
|
CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
|
||
|
CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
|
||
|
CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
|
||
|
CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
|
||
|
CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
|
||
|
CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId;
|
||
|
CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId;
|
||
|
|
||
|
CClassNode *cnd = getClassNode(Type);
|
||
|
|
||
|
bool useReference = cnd->ForceReference;
|
||
|
|
||
|
CDeclarationNode *dnd = cnd->getDeclarationNode(ForwardRefAttribute);
|
||
|
CIndexNode *ind = getIndexNode(ArrayIndex);
|
||
|
CDeclarationNode *knd = cnd->getKey();
|
||
|
XmlNode += " type='arrayref' classid='"+toString(cnd->Id)+"' forwardreferedid='"+toString(dnd->Id)+"' key='"+toString(knd->Id)+"' indexid='"+toString(ind->Id)+"' allownull='"+(useReference ? "true" : "false")+"'";
|
||
|
|
||
|
string arrayType = Type+(useReference ? "*" : "");
|
||
|
string access = (useReference ? "->" : ".");
|
||
|
|
||
|
setEnv("type", Type);
|
||
|
setEnv("indexsize", ind->getSizeName());
|
||
|
define(useReference, "useref");
|
||
|
|
||
|
string UCodeContext;
|
||
|
if (context != NULL)
|
||
|
UCodeContext = context->getUserCodeContext();
|
||
|
|
||
|
string onChangeUser = getUserCode("onChange", UCodeContext);
|
||
|
|
||
|
// EGS Compat
|
||
|
// -- begin
|
||
|
|
||
|
CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
|
||
|
CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
|
||
|
|
||
|
generateArrayStoreCode();
|
||
|
generateArrayApplyCode();
|
||
|
|
||
|
StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
|
||
|
|
||
|
ApplyId.add("if (index < "+ind->getSizeName()+")");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add( "if (__pdr.peekNextToken() == "+tokenName()+")");
|
||
|
ApplyId.add( "{");
|
||
|
ApplyId.add( "__pdr.popStructBegin("+tokenName()+");");
|
||
|
|
||
|
if (useReference)
|
||
|
{
|
||
|
generateClassPtrStoreCode(cppName()+"[index]");
|
||
|
|
||
|
generateClassPtrApplyCode(cppName()+"[index]");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StoreId.add(cppName()+"[index].store(__pdr);");
|
||
|
|
||
|
ApplyId.add(cppName()+"[index].apply(__pdr);");
|
||
|
ApplyId.add(cppName()+"[index]."+setUnnotifiedParentFunction+"(this);");
|
||
|
}
|
||
|
|
||
|
StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
|
||
|
|
||
|
ApplyId.add( "__pdr.popStructEnd("+tokenName()+");");
|
||
|
ApplyId.add( "}");
|
||
|
ApplyId.add("}");
|
||
|
ApplyId.add("else");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add( "__pdr.skipStruct();");
|
||
|
ApplyId.add("}");
|
||
|
|
||
|
generateArrayEndCode();
|
||
|
|
||
|
// -- end
|
||
|
|
||
|
|
||
|
//
|
||
|
// generate read accessor
|
||
|
//
|
||
|
Gen.startMethod((useReference ? arrayType : Type+"&"), getFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors);
|
||
|
Gen.add(ind->checkCode(indexVariable));
|
||
|
Gen.add("return "+cppName()+"["+indexVariable+"];");
|
||
|
|
||
|
Gen.startMethod(string("const ")+(useReference ? arrayType : Type+"&"), getFunc(), ind->getName()+" "+indexVariable, "methods", true, inlineAccessors);
|
||
|
Gen.add(ind->checkCode(indexVariable));
|
||
|
Gen.add("return "+cppName()+"["+indexVariable+"];");
|
||
|
|
||
|
DbSummary << "\t" << getFunc() << "\n";
|
||
|
|
||
|
//
|
||
|
// generate write accessor
|
||
|
//
|
||
|
if (useReference)
|
||
|
{
|
||
|
Gen.startMethod("void", setFunc(), arrayType+" "+valueVariable, "methods", false, inlineAccessors);
|
||
|
|
||
|
DbSummary << "\t" << setFunc() << "\n";
|
||
|
|
||
|
Gen.add("if ("+valueVariable+" == NULL)\treturn;");
|
||
|
Gen.add(ind->getName()+"\t"+keyVariable+" = "+valueVariable+"->"+cnd->getKey()->getFunc()+"();");
|
||
|
Gen.add(ind->checkCode(keyVariable));
|
||
|
Gen.add(Type+"*\t__prev = "+cppName()+"["+keyVariable+"];");
|
||
|
Gen.add("if (__prev != NULL)");
|
||
|
Gen.add("{");
|
||
|
Gen.add("__prev->"+setParentFunction+"(NULL);");
|
||
|
if (cnd->MapClass == NULL)
|
||
|
{
|
||
|
Gen.add("__prev->"+unregisterFunction+"();");
|
||
|
Gen.add("__prev->"+destroyFunction+"();");
|
||
|
Gen.add("delete __prev;");
|
||
|
}
|
||
|
Gen.add("}");
|
||
|
Gen.add(valueVariable+"->"+setParentFunction+"(this);");
|
||
|
Gen.add(cppName()+"["+keyVariable+"] = "+valueVariable+";");
|
||
|
}
|
||
|
|
||
|
if (cnd->MapClass == NULL && useReference && !cnd->HasInheritance && !cnd->DerivatedFlag)
|
||
|
{
|
||
|
Gen.startMethod(Type+"*", newFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors);
|
||
|
DbSummary << "\t" << newFunc() << "\n";
|
||
|
Gen.add(ind->checkCode(indexVariable));
|
||
|
Gen.add(Type+"*\t"+objectVariable+" = new "+Type+"();");
|
||
|
Gen.add(objectVariable+"->"+initFunction+"("+indexVariable+");");
|
||
|
Gen.add(objectVariable+"->"+registerFunction+"();");
|
||
|
Gen.add(setFunc()+"("+objectVariable+");");
|
||
|
}
|
||
|
|
||
|
if (cnd->MapClass == NULL && useReference)
|
||
|
{
|
||
|
Gen.startMethod("void", deleteFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors);
|
||
|
DbSummary << "\t" << deleteFunc() << "\n";
|
||
|
Gen.add(ind->checkCode(indexVariable));
|
||
|
Gen.add(Type+"*\t"+objectVariable+" = "+cppName()+"["+indexVariable+"];");
|
||
|
Gen.add(objectVariable+"->"+setParentFunction+"(NULL);");
|
||
|
Gen.add(objectVariable+"->"+unregisterFunction+"();");
|
||
|
Gen.add(objectVariable+"->"+destroyFunction+"();");
|
||
|
Gen.add("delete "+objectVariable+";");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate attribute
|
||
|
//
|
||
|
Gen.addAttribute(arrayType, cppName()+"["+ind->getSizeName()+"]", "attributes");
|
||
|
|
||
|
//
|
||
|
// generate init
|
||
|
//
|
||
|
if (!ClassNode->indexUsedInInit)
|
||
|
{
|
||
|
InitId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInInit = true;
|
||
|
}
|
||
|
if (useReference)
|
||
|
{
|
||
|
InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i] = NULL;");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i]."+initFunction+"(("+ind->getName()+")i);");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate destroy code
|
||
|
//
|
||
|
if (!ClassNode->indexUsedInDestroy)
|
||
|
{
|
||
|
DestroyId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInDestroy = true;
|
||
|
}
|
||
|
DestroyId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
|
||
|
DestroyId.add("{");
|
||
|
if (useReference)
|
||
|
{
|
||
|
DestroyId.add("if ("+cppName()+"[i] != NULL)");
|
||
|
DestroyId.add("{");
|
||
|
DestroyId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];");
|
||
|
DestroyId.add(objectVariable+"->"+destroyFunction+"();");
|
||
|
DestroyId.add("delete "+objectVariable+";");
|
||
|
DestroyId.add("}");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DestroyId.add(cppName()+"[i]."+destroyFunction+"();");
|
||
|
}
|
||
|
DestroyId.add("}");
|
||
|
|
||
|
//
|
||
|
// generate create code
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate fetch code
|
||
|
//
|
||
|
if (useReference)
|
||
|
{
|
||
|
if (!ClassNode->indexUsedInFetch)
|
||
|
{
|
||
|
FetchId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInFetch = true;
|
||
|
}
|
||
|
if (!ClassNode->tableAndRowIndicesUsedInFetch)
|
||
|
{
|
||
|
FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;");
|
||
|
ClassNode->tableAndRowIndicesUsedInFetch = true;
|
||
|
}
|
||
|
FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
|
||
|
FetchId.add("{");
|
||
|
FetchId.add(cppName()+"[i] = NULL;");
|
||
|
FetchId.add("// read table and row, create an object, affect to the ref, and fetch it");
|
||
|
FetchId.add("data.serial(tableIndex, rowIndex);");
|
||
|
FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")");
|
||
|
FetchId.add("{");
|
||
|
FetchId.add(cppName()+"[i] = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));");
|
||
|
FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+cppName()+"[i]);");
|
||
|
FetchId.add(cppName()+"[i]->"+fetchFunction+"(data);");
|
||
|
FetchId.add(cppName()+"[i]->"+setUnnotifiedParentFunction+"(this);");
|
||
|
FetchId.add("}");
|
||
|
FetchId.add("}");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!ClassNode->indexUsedInFetch)
|
||
|
{
|
||
|
FetchId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInFetch = true;
|
||
|
}
|
||
|
if (!ClassNode->tableAndRowIndicesUsedInFetch)
|
||
|
{
|
||
|
FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;");
|
||
|
ClassNode->tableAndRowIndicesUsedInFetch = true;
|
||
|
}
|
||
|
FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
|
||
|
FetchId.add("{");
|
||
|
FetchId.add("// read table and row, create an object, affect to the ref, and fetch it");
|
||
|
FetchId.add("data.serial(tableIndex, rowIndex);");
|
||
|
FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")");
|
||
|
FetchId.add("{");
|
||
|
FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, &"+cppName()+"[i]);");
|
||
|
FetchId.add(cppName()+"[i]."+fetchFunction+"(data);");
|
||
|
FetchId.add(cppName()+"[i]."+setUnnotifiedParentFunction+"(this);");
|
||
|
FetchId.add("}");
|
||
|
FetchId.add("}");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate register/unregister code
|
||
|
//
|
||
|
if (!useReference)
|
||
|
{
|
||
|
if (!ClassNode->indexUsedInRegister)
|
||
|
{
|
||
|
RegisterAttributesId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInRegister = true;
|
||
|
}
|
||
|
RegisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
|
||
|
RegisterAttributesId.add("{");
|
||
|
RegisterAttributesId.add(cppName()+"[i]."+registerFunction+"();");
|
||
|
RegisterAttributesId.add(cppName()+"[i]."+setParentFunction+"(this);");
|
||
|
RegisterAttributesId.add("}");
|
||
|
|
||
|
if (!ClassNode->indexUsedInUnregister)
|
||
|
{
|
||
|
UnregisterAttributesId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInUnregister = true;
|
||
|
}
|
||
|
UnregisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
|
||
|
UnregisterAttributesId.add("{");
|
||
|
UnregisterAttributesId.add(cppName()+"[i]."+unregisterFunction+"();");
|
||
|
UnregisterAttributesId.add("}");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!ClassNode->indexUsedInUnregister)
|
||
|
{
|
||
|
UnregisterAttributesId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInUnregister = true;
|
||
|
}
|
||
|
UnregisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
|
||
|
UnregisterAttributesId.add("{");
|
||
|
UnregisterAttributesId.add("if ("+cppName()+"[i] != NULL)");
|
||
|
UnregisterAttributesId.add("{");
|
||
|
UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];");
|
||
|
UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();");
|
||
|
UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();");
|
||
|
UnregisterAttributesId.add("delete "+objectVariable+";");
|
||
|
UnregisterAttributesId.add("}");
|
||
|
UnregisterAttributesId.add("}");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate init/release notification
|
||
|
//
|
||
|
|
||
|
if (!ClassNode->indexUsedInNotifyInit)
|
||
|
{
|
||
|
NotifyInitId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInNotifyInit = true;
|
||
|
}
|
||
|
NotifyInitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
|
||
|
NotifyInitId.add("{");
|
||
|
|
||
|
if (!ClassNode->indexUsedInNotifyRelease)
|
||
|
{
|
||
|
NotifyReleaseId.add("uint\ti;");
|
||
|
ClassNode->indexUsedInNotifyRelease = true;
|
||
|
}
|
||
|
NotifyReleaseId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
|
||
|
NotifyReleaseId.add("{");
|
||
|
|
||
|
if (!useReference)
|
||
|
{
|
||
|
NotifyInitId.add(cppName()+"[i]."+notifyInitFunction+"();");
|
||
|
|
||
|
NotifyReleaseId.add(cppName()+"[i]."+notifyReleaseFunction+"();");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NotifyInitId.add("if ("+cppName()+"[i] != NULL)");
|
||
|
NotifyInitId.add("{");
|
||
|
NotifyInitId.add(cppName()+"[i]->"+notifyInitFunction+"();");
|
||
|
NotifyInitId.add("}");
|
||
|
|
||
|
NotifyReleaseId.add("if ("+cppName()+"[i] != NULL)");
|
||
|
NotifyReleaseId.add("{");
|
||
|
NotifyReleaseId.add(cppName()+"[i]->"+notifyReleaseFunction+"();");
|
||
|
NotifyReleaseId.add("}");
|
||
|
}
|
||
|
|
||
|
NotifyInitId.add("}");
|
||
|
NotifyReleaseId.add("}");
|
||
|
|
||
|
|
||
|
//
|
||
|
// generate unlink code
|
||
|
//
|
||
|
if (useReference)
|
||
|
{
|
||
|
Gen.startMethod("void", unlinkFunc(), ind->getName()+" "+keyVariable, "internal", false, inlineInternal);
|
||
|
Gen.add(cppName()+"["+keyVariable+"] = NULL;");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate clear code
|
||
|
//
|
||
|
ClearId.add("for (uint i=0; i<"+ind->getSizeName()+"; ++i)");
|
||
|
ClearId.add("{");
|
||
|
if (!useReference)
|
||
|
{
|
||
|
ClearId.add(cppName()+"[i]."+clearFunction+"();");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//ClearId.add(cppName()+"[i]->"+setParentFunction+"(NULL);");
|
||
|
ClearId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];");
|
||
|
ClearId.add(objectVariable+"->"+unregisterFunction+"();");
|
||
|
ClearId.add(objectVariable+"->"+destroyFunction+"();");
|
||
|
ClearId.add("delete "+objectVariable+";");
|
||
|
}
|
||
|
ClearId.add("}");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void CDeclarationNode::generateSetContent(CCallContext *context)
|
||
|
{
|
||
|
setEnv("decltype", "set");
|
||
|
|
||
|
CClassGenerator &Gen = ClassNode->Gen;
|
||
|
CCppOutput& DbSummary = getDbNode()->DbSummary;
|
||
|
|
||
|
CClassGenerator::SMethodId &InitId = ClassNode->InitId;
|
||
|
CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
|
||
|
CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
|
||
|
CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
|
||
|
CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
|
||
|
CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
|
||
|
CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
|
||
|
CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
|
||
|
CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
|
||
|
CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
|
||
|
CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId;
|
||
|
CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId;
|
||
|
|
||
|
CClassNode *sub = getClassNode(Type);
|
||
|
CDeclarationNode *key = sub->getKey();
|
||
|
CTypeNode *keyType = getTypeNode(key->Type);
|
||
|
|
||
|
bool useReference = sub->ForceReference;
|
||
|
string access = (useReference ? "->" : ".");
|
||
|
|
||
|
string onChangeUser = getUserCode("onChange", context != NULL ? context->getUserCodeContext() : "");
|
||
|
|
||
|
|
||
|
string setType = "std::map<"+keyType->getName()+", " + Type + (useReference ? "*" : "") + ">";
|
||
|
|
||
|
CDeclarationNode *dnd = sub->getDeclarationNode(ForwardRefAttribute);
|
||
|
XmlNode += " type='set' classid='"+toString(sub->Id)+"' forwardreferedid='"+toString(dnd->Id)+"' key='"+toString(key->Id)+"' ";
|
||
|
|
||
|
setEnv("type", Type);
|
||
|
setEnv("keytype", keyType->getName());
|
||
|
define(useReference, "useref");
|
||
|
|
||
|
// EGS Compat
|
||
|
// -- begin
|
||
|
|
||
|
CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
|
||
|
CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
|
||
|
|
||
|
StoreId.add("// store "+Name);
|
||
|
StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
|
||
|
StoreId.add("for ("+setType+"::const_iterator it="+cppName()+".begin(); it!="+cppName()+".end(); ++it)");
|
||
|
StoreId.add("{");
|
||
|
StoreId.add( keyType->getName()+"\tkey = (*it).first;");
|
||
|
keyType->generateStoreCode(StoreId, "__Tok_MapKey", "key");
|
||
|
StoreId.add( "__pdr.pushStructBegin(__Tok_MapVal);");
|
||
|
|
||
|
if (useReference)
|
||
|
{
|
||
|
generateClassPtrStoreCode("(*it).second");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StoreId.add("(*it).second.store(__pdr);");
|
||
|
}
|
||
|
|
||
|
StoreId.add( "__pdr.pushStructEnd(__Tok_MapVal);");
|
||
|
StoreId.add("}");
|
||
|
StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
|
||
|
StoreId.add("// end of store "+Name);
|
||
|
|
||
|
ApplyId.add("// apply "+Name);
|
||
|
ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
|
||
|
ApplyId.add("{");
|
||
|
ApplyId.add( "__pdr.popStructBegin("+tokenName()+");");
|
||
|
ApplyId.add( "while (!__pdr.isEndOfStruct())");
|
||
|
ApplyId.add( "{");
|
||
|
ApplyId.add( keyType->getName()+"\tkey;");
|
||
|
keyType->generateApplyCode(ApplyId, "__Tok_MapKey", "key");
|
||
|
|
||
|
ApplyId.add( "__pdr.popStructBegin(__Tok_MapVal);");
|
||
|
if (useReference)
|
||
|
{
|
||
|
ApplyId.add( Type+"*\tobj;");
|
||
|
generateClassPtrApplyCode("obj");
|
||
|
ApplyId.add( "if (obj != NULL)");
|
||
|
ApplyId.add( "{");
|
||
|
ApplyId.add( cppName()+"[key] = obj;");
|
||
|
ApplyId.add( "}");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ApplyId.add( Type+"&\tobj = "+cppName()+"[key];");
|
||
|
ApplyId.add( "obj.apply(__pdr);");
|
||
|
ApplyId.add( "obj."+setUnnotifiedParentFunction+"(this);");
|
||
|
}
|
||
|
ApplyId.add( "__pdr.popStructEnd(__Tok_MapVal);");
|
||
|
ApplyId.add( "}");
|
||
|
ApplyId.add( "__pdr.popStructEnd("+tokenName()+");");
|
||
|
ApplyId.add("}");
|
||
|
ApplyId.add("// end of apply "+Name);
|
||
|
|
||
|
// -- end
|
||
|
|
||
|
|
||
|
//
|
||
|
// generate read accessor
|
||
|
//
|
||
|
Gen.startMethod(Type+"*", getFunc(), "const "+keyType->getName()+"& "+keyVariable, "methods", false, inlineAccessors);
|
||
|
DbSummary << "\t" << getFunc() << "\n";
|
||
|
Gen.add(setType+"::iterator _it = "+cppName()+".find("+keyVariable+");");
|
||
|
Gen.add("return (_it=="+cppName()+".end() ? NULL : "+(useReference ? "(*_it).second" : "&((*_it).second)")+");");
|
||
|
|
||
|
Gen.startMethod("const "+Type+"*", getFunc(), "const "+keyType->getName()+"& "+keyVariable, "methods", true, inlineAccessors);
|
||
|
Gen.add(setType+"::const_iterator _it = "+cppName()+".find("+keyVariable+");");
|
||
|
Gen.add("return (_it=="+cppName()+".end() ? NULL : "+(useReference ? "(*_it).second" : "&((*_it).second)")+");");
|
||
|
|
||
|
// generate map accessor
|
||
|
string stypedef = "T"+Name+"Map";
|
||
|
//Gen.addOther("typedef "+setType+"\t"+stypedef+";");
|
||
|
Gen.startMethod(setType+"::iterator", getFunc()+"Begin", "", "methods", false, inlineAccessors);
|
||
|
Gen.add("return "+cppName()+".begin();");
|
||
|
DbSummary << "\t" << getFunc() << "Begin" << "\n";
|
||
|
Gen.startMethod(setType+"::iterator", getFunc()+"End", "", "methods", false, inlineAccessors);
|
||
|
Gen.add("return "+cppName()+".end();");
|
||
|
DbSummary << "\t" << getFunc() << "End" << "\n";
|
||
|
Gen.startMethod(setType+"::const_iterator", getFunc()+"Begin", "", "methods", true, inlineAccessors);
|
||
|
Gen.add("return "+cppName()+".begin();");
|
||
|
Gen.startMethod(setType+"::const_iterator", getFunc()+"End", "", "methods", true, inlineAccessors);
|
||
|
Gen.add("return "+cppName()+".end();");
|
||
|
Gen.startMethod("const "+setType+" &", getFunc(), "", "methods", true, inlineAccessors);
|
||
|
Gen.add("return "+cppName()+";");
|
||
|
|
||
|
//
|
||
|
// generate write accessor
|
||
|
//
|
||
|
if (useReference)
|
||
|
{
|
||
|
Gen.startMethod("void", setFunc(), Type+"* "+valueVariable, "methods", false, inlineAccessors);
|
||
|
DbSummary << "\t" << setFunc() << "\n";
|
||
|
Gen.add("if ("+valueVariable+" == NULL)\treturn;");
|
||
|
Gen.add(keyType->getName()+"\t"+keyVariable+" = "+valueVariable+"->"+sub->getKey()->getFunc()+"();");
|
||
|
Gen.add(setType+"::iterator\t_it = "+cppName()+".find("+keyVariable+");");
|
||
|
Gen.add("if (_it != "+cppName()+".end())");
|
||
|
Gen.add("{");
|
||
|
Gen.add(Type+"*\t__prev = (*_it).second;");
|
||
|
Gen.add("if (__prev == "+valueVariable+")\treturn;");
|
||
|
Gen.add("__prev->"+setParentFunction+"(NULL);");
|
||
|
Gen.add("__prev->"+unregisterFunction+"();");
|
||
|
Gen.add("__prev->"+destroyFunction+"();");
|
||
|
Gen.add("delete __prev;");
|
||
|
Gen.add("}");
|
||
|
Gen.add(valueVariable+"->"+setParentFunction+"(this);");
|
||
|
Gen.add(cppName()+"["+keyVariable+"] = "+valueVariable+";");
|
||
|
if (!onChangeUser.empty())
|
||
|
{
|
||
|
Gen.add("{");
|
||
|
Gen.add(onChangeUser);
|
||
|
Gen.add("}");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (sub->MapClass == NULL && !sub->HasInheritance && !sub->DerivatedFlag)
|
||
|
{
|
||
|
Gen.startMethod(Type+"*", newFunc(), "const "+keyType->getName()+" &"+keyVariable, "methods", false, inlineAccessors);
|
||
|
DbSummary << "\t" << newFunc() << "\n";
|
||
|
Gen.add(setType+"::iterator\t__it = "+cppName()+".find("+keyVariable+");");
|
||
|
Gen.add("if (__it == "+cppName()+".end())");
|
||
|
Gen.add("{");
|
||
|
Gen.add("__it = "+cppName()+".insert("+setType+"::value_type("+keyVariable+", "+(useReference ? toString("new ") : toString(""))+Type+"())).first;");
|
||
|
Gen.add(Type+"*\t"+objectVariable+" = "+(useReference ? toString("") : toString("&"))+"((*__it).second);");
|
||
|
Gen.add(objectVariable+"->"+initFunction+"("+keyVariable+");");
|
||
|
Gen.add(objectVariable+"->"+registerFunction+"();");
|
||
|
Gen.add(objectVariable+"->"+setParentFunction+"(this);");
|
||
|
Gen.add("}");
|
||
|
if (!onChangeUser.empty())
|
||
|
{
|
||
|
Gen.add("{");
|
||
|
Gen.add(onChangeUser);
|
||
|
Gen.add("}");
|
||
|
}
|
||
|
Gen.add("return "+(useReference ? toString("") : toString("&"))+"((*__it).second);");
|
||
|
}
|
||
|
|
||
|
Gen.startMethod("void", deleteFunc(), "const "+keyType->getName()+" &"+keyVariable, "methods", false, inlineAccessors);
|
||
|
DbSummary << "\t" << deleteFunc() << "\n";
|
||
|
Gen.add(setType+"::iterator\t__it = "+cppName()+".find("+keyVariable+");");
|
||
|
Gen.add("if (__it == "+cppName()+".end())\treturn;");
|
||
|
if (useReference)
|
||
|
{
|
||
|
Gen.add(Type+"*\t"+objectVariable+" = (*__it).second;");
|
||
|
Gen.add(objectVariable+"->"+unregisterFunction+"();");
|
||
|
Gen.add(objectVariable+"->"+destroyFunction+"();");
|
||
|
Gen.add("delete "+objectVariable+";");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Gen.add(Type+"&\t"+objectVariable+" = (*__it).second;");
|
||
|
Gen.add(objectVariable+"."+unregisterFunction+"();");
|
||
|
Gen.add(cppName()+".erase(__it);");
|
||
|
}
|
||
|
if (!onChangeUser.empty())
|
||
|
{
|
||
|
Gen.add("{");
|
||
|
Gen.add(onChangeUser);
|
||
|
Gen.add("}");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate attribute
|
||
|
//
|
||
|
Gen.addAttribute(setType, cppName(), "attributes");
|
||
|
|
||
|
//
|
||
|
// generate init
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate destroy code
|
||
|
//
|
||
|
DestroyId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
|
||
|
DestroyId.add("{");
|
||
|
DestroyId.add(setType+"::iterator __itr=__it++;");
|
||
|
if (useReference)
|
||
|
{
|
||
|
DestroyId.add(Type+"*\t"+objectVariable+" = ((*__itr).second);");
|
||
|
DestroyId.add("if ("+objectVariable+" != NULL)");
|
||
|
DestroyId.add("{");
|
||
|
DestroyId.add(objectVariable+"->"+destroyFunction+"();");
|
||
|
DestroyId.add("delete "+objectVariable+";");
|
||
|
DestroyId.add("}");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DestroyId.add("((*__itr).second)."+destroyFunction+"();");
|
||
|
}
|
||
|
DestroyId.add("}");
|
||
|
DestroyId.add(cppName()+".clear();");
|
||
|
|
||
|
//
|
||
|
// generate create code
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// generate fetch code
|
||
|
//
|
||
|
if (!ClassNode->tableAndRowIndicesUsedInFetch)
|
||
|
{
|
||
|
FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;");
|
||
|
ClassNode->tableAndRowIndicesUsedInFetch = true;
|
||
|
}
|
||
|
FetchId.add("do");
|
||
|
FetchId.add("{");
|
||
|
FetchId.add("// read table and row, create an object, affect to the ref, and fetch it");
|
||
|
FetchId.add("data.serial(tableIndex, rowIndex);");
|
||
|
FetchId.add("if (rowIndex == "+INVALID_ROW_INDEXName+" || tableIndex == "+INVALID_TABLE_INDEXName+")\tbreak;");
|
||
|
|
||
|
FetchId.add(keyType->getName()+"\t"+keyVariable+";");
|
||
|
if (keyType->isEnum())
|
||
|
{
|
||
|
FetchId.add("data.serialEnum("+keyVariable+");");
|
||
|
}
|
||
|
else if (keyType->CppType != keyType->StorageType)
|
||
|
{
|
||
|
FetchId.add("{");
|
||
|
FetchId.add(keyType->StorageType+"\t_v;");
|
||
|
FetchId.add("data.serial(_v);");
|
||
|
FetchId.add(keyVariable+" = "+keyType->castToCpp("_v")+";");
|
||
|
FetchId.add("}");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FetchId.add("data.serial("+keyVariable+");");
|
||
|
}
|
||
|
if (useReference)
|
||
|
{
|
||
|
FetchId.add(Type+"*\t"+objectVariable+" = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));");
|
||
|
FetchId.add(cppName()+".insert(std::make_pair<"+keyType->getName()+","+Type+"*>("+keyVariable+", "+objectVariable+"));");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FetchId.add(cppName()+".insert(std::make_pair<"+keyType->getName()+","+Type+">("+keyVariable+", "+Type+"()));");
|
||
|
FetchId.add(Type+"*\t"+objectVariable+" = &("+cppName()+"["+keyVariable+"]);");
|
||
|
}
|
||
|
FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+objectVariable+");");
|
||
|
FetchId.add(objectVariable+"->"+fetchFunction+"(data);");
|
||
|
FetchId.add(objectVariable+"->"+setUnnotifiedParentFunction+"(this);");
|
||
|
FetchId.add("}");
|
||
|
FetchId.add("while (true);");
|
||
|
|
||
|
//
|
||
|
// generate register/unregister code
|
||
|
//
|
||
|
|
||
|
UnregisterAttributesId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
|
||
|
UnregisterAttributesId.add("{");
|
||
|
UnregisterAttributesId.add(setType+"::iterator __itr=__it++;");
|
||
|
if (useReference)
|
||
|
{
|
||
|
UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = (*__itr).second;");
|
||
|
UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();");
|
||
|
UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();");
|
||
|
UnregisterAttributesId.add("delete "+objectVariable+";");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UnregisterAttributesId.add(Type+"&\t"+objectVariable+" = (*__itr).second;");
|
||
|
UnregisterAttributesId.add(objectVariable+"."+unregisterFunction+"();");
|
||
|
}
|
||
|
UnregisterAttributesId.add("}");
|
||
|
|
||
|
//
|
||
|
// generate init/release notification
|
||
|
//
|
||
|
|
||
|
NotifyInitId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
|
||
|
NotifyInitId.add("{");
|
||
|
NotifyInitId.add(setType+"::iterator __itr=__it++;");
|
||
|
|
||
|
NotifyReleaseId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
|
||
|
NotifyReleaseId.add("{");
|
||
|
NotifyReleaseId.add(setType+"::iterator __itr=__it++;");
|
||
|
|
||
|
if (!useReference)
|
||
|
{
|
||
|
NotifyInitId.add("(*__itr).second."+notifyInitFunction+"();");
|
||
|
NotifyReleaseId.add("(*__itr).second."+notifyReleaseFunction+"();");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NotifyInitId.add("(*__itr).second->"+notifyInitFunction+"();");
|
||
|
NotifyReleaseId.add("(*__itr).second->"+notifyReleaseFunction+"();");
|
||
|
}
|
||
|
|
||
|
NotifyInitId.add("}");
|
||
|
NotifyReleaseId.add("}");
|
||
|
|
||
|
//
|
||
|
// generate unlink code
|
||
|
//
|
||
|
if (useReference)
|
||
|
{
|
||
|
Gen.startMethod("void", unlinkFunc(), keyType->getName()+" "+keyVariable, "internal", false, inlineInternal);
|
||
|
Gen.add(cppName()+".erase("+keyVariable+");");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// generate clear code
|
||
|
//
|
||
|
ClearId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
|
||
|
ClearId.add("{");
|
||
|
ClearId.add(setType+"::iterator __itr=__it++;");
|
||
|
if (!useReference)
|
||
|
{
|
||
|
ClearId.add(Type+"*\t"+objectVariable+" = &((*__itr).second);");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ClearId.add(Type+"*\t"+objectVariable+" = (*__itr).second;");
|
||
|
}
|
||
|
//ClearId.add(objectVariable+"->"+setParentFunction+"(NULL);");
|
||
|
ClearId.add(objectVariable+"->"+unregisterFunction+"();");
|
||
|
ClearId.add(objectVariable+"->"+destroyFunction+"();");
|
||
|
if (useReference)
|
||
|
{
|
||
|
ClearId.add("delete "+objectVariable+";");
|
||
|
}
|
||
|
ClearId.add("}");
|
||
|
ClearId.add(cppName()+".clear();");
|
||
|
}
|
||
|
|
||
|
//
|
||
|
string CDeclarationNode::displayPrintfPrefix()
|
||
|
{
|
||
|
if (DeclarationType != SimpleType)
|
||
|
error("can't display other declaration than simple type", "internal");
|
||
|
|
||
|
CTypeNode* type = getTypeNode(Type);
|
||
|
|
||
|
if (type->CppType == "CEntityId" || type->CppType == "CSheetId")
|
||
|
return "%s";
|
||
|
else if (type->CppType == "uint64" || type->CppType == "sint64")
|
||
|
return "%\"NL_I64\"d";
|
||
|
else if (type->CppType == "float" || type->CppType == "double")
|
||
|
return "%g";
|
||
|
else
|
||
|
return "%d";
|
||
|
}
|
||
|
|
||
|
string CDeclarationNode::displayCppCode(string replVar)
|
||
|
{
|
||
|
if (DeclarationType != SimpleType)
|
||
|
error("can't display other declaration than simple type", "internal");
|
||
|
|
||
|
if (replVar.empty())
|
||
|
replVar = cppName();
|
||
|
|
||
|
CTypeNode* type = getTypeNode(Type);
|
||
|
|
||
|
if (type->CppType == "CEntityId" || type->CppType == "CSheetId")
|
||
|
return replVar+".toString().c_str()";
|
||
|
else
|
||
|
return replVar;
|
||
|
}
|
||
|
|
||
|
|
||
|
string CDeclarationNode::toUint64(string replVar)
|
||
|
{
|
||
|
if (DeclarationType != SimpleType)
|
||
|
error("can't display other declaration than simple type", "internal");
|
||
|
|
||
|
if (replVar.empty())
|
||
|
replVar = cppName();
|
||
|
|
||
|
CTypeNode* type = getTypeNode(Type);
|
||
|
|
||
|
if (type->CppType == "CEntityId")
|
||
|
return replVar+".asUint64()";
|
||
|
else if (type->CppType == "CSheetId")
|
||
|
return "(uint64)("+replVar+".asInt())";
|
||
|
else
|
||
|
return "(uint64)"+replVar;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
bool CLogMsgNode::prolog()
|
||
|
{
|
||
|
getDbNode()->LogNodes.push_back(this);
|
||
|
|
||
|
getFileNode()->IncludeDbFile = true;
|
||
|
getFileNode()->IncludeStandard = true;
|
||
|
getFileNode()->IncludePDSLib = true;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void CLogMsgNode::generateContent()
|
||
|
{
|
||
|
//
|
||
|
uint j;
|
||
|
|
||
|
CFunctionGenerator logfunc;
|
||
|
CClassGenerator logclass;
|
||
|
string argcall;
|
||
|
|
||
|
CFunctionGenerator& initDb = getDbNode()->initDb;
|
||
|
|
||
|
logfunc.init(Name);
|
||
|
logfunc.setType("void");
|
||
|
logfunc.IsInline = inlineLogFunctions;
|
||
|
|
||
|
logclass.init("Log"+Name);
|
||
|
logclass.createPublic("pub");
|
||
|
logclass.createPrivate("priv");
|
||
|
|
||
|
CClassGenerator::SMethodId startlogid = logclass.startMethod("void", logStartFunction, "", "priv", false, inlineLogFunctions);
|
||
|
CClassGenerator::SMethodId stoplogid = logclass.startMethod("void", logStopFunction, "", "priv", false, inlineLogFunctions);
|
||
|
startlogid.add(pdslibFunc("pushContext")+"();");
|
||
|
stoplogid.add(pdslibFunc("popContext")+"();");
|
||
|
|
||
|
map<string, CParseNode*> params;
|
||
|
|
||
|
for (j=0; j<Params.size(); ++j)
|
||
|
{
|
||
|
string type = Params[j].first;
|
||
|
string name = Params[j].second;
|
||
|
|
||
|
CTypeNode *tnd;
|
||
|
CClassNode *cnd;
|
||
|
if ( (tnd = getTypeNode(type, false)) )
|
||
|
{
|
||
|
pair<map<string, CParseNode*>::iterator, bool> res = params.insert(make_pair<string, CParseNode*>(name, tnd));
|
||
|
if (!res.second)
|
||
|
error("log parameter '"+name+"' already defined");
|
||
|
|
||
|
if (!logfunc.Proto.empty())
|
||
|
logfunc.Proto += ", ";
|
||
|
if (!argcall.empty())
|
||
|
argcall += ", ";
|
||
|
|
||
|
logfunc.Proto += tnd->getName()+" "+name;
|
||
|
argcall += name;
|
||
|
}
|
||
|
else if ( (cnd = getClassNode(type, false)) )
|
||
|
{
|
||
|
pair<map<string, CParseNode*>::iterator, bool> res = params.insert(make_pair<string, CParseNode*>(name, cnd));
|
||
|
if (!res.second)
|
||
|
error("log parameter '"+name+"' already defined");
|
||
|
|
||
|
if (!logfunc.Proto.empty())
|
||
|
logfunc.Proto += ", ";
|
||
|
if (!argcall.empty())
|
||
|
argcall += ", ";
|
||
|
|
||
|
logfunc.Proto += "const "+type+"& "+name;
|
||
|
argcall += name;
|
||
|
}
|
||
|
else if (type == "string")
|
||
|
{
|
||
|
CExtLogTypeNode* extnd = new CExtLogTypeNode();
|
||
|
extnd->ExtLogType = "string";
|
||
|
pair<map<string, CParseNode*>::iterator, bool> res = params.insert(make_pair<string, CParseNode*>(name, extnd));
|
||
|
if (!res.second)
|
||
|
error("log parameter '"+name+"' already defined");
|
||
|
|
||
|
if (!logfunc.Proto.empty())
|
||
|
logfunc.Proto += ", ";
|
||
|
if (!argcall.empty())
|
||
|
argcall += ", ";
|
||
|
|
||
|
logfunc.Proto += "const std::string& "+name;
|
||
|
argcall += name;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
error("'"+type+"' not found as a class or a type");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
initDb.add("// Init "+Name+" log message and parameters");
|
||
|
|
||
|
for (j=0; j<Logs.size(); ++j)
|
||
|
{
|
||
|
uint logId = Id+j;
|
||
|
|
||
|
logfunc.add(pdslibFunc("log")+"("+toString(logId)+");");
|
||
|
startlogid.add(pdslibFunc("log")+"("+toString(logId)+");");
|
||
|
|
||
|
const char *cptr = Logs[j].c_str();
|
||
|
string log;
|
||
|
|
||
|
// parse log line
|
||
|
|
||
|
getDbNode()->xmlDescription.push_back("<logmsg id='"+toString(logId)+"' context='"+string(Context ? "true" : "false")+"'>");
|
||
|
|
||
|
uint paramNum = 0;
|
||
|
|
||
|
initDb.add(pdslibFunc("initLog")+"("+toString(logId)+");");
|
||
|
|
||
|
while (*cptr != '\0')
|
||
|
{
|
||
|
if (*cptr == '$')
|
||
|
{
|
||
|
++cptr;
|
||
|
if (*cptr == '\0')
|
||
|
error("log format corrupted in line \""+Logs[j]+"\"");
|
||
|
|
||
|
if (*cptr == '$')
|
||
|
{
|
||
|
log += "$$";
|
||
|
++cptr;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
string param;
|
||
|
string var;
|
||
|
|
||
|
while (*cptr!='\0' && *cptr!='$' && *cptr!='.')
|
||
|
param += *(cptr++);
|
||
|
|
||
|
if (*cptr == '\0')
|
||
|
error("log format corrupted in line \""+Logs[j]+"\"");
|
||
|
|
||
|
if (*cptr == '.')
|
||
|
{
|
||
|
++cptr;
|
||
|
while (*cptr!='\0' && *cptr!='$')
|
||
|
var += *(cptr++);
|
||
|
}
|
||
|
|
||
|
if (*cptr != '$')
|
||
|
error("log format corrupted in line \""+Logs[j]+"\"");
|
||
|
|
||
|
++cptr;
|
||
|
|
||
|
map<string, CParseNode*>::iterator it = params.find(param);
|
||
|
|
||
|
if (it == params.end())
|
||
|
error("'"+param+"' ot found in prototype, at line \""+Logs[j]+"\"");
|
||
|
|
||
|
CTypeNode *tnd = NULL;
|
||
|
CExtLogTypeNode* extnd = NULL;
|
||
|
|
||
|
if (var.empty())
|
||
|
{
|
||
|
// is simple type
|
||
|
tnd = dynamic_cast<CTypeNode*>((*it).second);
|
||
|
extnd = dynamic_cast<CExtLogTypeNode*>((*it).second);
|
||
|
if (tnd != NULL)
|
||
|
{
|
||
|
logfunc.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param)+");");
|
||
|
startlogid.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param)+");");
|
||
|
}
|
||
|
else if (extnd != NULL && extnd->ExtLogType == "string")
|
||
|
{
|
||
|
logfunc.add(pdslibFunc("logPush")+"("+param+");");
|
||
|
startlogid.add(pdslibFunc("logPush")+"("+param+");");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
error("misuse of parameter '"+param+"' at line \""+Logs[j]+"\", missing attribute name");
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// is class
|
||
|
CClassNode *cnd = dynamic_cast<CClassNode*>((*it).second);
|
||
|
if (!cnd)
|
||
|
error("misuse of parameter '"+param+"' at line \""+Logs[j]+"\", should be a class");
|
||
|
|
||
|
CDeclarationNode *dnd = cnd->getDeclaration(var);
|
||
|
|
||
|
if (!dnd->IsType)
|
||
|
error("attribute '"+var+"' is not a simple type");
|
||
|
|
||
|
tnd = getTypeNode(dnd->Type);
|
||
|
|
||
|
logfunc.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param+"."+dnd->getFunc()+"()")+");");
|
||
|
startlogid.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param+"."+dnd->getFunc()+"()")+");");
|
||
|
}
|
||
|
|
||
|
if (tnd != NULL)
|
||
|
{
|
||
|
getDbNode()->xmlDescription.push_back("<param id='"+toString(paramNum)+"' typeid='"+toString(tnd->Id)+"'/>");
|
||
|
initDb.add(pdslibFunc("initLogParam")+"("+toString(logId)+", "+toString(paramNum)+", "+toString(tnd->Size)+");");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
getDbNode()->xmlDescription.push_back("<param id='"+toString(paramNum)+"' typeid='"+extnd->ExtLogType+"'/>");
|
||
|
initDb.add(pdslibFunc("initLogParam")+"("+toString(logId)+", "+toString(paramNum)+", "+toString(sizeof(uint16))+");");
|
||
|
}
|
||
|
|
||
|
|
||
|
log += "$"+toString(paramNum);
|
||
|
|
||
|
++paramNum;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
log += *(cptr++);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
getDbNode()->xmlDescription.push_back("<msg>"+xmlSpecialChars(log)+"</msg>");
|
||
|
getDbNode()->xmlDescription.push_back("</logmsg>");
|
||
|
}
|
||
|
|
||
|
logclass.get(startlogid).Proto = logfunc.Proto;
|
||
|
|
||
|
CClassGenerator::SMethodId construct = logclass.startConstructor(logfunc.Proto, "pub", inlineLogFunctions, "");
|
||
|
construct.add(logStartFunction+"("+argcall+");");
|
||
|
CClassGenerator::SMethodId destruct = logclass.startDestructor("pub", inlineLogFunctions);
|
||
|
destruct.add(logStopFunction+"();");
|
||
|
|
||
|
CFileNode* file = getFileNode();
|
||
|
|
||
|
if (Context)
|
||
|
{
|
||
|
logclass.flush(file->hOutput(), file->cppOutput(), file->inlineOutput());
|
||
|
file->hOutput() << "\n";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
logfunc.flush(file->hOutput(), file->cppOutput(), file->inlineOutput());
|
||
|
file->hOutput() << "\n";
|
||
|
}
|
||
|
}
|
||
|
|