1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2015-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "cpp_output.h"
23 #include "templatizer.h"
25 #include "parser_rules.h"
27 #include <nel/misc/path.h>
28 #include <nel/misc/sha1.h>
31 using namespace NLMISC
;
32 //using namespace RY_PDS;
35 bool GenerateCpp
= true;
36 bool GenerateXmlDescription
= true;
37 bool VerboseMode
= false;
38 bool GenerateDebugMessages
= false;
39 bool GenerateHAuto
= false;
40 bool GenerateOnlyLogs
= false;
44 CTemplatizer Templatizer
;
48 CEnumNode
*CurrentEnumNode
= NULL
;
50 string
DbDescriptionVersion("0.0");
52 string
formatDescription(const string
&str
)
58 while (pos
< str
.size() && (str
[pos
] == ' ' || str
[pos
] == '\t' || str
[pos
] == '\r' || str
[pos
] == '\n'))
63 while (pos
< str
.size())
71 while (pos
< str
.size() && str
[pos
] != '\n')
74 while (pos
< str
.size() && (str
[pos
] == ' ' || str
[pos
] == '\t' || str
[pos
] == '\r' || str
[pos
] == '\n'))
81 string
strReplace(string str
, const string
&search
, const string
&replace
)
83 std::string::size_type pos
= 0;
84 while ((pos
= str
.find(search
)) != string::npos
)
85 str
.replace(pos
, search
.size(), replace
);
89 string
xmlSpecialChars(string str
)
91 str
= strReplace(str
, "&", "&");
92 str
= strReplace(str
, "<", "<");
93 str
= strReplace(str
, ">", ">");
94 str
= strReplace(str
, "\"", """);
95 str
= strReplace(str
, "'", "'");
100 string
getFullStdPathNoExt(const string
&path
)
102 string dir
= NLMISC::toLowerAscii(NLMISC::CFile::getPath(path
));
103 string file
= NLMISC::toLowerAscii(NLMISC::CFile::getFilenameWithoutExtension(path
));
105 return dir
.empty() ? file
: NLMISC::CPath::standardizePath(dir
)+file
;
108 string
getFullStdPath(const string
&path
)
110 string dir
= NLMISC::toLowerAscii(NLMISC::CFile::getPath(path
));
111 string file
= NLMISC::toLowerAscii(NLMISC::CFile::getFilename(path
));
113 return dir
.empty() ? file
: NLMISC::CPath::standardizePath(dir
)+file
;
116 string
appendArg(const std::string
& firstArgs
, const std::string
& nextArg
)
118 if (firstArgs
.empty())
120 return firstArgs
+ ", " + nextArg
;
126 CParseNode
*parse(const string
&file
)
128 HashKey
= getSHA1(file
);
130 Tokenizer
.readFile(file
);
132 if (Tokenizer
.tokenize())
133 return parseMain(Tokenizer
);
144 bool CDbNode::prolog()
146 addTypeNode("CSheetId", "NLMISC::CSheetId", "NLMISC::CSheetId::Unknown");
147 addTypeNode("CEntityId", "NLMISC::CEntityId", "NLMISC::CEntityId::Unknown");
148 addTypeNode("double", "double", "0.0");
149 addTypeNode("float", "float", "0.0f");
150 addTypeNode("sint64", "sint64", "(sint64)0");
151 addTypeNode("uint64", "uint64", "(uint64)0");
152 addTypeNode("sint32", "sint32", "0");
153 addTypeNode("uint32", "uint32", "0");
154 addTypeNode("sint16", "sint16", "0");
155 addTypeNode("uint16", "uint16", "0");
156 addTypeNode("sint8", "sint8", "0");
157 addTypeNode("uint8", "uint8", "0");
158 addTypeNode("ucchar", "ucchar", "0");
159 addTypeNode("char", "char", "0");
160 addTypeNode("bool", "bool", "false");
167 bool inlineAccessors
= false;
168 string getFunctionPrefix
= "get";
169 string setFunctionPrefix
= "set";
170 string newFunction
= "addTo";
171 string deleteFunction
= "deleteFrom";
173 string indexVariable
= "__i";
174 string valueVariable
= "__v";
175 string keyVariable
= "__k";
176 string objectVariable
= "__o";
178 bool inlineUserInitDefaultCode
= false;
179 string userInitFunction
= "init";
180 string userReleaseFunction
= "release";
182 bool inlineStaticPublic
= false;
183 string staticCreateFunction
= "create";
184 string staticRemoveFunction
= "remove";
185 string staticSetUserFactoryFunction
= "setFactory";
186 string staticLoadFunction
= "load";
187 string staticUnloadFunction
= "unload";
188 string staticSetLoadCbFunction
= "setLoadCallback";
189 string staticGetFunction
= "get";
190 string staticCastFunction
= "cast";
191 string staticConstCastFunction
= "cast";
192 string staticBeginFunction
= "begin";
193 string staticEndFunction
= "end";
195 bool inlineInternal
= false;
196 string initFunction
= "pds__init";
197 string destroyFunction
= "pds__destroy";
198 string registerFunction
= "pds__register";
199 string registerAttributesFunction
= "pds__registerAttributes";
200 string unregisterFunction
= "pds__unregister";
201 string unregisterAttributesFunction
= "pds__unregisterAttributes";
202 string fetchFunction
= "pds__fetch";
203 string setParentFunction
= "pds__setParent";
204 string setUnnotifiedParentFunction
= "pds__setParentUnnotified";
205 string getTableFunction
= "pds__getTable";
206 string unlinkFunction
= "pds__unlink";
207 string notifyInitFunction
= "pds__notifyInit";
208 string notifyReleaseFunction
= "pds__notifyRelease";
210 string clearFunction
= "clear";
211 string storeFunction
= "store";
212 string applyFunction
= "apply";
213 string declareTokensFunction
= "pds__declareTokens";
216 bool inlineStaticInternal
= false;
217 string staticInitFactoryFunction
= "pds_static__setFactory";
218 string staticFactoryFunction
= "pds_static__factory";
219 string staticFetchFunction
= "pds_static__fetch";
220 string staticInitFunction
= "pds_static__init";
221 string staticNotifyLoadFailure
= "pds_static__notifyFailure";
222 string staticLoadCbAttribute
= "__pds__LoadCallback";
224 bool inlineLog
= false;
225 string logStartFunction
= "pds__startLog";
226 string logStopFunction
= "pds__stopLog";
228 string PDSNamespace
= "RY_PDS";
229 string CPDSLibName
= PDSNamespace
+"::CPDSLib";
230 string objectIndexName
= PDSNamespace
+"::CObjectIndex";
231 string nullIndexName
= PDSNamespace
+"::CObjectIndex::null()";
232 string TTableIndexName
= PDSNamespace
+"::TTableIndex";
233 string TRowIndexName
= PDSNamespace
+"::TRowIndex";
234 string TColumnIndexName
= PDSNamespace
+"::TColumnIndex";
235 string INVALID_TABLE_INDEXName
= PDSNamespace
+"::INVALID_TABLE_INDEX";
236 string INVALID_ROW_INDEXName
= PDSNamespace
+"::INVALID_ROW_INDEX";
237 string indexAllocatorName
= PDSNamespace
+"::CIndexAllocator";
238 string pdBaseDataName
= PDSNamespace
+"::IPDBaseData";
239 //string pdBaseInheritDataName = PDSNamespace+"::IPDBaseInheritData";
240 string CPDataName
= PDSNamespace
+"::CPData";
241 string TPDFactoryName
= PDSNamespace
+"::TPDFactory";
242 string TPDFetchName
= PDSNamespace
+"::TPDFetch";
243 string TPDFetchFailureName
= PDSNamespace
+"::TPDFetchFailure";
245 bool inlineLogFunctions
= false;
247 string
pdslibFunc(const std::string
& func
)
249 //return CPDSLibName+"::"+func;
250 return "PDSLib."+func
;
253 bool CDbNode::epilog()
257 Env
= Templatizer
.RootEnv
;
260 string fullfile
= getFullStdPathNoExt(MainFile
.empty() ? Name
: MainFile
);
261 string filename
= NLMISC::toLowerAscii(NLMISC::CFile::getFilenameWithoutExtension(fullfile
));
263 setEnv("filename", filename
);
264 setEnv("fullfilename", fullfile
);
265 setEnv("headerfilename", strReplace(strupr(filename
+".h"), ".", "_"));
267 DbHpp
.setFileHeader(filename
+".h", "Initialisation of the "+Name
+" database, declarations\n"+Description
);
268 DbCpp
.setFileHeader(filename
+".cpp", "Initialisation of the "+Name
+" database, implementation\n"+Description
);
269 DbHppInline
.setFileHeader(filename
+"_inline.h", "Initialisation of the "+Name
+" database, inline implementation\n"+Description
);
272 DbSummary
<< "Summary of " << Name
<< " database classes of database\n";
273 DbSummary
<< "-----------------------------------------------------------------------------\n\n";
274 DbSummary
<< "This file is automatically generated.\n";
275 DbSummary
<< "This is a reminder of all classes generated and methods implemented.\n\n\n";
277 DbSummary
<< "Database " << Name
<< " is managed through 4 functions located in " << fullfile
<< ".h:\n\n";
279 DbSummary
<< Name
<< "::init():\n";
280 DbSummary
<< "Initialises database context and connection towards database server (refered as PDS).\n";
281 DbSummary
<< "All user factories must have been set before call to this function.\n";
282 DbSummary
<< "Call this function in service init method.\n\n";
284 DbSummary
<< Name
<< "::ready():\n";
285 DbSummary
<< "Tells whether the whole database engine is ready to work.\n";
286 DbSummary
<< "You must not update any value nor call update() unless ready() is true.\n\n";
288 DbSummary
<< Name
<< "::update():\n";
289 DbSummary
<< "Updates the database engine and sends updates to the PDS.\n";
290 DbSummary
<< "Call this function each tick, provided ready() returned true.\n\n";
292 DbSummary
<< Name
<< "::release():\n";
293 DbSummary
<< "Releases the database engine. Drops all data, closes the connection to the PDS.\n";
294 DbSummary
<< "Call this function in service release method.\n\n";
297 DbSummary
<< "Summary of generated classes for " << Name
<< "\n\n";
299 DbHpp
<< "\n#ifndef " << strReplace(strupr(filename
+".h"), ".", "_") << "\n";
300 DbHpp
<< "#define " << strReplace(strupr(filename
+".h"), ".", "_") << "\n";
302 DbHpp
<< "#include <nel/misc/types_nl.h>\n";
303 DbHpp
<< "#include <pd_lib/pd_lib.h>\n";
305 DbHpp
<< "namespace " << Name
<< "\n{\n\n";
310 DbCpp
<< "\n#include \"" << Pch
<< "\"\n\n";
313 DbCpp
<< "#include \"" << filename
<< ".h\"\n\n";
314 DbCpp
<< "namespace " << Name
<< "\n{\n\n";
317 DbCpp
<< "RY_PDS::CPDSLib PDSLib;\n";
319 DbHppInline
<< "namespace " << Name
<< "\n{\n\n";
320 DbHppInline
.unindent();
324 for (i
=0; i
<ClassNodes
.size(); ++i
)
326 CClassNode
*classnd
= ClassNodes
[i
];
331 for (i
=0; i
<TypeNodes
.size(); ++i
)
333 CTypeNode
*typend
= TypeNodes
[i
];
337 xmlDescription
.clear();
338 xmlDescription
.push_back("<?xml version='1.0'?>");
339 xmlDescription
.push_back("<dbdescription version='"+DbDescriptionVersion
+"'>");
340 //xmlDescription.push_back("<db name='"+Name+"' types='"+toString(maxTypeId)+"' classes='"+toString(maxClassId)+"' hashkey='"+HashKey.toString()+"'>");
341 xmlDescription
.push_back("<db name='"+Name
+"' types='"+toString(maxTypeId
)+"' classes='"+toString(maxClassId
)+"'>");
349 // Check dependencies order
350 vector
<CClassNode
*> classesOrder
;
351 vector
<CFileNode
*> filesOrder
;
352 buildClassOrder(classesOrder
, filesOrder
);
354 // generate all file prologs
355 for (i
=0; i
<FileNodes
.size(); ++i
)
357 CFileNode
*child
= FileNodes
[i
];
358 child
->generateProlog();
365 initDb
.IsInline
= false;
366 initDb
.Proto
= "uint32 overrideDbId";
367 initDb
.Type
= "void";
368 initDb
.Description
= "Initialise the whole database engine.\nCall this function at service init.";
370 readyDb
.init("ready");
371 readyDb
.IsInline
= false;
372 readyDb
.Proto
.clear();
373 readyDb
.Type
= "bool";
374 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.";
376 updateDb
.init("update");
377 updateDb
.IsInline
= false;
378 updateDb
.Proto
.clear();
379 updateDb
.Type
= "void";
380 updateDb
.Description
= "Update the database engine.\nCall this method once per tick, only if engine is ready (see also ready() above).";
382 logChatDb
.init("logChat");
383 logChatDb
.IsInline
= false;
384 logChatDb
.Proto
= "const ucstring& sentence, const NLMISC::CEntityId& from, const std::vector<NLMISC::CEntityId>& to";
385 logChatDb
.Type
= "void";
386 logChatDb
.Description
= "Logs chat sentence with sender and receipiants.";
388 logTellDb
.init("logTell");
389 logTellDb
.IsInline
= false;
390 logTellDb
.Proto
= "const ucstring& sentence, const NLMISC::CEntityId& from, const NLMISC::CEntityId& to";
391 logTellDb
.Type
= "void";
392 logTellDb
.Description
= "Logs tell sentence with sender and single recipient (might be player or group).";
394 releaseDb
.init("release");
395 releaseDb
.IsInline
= false;
396 releaseDb
.Proto
.clear();
397 releaseDb
.Type
= "void";
398 releaseDb
.Description
= "Release the whole database engine.\nCall this function at service release.";
401 generateClassesDeclaration();
404 generateClassesContent(classesOrder
);
407 generateLogContent();
409 xmlDescription
.push_back("</db>");
410 xmlDescription
.push_back("</dbdescription>");;
412 initDb
.add("std::string\txmlDescription;");
416 for (i
=0; i
<xmlDescription
.size(); ++i
)
418 initDb
.add("xmlDescription += \""+xmlDescription
[i
]+"\\n\";");
419 DbXml
<< xmlDescription
[i
] << "\n";
422 DbXml
.flush(fullfile
+".xml");
424 DbHpp
<< "/// \\name Public API for " << Name
<< " database\n";
428 initDb
.add(pdslibFunc("init")+"(xmlDescription, overrideDbId);");
429 initDb
.flush(DbHpp
, DbCpp
, DbHppInline
);
431 readyDb
.add("return "+pdslibFunc("PDSReady")+"();");
432 readyDb
.flush(DbHpp
, DbCpp
, DbHppInline
);
434 updateDb
.add(pdslibFunc("update")+"();");
435 updateDb
.flush(DbHpp
, DbCpp
, DbHppInline
);
437 logChatDb
.add(pdslibFunc("logChat")+"(sentence, from, to);");
438 logChatDb
.flush(DbHpp
, DbCpp
, DbHppInline
);
440 logTellDb
.add("std::vector<NLMISC::CEntityId>\tids;");
441 logTellDb
.add("ids.push_back(to);");
442 logTellDb
.add(pdslibFunc("logChat")+"(sentence, from, ids);");
443 logTellDb
.flush(DbHpp
, DbCpp
, DbHppInline
);
445 releaseDb
.add(pdslibFunc("release")+"();");
446 releaseDb
.flush(DbHpp
, DbCpp
, DbHppInline
);
448 DbHpp
<< "\n// @}\n\n";
450 DbHpp
<< "extern RY_PDS::CPDSLib PDSLib;\n";
453 DbHpp
<< "\n} // End of " << Name
<<"\n";
455 generateIncludes(filesOrder
);
457 DbHpp
<< "\n#include \"" << filename
<< "_inline.h\"\n\n";
458 DbHpp
<< "\n#endif\n";
459 DbHpp
.flush(fullfile
+".h");
462 DbCpp
<< "\n} // End of " << Name
<<"\n";
463 DbCpp
.flush(fullfile
+".cpp");
465 DbHppInline
.indent();
466 DbHppInline
<< "\n} // End of " << Name
<<"\n";
467 DbHppInline
.flush(fullfile
+"_inline.h");
469 DbSummary
.flush(fullfile
+"_summary.txt");
471 for (i
=0; i
<FileNodes
.size(); ++i
)
473 CFileNode
*child
= FileNodes
[i
];
474 child
->generateEpilog();
482 void CDbNode::pass1()
486 * - all type names and class names are known
487 * -> look for classes in set or backreferences
495 for (i
=0; i
<ClassNodes
.size(); ++i
)
497 CClassNode
*classnd
= ClassNodes
[i
];
498 classnd
->checkClassReferences();
499 classnd
->Id
= classId
++;
501 classnd
->getFileNode()->IncludeStandard
= true;
502 classnd
->getFileNode()->IncludeDbFile
= true;
505 for (i
=0; i
<TypeNodes
.size(); ++i
)
507 CTypeNode
*typend
= TypeNodes
[i
];
509 typend
->Id
= typeId
++;
512 if (typend
->StorageType
== "bool") tsize
= 1;
513 if (typend
->StorageType
== "char") tsize
= 1;
514 if (typend
->StorageType
== "ucchar") tsize
= 2;
515 if (typend
->StorageType
== "uint8") tsize
= 1;
516 if (typend
->StorageType
== "sint8") tsize
= 1;
517 if (typend
->StorageType
== "uint16") tsize
= 2;
518 if (typend
->StorageType
== "sint16") tsize
= 2;
519 if (typend
->StorageType
== "uint32") tsize
= 4;
520 if (typend
->StorageType
== "sint32") tsize
= 4;
521 if (typend
->StorageType
== "uint64") tsize
= 8;
522 if (typend
->StorageType
== "sint64") tsize
= 8;
523 if (typend
->StorageType
== "float") tsize
= 4;
524 if (typend
->StorageType
== "double") tsize
= 8;
525 if (typend
->StorageType
== "CEntityId") tsize
= 8;
526 if (typend
->StorageType
== "CSheetId") tsize
= 4;
528 typend
->Size
= tsize
;
530 string xmlnode
= "<typedef name='"+typend
->Name
+"' id='"+toString(typend
->Id
)+"' size='"+toString(tsize
)+"' storage='"+typend
->StorageType
+"'";
532 if (typend
->isEnum())
534 CEnumNode
*enumnd
= static_cast<CEnumNode
*>(typend
);
536 xmlnode
+= " type='enum'>";
537 xmlDescription
.push_back(xmlnode
);
539 for (j
=0; j
<enumnd
->Values
.size(); ++j
)
540 xmlDescription
.push_back("<enumvalue name='"+enumnd
->Values
[j
].first
+"' value='"+toString(enumnd
->Values
[j
].second
)+"'/>");
541 xmlDescription
.push_back("</typedef>");
543 else if (typend
->isDimension())
545 CDimensionNode
*dimnd
= static_cast<CDimensionNode
*>(typend
);
547 xmlnode
+= " type='dimension' dimension='"+toString(dimnd
->Dimension
)+"'/>";
548 xmlDescription
.push_back(xmlnode
);
552 xmlnode
+= " type='type'/>";
553 xmlDescription
.push_back(xmlnode
);
558 void CDbNode::pass2()
562 * - class hierarchy, backreferences and in set information are known
563 * -> fill up attributes
568 for (i
=0; i
<ClassNodes
.size(); ++i
)
570 CClassNode
*child
= ClassNodes
[i
];
572 if (!child
->Inherited
.empty() && child
->MappedFlag
&& !child
->HasParent
)
573 child
->error("class cannot inherit another class and be mapped. Try to map base class instead.");
575 if (child
->MappedFlag
&& child
->getClassKey() == NULL
)
576 child
->error("class is mapped and has no key defined");
578 child
->ForceReference
= (child
->HasInheritance
|| child
->MappedFlag
|| child
->DerivatedFlag
|| (child
->HasParent
&& !child
->ParentIsHidden
));
580 if (child
->ForceReference
&& child
->ParentIsHidden
)
581 child
->error("Parent attribute cannot be hidden because class has inheritance, is mapped or is derivated.");
583 child
->getFileNode()->IncludePDSLib
= true;
585 if (!child
->Inherited
.empty())
587 CClassNode
*icln
= child
;
588 CClassNode
*lastMapped
= (child
->MappedFlag
? child
: NULL
);
589 while (!icln
->Inherited
.empty())
591 icln
= getClassNode(icln
->Inherited
);
592 if (icln
->MappedFlag
)
594 if (lastMapped
!= NULL
)
595 lastMapped
->error("class cannot be remapped since parent "+icln
->Name
+" is already mapped");
601 if (icln->MappedFlag)
602 child->MapClass = icln;
604 child
->MapClass
= lastMapped
;
606 else if (child
->MappedFlag
)
608 child
->MapClass
= child
;
611 child
->fillAttributes();
616 void CDbNode::pass3()
620 * - attributes are known
621 * -> fill up backrefs and array/set forwardrefs
626 for (i
=0; i
<ClassNodes
.size(); ++i
)
628 CClassNode
*child
= ClassNodes
[i
];
632 for (i
=0; i
<ClassNodes
.size(); ++i
)
634 CClassNode
*child
= ClassNodes
[i
];
635 child
->computeFriends();
639 void CDbNode::pass4()
643 * - everything is ok in database descriptor
649 for (i
=0; i
<FileNodes
.size(); ++i
)
651 CFileNode
* file
= FileNodes
[i
];
652 file
->Hpp
<< "\n\n//\n// Typedefs & Enums\n//\n\n";
655 for (i
=0; i
<TypeNodes
.size(); ++i
)
657 CTypeNode
*type
= TypeNodes
[i
];
658 if (type
->ExternFlag
|| type
->InternFlag
)
661 type
->generateContent();
668 void CDbNode::generateClassesDeclaration()
673 DbHpp
<< "// Global Forward Declarations\n";
676 for (i
=0; i
<ClassNodes
.size(); ++i
)
678 DbHpp
<< "class " << ClassNodes
[i
]->Name
<< ";\n";
685 void CDbNode::generateIncludes(vector
<CFileNode
*>& filesOrder
)
690 DbHpp
<< "// Includes\n";
693 for (i
=0; i
<filesOrder
.size(); ++i
)
695 if (!filesOrder
[i
]->SeparatedFlag
)
697 filesOrder
[i
]->setEnv("as", getFileNoExtPath(filesOrder
[i
]->IncludeAs
));
698 DbHpp
<< "#include \"" << getFileNoExtPath(filesOrder
[i
]->IncludeAs
) << ".h\"\n";
704 for (i
=0; i
<filesOrder
.size(); ++i
)
706 if (filesOrder
[i
]->IncludeDbFile
&& !filesOrder
[i
]->SeparatedFlag
)
708 filesOrder
[i
]->define("incinline");
709 DbHpp
<< "#include \"" << getFileNoExtPath(filesOrder
[i
]->IncludeAs
) << "_inline.h\"\n";
717 void CDbNode::generateClassesContent(vector
<CClassNode
*>& classesOrder
)
722 // output classes content
724 for (i
=0; i
<classesOrder
.size(); ++i
)
726 CClassNode
*cln
= classesOrder
[i
];
728 initDb
.add(pdslibFunc("registerClassMapping")+"("+toString(cln
->Id
)+", \""+cln
->Name
+"\");");
729 cln
->generateContent();
733 void CDbNode::buildClassOrder(vector
<CClassNode
*>& classesOrder
, vector
<CFileNode
*>& filesOrder
)
735 set
<CClassNode
*> checkedClasses
;
739 for (i
=0; i
<ClassNodes
.size(); ++i
)
741 CClassNode
*child
= ClassNodes
[i
];
743 if (checkedClasses
.find(child
) != checkedClasses
.end())
746 set
<CClassNode
*> beingChecked
;
747 child
->checkDependencies(beingChecked
, checkedClasses
, classesOrder
);
750 set
<CFileNode
*> checkedFiles
;
753 for (i
=0; i
<FileNodes
.size(); ++i
)
755 CFileNode
*child
= FileNodes
[i
];
757 if (checkedFiles
.find(child
) != checkedFiles
.end())
760 set
<CFileNode
*> beingChecked
;
761 child
->checkDependencies(beingChecked
, checkedFiles
, filesOrder
);
764 for (i
=0; i
<filesOrder
.size(); ++i
)
765 filesOrder
[i
]->Env
= Env
->nextArrayNode("files");
767 for (i
=0; i
<classesOrder
.size(); ++i
)
768 classesOrder
[i
]->Env
= classesOrder
[i
]->getFileNode()->Env
->nextArrayNode("classes");
772 void CDbNode::generateLogContent()
778 for (i
=0; i
<LogNodes
.size(); ++i
)
780 CLogMsgNode
*child
= LogNodes
[i
];
782 logid
+= (uint
)child
->Logs
.size();
784 child
->generateContent();
788 // get file path from this file
789 string
CDbNode::getFileNoExtPath(const std::string
& file
)
791 string thisPath
= NLMISC::CFile::getPath(NLMISC::toLowerAscii(getDbFile()));
792 string filePath
= NLMISC::CFile::getPath(NLMISC::toLowerAscii(file
));
793 string fileName
= NLMISC::CFile::getFilename(NLMISC::toLowerAscii(file
));
795 if (thisPath
== filePath
)
796 return CFile::getFilenameWithoutExtension(fileName
);
798 return CPath::standardizePath(filePath
)+CFile::getFilenameWithoutExtension(NLMISC::toLowerAscii(file
));
805 bool CFileNode::prolog()
807 CDbNode
* db
= getDbNode();
808 db
->FileNodes
.push_back(this);
810 if (GenerateOnlyLogs
)
816 bool CFileNode::epilog()
821 bool CFileNode::generateProlog()
823 CDbNode
* db
= getDbNode();
825 if (!db
->Description
.empty())
826 Hpp
<< db
->Description
<< "\n";
828 string filename
= NLMISC::toLowerAscii(CFile::getFilenameWithoutExtension(Name
));
830 setEnv("fullfilename", getFullStdPathNoExt(Name
));
831 setEnv("filename", filename
);
832 setEnv("headerfilename", strReplace(strupr(filename
+".h"), ".", "_"));
833 setEnv("description", Description
);
835 Hpp
.setFileHeader(filename
+".h", Description
);
836 Cpp
.setFileHeader(filename
+".cpp", Description
);
837 HppInline
.setFileHeader(filename
+"_inline.h", Description
);
839 Hpp
<< "\n#ifndef " << strReplace(strupr(filename
+".h"), ".", "_") << "\n";
840 Hpp
<< "#define " << strReplace(strupr(filename
+".h"), ".", "_") << "\n\n";
843 Hpp
<< "#include <nel/misc/types_nl.h>\n";
844 Hpp
<< "#include <nel/misc/debug.h>\n";
845 Hpp
<< "#include <nel/misc/common.h>\n";
849 Hpp
<< "#include <nel/misc/hierarchical_timer.h>\n";
855 Hpp
<< "#include <nel/misc/entity_id.h>\n";
856 Hpp
<< "#include <nel/misc/sheet_id.h>\n";
859 Hpp
<< "#include <vector>\n";
860 Hpp
<< "#include <map>\n";
865 Hpp
<< "#include <pd_lib/pd_lib.h>\n";
866 Hpp
<< "#include <game_share/persistent_data.h>\n";
872 string fullfile
= getFullStdPathNoExt(db
->MainFile
.empty() ? db
->Name
: db
->MainFile
);
873 string filename
= NLMISC::toLowerAscii(NLMISC::CFile::getFilenameWithoutExtension(fullfile
));
874 Hpp
<< "#include \"" << filename
<< ".h\"\n";
878 Hpp
<< "// User #includes\n";
880 for (i
=0; i
<IncludeNodes
.size(); ++i
)
882 Env
->nextArrayNode("incuser")->set("as", IncludeNodes
[i
]->Name
);
883 Hpp
<< "#include \"" << IncludeNodes
[i
]->Name
<< "\"\n";
886 Hpp
<< "\nnamespace " << db
->Name
<< "\n{\n\n";
889 if (!db
->Description
.empty())
890 HppInline
<< db
->Description
;
891 HppInline
<< "namespace " << db
->Name
<< "\n{\n\n";
892 HppInline
.unindent();
893 Hpp
<< "//\n// Forward declarations\n//\n\n";
895 if (!db
->Pch
.empty())
898 Cpp
<< "#include \""+db
->Pch
+"\"";
902 if (SeparatedFlag
|| !IncludeDbFile
)
904 Cpp
<< "#include \"" << filename
<< ".h\"\n";
908 Cpp
<< "#include \"" << getFileNoExtPath(getDbNode()->getDbFile()) << ".h\"\n";
912 Cpp
<< "namespace " << db
->Name
<< "\n{\n\n";
918 bool CFileNode::generateEpilog()
920 CDbNode
* db
= getDbNode();
922 string fullfile
= getFullStdPathNoExt(Name
);
923 string filename
= NLMISC::toLowerAscii(CFile::getFilenameWithoutExtension(Name
));
926 Hpp
<< "\n} // End of " << db
->Name
<<"\n";
928 if (!IncludeDbFile
|| SeparatedFlag
)
930 // add inline #include
931 Hpp
<< "\n\n//\n// Inline implementations\n//\n\n";
932 Hpp
<< "#include \"" << filename
<< "_inline.h\"\n";
938 HppInline
<< "\n} // End of " << db
->Name
<<"\n";
941 Cpp
<< "\n} // End of " << db
->Name
<<"\n";
949 string
CFileNode::getFileNoExtPath(const string
& file
)
951 string thisPath
= NLMISC::CFile::getPath(NLMISC::toLowerAscii(Name
));
952 string filePath
= NLMISC::CFile::getPath(NLMISC::toLowerAscii(file
));
953 string fileName
= NLMISC::CFile::getFilename(NLMISC::toLowerAscii(file
));
955 if (thisPath
== filePath
)
956 return CFile::getFilenameWithoutExtension(fileName
);
958 return CFile::getFilenameWithoutExtension(NLMISC::toLowerAscii(file
));
961 void CFileNode::writeFile()
963 string fullfile
= getFullStdPathNoExt(Name
);
965 Hpp
.flush(fullfile
+".h");
966 Cpp
.flush(fullfile
+".cpp");
967 HppInline
.flush(fullfile
+"_inline.h");
970 void CFileNode::checkDependencies(set
<CFileNode
*> &beingChecked
,
971 set
<CFileNode
*> &checkedFiles
,
972 vector
<CFileNode
*> &filesOrder
)
974 if (beingChecked
.find(this) != beingChecked
.end())
975 error("circular dependency in file '"+Name
+"'");
977 if (checkedFiles
.find(this) != checkedFiles
.end())
980 beingChecked
.insert(this);
981 checkedFiles
.insert(this);
983 set
<CFileNode
*>::iterator it
;
984 for (it
=Dependencies
.begin(); it
!=Dependencies
.end(); ++it
)
986 CFileNode
*fileNode
= *it
;
987 if (fileNode
== this)
990 fileNode
->checkDependencies(beingChecked
, checkedFiles
, filesOrder
);
993 filesOrder
.push_back(this);
1003 bool CTypeNode::prolog()
1005 CDbNode
* db
= getDbNode();
1006 db
->TypeNodes
.push_back(this);
1011 bool CTypeNode::generateContent()
1013 hOutput() << "/** " << Name
<< "\n";
1014 if (!Description
.empty())
1016 hOutput() << Description
<< "\n";
1020 getFileLine(line
, col
, file
);
1021 hOutput() << "defined at " << file
<< ":" << line
<< "\n";
1022 hOutput() << "*/\n";
1024 hOutput() << "typedef " << getCppType() << " " << Name
<< ";\n\n";
1027 if (ToCppType
!= NULL
)
1029 CCppCodeNode
*tocpp
= static_cast<CCppCodeNode
*>(ToCppType
);
1031 CFunctionGenerator toCppFunc
;
1033 toCppFunc
.init(storageToCpp());
1034 toCppFunc
.setType(getName());
1035 toCppFunc
.IsInline
= true;
1036 toCppFunc
.Proto
= StorageType
+" _v";
1038 toCppFunc
.add(getName()+"\t__res;");
1039 toCppFunc
.add(strReplace(strReplace(tocpp
->RawCode
, "$("+CppType
+")", "__res"), "$("+StorageType
+")", "_v"));
1040 toCppFunc
.add("return __res;");
1041 toCppFunc
.flush(hOutput(), cppOutput(), inlineOutput());
1043 if (ToStorageType
!= NULL
)
1045 CCppCodeNode
*tostorage
= static_cast<CCppCodeNode
*>(ToStorageType
);
1047 CFunctionGenerator toStorageFunc
;
1049 toStorageFunc
.init(cppToStorage());
1050 toStorageFunc
.setType(StorageType
);
1051 toStorageFunc
.IsInline
= true;
1052 toStorageFunc
.Proto
= getName()+" _v";
1054 toStorageFunc
.add(StorageType
+"\t__res;");
1055 toStorageFunc
.add(strReplace(strReplace(tostorage
->RawCode
, "$("+StorageType
+")", "__res"), "$("+CppType
+")", "_v"));
1056 toStorageFunc
.add("return __res;");
1057 toStorageFunc
.flush(hOutput(), cppOutput(), inlineOutput());
1068 bool CIncludeNode::prolog()
1070 CFileNode
* file
= getFileNode();
1071 file
->IncludeNodes
.push_back(this);
1077 bool CUsePchNode::prolog()
1079 CDbNode
* db
= getDbNode();
1086 bool CCppCodeNode::prolog()
1097 bool CDimensionNode::prolog()
1099 CDbNode
* db
= getDbNode();
1100 db
->TypeNodes
.push_back(this);
1102 if (Dimension
< 256)
1103 StorageType
= "uint8";
1104 else if (Dimension
< 65536)
1105 StorageType
= "uint16";
1107 StorageType
= "uint32";
1114 bool CDimensionNode::epilog()
1119 bool CDimensionNode::generateContent()
1121 hOutput() << "/** " << Name
<< "\n";
1122 if (!Description
.empty())
1124 hOutput() << Description
<< "\n";
1128 getFileLine(line
, col
, file
);
1129 hOutput() << "defined at " << file
<< ":" << line
<< "\n";
1130 hOutput() << "*/\n";
1132 hOutput() << "typedef " << CppType
<< " " << Name
<< ";\n";
1133 hOutput() << "const " << getName() << "\t" << getSizeName() << " = " << Dimension
<< ";\n\n";
1139 bool CEnumNode::prolog()
1141 CDbNode
* db
= getDbNode();
1142 db
->TypeNodes
.push_back(this);
1144 if (Name
.empty() || Name
[0] != 'T')
1145 error("enum name '"+Name
+"' is invalid, must begin with a 'T'");
1149 CurrentEnumNode
= this;
1157 bool CEnumNode::epilog()
1161 for (i
=0; i
<Nodes
.size(); ++i
)
1163 CEnumNode
*nd
= dynamic_cast<CEnumNode
*>(Nodes
[i
]);
1166 Values
.insert(Values
.end(), nd
->Values
.begin(), nd
->Values
.end());
1169 for (i
=0; i
<Values
.size(); ++i
)
1171 if (MinValue
> Values
[i
].second
)
1172 MinValue
= Values
[i
].second
;
1173 if (MaxValue
< Values
[i
].second
)
1174 MaxValue
= Values
[i
].second
;
1177 CurrentEnumNode
= NULL
;
1181 bool CEnumSimpleValueNode::prolog()
1183 CEnumNode
*parent
= dynamic_cast<CEnumNode
*>(Parent
);
1186 CurrentValue
= parent
->CurrentValue
;
1193 for (i
=0; i
<Names
.size(); ++i
)
1195 CurrentEnumNode
->Values
.push_back(std::pair
<string
, uint32
>(Names
[i
], CurrentValue
));
1198 ++(parent
->CurrentValue
);
1203 bool CEnumSimpleValueNode::epilog()
1208 bool CEnumRangeNode::prolog()
1210 CEnumNode
*parent
= dynamic_cast<CEnumNode
*>(Parent
);
1213 CurrentValue
= parent
->CurrentValue
;
1220 CurrentEnumNode
->Values
.push_back(std::pair
<string
, uint32
>(Name
, CurrentValue
));
1225 bool CEnumRangeNode::epilog()
1227 CEnumNode
*parent
= dynamic_cast<CEnumNode
*>(Parent
);
1230 parent
->CurrentValue
= CurrentValue
;
1234 for (i
=0; i
<Nodes
.size(); ++i
)
1236 CEnumNode
*nd
= dynamic_cast<CEnumNode
*>(Nodes
[i
]);
1239 Values
.insert(Values
.end(), nd
->Values
.begin(), nd
->Values
.end());
1242 if (!EndRange
.empty())
1244 CurrentEnumNode
->Values
.push_back(std::pair
<string
, uint32
>(EndRange
, CurrentValue
));
1251 bool CEnumNode::generateContent()
1253 hOutput() << "/** " << Name
<< "\n";
1254 if (!Description
.empty())
1256 hOutput() << Description
<< "\n";
1260 getFileLine(line
, col
, file
);
1261 hOutput() << "defined at " << file
<< ":" << line
<< "\n";
1262 hOutput() << "*/\n";
1264 string enumTruncName
= Name
.substr(1);
1265 CClassGenerator gen
;
1266 gen
.init("C"+enumTruncName
);
1267 gen
.createPublic("enum", "Enum values", "");
1268 gen
.createPublic("conv", "Conversion methods", "Use these methods to convert from enum value to string (and vice versa)");
1269 gen
.createPrivate("init", "Enum initialisation", "");
1272 gen
.addOther("enum "+Name
+"\n", "enum");
1273 gen
.addOther("{\n", "enum");
1274 for (j
=0; j
<Values
.size(); ++j
)
1275 gen
.addOther(Values
[j
].first
+" = "+toString(Values
[j
].second
)+",\n", "enum");
1276 gen
.addOther(getUnscopedUseSize()+" = "+toString(MaxValue
-MinValue
+1)+",\n", "enum");
1277 gen
.addOther(getUnknownValue()+" = "+toString(MaxValue
-MinValue
+1)+",\n", "enum");
1278 if (!EndRange
.empty())
1279 gen
.addOther(EndRange
+" = "+toString(MaxValue
-MinValue
+1)+",\n", "enum");
1280 gen
.addOther("};\n", "enum");
1282 gen
.startMethod("const std::string&", "toString", Name
+" v", "conv", false, true, true);
1283 gen
.add("if (v < 0 || v >= "+getUnscopedUseSize()+")");
1285 gen
.add("nlwarning(\""+Name
+"::toString(): value '%u' is not matched, \\\"Unknown\\\" string returned\", v);");
1286 gen
.add("return _UnknownString;");
1288 //gen.add(checkCode("v"));
1289 gen
.add("if (!_Initialised)");
1293 gen
.add("return _StrTable[v];");
1295 gen
.startMethod(getName(), "fromString", "const std::string& v", "conv", false, true, true);
1296 gen
.add("if (!_Initialised)");
1300 gen
.add("if(v==_UnknownString)");
1302 gen
.add("return Unknown;");
1304 gen
.add("const std::map<std::string, "+Name
+">::const_iterator\tit = _ValueMap.find(NLMISC::toLowerAscii(v));");
1305 gen
.add("if (it == _ValueMap.end())");
1307 gen
.add("nlwarning(\""+Name
+"::toString(): string '%s' is not matched, 'Unknown' enum value returned\", v.c_str());");
1308 gen
.add("return "+getUnknownValue()+";");
1310 gen
.add("return (*it).second;");
1313 gen
.startMethod("void", "init", "", "init", false, false, true);
1314 gen
.add("_StrTable.clear();");
1315 gen
.add("_ValueMap.clear();");
1316 gen
.add("_StrTable.resize("+toString(getSize()+1)+");");
1317 gen
.add("uint\ti;");
1318 gen
.add("for (i=0; i<"+toString(Values
.size())+"; ++i)");
1320 gen
.add("_StrTable["+Name
+"Convert[i].Value] = "+Name
+"Convert[i].Name;");
1321 gen
.add("_ValueMap[NLMISC::toLowerAscii(std::string("+Name
+"Convert[i].Name))] = "+Name
+"Convert[i].Value;");
1324 gen
.add("_Initialised = true;");
1327 gen
.addAttribute("bool", "_Initialised", "init", true, "false");
1328 gen
.addAttribute("std::string", "_UnknownString", "init", true, "\""+getUnknownValue()+"\"");
1329 gen
.addAttribute("std::vector<std::string>", "_StrTable", "init", true);
1330 gen
.addAttribute("std::map<std::string, "+Name
+">", "_ValueMap", "init", true, "", false, "std::map<std::string, "+getName()+">");
1332 cppOutput() << "static const struct { char* Name; " << getName() << " Value; } " << Name
<< "Convert[] =\n";
1333 cppOutput() << "{\n";
1334 for (j
=0; j
<Values
.size(); ++j
)
1335 cppOutput() << "{ \"" << Values
[j
].first
<< "\", C"+enumTruncName
+"::"+Values
[j
].first
+" },\n";
1336 cppOutput() << "};\n";
1338 gen
.flush(hOutput(), cppOutput(), inlineOutput());
1348 bool CClassNode::prolog()
1350 CDbNode
* db
= getDbNode();
1351 db
->ClassNodes
.push_back(this);
1356 bool CClassNode::epilog()
1361 string
CClassNode::getUserCode(const string
& name
)
1364 for (i
=0; i
<Nodes
.size(); ++i
)
1366 CCppCodeNode
*code
= dynamic_cast<CCppCodeNode
*>(Nodes
[i
]);
1370 if (code
->Name
== name
)
1371 return code
->RawCode
;
1378 void CClassNode::checkClassReferences()
1380 if (!Implements
.empty())
1382 Gen
.Inherit
+= (HasRowAccess
? string(", ") : string(""))+"public "+Implements
;
1383 getDbNode()->Implemented
.insert(Implements
);
1387 if (!Inherited
.empty())
1389 HasInheritance
= true;
1390 CClassNode
*nd
= getClassNode(Inherited
);
1391 nd
->HasInheritance
= true;
1392 nd
->ChildrenClasses
.push_back(Name
);
1394 Dependencies
.insert(nd
);
1395 getFileNode()->Dependencies
.insert(nd
->getFileNode());
1398 CClassNode
* inherit
= this;
1399 while (inherit
!= NULL
)
1402 inherit
->PDSMapped
= true;
1404 inherit
->Legacy
.insert(this);
1405 inherit
= getClassNode(inherit
->Inherited
, false);
1410 for (i
=0; i
<Nodes
.size(); ++i
)
1412 CDeclarationNode
*decl
= dynamic_cast<CDeclarationNode
*>(Nodes
[i
]);
1418 if (decl
->ParentFlag
)
1421 decl
->error("class '"+Name
+"' already has a parent");
1424 // decl->error("class '"+Name+"' can't have a parent and be mapped at the same time");
1426 CClassNode
* inherit
= this;
1427 while (inherit
!= NULL
)
1429 inherit
->PDSMapped
= false;
1430 inherit
= getClassNode(inherit
->Inherited
, false);
1433 ParentClass
= decl
->ParentClass
;
1436 ParentIsHidden
= decl
->HiddenFlag
;
1438 decl
->getClassNode(decl
->ParentClass
)->IsBackReferenced
= true;
1440 else if (decl
->SetFlag
)
1442 decl
->getClassNode(decl
->Type
)->IsInSet
= true;
1447 void CClassNode::fillAttributes()
1449 if (HasParent
&& !IsBackReferenced
&& !HasInheritance
&& !IsInSet
&& !DerivatedFlag
&& !MappedFlag
)
1450 error("class '"+Name
+"' has a parent whereas it is not backreferenced, has no inherited link and is not mapped");
1453 for (i
=0; i
<Nodes
.size(); ++i
)
1455 CDeclarationNode
*decl
= dynamic_cast<CDeclarationNode
*>(Nodes
[i
]);
1460 for (j
=0; j
<Nodes
.size(); ++j
)
1461 if (j
!= i
&& dynamic_cast<CDeclarationNode
*>(Nodes
[j
]) != NULL
&& Nodes
[j
]->Name
== decl
->Name
)
1462 decl
->error("attribute '"+decl
->Name
+"' already defined");
1464 if (decl
->ParentFlag
)
1466 decl
->DeclarationType
= BackRef
;
1468 else if (decl
->ArrayFlag
)
1470 CClassNode
*classNd
= NULL
;
1471 CTypeNode
*typeNd
= NULL
;
1473 if ( (classNd
= decl
->getClassNode(decl
->Type
, false)) )
1475 if (classNd
->IsBackReferenced
|| classNd
->ForceReference
)
1477 if (decl
->ForwardRefAttribute
.empty())
1478 decl
->error("no forward reference to parent in array declaration, class '"+decl
->Type
+"' is backref'd or has inheritance");
1480 classNd
->IsInArrayRef
= true;
1482 decl
->DeclarationType
= ArrayRef
;
1484 if (classNd
->ParentIsHidden
)
1485 Dependencies
.insert(classNd
);
1489 if (!decl
->ForwardRefAttribute
.empty())
1490 decl
->error("forward reference declared whereas subclass is not backreferenced and has no inheritance link");
1492 Dependencies
.insert(classNd
);
1494 classNd
->IsInArray
= true;
1495 decl
->IsRef
= false;
1496 decl
->DeclarationType
= ArrayClass
;
1499 else if ( (typeNd
= decl
->getTypeNode(decl
->Type
, false)) )
1501 decl
->DeclarationType
= ArrayType
;
1505 decl
->error("type or class '"+decl
->Type
+"' not found");
1508 else if (decl
->SetFlag
)
1511 decl
->DeclarationType
= Set
;
1515 CClassNode
*classNd
= NULL
;
1516 CTypeNode
*typeNd
= NULL
;
1518 if ( (classNd
= decl
->getClassNode(decl
->Type
, false)) )
1520 if (classNd
->IsBackReferenced
|| classNd
->ForceReference
)
1522 if (decl
->ForwardRefAttribute
.empty())
1523 decl
->error("no forward reference to parent in array declaration, class '"+decl
->Type
+"' is backref'd or has inheritance");
1527 decl
->DeclarationType
= ForwardRef
;
1531 if (!decl
->ForwardRefAttribute
.empty())
1532 decl
->error("forward reference declared whereas subclass is not backreferenced and has no inheritance link");
1534 Dependencies
.insert(classNd
);
1536 decl
->IsRef
= false;
1538 decl
->DeclarationType
= SimpleClass
;
1541 else if ( (typeNd
= decl
->getTypeNode(decl
->Type
, false)) )
1543 decl
->IsType
= true;
1545 decl
->DeclarationType
= SimpleType
;
1549 decl
->error("type or class '"+decl
->Type
+"' not found");
1554 CDeclarationNode
*declNd
= getClassKey();
1557 if (!declNd
->IsType
)
1558 error("attribute '"+declNd
->Name
+"' can't be a key, only simple type allowed");
1560 declNd
->IsKey
= true;
1564 void CClassNode::fillRefs()
1567 for (i
=0; i
<Nodes
.size(); ++i
)
1569 CDeclarationNode
*decl
= dynamic_cast<CDeclarationNode
*>(Nodes
[i
]);
1573 switch (decl
->DeclarationType
)
1577 // check parent is a valid class
1578 CClassNode
*cln
= decl
->getClassNode(decl
->ParentClass
);
1579 CDeclarationNode
*dln
= dynamic_cast<CDeclarationNode
*>(cln
->getNode(decl
->ParentField
));
1580 if (!dln
) decl
->error("attribute '"+decl
->ParentField
+"' not found in class '"+decl
->ParentClass
+"'");
1582 if (!dln
->ArrayFlag
&& !dln
->SetFlag
&& !ForceReference
)
1583 decl
->error("back reference 'parent "+decl
->ParentClass
+":"+decl
->ParentField
+" "+decl
->Name
+"' is not forwarded in class '"+decl
->ParentClass
+"' with an array or a set");
1585 if (dln
->Type
!= Name
|| dln
->ForwardRefAttribute
!= decl
->Name
)
1586 decl
->error("back reference 'parent "+decl
->ParentClass
+":"+decl
->ParentField
+" "+decl
->Name
+"' is not correctly forwarded in class '"+decl
->ParentClass
+"'");
1588 Friends
.insert(cln
->Name
);
1594 CClassNode
*cln
= decl
->getClassNode(decl
->Type
);
1595 CDeclarationNode
*dln
= dynamic_cast<CDeclarationNode
*>(cln
->getNode(decl
->ForwardRefAttribute
));
1596 if (!dln
) decl
->error("attribute '"+decl
->ForwardRefAttribute
+"' not found in class '"+decl
->Type
+"'");
1598 if (!dln
->ParentFlag
)
1599 decl
->error("set '"+decl
->Type
+":"+decl
->ForwardRefAttribute
+"<> "+decl
->Name
+"' is not backref'd in class '"+decl
->Type
+"'");
1601 if (dln
->ParentClass
!= Name
|| dln
->ParentField
!= decl
->Name
)
1602 decl
->error("set '"+decl
->Type
+":"+decl
->ForwardRefAttribute
+"<> "+decl
->Name
+"' is not correctly backref'd in class '"+decl
->Type
+"'");
1604 if (cln
->getClassKey() == NULL
)
1605 decl
->error("class '"+decl
->Type
+"' has no key defined, whereas it is used in a set");
1607 cln
->Friends
.insert(Name
);
1608 ForwardFriends
.insert(cln
->Name
);
1614 if (decl
->ForwardRefAttribute
.empty())
1615 decl
->error("No forward reference defined");
1617 CClassNode
*cln
= decl
->getClassNode(decl
->Type
);
1618 CDeclarationNode
*dln
= dynamic_cast<CDeclarationNode
*>(cln
->getNode(decl
->ForwardRefAttribute
));
1619 CTypeNode
*tln
= decl
->getTypeNode(decl
->ArrayIndex
);
1620 getFileNode()->Dependencies
.insert(tln
->getFileNode());
1621 if (!dln
) decl
->error("attribute '"+decl
->ForwardRefAttribute
+"' not found in class '"+decl
->Type
+"'");
1623 if (!dln
->ParentFlag
)
1624 decl
->error("array '"+decl
->Type
+":"+decl
->ForwardRefAttribute
+"["+decl
->ArrayIndex
+"] "+decl
->Name
+"' is not backref'd in class '"+decl
->Type
+"'");
1626 if (dln
->ParentClass
!= Name
|| dln
->ParentField
!= decl
->Name
)
1627 decl
->error("array '"+decl
->Type
+":"+decl
->ForwardRefAttribute
+"["+decl
->ArrayIndex
+"] "+decl
->Name
+"' is not correctly backref'd in class '"+decl
->Type
+"'");
1629 if (cln
->getClassKey() == NULL
)
1630 decl
->error("class '"+decl
->Type
+"' has no key defined, whereas it is used in an array of ref");
1631 CDeclarationNode
*kdn
= dynamic_cast<CDeclarationNode
*>(cln
->getClassKey());
1632 if (!kdn
) decl
->error("attribute '"+cln
->ClassKey
+"' not found in class '"+cln
->Name
+"'");
1634 if (kdn
->Type
!= decl
->ArrayIndex
)
1635 decl
->error("type in array definition mismatch class '"+cln
->Name
+"' key definition");
1637 cln
->Friends
.insert(Name
);
1638 ForwardFriends
.insert(cln
->Name
);
1644 if (decl
->ForwardRefAttribute
.empty())
1645 decl
->error("No forward reference defined");
1647 CClassNode
*cln
= decl
->getClassNode(decl
->Type
);
1648 CDeclarationNode
*dln
= dynamic_cast<CDeclarationNode
*>(cln
->getNode(decl
->ForwardRefAttribute
));
1649 if (!dln
) decl
->error("attribute '"+decl
->ForwardRefAttribute
+"' not found in class '"+decl
->Type
+"'");
1651 if (!dln
->ParentFlag
)
1652 decl
->error("set '"+decl
->Type
+":"+decl
->ForwardRefAttribute
+"<> "+decl
->Name
+"' is not backref'd in class '"+decl
->Type
+"'");
1654 if (dln
->ParentClass
!= Name
|| dln
->ParentField
!= decl
->Name
)
1655 decl
->error("set '"+decl
->Type
+":"+decl
->ForwardRefAttribute
+"<> "+decl
->Name
+"' is not correctly backref'd in class '"+decl
->Type
+"'");
1657 cln
->Friends
.insert(Name
);
1658 ForwardFriends
.insert(cln
->Name
);
1664 CTypeNode
*tln
= decl
->getTypeNode(decl
->ArrayIndex
);
1665 getFileNode()->Dependencies
.insert(tln
->getFileNode());
1672 CTypeNode
*tln
= decl
->getTypeNode(decl
->ArrayIndex
);
1673 getFileNode()->Dependencies
.insert(tln
->getFileNode());
1677 CClassNode
*cln
= decl
->getClassNode(decl
->Type
);
1678 cln
->Friends
.insert(Name
);
1683 decl
->error("Can't decide declaration type");
1689 void CClassNode::computeFriends()
1696 set
<string
>::iterator itf
, itsf
;
1698 for (itf
=Friends
.begin(); !added
&& itf
!=Friends
.end(); ++itf
)
1700 CClassNode
* pfriend
= getClassNode(*itf
);
1702 for (itsf
=pfriend
->Friends
.begin(); !added
&& itsf
!=pfriend
->Friends
.end(); ++itsf
)
1704 const string
& sfriend
= *itsf
;
1705 if (Friends
.find(*itsf
) == Friends
.end())
1707 Friends
.insert(*itsf
);
1717 void CClassNode::checkDependencies(set
<CClassNode
*> &beingChecked
,
1718 set
<CClassNode
*> &checkedClasses
,
1719 vector
<CClassNode
*> &classesOrder
)
1721 if (beingChecked
.find(this) != beingChecked
.end())
1722 error("circular dependency in class '"+Name
+"'");
1724 if (checkedClasses
.find(this) != checkedClasses
.end())
1727 beingChecked
.insert(this);
1728 checkedClasses
.insert(this);
1730 set
<CClassNode
*>::iterator it
;
1731 for (it
=Dependencies
.begin(); it
!=Dependencies
.end(); ++it
)
1733 CClassNode
*classNode
= *it
;
1735 classNode
->checkDependencies(beingChecked
, checkedClasses
, classesOrder
);
1738 classesOrder
.push_back(this);
1743 void CClassNode::buildInit()
1745 CDbNode
*db
= getDbNode();
1750 if (!Inherited
.empty())
1752 CClassNode
*mother
= getClassNode(Inherited
);
1755 mother
->buildInit();
1756 Init
= mother
->Init
;
1759 for (i
=0; i
<Init
.size(); ++i
)
1761 if (!InitProto
.empty())
1763 if (!InitCallArgs
.empty())
1764 InitCallArgs
+= ", ";
1766 CTypeNode
* typeNode
= getTypeNode(Init
[i
]->Type
);
1767 InitProto
+= "const "+typeNode
->getName()+" &"+Init
[i
]->Name
;
1768 InitCallArgs
+= Init
[i
]->Name
;
1773 if (!ClassKey
.empty())
1775 CDeclarationNode
*decl
= dynamic_cast<CDeclarationNode
*>(getNode(ClassKey
));
1778 Init
.push_back(decl
);
1780 if (!InitProto
.empty())
1783 CTypeNode
* typeNode
= getTypeNode(decl
->Type
);
1784 InitProto
+= "const "+typeNode
->getName()+" &"+decl
->Name
;
1794 void CClassNode::computeAttributesColumns()
1799 CDbNode
*db
= getDbNode();
1802 if (!Inherited
.empty())
1804 CClassNode
*mother
= getClassNode(Inherited
);
1805 mother
->computeAttributesColumns();
1806 Columns
= mother
->Columns
;
1808 Attributes
= mother
->Attributes
;
1811 uint attribId
= (uint
)Attributes
.size();
1813 for (i
=0; i
<Nodes
.size(); ++i
)
1815 CDeclarationNode
*decl
= dynamic_cast<CDeclarationNode
*>(Nodes
[i
]);
1819 Attributes
.push_back(decl
);
1821 decl
->Column
= Columns
;
1822 decl
->Id
= attribId
++;
1825 // All for backref, set, forwardref, type
1826 switch (decl
->DeclarationType
)
1830 col
.Name
= decl
->Name
;
1831 col
.Type
= ForwardRef
;
1832 col
.TypeStr
= "forwardref";
1833 col
.TypeId
= decl
->getClassNode(decl
->Type
)->Id
;
1835 decl
->ColumnList
.push_back(col
);
1839 col
.Name
= decl
->Name
;
1841 col
.TypeStr
= "backref";
1842 col
.TypeId
= decl
->getClassNode(decl
->ParentClass
)->Id
;
1844 decl
->ColumnList
.push_back(col
);
1848 col
.Name
= decl
->Name
;
1849 col
.Type
= SimpleType
;
1850 col
.TypeStr
= "type";
1851 col
.TypeId
= decl
->getTypeNode(decl
->Type
)->Id
;
1852 col
.ByteSize
= decl
->getTypeNode(decl
->Type
)->Size
;
1853 decl
->ColumnList
.push_back(col
);
1857 col
.Name
= decl
->Name
;
1859 col
.TypeStr
= "set";
1860 col
.TypeId
= decl
->getClassNode(decl
->Type
)->Id
;
1862 decl
->ColumnList
.push_back(col
);
1866 CClassNode
*sub
= decl
->getClassNode(decl
->Type
);
1867 sub
->computeAttributesColumns();
1868 decl
->Columns
= sub
->Columns
;
1871 for (i
=0; i
<sub
->Attributes
.size(); ++i
)
1873 CDeclarationNode
*attrib
= sub
->Attributes
[i
];
1875 for (j
=0; j
<attrib
->ColumnList
.size(); ++j
)
1877 col
.Name
= decl
->Name
+"."+attrib
->ColumnList
[j
].Name
;
1878 col
.Type
= attrib
->ColumnList
[j
].Type
;
1879 col
.TypeStr
= attrib
->ColumnList
[j
].TypeStr
;
1880 col
.TypeId
= attrib
->ColumnList
[j
].TypeId
;
1881 col
.ByteSize
= attrib
->ColumnList
[j
].ByteSize
;
1882 decl
->ColumnList
.push_back(col
);
1889 CIndexNode
*indexNd
= decl
->getIndexNode(decl
->ArrayIndex
);
1890 uint numInEnum
= indexNd
->getSize();
1891 decl
->Columns
= numInEnum
;
1894 for (i
=0; i
<numInEnum
; ++i
)
1896 col
.Name
= decl
->Name
+"["+indexNd
->getIndexName(i
)+"]";
1897 col
.Type
= ForwardRef
;
1898 col
.TypeStr
= "forwardref";
1899 col
.TypeId
= decl
->getClassNode(decl
->Type
)->Id
;
1901 decl
->ColumnList
.push_back(col
);
1907 CIndexNode
*indexNd
= decl
->getIndexNode(decl
->ArrayIndex
);
1908 uint numInEnum
= indexNd
->getSize();
1909 decl
->Columns
= numInEnum
;
1912 for (i
=0; i
<numInEnum
; ++i
)
1914 col
.Name
= decl
->Name
+"["+indexNd
->getIndexName(i
)+"]";
1915 col
.Type
= SimpleType
;
1916 col
.TypeStr
= "type";
1917 col
.TypeId
= decl
->getTypeNode(decl
->Type
)->Id
;
1918 col
.ByteSize
= decl
->getTypeNode(decl
->Type
)->Size
;
1919 decl
->ColumnList
.push_back(col
);
1925 CIndexNode
*indexNd
= decl
->getIndexNode(decl
->ArrayIndex
);
1927 CClassNode
*sub
= decl
->getClassNode(decl
->Type
);
1928 sub
->computeAttributesColumns();
1930 uint numInEnum
= indexNd
->getSize();
1931 decl
->Columns
= numInEnum
*sub
->Columns
;
1934 for (k
=0; k
<numInEnum
; ++k
)
1936 for (i
=0; i
<sub
->Attributes
.size(); ++i
)
1938 CDeclarationNode
*attrib
= sub
->Attributes
[i
];
1940 for (j
=0; j
<attrib
->ColumnList
.size(); ++j
)
1942 col
.Name
= decl
->Name
+"["+indexNd
->getIndexName(k
)+"]."+attrib
->ColumnList
[j
].Name
;
1943 col
.Type
= attrib
->ColumnList
[j
].Type
;
1944 col
.TypeStr
= attrib
->ColumnList
[j
].TypeStr
;
1945 col
.TypeId
= attrib
->ColumnList
[j
].TypeId
;
1946 col
.ByteSize
= attrib
->ColumnList
[j
].ByteSize
;
1947 decl
->ColumnList
.push_back(col
);
1955 Columns
+= decl
->Columns
;
1963 bool CClassNode::generateContent()
1965 nlassert(Env
!= NULL
);
1969 getFileLine(line
, col
, file
);
1971 setEnv("name", Name
);
1972 if (!Description
.empty())
1973 setEnv("description", Description
);
1974 setEnv("deffile", file
);
1975 setEnv("defline", line
);
1977 computeAttributesColumns();
1982 // generate description
1984 hOutput() << "/** " << Name
<< "\n";
1985 if (!Description
.empty())
1986 hOutput() << Description
<< "\n";
1988 hOutput() << "defined at " << file
<< ":" << line
<< "\n";
1989 hOutput() << "*/\n";
1991 CCppOutput
& DbSummary
= getDbNode()->DbSummary
;
1992 DbSummary
<< "Class " << getDbNode()->Name
<< "::" << Name
<< ":\n";
1993 DbSummary
<< "----------------------------------------------------------\n";
1994 DbSummary
<< "located in file \"" << getFullStdPathNoExt(getFileNode()->Name
) << ".h\"\n";
1995 DbSummary
<< "defined in file \"" << getFullStdPath(file
) << "\"\n";
1996 DbSummary
<< "The class contains:\n\n";
1999 Gen
.createPublic("methods", "Accessors and Mutators methods", "Use these methods to change a value, add or delete elements.");
2000 Gen
.createPublic("map", "Public Management methods", "Use these methods to create, load, unload and get\nan object from database.");
2001 Gen
.createPublic("user", "User defined attributes and methods", "This code was verbatim copied from source file");
2002 Gen
.createPublic("construct", "Public constructor", "This constructor is public to allow direct instanciation of the class");
2003 Gen
.createPublic("persist", "Persistent methods declaration", "");
2004 Gen
.createProtected("userinit", "User defined init and release methods", "Overload those methods to implement init and release behaviours");
2005 Gen
.createProtected("attributes", "Attributes", "Don't modify those value manually, use accessors and mutators above");
2006 Gen
.createProtected("internal", "Internal Management methods");
2007 Gen
.createProtected("inherit map");
2008 Gen
.createProtected("factories", "Default Factory and Fetch methods");
2009 Gen
.createProtected("friends");
2014 Gen
.startRaw("persist", false);
2015 ApplyId
= Gen
.startMethod("void", applyFunction
, "CPersistentDataRecord &__pdr", "persist", false, inlineInternal
, false, false, "", HasInheritance
);
2016 StoreId
= Gen
.startMethod("void", storeFunction
, "CPersistentDataRecord &__pdr", "persist", true, inlineInternal
, false, false, "", HasInheritance
);
2018 ClearId
= Gen
.startMethod("void", clearFunction
, "", "map", false, inlineStaticPublic
, false, false, "", HasInheritance
);
2019 Gen
.setDescription("Clear whole object content but key (delete subobjects if there are, key is left unmodified), default clear value is 0.");
2021 StoreId
.add("uint16\t__Tok_MapKey = __pdr.addString(\"__Key__\");");
2022 StoreId
.add("uint16\t__Tok_MapVal = __pdr.addString(\"__Val__\");");
2023 StoreId
.add("uint16\t__Tok_ClassName = __pdr.addString(\"__Class__\");");
2024 ApplyId
.add("uint16\t__Tok_MapKey = __pdr.addString(\"__Key__\");");
2025 ApplyId
.add("uint16\t__Tok_MapVal = __pdr.addString(\"__Val__\");");
2026 ApplyId
.add("uint16\t__Tok_ClassName = __pdr.addString(\"__Class__\");");
2028 if (!Inherited
.empty())
2030 StoreId
.add("uint16\t__Tok_Parent = __pdr.addString(\"__Parent__\");");
2031 ApplyId
.add("uint16\t__Tok_Parent = __pdr.addString(\"__Parent__\");");
2034 for (j
=0; j
<Attributes
.size(); ++j
)
2036 CDeclarationNode
* decl
= Attributes
[j
];
2037 if (decl
->Parent
!= this)
2040 if (decl
->DeclarationType
== BackRef
)
2042 ApplyId
.add(decl
->cppName()+" = NULL;");
2046 StoreId
.add("uint16\t"+decl
->tokenName()+" = __pdr.addString(\""+decl
->Name
+"\");");
2047 ApplyId
.add("uint16\t"+decl
->tokenName()+" = __pdr.addString(\""+decl
->Name
+"\");");
2051 ApplyId
.add("while (!__pdr.isEndOfStruct())");
2053 ApplyId
.add( "if (false) {}");
2055 if (!Inherited
.empty())
2057 StoreId
.add("__pdr.pushStructBegin(__Tok_Parent);");
2058 StoreId
.add(Inherited
+"::store(__pdr);");
2059 StoreId
.add("__pdr.pushStructEnd(__Tok_Parent);");
2061 ApplyId
.add("else if (__pdr.peekNextToken() == __Tok_Parent)");
2063 ApplyId
.add( "__pdr.popStructBegin(__Tok_Parent);");
2064 ApplyId
.add( Inherited
+"::apply(__pdr);");
2065 ApplyId
.add( "__pdr.popStructEnd(__Tok_Parent);");
2072 for (j
=0; j
<Nodes
.size(); ++j
)
2074 CCppCodeNode
* cpp
= dynamic_cast<CCppCodeNode
*>(Nodes
[j
]);
2075 if (cpp
== NULL
|| !cpp
->Name
.empty())
2078 Gen
.addOther(cpp
->RawCode
, "user");
2081 HasRowAccess
= false;
2082 HasTableAccess
= false;
2084 if (!Inherited
.empty())
2086 setEnv("inherit", Inherited
);
2087 setEnv("inheritclass", Inherited
);
2089 Gen
.Inherit
+= "public "+Inherited
;
2090 HasRowAccess
= true;
2091 HasTableAccess
= true;
2093 else if (HasInheritance
|| IsBackReferenced
|| IsInSet
|| ForceReference
)
2095 setEnv("inherit", pdBaseDataName
);
2097 Gen
.Inherit
+= "public "+pdBaseDataName
;
2098 HasTableAccess
= true;
2099 HasRowAccess
= true;
2102 if (Legacy
.size() > 1 && HasTableAccess
)
2104 CClassGenerator::SMethodId castId
= Gen
.startMethod(Name
+"*", staticCastFunction
, pdBaseDataName
+"* obj", "map", false, inlineStaticPublic
, true, false, "", false, false);
2105 Gen
.setDescription("Cast base object to "+Name
);
2106 castId
.add("switch (obj->getTable())");
2108 std::set
<CClassNode
*>::iterator itl
;
2109 for (itl
=Legacy
.begin(); itl
!=Legacy
.end(); ++itl
)
2111 CClassNode
* child
= (*itl
);
2112 castId
.add("case "+toString(child
->Id
)+":");
2114 castId
.add("return static_cast<"+Name
+"*>(obj);");
2116 castId
.add("return NULL;");
2118 CClassGenerator::SMethodId constCastId
= Gen
.startMethod("const "+Name
+"*", staticConstCastFunction
, "const "+pdBaseDataName
+"* obj", "map", false, inlineStaticPublic
, true, false, "", false, false);
2119 Gen
.setDescription("Cast base object to const "+Name
);
2120 constCastId
.add("switch (obj->getTable())");
2121 constCastId
.add("{");
2122 for (itl
=Legacy
.begin(); itl
!=Legacy
.end(); ++itl
)
2124 CClassNode
* child
= (*itl
);
2125 constCastId
.add("case "+toString(child
->Id
)+":");
2127 constCastId
.add("return static_cast<const "+Name
+"*>(obj);");
2128 constCastId
.add("}");
2129 constCastId
.add("return NULL;");
2131 else if (Legacy
.size() == 1 && HasTableAccess
)
2133 CClassGenerator::SMethodId castId
= Gen
.startMethod(Name
+"*", staticCastFunction
, pdBaseDataName
+"* obj", "map", false, inlineStaticPublic
, true, false, "", false, false);
2134 std::set
<CClassNode
*>::iterator itl
= Legacy
.begin();
2135 Gen
.setDescription("Cast base object to "+Name
);
2136 castId
.add("return (obj->getTable() == "+toString((*itl
)->Id
)+") ? static_cast<"+Name
+"*>(obj) : NULL;");
2138 CClassGenerator::SMethodId constCastId
= Gen
.startMethod("const "+Name
+"*", staticConstCastFunction
, "const "+pdBaseDataName
+"* obj", "map", false, inlineStaticPublic
, true, false, "", false, false);
2139 Gen
.setDescription("Cast base object to const "+Name
);
2140 constCastId
.add("return (obj->getTable() == "+toString((*itl
)->Id
)+") ? static_cast<const "+Name
+"*>(obj) : NULL;");
2147 define("hasrowaccess");
2149 define("hastableaccess");
2151 if (!Implements
.empty())
2153 setEnv("implements", Implements
);
2154 Gen
.Inherit
+= (HasRowAccess
? string(", ") : string(""))+"public "+Implements
;
2158 // generate init method
2162 setEnv("initproto", InitProto
);
2164 InitId
= Gen
.startMethod("void", initFunction
, InitProto
, "internal", false, inlineInternal
, false, false, "", HasInheritance
);
2165 if (!Inherited
.empty())
2167 InitId
.add(Inherited
+ "::" + initFunction
+ "(" + InitCallArgs
+ ");");
2168 setEnv("initcallargs", InitCallArgs
);
2171 DestroyId
= Gen
.startMethod("void", destroyFunction
, "", "internal", false, inlineInternal
, false, false, "", HasInheritance
);
2172 FetchId
= Gen
.startMethod("void", fetchFunction
, CPDataName
+" &data", "internal", false, inlineInternal
, false, false, "", HasInheritance
);
2173 RegisterId
= Gen
.startMethod("void", registerFunction
, "", "internal", false, inlineInternal
, false, false, "", HasInheritance
);
2174 RegisterAttributesId
= Gen
.startMethod("void", registerAttributesFunction
, "", "internal", false, inlineInternal
, false, false, "", HasInheritance
);
2175 UnregisterId
= Gen
.startMethod("void", unregisterFunction
, "", "internal", false, inlineInternal
, false, false, "", HasInheritance
);
2176 UnregisterAttributesId
= Gen
.startMethod("void", unregisterAttributesFunction
, "", "internal", false, inlineInternal
, false, false, "", HasInheritance
);
2178 SetUnnotifiedParentId
;
2181 SetParentId
= Gen
.startMethod("void", setParentFunction
, ParentClass
+"* __parent", "internal", false, inlineInternal
);
2182 SetUnnotifiedParentId
= Gen
.startMethod("void", setUnnotifiedParentFunction
, ParentClass
+"* __parent", "internal", false, inlineInternal
);
2185 if (HasRowAccess
&& GenerateDebugMessages
)
2187 DestroyId
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": destroy %u:%u\", "+getId()+", __BaseRow);");
2188 FetchId
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": fetch %u:%u\", "+getId()+", __BaseRow);");
2191 if (!Inherited
.empty())
2193 FetchId
.add(Inherited
+"::"+fetchFunction
+"(data);");
2198 UserInitId
= Gen
.startMethod("void", userInitFunction
, "", "userinit", false, inlineUserInitDefaultCode
, false, false, "", true);
2199 UserReleaseId
= Gen
.startMethod("void", userReleaseFunction
, "", "userinit", false, inlineUserInitDefaultCode
, false, false, "", true);
2202 NotifyInitId
= Gen
.startMethod("void", notifyInitFunction
, "", "internal", false, inlineInternal
, false, false, "", HasInheritance
);
2203 string initUCode
= getUserCode("onInit");
2204 if (!Inherited
.empty())
2205 Gen
.add(Inherited
+"::"+notifyInitFunction
+"();");
2207 Gen
.add(userInitFunction
+"();");
2208 if (!initUCode
.empty())
2213 getFileLine(line
, col
, file
);
2214 Gen
.add("// "+Name
+" init user code, defined at "+file
+":"+toString(line
));
2219 NotifyReleaseId
= Gen
.startMethod("void", notifyReleaseFunction
, "", "internal", false, inlineInternal
, false, false, "", HasInheritance
);
2220 string releaseUCode
= getUserCode("onRelease");
2221 if (!releaseUCode
.empty())
2226 getFileLine(line
, col
, file
);
2227 Gen
.add("// "+Name
+" release user code, defined at "+file
+":"+toString(line
));
2228 Gen
.add(releaseUCode
);
2232 Gen
.add(userReleaseFunction
+"();");
2233 if (!Inherited
.empty())
2234 Gen
.add(Inherited
+"::"+notifyReleaseFunction
+"();");
2235 else if (HasRowAccess
)
2236 Gen
.add(pdslibFunc("release")+"("+getId()+", __BaseRow);");
2238 if (!Inherited
.empty())
2240 DestroyId
.add(Inherited
+"::"+destroyFunction
+"();");
2241 ClearId
.add(Inherited
+"::"+clearFunction
+"();");
2245 // Generate XML description
2248 xmlnode
+= "<classdef";
2249 xmlnode
+= " name='"+Name
+"'";
2250 xmlnode
+= " id='"+toString(Id
)+"'";
2251 if (!Inherited
.empty())
2253 CClassNode
*inh
= getClassNode(Inherited
);
2254 xmlnode
+= " inherit='"+toString(inh
->Id
)+"'";
2256 CDeclarationNode
*dln
= getClassKey();
2259 xmlnode
+= " key='"+toString(dln
->Id
)+"'";
2261 if (MapClass
&& !MapClass
->HasParent
)
2263 xmlnode
+= " mapped='"+toString(MapClass
->Id
)+"'";
2268 if (!Reserve.empty())
2270 xmlnode += " allocate='"+(Reserve)+"'";
2274 xmlnode += " allocate='10000'";
2278 xmlnode
+= " columns='"+toString(Columns
)+"'";
2280 getDbNode()->xmlDescription
.push_back(xmlnode
);
2282 indexUsedInInit
= false;
2283 indexUsedInDestroy
= false;
2284 indexUsedInFetch
= false;
2285 tableAndRowIndicesUsedInFetch
= false;
2286 indexUsedInRegister
= false;
2287 indexUsedInUnregister
= false;
2289 // generate code for init of new index
2292 RegisterId
.add("__BaseRow = _IndexAllocator.allocate();");
2293 if (GenerateDebugMessages
)
2295 if (MapClass
!= NULL
)
2297 CDeclarationNode
* key
= MapClass
->getKey();
2298 RegisterId
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": register %u:%u, key="+key
->displayPrintfPrefix()+"\", "+getId()+", __BaseRow, "+key
->displayCppCode()+");");
2302 RegisterId
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": register %u:%u\", "+getId()+", __BaseRow);");
2309 oeid
= ", "+getClassKey()->cppName();
2312 RegisterId
.add(pdslibFunc("allocateRow")+"("+getId()+", __BaseRow, "+(PDSMapped
? MapClass
->getKey()->toUint64() : "0")+oeid
+");");
2313 RegisterId
.add(registerAttributesFunction
+ "();");
2315 RegisterAttributesId
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": registerAttributes %u:%u\", "+getId()+", __BaseRow);");
2317 // send key to the pds (if key exists)
2318 if (!ClassKey
.empty())
2320 CDeclarationNode
*keyNode
= getKey();
2321 CTypeNode
*keyTypeNode
= getTypeNode(keyNode
->Type
);
2323 RegisterAttributesId
.add(pdslibFunc("set")+"("+getId()+", __BaseRow, ("+TColumnIndexName
+")("+toString(keyNode
->Column
)+"), "+keyTypeNode
->castToPDS(getKey()->cppName())+");");
2326 if (!Inherited
.empty())
2328 RegisterAttributesId
.add(Inherited
+ "::" + registerAttributesFunction
+ "();");
2331 UnregisterAttributesId
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": unregisterAttributes %u:%u\", "+getId()+", __BaseRow);");
2333 if (!Inherited
.empty())
2335 UnregisterAttributesId
.add(Inherited
+ "::" + unregisterAttributesFunction
+ "();");
2340 UnregisterAttributesId
.add(setParentFunction
+"(NULL);");
2343 if (GenerateDebugMessages
)
2345 if (MapClass
!= NULL
)
2347 CDeclarationNode
* key
= MapClass
->getKey();
2348 UnregisterId
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": unregister %u:%u, key="+key
->displayPrintfPrefix()+"\", "+getId()+", __BaseRow, "+key
->displayCppCode()+");");
2351 UnregisterId
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": unregister %u:%u\", "+getId()+", __BaseRow);");
2354 UnregisterId
.add(unregisterAttributesFunction
+ "();");
2359 oeid
= ", "+getClassKey()->cppName();
2362 UnregisterId
.add(pdslibFunc("deallocateRow")+"("+getId()+", __BaseRow"+oeid
+");");
2363 UnregisterId
.add("_IndexAllocator.deallocate(__BaseRow);");
2364 //UnregisterId.add(destroyFunction+"();");
2368 // add attributes and methods
2369 // - attributes are in private part
2370 // - read accessor are public
2371 // - write accessor are public or delegated in public accessor objects
2373 for (j
=0; j
<Nodes
.size(); ++j
)
2375 CDeclarationNode
*dln
= dynamic_cast<CDeclarationNode
*>(Nodes
[j
]);
2379 dln
->Env
= Env
->nextArrayNode("dcl");
2381 dln
->generateContent();
2387 for (j
=0; j
<Attributes
.size(); ++j
)
2389 CDeclarationNode
*dln
= Attributes
[j
];
2390 getDbNode()->xmlDescription
.push_back("<attribute "+dln
->XmlNode
+"/>");
2393 for (k
=0; k
<dln
->ColumnList
.size(); ++k
)
2395 CColumn
&column
= dln
->ColumnList
[k
];
2396 //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)+"'/>");
2400 //getDbNode()->xmlDescription.push_back("</attribute>");
2403 getDbNode()->xmlDescription
.push_back("</classdef>");
2407 Gen
.startConstructor("", "construct");
2408 Gen
.add("__BaseTable = "+toString(Id
)+";");
2410 Gen
.startDestructor("construct", true, DerivatedFlag
|| HasInheritance
);
2413 // when inited/fetched a mapped class, map id to object
2416 InitId
.add("_Map["+getKey()->getFunc()+"()] = this;");
2417 FetchId
.add("_Map["+getKey()->getFunc()+"()] = this;");
2418 DestroyId
.add("_Map.erase("+getKey()->getFunc()+"());");
2422 // generate IPDBaseData API
2425 if (MappedFlag
|| DerivatedFlag
|| HasInheritance
|| ForceReference
)
2429 Gen
.startMethod("void", staticSetUserFactoryFunction
, TPDFactoryName
+" userFactory", "map", false, inlineStaticPublic
, true);
2430 Gen
.setDescription("Set user factory for this class (as class is indicated as derived, a home made constructor must be provided)");
2431 Gen
.add(staticInitFactoryFunction
+"(userFactory);");
2434 Gen
.startMethod("void", staticInitFactoryFunction
, TPDFactoryName
+" userFactory", "factories", false, inlineStaticInternal
, true);
2435 Gen
.add("if (!_FactoryInitialised)");
2437 Gen
.add(pdslibFunc("registerClass")+"(" + toString(Id
) + ", userFactory, "+staticFetchFunction
+", "+((MappedFlag
&& !HasParent
) ? staticNotifyLoadFailure
: string("NULL"))+");");
2438 Gen
.add("_FactoryInitialised = true;");
2441 Gen
.addAttribute("bool", "_FactoryInitialised", "factories", true);
2443 if (MappedFlag
|| HasInheritance
|| ForceReference
)
2446 // create: create an object, then init attributes and register
2449 Gen
.startMethod(Name
+"*", staticCreateFunction
, InitProto
, "map", false, inlineStaticPublic
, true);
2450 Gen
.setDescription("Create an object of the "+Name
+" class, and declare it to the PDS.");
2451 if (GenerateDebugMessages
)
2453 Gen
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": create\");");
2457 Gen
.add(Name
+ "\t*"+objectVariable
+" = static_cast<" + Name
+ "*>("+pdslibFunc("create")+"("+toString(Id
)+"));");
2461 Gen
.add(Name
+ "\t*"+objectVariable
+" = static_cast<" + Name
+ "*>("+staticFactoryFunction
+"());");
2464 string str
= objectVariable
+"->" + initFunction
+ "(";
2466 for (i
=0; i
<Init
.size(); ++i
)
2467 str
+= (i
!= 0 ? ", " : "") + Init
[i
]->Name
;
2470 Gen
.add(objectVariable
+"->" + registerFunction
+ "();");
2474 Gen.add("_Map["+MapClass->ClassKey+"] = "+objectVariable+";");
2477 Gen
.add(objectVariable
+"->"+notifyInitFunction
+"();");
2478 Gen
.add("return "+objectVariable
+";");
2483 CDeclarationNode
*dln
= (MapClass
!= NULL
? MapClass
->getKey() : NULL
);
2484 CTypeNode
*keyType
= getTypeNode(dln
->Type
);
2486 // only authorize remove/load/unload for mapped objects that are roots
2489 Gen
.startMethod("void", staticRemoveFunction
, "const "+keyType
->getName()+"& "+dln
->Name
, "map", false, inlineStaticPublic
, true);
2490 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.");
2491 if (GenerateDebugMessages
)
2493 Gen
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": remove "+dln
->displayPrintfPrefix()+"\", "+dln
->displayCppCode(dln
->Name
)+");");
2495 Gen
.add("std::map<" + keyType
->getName() + "," + Name
+ "*>::iterator\tit = _Map.find("+dln
->Name
+");");
2496 Gen
.add("if (it != _Map.end())");
2498 Gen
.add(Name
+ "*\t__o = (*it).second;");
2499 Gen
.add("__o->"+notifyReleaseFunction
+"();");
2500 Gen
.add("__o->"+unregisterFunction
+"();");
2501 Gen
.add("__o->"+destroyFunction
+"();");
2502 Gen
.add("delete __o;");
2503 //Gen.add("_Map.erase(it);");
2506 Gen
.startMethod("void", staticLoadFunction
, "const "+keyType
->getName()+"& "+dln
->Name
, "map", false, inlineStaticPublic
, true);
2507 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.");
2508 if (GenerateDebugMessages
)
2510 Gen
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": load "+dln
->displayPrintfPrefix()+"\", "+dln
->displayCppCode(dln
->Name
)+");");
2512 Gen
.add(pdslibFunc("load")+"("+toString(Id
)+", "+dln
->toUint64(dln
->Name
)+");");
2514 Gen
.startMethod("void", staticSetLoadCbFunction
, "void (*callback)(const "+keyType
->getName()+"& key, "+Name
+"* object)", "map", false, inlineStaticPublic
, true);
2515 Gen
.setDescription("Setup load callback so client is warned that load succeded or failed.");
2516 Gen
.add(staticLoadCbAttribute
+" = callback;");
2518 Gen
.startMethod("void", staticNotifyLoadFailure
, "uint64 key", "factories", false, inlineStaticInternal
, true);
2519 Gen
.add("if ("+staticLoadCbAttribute
+" != NULL)");
2521 Gen
.add(staticLoadCbAttribute
+"("+keyType
->castFromUser("key")+", NULL);");
2524 Gen
.addAttribute("void", staticLoadCbAttribute
, "factories", true, "NULL", true, "const "+keyType
->getName()+"& key, "+Name
+"* object");
2528 Gen
.startMethod("void", staticUnloadFunction
, "const " + keyType
->getName() + " &" + dln
->Name
, "map", false, inlineStaticPublic
, true);
2529 Gen
.setDescription("Unload an object from the client memory. Object still exists in database and can be retrieved again using load.");
2530 if (GenerateDebugMessages
)
2532 Gen
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": unload "+dln
->displayPrintfPrefix()+"\", "+dln
->displayCppCode(dln
->Name
)+");");
2534 Gen
.add("std::map<" + keyType
->getName() + "," + Name
+ "*>::iterator\tit = _Map.find("+dln
->Name
+");");
2535 Gen
.add("if (it != _Map.end())");
2537 Gen
.add(Name
+ "*\t__o = (*it).second;");
2538 Gen
.add("__o->"+notifyReleaseFunction
+"();");
2539 Gen
.add("__o->"+destroyFunction
+"();");
2540 Gen
.add("delete __o;");
2541 //Gen.add("_Map.erase(it);");
2545 std::string mapType
= "std::map<"+keyType
->getName()+", "+Name
+"*>";
2547 Gen
.startMethod(Name
+"*", staticGetFunction
, "const " + keyType
->getName() + " &" + dln
->Name
, "map", false, inlineStaticPublic
, true);
2548 Gen
.setDescription("Get an object in client. Object must have been previously loaded from database with a load.");
2549 if (GenerateDebugMessages
)
2551 Gen
.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name
+": get "+dln
->displayPrintfPrefix()+"\", "+dln
->displayCppCode(dln
->Name
)+");");
2553 Gen
.add(mapType
+"::iterator\t__it = _Map.find("+dln
->Name
+");");
2554 if (GenerateDebugMessages
)
2556 Gen
.add("if (__it == _Map.end())");
2557 Gen
.add("nlwarning(\""+Name
+": unable to get %\"NL_I64\"u, not found in map.\", "+dln
->toUint64(dln
->Name
)+");");
2559 Gen
.add("return (__it != _Map.end()) ? (*__it).second : NULL;");
2561 Gen
.startMethod(mapType
+"::iterator", staticBeginFunction
, "", "map", false, inlineStaticPublic
, true);
2562 Gen
.setDescription("Return the begin iterator of the global map of "+Name
);
2563 Gen
.add("return _Map.begin();");
2565 Gen
.startMethod(mapType
+"::iterator", staticEndFunction
, "", "map", false, inlineStaticPublic
, true);
2566 Gen
.setDescription("Return the end iterator of the global map of "+Name
);
2567 Gen
.add("return _Map.end();");
2573 // generate internal management functions
2576 if (HasRowAccess
|| MappedFlag
)
2580 CDeclarationNode
*dln
= (MappedFlag
? getKey() : NULL
);
2581 CTypeNode
*keyType
= getTypeNode(dln
->Type
);
2582 Gen
.addAttribute("std::map<" + keyType
->getName() + "," + Name
+ "*>", "_Map", "inherit map", true);
2585 Gen
.addAttribute(indexAllocatorName
, "_IndexAllocator", "factories", true);
2587 Gen
.startMethod("void", staticInitFunction
, "", "internal", false, inlineInternal
, true, false, "", false);
2588 Gen
.add(pdslibFunc("setIndexAllocator")+"("+toString(Id
)+", _IndexAllocator);");
2589 if (MappedFlag
|| DerivatedFlag
|| HasInheritance
|| ForceReference
)
2593 // check factory has been set
2594 Gen
.add("nlassertex(_FactoryInitialised, (\"User Factory for class "+Name
+" not set!\"));");
2595 Gen
.add("// factory must have been set by user before database init called!");
2596 Gen
.add("// You must provide a factory for the class "+Name
+" as it is marked as derived");
2597 Gen
.add("// Call "+getDbNode()->Name
+"::"+Name
+"::"+staticSetUserFactoryFunction
+"() with a factory before any call to "+getDbNode()->Name
+"::init()!");
2601 Gen
.add(staticInitFactoryFunction
+"("+staticFactoryFunction
+");");
2605 getDbNode()->initDb
.add(Name
+"::"+staticInitFunction
+"();");
2609 if (!DerivatedFlag
) // forbid factory function for derivated classes
2611 Gen
.startMethod(pdBaseDataName
+"*", staticFactoryFunction
, "", "factories", false, inlineStaticInternal
, true);
2612 Gen
.add("return new " + Name
+ "();");
2615 if (Inherited
.empty())
2617 Gen
.startMethod("void", staticFetchFunction
, pdBaseDataName
+" *object, "+CPDataName
+" &data", "factories", false, inlineStaticInternal
, true);
2618 Gen
.add(Name
+ "\t*"+objectVariable
+" = static_cast<" + Name
+ "*>(object);");
2619 Gen
.add(objectVariable
+"->"+fetchFunction
+"(data);");
2622 //Gen.add("_Map["+objectVariable+"->"+getKey()->getFunc()+"()] = "+objectVariable+";");
2625 Gen
.add("if ("+staticLoadCbAttribute
+" != NULL)");
2627 Gen
.add(staticLoadCbAttribute
+"("+objectVariable
+"->"+getKey()->getFunc()+"(), "+objectVariable
+");");
2631 Gen
.add(objectVariable
+"->"+notifyInitFunction
+"();");
2639 ApplyId
.add( "else");
2641 ApplyId
.add( "nlwarning(\"Skipping unrecognised token: %s\", __pdr.peekNextTokenName().c_str());");
2642 ApplyId
.add( "__pdr.skipData();");
2646 if (MappedFlag
&& !HasParent
)
2648 ApplyId
.add(notifyInitFunction
+"();");
2652 //EGSImplId.add("\n#include \"game_share/persistent_data_template.h\"");
2653 //EGSImplId.add("#undef PERSISTENT_CLASS");
2654 //EGSImplId.add("#undef PERSISTENT_DATA");
2658 set
<string
>::iterator itf
;
2659 for (itf
=Friends
.begin(); itf
!=Friends
.end(); ++itf
)
2661 Gen
.addOther("friend class "+(*itf
)+";\n", "friends");
2662 for (itf
=ForwardFriends
.begin(); itf
!=ForwardFriends
.end(); ++itf
)
2664 Gen
.addOther("friend class "+(*itf
)+";\n", "friends");
2665 Gen
.addOther("friend class "+CPDSLibName
+";\n", "friends");
2666 CDbNode
* dbNode
= getDbNode();
2667 Gen
.addOther("friend void "+dbNode
->Name
+"::init(uint32);\n", "friends");
2669 Gen
.flush(hOutput(), cppOutput(), inlineOutput());
2671 DbSummary
<< "\n\n";
2676 void CClassNode::generateContentInCall(CCallContext
*context
)
2679 for (j
=0; j
<Nodes
.size(); ++j
)
2681 CDeclarationNode
*dln
= dynamic_cast<CDeclarationNode
*>(Nodes
[j
]);
2685 dln
->generateContent(context
);
2698 bool CDeclarationNode::prolog()
2703 bool CDeclarationNode::epilog()
2710 void CDeclarationNode::generateContent(CCallContext
*context
)
2712 ClassNode
= static_cast<CClassNode
*>(Parent
);
2714 nlassert(Env
!= NULL
);
2716 setEnv("name", Name
);
2718 XmlNode
= "name='"+Name
+"' id='"+toString(Id
)+"' columnid='"+toString(Column
)+"' columns='"+toString(Columns
)+"'";
2720 if (context
== NULL
)
2722 CCppOutput
& DbSummary
= getDbNode()->DbSummary
;
2723 DbSummary
<< "Attribute " << Name
<< ":\n";
2726 switch (DeclarationType
)
2729 generateTypeContent(context
);
2733 generateClassContent(context
);
2737 generateBackRefContent();
2741 generateForwardRefContent();
2745 generateArrayTypeContent(context
);
2749 generateArrayClassContent(context
);
2753 generateArrayRefContent(context
);
2757 generateSetContent(context
);
2761 error("Can't decide declaration type");
2765 if (context
== NULL
)
2767 ClassNode
->Gen
.separator("methods");
2774 std::string
CDeclarationNode::getAccessorName(CCallContext
*context
, const std::string
& accessortype
, const std::string
& sep
)
2776 return context
->getRootCaller()->Name
+ sep
+accessortype
+ context
->getCallString();
2780 void CDeclarationNode::generateTypeContent(CCallContext
*context
)
2782 CClassGenerator
& Gen
= ClassNode
->Gen
;
2783 CCppOutput
& DbSummary
= getDbNode()->DbSummary
;
2785 CClassGenerator::SMethodId
&InitId
= ClassNode
->InitId
;
2786 CClassGenerator::SMethodId
&ClearId
= ClassNode
->ClearId
;
2787 CClassGenerator::SMethodId
&DestroyId
= ClassNode
->DestroyId
;
2788 CClassGenerator::SMethodId
&FetchId
= ClassNode
->FetchId
;
2789 CClassGenerator::SMethodId
&RegisterId
= ClassNode
->RegisterId
;
2790 CClassGenerator::SMethodId
&RegisterAttributesId
= ClassNode
->RegisterAttributesId
;
2791 CClassGenerator::SMethodId
&UnregisterId
= ClassNode
->UnregisterId
;
2792 CClassGenerator::SMethodId
&UnregisterAttributesId
= ClassNode
->UnregisterAttributesId
;
2793 CClassGenerator::SMethodId
&SetParentId
= ClassNode
->SetParentId
;
2794 CClassGenerator::SMethodId
&SetUnnotifiedParentId
= ClassNode
->SetUnnotifiedParentId
;
2796 string UCodeContext
;
2797 if (context
!= NULL
)
2798 UCodeContext
= context
->getUserCodeContext();
2800 string onGetUser
= getUserCode("onGet", UCodeContext
);
2801 string onSetUser
= getUserCode("onSet", UCodeContext
);
2802 string onChangeUser
= getUserCode("onChange", UCodeContext
);
2804 CTypeNode
*tnd
= getTypeNode(Type
);
2805 XmlNode
+= " type='type' typeid='"+toString(tnd
->Id
)+"'";
2807 setEnv("decltype", "type");
2808 setEnv("type", tnd
->getName());
2809 define(IsKey
, "iskey");
2810 setEnv("defaultvalue", tnd
->getDefaultValue());
2811 setEnv("checkcode", tnd
->checkCode(Name
));
2813 CCallContext
ctx(this);
2814 if (context
!= NULL
)
2815 ctx
= context
->getSubContext(this);
2816 CClassGenerator
&gen
= ctx
.getRootCaller()->Gen
;
2821 CClassGenerator::SMethodId
& StoreId
= ClassNode
->StoreId
;
2822 CClassGenerator::SMethodId
& ApplyId
= ClassNode
->ApplyId
;
2825 ApplyId
.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
2827 tnd
->generateApplyCode(ApplyId
, tokenName(), cppName());
2830 tnd
->generateStoreCode(StoreId
, tokenName(), cppName());
2834 CTemplatizerEnv
* env
= ctx
.getRootDeclaration()->Env
->nextArrayNode("accessors");
2836 env
->set("name", Name
);
2837 env
->set("type", tnd
->getName());
2838 env
->set("defaultvalue", tnd
->getDefaultValue());
2839 env
->set("checkcode", tnd
->checkCode(Name
));
2840 env
->define(ctx
.getRootCaller()->HasRowAccess
, "rowaccess");
2841 env
->define(IsKey
, "iskey");
2842 env
->set("rootcallerid", ctx
.getRootCaller()->getId());
2843 env
->set("callstr", ctx
.getCallString());
2844 env
->set("callargs", ctx
.getCallArgList());
2845 env
->set("callpath", ctx
.getCallPath());
2846 env
->set("column", ctx
.getColumn());
2847 env
->set("valuevar", valueVariable
);
2848 env
->set("castcpp", tnd
->castToCpp(valueVariable
));
2849 env
->set("castpds", tnd
->castToPDS(valueVariable
));
2851 vector
<string
> checks
= ctx
.getCheckCode();
2852 for (uint i
=0; i
<checks
.size(); ++i
)
2853 env
->nextArrayNode("checks")->set("check", checks
[i
]);
2854 env
->nextArrayNode("checks")->set("check", tnd
->checkCode(valueVariable
));
2856 if (!onGetUser
.empty()) env
->set("onget", onGetUser
);
2857 if (!onSetUser
.empty()) env
->set("onset", onSetUser
);
2858 if (!onChangeUser
.empty()) env
->set("onchange", onChangeUser
);
2861 // generate read accessor
2863 if (ctx
.getRootCaller()->HasRowAccess
)
2865 string arglist
= ctx
.getCallArgList();
2867 gen
.startMethod(tnd
->getName(), getFunctionPrefix
+ctx
.getCallString(), arglist
, "methods", true, inlineAccessors
);
2869 DbSummary
<< "\t" << getFunctionPrefix
+ctx
.getCallString() << "\n";
2872 vector
<string
> checks
= ctx
.getCheckCode();
2873 for (i
=0; i
<checks
.size(); ++i
)
2878 if (!onGetUser
.empty())
2884 gen
.add("return "+ctx
.getCallPath()+";");
2888 // generate write accessor
2890 if (ctx
.getRootCaller()->HasRowAccess
&& !IsKey
)
2892 string arglist
= ctx
.getCallArgList();
2894 if (!arglist
.empty())
2896 arglist
+= tnd
->getName()+" "+valueVariable
;
2897 gen
.startMethod("void", setFunctionPrefix
+ctx
.getCallString(), appendArg(arglist
, "bool forceWrite=false"), "methods", false, inlineAccessors
);
2899 DbSummary
<< "\t" << setFunctionPrefix
<< ctx
.getCallString() << "\n";
2903 gen
.add("H_AUTO("+getAccessorName(&ctx
, setFunctionPrefix
, "_")+")");
2911 verbStr
= "nlinfo(\"" + ctx
.getRootCaller()->Name
+ "(%d:%d)::" +setFunctionPrefix
+ ctx
.getCallString() + "(";
2913 callStr
= ctx
.getDebugCallStringFmt();
2914 if (!callStr
.empty())
2917 callStr
+= valueVariable
+"="+tnd
->getPrintfFmt();
2920 verbStr
+= ")\", __BaseTable, __BaseRow, ";
2922 callStr
= ctx
.getDebugCallStringVal();
2923 if (!callStr
.empty())
2926 callStr
+= tnd
->getPrintfVal(valueVariable
);
2935 vector
<string
> checks
= ctx
.getCheckCode();
2936 for (i
=0; i
<checks
.size(); ++i
)
2940 gen
.add(tnd
->checkCode(valueVariable
));
2943 if (!onChangeUser
.empty())
2945 gen
.add("if ("+ctx
.getCallPath()+" != "+tnd
->castToCpp(valueVariable
)+")");
2947 gen
.add(onChangeUser
);
2950 if (!onSetUser
.empty())
2956 if (WriteTriggerFlag
)
2958 gen
.add("if (forceWrite && ("+ctx
.getCallPath()+" != "+tnd
->castToCpp(valueVariable
)+"))");
2962 gen
.add("if (("+ctx
.getCallPath()+" != "+tnd
->castToCpp(valueVariable
)+") || forceWrite)");
2965 bool useEntityId
= ctx
.hasRootEntityIdKey();
2968 gen
.add(pdslibFunc("set")+"("+ctx
.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName
+")("+ctx
.getColumn()+"), "+tnd
->castToPDS(valueVariable
)+", "+ctx
.getRootCaller()->getKey()->cppName()+");");
2972 gen
.add(pdslibFunc("set")+"("+ctx
.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName
+")("+ctx
.getColumn()+"), "+tnd
->castToPDS(valueVariable
)+");");
2975 gen
.add(ctx
.getCallPath()+" = "+tnd
->castToCpp(valueVariable
)+";");
2979 // generate attribute
2981 Gen
.addAttribute(tnd
->getName(), cppName(), "attributes");
2984 string defaultValue
;
2985 if (!DefaultValue
.empty())
2986 defaultValue
= DefaultValue
;
2988 defaultValue
= tnd
->getDefaultValue();
2995 InitId
.add(cppName()+" = "+defaultValue
+";");
2999 InitId
.add(tnd
->checkCode(Name
));
3000 InitId
.add(cppName()+" = "+Name
+";");
3004 // generate create code
3009 // generate fetch code
3012 FetchId
.add("data.serialEnum("+cppName()+");");
3013 else if (tnd
->CppType
!= tnd
->StorageType
)
3016 FetchId
.add(tnd
->StorageType
+"\t_v;");
3017 FetchId
.add("data.serial(_v);");
3018 FetchId
.add(cppName()+" = "+tnd
->castToCpp("_v")+";");
3023 FetchId
.add("data.serial("+cppName()+");");
3027 // generate clear code
3029 if (ctx
.getRootCaller()->HasRowAccess
&& !IsKey
)
3031 ctx
.getRootCaller()->ClearId
.add(ctx
.getCallPath()+" = "+defaultValue
+";");
3032 ctx
.getRootCaller()->ClearId
.add(pdslibFunc("set")+"("+ctx
.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName
+")("+ctx
.getColumn()+"), "+tnd
->castToPDS(defaultValue
)+");");
3043 void CDeclarationNode::generateClassContent(CCallContext
*context
)
3045 setEnv("decltype", "class");
3047 CClassGenerator
&Gen
= ClassNode
->Gen
;
3048 CCppOutput
& DbSummary
= getDbNode()->DbSummary
;
3050 CClassGenerator::SMethodId
&InitId
= ClassNode
->InitId
;
3051 CClassGenerator::SMethodId
&ClearId
= ClassNode
->ClearId
;
3052 CClassGenerator::SMethodId
&DestroyId
= ClassNode
->DestroyId
;
3053 CClassGenerator::SMethodId
&FetchId
= ClassNode
->FetchId
;
3054 CClassGenerator::SMethodId
&RegisterId
= ClassNode
->RegisterId
;
3055 CClassGenerator::SMethodId
&RegisterAttributesId
= ClassNode
->RegisterAttributesId
;
3056 CClassGenerator::SMethodId
&UnregisterId
= ClassNode
->UnregisterId
;
3057 CClassGenerator::SMethodId
&UnregisterAttributesId
= ClassNode
->UnregisterAttributesId
;
3058 CClassGenerator::SMethodId
&SetParentId
= ClassNode
->SetParentId
;
3059 CClassGenerator::SMethodId
&SetUnnotifiedParentId
= ClassNode
->SetUnnotifiedParentId
;
3061 CClassNode
*cnd
= getClassNode(Type
);
3062 XmlNode
+= " type='class' classid='"+toString(cnd
->Id
)+"'";
3064 setEnv("type", Type
);
3069 CClassGenerator::SMethodId
& StoreId
= ClassNode
->StoreId
;
3070 CClassGenerator::SMethodId
& ApplyId
= ClassNode
->ApplyId
;
3072 StoreId
.add("__pdr.pushStructBegin("+tokenName()+");");
3073 StoreId
.add(cppName()+".store(__pdr);");
3074 StoreId
.add("__pdr.pushStructEnd("+tokenName()+");");
3076 ApplyId
.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
3078 ApplyId
.add("__pdr.popStructBegin("+tokenName()+");");
3079 ApplyId
.add(cppName()+".apply(__pdr);");
3080 ApplyId
.add("__pdr.popStructEnd("+tokenName()+");");
3087 // export class accessors into root caller
3090 if (context
!= NULL
)
3092 ctx
.Context
.push_back(this);
3093 cnd
->generateContentInCall(&ctx
);
3096 // generate attribute
3098 Gen
.addAttribute(Type
, cppName(), "attributes");
3103 InitId
.add(cppName()+"."+initFunction
+"();");
3106 // generate create code
3110 // generate fetch code
3112 FetchId
.add(cppName()+"."+fetchFunction
+"(data);");
3115 // generate clear code
3117 //ClearId.add(cppName()+"."+clearFunction+"();");
3125 void CDeclarationNode::generateBackRefContent()
3127 setEnv("decltype", "backref");
3128 define(HiddenFlag
, "hidden");
3130 CClassGenerator
&Gen
= ClassNode
->Gen
;
3131 CCppOutput
& DbSummary
= getDbNode()->DbSummary
;
3133 CClassGenerator::SMethodId
&InitId
= ClassNode
->InitId
;
3134 CClassGenerator::SMethodId
&ClearId
= ClassNode
->ClearId
;
3135 CClassGenerator::SMethodId
&DestroyId
= ClassNode
->DestroyId
;
3136 CClassGenerator::SMethodId
&FetchId
= ClassNode
->FetchId
;
3137 CClassGenerator::SMethodId
&RegisterId
= ClassNode
->RegisterId
;
3138 CClassGenerator::SMethodId
&RegisterAttributesId
= ClassNode
->RegisterAttributesId
;
3139 CClassGenerator::SMethodId
&UnregisterId
= ClassNode
->UnregisterId
;
3140 CClassGenerator::SMethodId
&UnregisterAttributesId
= ClassNode
->UnregisterAttributesId
;
3141 CClassGenerator::SMethodId
&SetParentId
= ClassNode
->SetParentId
;
3142 CClassGenerator::SMethodId
&SetUnnotifiedParentId
= ClassNode
->SetUnnotifiedParentId
;
3144 CClassNode
*cnd
= getClassNode(ParentClass
);
3145 CDeclarationNode
*dnd
= cnd
->getDeclarationNode(ParentField
);
3146 CDeclarationNode
*knd
= (ClassNode
->ClassKey
.empty() ? NULL
: ClassNode
->getKey());
3147 XmlNode
+= " type='backref' classid='"+toString(cnd
->Id
)+"' backreferentid='"+toString(dnd
->Id
)+"'";
3149 XmlNode
+= " key='"+toString(knd
->Id
)+"'";
3151 setEnv("type", ParentClass
);
3154 // generate read accessor
3156 Gen
.startMethod(ParentClass
+"*", getFunc(), "", "methods", false, inlineAccessors
);
3157 Gen
.add("return "+cppName()+";");
3159 Gen
.startMethod("const "+ParentClass
+"*", getFunc(), "", "methods", true, inlineAccessors
);
3160 Gen
.add("return "+cppName()+";");
3162 DbSummary
<< "\t" << getFunc() << "\n";
3165 // generate write accessor
3169 // generate attribute
3171 Gen
.addAttribute(ParentClass
+"*", cppName(), "attributes");
3176 InitId
.add(cppName()+" = NULL;");
3179 // generate create code
3183 // generate fetch code
3185 FetchId
.add(cppName()+" = NULL;");
3188 // generate set parent code
3191 bool useId
= ClassNode
->useEntityId();
3192 bool parentUseId
= cnd
->useEntityId();
3195 SetParentId
.add("NLMISC::CEntityId\tprevId;");
3199 //SetParentId.add(pdslibFunc("set")+"("+ClassNode->getId()+", getRow(), ("+TColumnIndexName+")("+toString(Column)+"), (__parent != NULL ? "+objectIndexName+"("+(cnd->HasInheritance ? toString("__parent->getTable()") : toString(cnd->Id))+", __parent->getRow()) : "+nullIndexName+"));");
3201 SetParentId
.add("if ("+cppName()+" != NULL)");
3202 SetParentId
.add("{");
3205 SetParentId
.add("prevId = "+cppName()+"->"+getFunctionPrefix
+cnd
->getKey()->Name
+"();");
3207 if (ClassNode
->getClassKey() == NULL
)
3209 SetParentId
.add(cppName()+"->"+dnd
->unlinkFunc()+"();");
3213 SetParentId
.add(cppName()+"->"+dnd
->unlinkFunc()+"("+ClassNode
->getKey()->cppName()+");");
3215 SetParentId
.add("}");
3221 SetParentId
.add("if ("+cppName()+" != NULL)");
3222 SetParentId
.add("{");
3223 SetParentId
.add("prevId = "+cppName()+"->"+cnd
->getKey()->cppName()+";");
3224 SetParentId
.add("}");
3232 oeid
= ", "+ClassNode
->getKey()->cppName();
3235 peid
= ", ("+cppName()+" != NULL ? "+cppName()+"->"+getFunctionPrefix
+cnd
->getKey()->Name
+"() : NLMISC::CEntityId::Unknown), prevId";
3237 SetParentId
.add(cppName()+" = __parent;");
3238 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
+");");
3240 SetUnnotifiedParentId
.add(cppName()+" = __parent;");
3249 void CDeclarationNode::generateClassPtrApplyCode(const std::string
& value
)
3251 CClassGenerator::SMethodId
& ApplyId
= ClassNode
->ApplyId
;
3253 ApplyId
.add(value
+" = NULL;");
3254 ApplyId
.add("if (__pdr.peekNextToken() == __Tok_ClassName)");
3256 ApplyId
.add( "std::string\t__className;");
3257 ApplyId
.add( "__pdr.pop(__Tok_ClassName, __className);");
3258 ApplyId
.add( value
+" = "+Type
+"::cast("+pdslibFunc("create")+"(__className));");
3259 ApplyId
.add( "if ("+value
+" != NULL)");
3261 ApplyId
.add( "__pdr.popStructBegin("+tokenName()+");");
3262 ApplyId
.add( value
+"->apply(__pdr);");
3263 ApplyId
.add( value
+"->"+setUnnotifiedParentFunction
+"(this);");
3264 ApplyId
.add( "__pdr.popStructEnd("+tokenName()+");");
3266 ApplyId
.add( "else");
3268 ApplyId
.add( "__pdr.skipStruct();");
3273 void CDeclarationNode::generateClassPtrStoreCode(const std::string
& value
)
3275 CClassGenerator::SMethodId
& StoreId
= ClassNode
->StoreId
;
3277 StoreId
.add("if ("+value
+" != NULL)");
3279 StoreId
.add( "std::string\t__className = "+pdslibFunc("getClassName")+"("+value
+");");
3280 StoreId
.add( "__pdr.push(__Tok_ClassName, __className);");
3281 StoreId
.add( "__pdr.pushStructBegin("+tokenName()+");");
3282 StoreId
.add( value
+"->store(__pdr);");
3283 StoreId
.add( "__pdr.pushStructEnd("+tokenName()+");");
3289 void CDeclarationNode::generateForwardRefContent()
3291 setEnv("decltype", "forwardref");
3293 CClassGenerator
&Gen
= ClassNode
->Gen
;
3294 CCppOutput
& DbSummary
= getDbNode()->DbSummary
;
3296 CClassGenerator::SMethodId
&InitId
= ClassNode
->InitId
;
3297 CClassGenerator::SMethodId
&ClearId
= ClassNode
->ClearId
;
3298 CClassGenerator::SMethodId
&DestroyId
= ClassNode
->DestroyId
;
3299 CClassGenerator::SMethodId
&FetchId
= ClassNode
->FetchId
;
3300 CClassGenerator::SMethodId
&RegisterId
= ClassNode
->RegisterId
;
3301 CClassGenerator::SMethodId
&RegisterAttributesId
= ClassNode
->RegisterAttributesId
;
3302 CClassGenerator::SMethodId
&UnregisterId
= ClassNode
->UnregisterId
;
3303 CClassGenerator::SMethodId
&UnregisterAttributesId
= ClassNode
->UnregisterAttributesId
;
3304 CClassGenerator::SMethodId
&SetParentId
= ClassNode
->SetParentId
;
3305 CClassGenerator::SMethodId
&NotifyInitId
= ClassNode
->NotifyInitId
;
3306 CClassGenerator::SMethodId
&NotifyReleaseId
= ClassNode
->NotifyReleaseId
;
3308 CClassNode
*cnd
= getClassNode(Type
);
3309 CDeclarationNode
*dnd
= cnd
->getDeclarationNode(ForwardRefAttribute
);
3310 CDeclarationNode
*knd
= (cnd
->ClassKey
.empty() ? NULL
: cnd
->getKey());
3311 XmlNode
+= " type='forwardref' classid='"+toString(cnd
->Id
)+"' forwardreferedid='"+toString(dnd
->Id
)+"'";
3313 XmlNode
+= " key='"+toString(knd
->Id
)+"'";
3315 setEnv("type", Type
);
3320 CClassGenerator::SMethodId
& StoreId
= ClassNode
->StoreId
;
3321 CClassGenerator::SMethodId
& ApplyId
= ClassNode
->ApplyId
;
3323 StoreId
.add("// store "+Name
);
3324 StoreId
.add("__pdr.pushStructBegin("+tokenName()+");");
3325 generateClassPtrStoreCode(cppName());
3326 StoreId
.add("__pdr.pushStructEnd("+tokenName()+");");
3328 ApplyId
.add("// apply "+Name
);
3329 ApplyId
.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
3331 ApplyId
.add( "__pdr.popStructBegin("+tokenName()+");");
3332 generateClassPtrApplyCode(cppName());
3333 ApplyId
.add( "__pdr.popStructEnd("+tokenName()+");");
3340 // generate read accessor
3342 Gen
.startMethod(Type
+"*", getFunc(), "", "methods", false, inlineAccessors
);
3343 Gen
.add("return "+cppName()+";");
3345 Gen
.startMethod("const "+Type
+"*", getFunc(), "", "methods", true, inlineAccessors
);
3346 Gen
.add("return "+cppName()+";");
3348 DbSummary
<< "\t" << getFunc() << "\n";
3351 // generate write accessor
3353 Gen
.startMethod("void", setFunc(), Type
+"* "+valueVariable
, "methods", false, inlineAccessors
);
3354 Gen
.add("if ("+cppName()+" != NULL)");
3356 Gen
.add(cppName()+"->"+setParentFunction
+"(NULL);");
3358 Gen
.add(valueVariable
+"->"+setParentFunction
+"(this);");
3359 Gen
.add(cppName()+" = "+valueVariable
+";");
3361 DbSummary
<< "\t" << setFunc() << "\n";
3364 // generate attribute
3366 Gen
.addAttribute(Type
+"*", cppName(), "attributes");
3371 InitId
.add(cppName()+" = NULL;");
3374 // generate destroy code
3376 DestroyId
.add("if ("+cppName()+" != NULL)");
3378 DestroyId
.add(Type
+"*\t__o = "+cppName()+";");
3379 DestroyId
.add("__o->"+destroyFunction
+"();");
3380 DestroyId
.add("delete __o;");
3384 // generate create code
3388 // generate fetch code
3390 FetchId
.add("// read table and row, create an object, affect to the ref, and fetch it");
3391 if (!ClassNode
->tableAndRowIndicesUsedInFetch
)
3393 FetchId
.add(TTableIndexName
+"\ttableIndex;\n"+TRowIndexName
+"\trowIndex;");
3394 ClassNode
->tableAndRowIndicesUsedInFetch
= true;
3396 FetchId
.add(cppName()+" = NULL;");
3397 FetchId
.add("data.serial(tableIndex, rowIndex);");
3398 FetchId
.add("if (rowIndex != "+INVALID_ROW_INDEXName
+" && tableIndex != "+INVALID_TABLE_INDEXName
+")");
3400 FetchId
.add(cppName()+" = static_cast<"+Type
+"*>("+pdslibFunc("create")+"(tableIndex));");
3401 FetchId
.add(pdslibFunc("setRowIndex")+"(rowIndex, "+cppName()+");");
3402 FetchId
.add(cppName()+"->"+fetchFunction
+"(data);");
3403 FetchId
.add(cppName()+"->"+setUnnotifiedParentFunction
+"(this);");
3407 // generate register/unregister code
3410 UnregisterAttributesId
.add("if ("+cppName()+" != NULL)");
3411 UnregisterAttributesId
.add("{");
3412 UnregisterAttributesId
.add(Type
+"*\t"+objectVariable
+" = "+cppName()+";");
3413 UnregisterAttributesId
.add(objectVariable
+"->"+unregisterFunction
+"();");
3414 UnregisterAttributesId
.add(objectVariable
+"->"+destroyFunction
+"();");
3415 UnregisterAttributesId
.add("delete "+objectVariable
+";");
3416 UnregisterAttributesId
.add("}");
3419 // generate init/release notification
3422 NotifyInitId
.add("if ("+cppName()+" != NULL)");
3423 NotifyInitId
.add("{");
3424 NotifyInitId
.add(cppName()+"->"+notifyInitFunction
+"();");
3425 NotifyInitId
.add("}");
3427 NotifyReleaseId
.add("if ("+cppName()+" != NULL)");
3428 NotifyReleaseId
.add("{");
3429 NotifyReleaseId
.add(cppName()+"->"+notifyReleaseFunction
+"();");
3430 NotifyReleaseId
.add("}");
3433 // generate unlink code
3436 if (cnd
->getClassKey() != NULL
)
3438 CDeclarationNode
* kd
= cnd
->getClassKey();
3439 CTypeNode
* keyType
= getTypeNode(kd
->Type
);
3440 unlinkProto
= keyType
->getName()+" dummy";
3442 Gen
.startMethod("void", unlinkFunc(), unlinkProto
, "internal", false, inlineInternal
);
3444 Gen
.add(cppName()+" = NULL;");
3448 // generate clear code
3450 //ClearId.add(cppName()+"->"+setParentFunction+"(NULL);");
3451 ClearId
.add(Type
+"*\t"+objectVariable
+" = "+cppName()+";");
3452 ClearId
.add(objectVariable
+"->"+unregisterFunction
+"();");
3453 ClearId
.add(objectVariable
+"->"+destroyFunction
+"();");
3454 ClearId
.add("delete "+objectVariable
+";");
3459 void CDeclarationNode::generateArrayApplyCode()
3461 CClassGenerator::SMethodId
& ApplyId
= ClassNode
->ApplyId
;
3463 ApplyId
.add("// apply "+Name
);
3464 ApplyId
.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
3466 ApplyId
.add( "__pdr.popStructBegin("+tokenName()+");");
3467 ApplyId
.add( "uint\tindex = 0;");
3468 ApplyId
.add( "while (!__pdr.isEndOfStruct())");
3471 CIndexNode
*ind
= getIndexNode(ArrayIndex
);
3474 ApplyId
.add("std::string\tindexname;");
3475 ApplyId
.add("__pdr.pop(__Tok_MapKey, indexname);");
3476 ApplyId
.add("index = "+ind
->getFromStringCode("indexname")+";");
3480 void CDeclarationNode::generateArrayStoreCode()
3482 CClassGenerator::SMethodId
& StoreId
= ClassNode
->StoreId
;
3484 StoreId
.add("// store "+Name
);
3485 StoreId
.add("__pdr.pushStructBegin("+tokenName()+");");
3486 CIndexNode
*ind
= getIndexNode(ArrayIndex
);
3488 StoreId
.add("for (uint index=0; index<"+ind
->getSizeName()+"; ++index)");
3493 StoreId
.add("std::string\tindexname = "+ind
->getToStringCode(ind
->castFromUser("index"))+";");
3494 StoreId
.add("__pdr.push(__Tok_MapKey, indexname);");
3499 void CDeclarationNode::generateArrayEndCode()
3501 CClassGenerator::SMethodId
& StoreId
= ClassNode
->StoreId
;
3502 CClassGenerator::SMethodId
& ApplyId
= ClassNode
->ApplyId
;
3504 ApplyId
.add( "++index;");
3506 ApplyId
.add( "__pdr.popStructEnd("+tokenName()+");");
3510 StoreId
.add("__pdr.pushStructEnd("+tokenName()+");");
3515 void CDeclarationNode::generateArrayTypeContent(CCallContext
*context
)
3517 setEnv("decltype", "arraytype");
3519 CClassGenerator
&Gen
= ClassNode
->Gen
;
3520 CCppOutput
& DbSummary
= getDbNode()->DbSummary
;
3522 CClassGenerator::SMethodId
&InitId
= ClassNode
->InitId
;
3523 CClassGenerator::SMethodId
&ClearId
= ClassNode
->ClearId
;
3524 CClassGenerator::SMethodId
&DestroyId
= ClassNode
->DestroyId
;
3525 CClassGenerator::SMethodId
&FetchId
= ClassNode
->FetchId
;
3526 CClassGenerator::SMethodId
&RegisterId
= ClassNode
->RegisterId
;
3527 CClassGenerator::SMethodId
&RegisterAttributesId
= ClassNode
->RegisterAttributesId
;
3528 CClassGenerator::SMethodId
&UnregisterId
= ClassNode
->UnregisterId
;
3529 CClassGenerator::SMethodId
&UnregisterAttributesId
= ClassNode
->UnregisterAttributesId
;
3530 CClassGenerator::SMethodId
&SetParentId
= ClassNode
->SetParentId
;
3531 CClassGenerator::SMethodId
&SetUnnotifiedParentId
= ClassNode
->SetUnnotifiedParentId
;
3533 string UCodeContext
;
3534 if (context
!= NULL
)
3535 UCodeContext
= context
->getUserCodeContext();
3537 string onGetUser
= getUserCode("onGet", UCodeContext
);
3538 string onSetUser
= getUserCode("onSet", UCodeContext
);
3539 string onChangeUser
= getUserCode("onChange", UCodeContext
);
3541 CTypeNode
*tnd
= getTypeNode(Type
);
3542 CIndexNode
*ind
= getIndexNode(ArrayIndex
);
3543 XmlNode
+= " type='arraytype' typeid='"+toString(tnd
->Id
)+"' indexid='"+toString(ind
->Id
)+"'";
3545 CCallContext
ctx(this);
3546 if (context
!= NULL
)
3547 ctx
= context
->getSubContext(this);
3548 CClassGenerator
&gen
= ctx
.getRootCaller()->Gen
;
3550 setEnv("type", tnd
->getName());
3551 setEnv("indexsize", ind
->getSizeName());
3556 CClassGenerator::SMethodId
& StoreId
= ClassNode
->StoreId
;
3557 CClassGenerator::SMethodId
& ApplyId
= ClassNode
->ApplyId
;
3559 generateArrayApplyCode();
3560 generateArrayStoreCode();
3562 ApplyId
.add(tnd
->getName()+"\tvalue;");
3563 tnd
->generateApplyCode(ApplyId
, "__Tok_MapVal", "value");
3564 ApplyId
.add("if (index != "+toString(ind
->getSize())+")");
3566 ApplyId
.add( cppName()+"[index] = value;");
3569 tnd
->generateStoreCode(ApplyId
, "__Tok_MapVal", cppName()+"[index]");
3571 generateArrayEndCode();
3577 // generate read accessor
3579 if (ctx
.getRootCaller()->HasRowAccess
)
3581 string arglist
= ctx
.getCallArgList();
3582 ctx
.getRootCaller()->Gen
.startMethod(tnd
->getName(), getFunctionPrefix
+ctx
.getCallString(), arglist
, "methods", true, inlineAccessors
);
3584 DbSummary
<< "\t" << getFunctionPrefix
+ctx
.getCallString() << "\n";
3587 vector
<string
> checks
= ctx
.getCheckCode();
3588 for (i
=0; i
<checks
.size(); ++i
)
3591 if (!onGetUser
.empty())
3597 gen
.add("return "+ctx
.getCallPath()+";");
3601 // generate write accessor
3603 if (ctx
.getRootCaller()->HasRowAccess
)
3605 string arglist
= ctx
.getCallArgList();
3606 if (!arglist
.empty())
3608 arglist
+= tnd
->getName()+" "+valueVariable
;
3609 gen
.startMethod("void", setFunctionPrefix
+ctx
.getCallString(), appendArg(arglist
, "bool forceWrite=false"), "methods", false, inlineAccessors
);
3611 DbSummary
<< "\t" << setFunctionPrefix
+ctx
.getCallString() << "\n";
3615 gen
.add("H_AUTO("+getAccessorName(&ctx
, getFunctionPrefix
, "_")+")");
3623 verbStr
= "nlinfo(\"" + ctx
.getRootCaller()->Name
+ "(%d:%d)::" +setFunctionPrefix
+ ctx
.getCallString() + "(";
3625 callStr
= ctx
.getDebugCallStringFmt();
3626 if (!callStr
.empty())
3629 callStr
+= valueVariable
+"="+tnd
->getPrintfFmt();
3632 verbStr
+= ")\", __BaseTable, __BaseRow, ";
3634 callStr
= ctx
.getDebugCallStringVal();
3635 if (!callStr
.empty())
3638 callStr
+= tnd
->getPrintfVal(valueVariable
);
3647 vector
<string
> checks
= ctx
.getCheckCode();
3648 for (i
=0; i
<checks
.size(); ++i
)
3650 gen
.add(tnd
->checkCode(valueVariable
));
3652 if (!onChangeUser
.empty())
3654 gen
.add("if ("+ctx
.getCallPath()+" != "+tnd
->castToCpp(valueVariable
)+")");
3656 gen
.add(onChangeUser
);
3659 if (!onSetUser
.empty())
3665 if (WriteTriggerFlag
)
3667 gen
.add("if (forceWrite && ("+ctx
.getCallPath()+" != "+tnd
->castToCpp(valueVariable
)+"))");
3671 gen
.add("if (("+ctx
.getCallPath()+" != "+tnd
->castToCpp(valueVariable
)+") || forceWrite)");
3674 bool useEntityId
= ctx
.hasRootEntityIdKey();
3677 gen
.add(pdslibFunc("set")+"("+ctx
.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName
+")("+ctx
.getColumn()+"), "+tnd
->castToPDS(valueVariable
)+", "+ctx
.getRootCaller()->getKey()->cppName()+");");
3681 gen
.add(pdslibFunc("set")+"("+ctx
.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName
+")("+ctx
.getColumn()+"), "+tnd
->castToPDS(valueVariable
)+");");
3683 //gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");");
3685 gen
.add(ctx
.getCallPath()+" = "+tnd
->castToCpp(valueVariable
)+";");
3689 // generate attribute
3691 Gen
.addAttribute(tnd
->getName(), cppName()+"["+ind
->getSizeName()+"]", "attributes");
3696 if (!ClassNode
->indexUsedInInit
)
3698 InitId
.add("uint\ti;");
3699 ClassNode
->indexUsedInInit
= true;
3702 InitId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)\t"+cppName()+"[i] = "+tnd
->getDefaultValue()+";");
3705 // generate create code
3709 // generate fetch code
3711 if (!ClassNode
->indexUsedInFetch
)
3713 FetchId
.add("uint\ti;");
3714 ClassNode
->indexUsedInFetch
= true;
3718 FetchId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)\tdata.serialEnum("+cppName()+"[i]);");
3719 else if (tnd
->CppType
!= tnd
->StorageType
)
3721 FetchId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)");
3723 FetchId
.add(tnd
->StorageType
+"\t_v;");
3724 FetchId
.add("data.serial(_v);");
3725 FetchId
.add(cppName()+"[i] = "+tnd
->castToCpp("_v")+";");
3730 FetchId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)\tdata.serial("+cppName()+"[i]);");
3734 // generate clear code
3736 if (ctx
.getRootCaller()->HasRowAccess
)
3738 string forIndex
= "__i"+toString(ctx
.getContextIndex());
3739 ctx
.getRootCaller()->ClearId
.add("for (uint "+forIndex
+"=0; "+forIndex
+"<"+ind
->getSizeName()+"; ++"+forIndex
+")");
3740 ctx
.getRootCaller()->ClearId
.add("{");
3741 ctx
.getRootCaller()->ClearId
.add(ctx
.getCallPath()+" = "+tnd
->getDefaultValue()+";");
3742 ctx
.getRootCaller()->ClearId
.add(pdslibFunc("set")+"("+ctx
.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName
+")("+ctx
.getColumn()+"), "+tnd
->castToPDS(tnd
->getDefaultValue())+");");
3743 ctx
.getRootCaller()->ClearId
.add("}");
3752 void CDeclarationNode::generateArrayClassContent(CCallContext
*context
)
3754 setEnv("decltype", "arrayclass");
3756 CClassGenerator
&Gen
= ClassNode
->Gen
;
3757 CCppOutput
& DbSummary
= getDbNode()->DbSummary
;
3759 CClassGenerator::SMethodId
&InitId
= ClassNode
->InitId
;
3760 CClassGenerator::SMethodId
&ClearId
= ClassNode
->ClearId
;
3761 CClassGenerator::SMethodId
&DestroyId
= ClassNode
->DestroyId
;
3762 CClassGenerator::SMethodId
&FetchId
= ClassNode
->FetchId
;
3763 CClassGenerator::SMethodId
&RegisterId
= ClassNode
->RegisterId
;
3764 CClassGenerator::SMethodId
&RegisterAttributesId
= ClassNode
->RegisterAttributesId
;
3765 CClassGenerator::SMethodId
&UnregisterId
= ClassNode
->UnregisterId
;
3766 CClassGenerator::SMethodId
&UnregisterAttributesId
= ClassNode
->UnregisterAttributesId
;
3767 CClassGenerator::SMethodId
&SetParentId
= ClassNode
->SetParentId
;
3768 CClassGenerator::SMethodId
&SetUnnotifiedParentId
= ClassNode
->SetUnnotifiedParentId
;
3770 CClassNode
*sub
= getClassNode(Type
);
3771 CIndexNode
*ind
= getIndexNode(ArrayIndex
);
3772 XmlNode
+= " type='arrayclass' classid='"+toString(sub
->Id
)+"' indexid='"+toString(ind
->Id
)+"'";
3774 setEnv("type", Type
);
3775 setEnv("indexsize", ind
->getSizeName());
3780 CClassGenerator::SMethodId
& StoreId
= ClassNode
->StoreId
;
3781 CClassGenerator::SMethodId
& ApplyId
= ClassNode
->ApplyId
;
3783 generateArrayApplyCode();
3784 generateArrayStoreCode();
3786 // StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
3787 StoreId
.add("__pdr.pushStructBegin(__Tok_MapVal);");
3788 StoreId
.add(cppName()+"[index].store(__pdr);");
3789 StoreId
.add("__pdr.pushStructEnd(__Tok_MapVal);");
3790 // StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
3792 ApplyId
.add("if (index < "+ind
->getSizeName()+")");
3794 // ApplyId.add("__pdr.popStructBegin("+tokenName()+");");
3795 ApplyId
.add("__pdr.popStructBegin(__pdr.peekNextToken());");
3796 ApplyId
.add(cppName()+"[index].apply(__pdr);");
3797 ApplyId
.add("__pdr.popStructEnd(__pdr.peekNextToken());");
3798 // ApplyId.add("__pdr.popStructEnd("+tokenName()+");");
3800 ApplyId
.add("else");
3802 ApplyId
.add( "__pdr.skipStruct();");
3805 generateArrayEndCode();
3811 // export class accessors into root caller
3815 if (context
!= NULL
)
3817 ctx
.Context
.push_back(this);
3819 if (ctx
.getRootCaller()->HasRowAccess
)
3821 string forIndex
= "__i"+toString(ctx
.getContextIndex());
3822 ctx
.getRootCaller()->ClearId
.add("for (uint "+forIndex
+"=0; "+forIndex
+"<"+ind
->getSizeName()+"; ++"+forIndex
+")");
3823 ctx
.getRootCaller()->ClearId
.add("{");
3826 sub
->generateContentInCall(&ctx
);
3828 if (ctx
.getRootCaller()->HasRowAccess
)
3830 ctx
.getRootCaller()->ClearId
.add("}");
3834 // generate attribute
3836 Gen
.addAttribute(Type
, cppName()+"["+ind
->getSizeName()+"]", "attributes");
3843 // generate create code
3847 // generate fetch code
3849 if (!ClassNode
->indexUsedInFetch
)
3851 FetchId
.add("uint\ti;");
3852 ClassNode
->indexUsedInFetch
= true;
3854 FetchId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)\t"+cppName()+"[i]."+fetchFunction
+"(data);");
3857 // generate clear code
3866 void CDeclarationNode::generateArrayRefContent(CCallContext
*context
)
3868 setEnv("decltype", "arrayref");
3870 CClassGenerator
&Gen
= ClassNode
->Gen
;
3871 CCppOutput
& DbSummary
= getDbNode()->DbSummary
;
3873 CClassGenerator::SMethodId
&InitId
= ClassNode
->InitId
;
3874 CClassGenerator::SMethodId
&ClearId
= ClassNode
->ClearId
;
3875 CClassGenerator::SMethodId
&DestroyId
= ClassNode
->DestroyId
;
3876 CClassGenerator::SMethodId
&FetchId
= ClassNode
->FetchId
;
3877 CClassGenerator::SMethodId
&RegisterId
= ClassNode
->RegisterId
;
3878 CClassGenerator::SMethodId
&RegisterAttributesId
= ClassNode
->RegisterAttributesId
;
3879 CClassGenerator::SMethodId
&UnregisterId
= ClassNode
->UnregisterId
;
3880 CClassGenerator::SMethodId
&UnregisterAttributesId
= ClassNode
->UnregisterAttributesId
;
3881 CClassGenerator::SMethodId
&SetParentId
= ClassNode
->SetParentId
;
3882 CClassGenerator::SMethodId
&SetUnnotifiedParentId
= ClassNode
->SetUnnotifiedParentId
;
3883 CClassGenerator::SMethodId
&NotifyInitId
= ClassNode
->NotifyInitId
;
3884 CClassGenerator::SMethodId
&NotifyReleaseId
= ClassNode
->NotifyReleaseId
;
3886 CClassNode
*cnd
= getClassNode(Type
);
3888 bool useReference
= cnd
->ForceReference
;
3890 CDeclarationNode
*dnd
= cnd
->getDeclarationNode(ForwardRefAttribute
);
3891 CIndexNode
*ind
= getIndexNode(ArrayIndex
);
3892 CDeclarationNode
*knd
= cnd
->getKey();
3893 XmlNode
+= " type='arrayref' classid='"+toString(cnd
->Id
)+"' forwardreferedid='"+toString(dnd
->Id
)+"' key='"+toString(knd
->Id
)+"' indexid='"+toString(ind
->Id
)+"' allownull='"+(useReference
? "true" : "false")+"'";
3895 string arrayType
= Type
+(useReference
? "*" : "");
3896 string access
= (useReference
? "->" : ".");
3898 setEnv("type", Type
);
3899 setEnv("indexsize", ind
->getSizeName());
3900 define(useReference
, "useref");
3902 string UCodeContext
;
3903 if (context
!= NULL
)
3904 UCodeContext
= context
->getUserCodeContext();
3906 string onChangeUser
= getUserCode("onChange", UCodeContext
);
3911 CClassGenerator::SMethodId
& StoreId
= ClassNode
->StoreId
;
3912 CClassGenerator::SMethodId
& ApplyId
= ClassNode
->ApplyId
;
3914 generateArrayStoreCode();
3915 generateArrayApplyCode();
3917 StoreId
.add("__pdr.pushStructBegin("+tokenName()+");");
3919 ApplyId
.add("if (index < "+ind
->getSizeName()+")");
3921 ApplyId
.add( "if (__pdr.peekNextToken() == "+tokenName()+")");
3923 ApplyId
.add( "__pdr.popStructBegin("+tokenName()+");");
3927 generateClassPtrStoreCode(cppName()+"[index]");
3929 generateClassPtrApplyCode(cppName()+"[index]");
3933 StoreId
.add(cppName()+"[index].store(__pdr);");
3935 ApplyId
.add(cppName()+"[index].apply(__pdr);");
3936 ApplyId
.add(cppName()+"[index]."+setUnnotifiedParentFunction
+"(this);");
3939 StoreId
.add("__pdr.pushStructEnd("+tokenName()+");");
3941 ApplyId
.add( "__pdr.popStructEnd("+tokenName()+");");
3944 ApplyId
.add("else");
3946 ApplyId
.add( "__pdr.skipStruct();");
3949 generateArrayEndCode();
3955 // generate read accessor
3957 Gen
.startMethod((useReference
? arrayType
: Type
+"&"), getFunc(), ind
->getName()+" "+indexVariable
, "methods", false, inlineAccessors
);
3958 Gen
.add(ind
->checkCode(indexVariable
));
3959 Gen
.add("return "+cppName()+"["+indexVariable
+"];");
3961 Gen
.startMethod(string("const ")+(useReference
? arrayType
: Type
+"&"), getFunc(), ind
->getName()+" "+indexVariable
, "methods", true, inlineAccessors
);
3962 Gen
.add(ind
->checkCode(indexVariable
));
3963 Gen
.add("return "+cppName()+"["+indexVariable
+"];");
3965 DbSummary
<< "\t" << getFunc() << "\n";
3968 // generate write accessor
3972 Gen
.startMethod("void", setFunc(), arrayType
+" "+valueVariable
, "methods", false, inlineAccessors
);
3974 DbSummary
<< "\t" << setFunc() << "\n";
3976 Gen
.add("if ("+valueVariable
+" == NULL)\treturn;");
3977 Gen
.add(ind
->getName()+"\t"+keyVariable
+" = "+valueVariable
+"->"+cnd
->getKey()->getFunc()+"();");
3978 Gen
.add(ind
->checkCode(keyVariable
));
3979 Gen
.add(Type
+"*\t__prev = "+cppName()+"["+keyVariable
+"];");
3980 Gen
.add("if (__prev != NULL)");
3982 Gen
.add("__prev->"+setParentFunction
+"(NULL);");
3983 if (cnd
->MapClass
== NULL
)
3985 Gen
.add("__prev->"+unregisterFunction
+"();");
3986 Gen
.add("__prev->"+destroyFunction
+"();");
3987 Gen
.add("delete __prev;");
3990 Gen
.add(valueVariable
+"->"+setParentFunction
+"(this);");
3991 Gen
.add(cppName()+"["+keyVariable
+"] = "+valueVariable
+";");
3994 if (cnd
->MapClass
== NULL
&& useReference
&& !cnd
->HasInheritance
&& !cnd
->DerivatedFlag
)
3996 Gen
.startMethod(Type
+"*", newFunc(), ind
->getName()+" "+indexVariable
, "methods", false, inlineAccessors
);
3997 DbSummary
<< "\t" << newFunc() << "\n";
3998 Gen
.add(ind
->checkCode(indexVariable
));
3999 Gen
.add(Type
+"*\t"+objectVariable
+" = new "+Type
+"();");
4000 Gen
.add(objectVariable
+"->"+initFunction
+"("+indexVariable
+");");
4001 Gen
.add(objectVariable
+"->"+registerFunction
+"();");
4002 Gen
.add(setFunc()+"("+objectVariable
+");");
4005 if (cnd
->MapClass
== NULL
&& useReference
)
4007 Gen
.startMethod("void", deleteFunc(), ind
->getName()+" "+indexVariable
, "methods", false, inlineAccessors
);
4008 DbSummary
<< "\t" << deleteFunc() << "\n";
4009 Gen
.add(ind
->checkCode(indexVariable
));
4010 Gen
.add(Type
+"*\t"+objectVariable
+" = "+cppName()+"["+indexVariable
+"];");
4011 Gen
.add(objectVariable
+"->"+setParentFunction
+"(NULL);");
4012 Gen
.add(objectVariable
+"->"+unregisterFunction
+"();");
4013 Gen
.add(objectVariable
+"->"+destroyFunction
+"();");
4014 Gen
.add("delete "+objectVariable
+";");
4018 // generate attribute
4020 Gen
.addAttribute(arrayType
, cppName()+"["+ind
->getSizeName()+"]", "attributes");
4025 if (!ClassNode
->indexUsedInInit
)
4027 InitId
.add("uint\ti;");
4028 ClassNode
->indexUsedInInit
= true;
4032 InitId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)\t"+cppName()+"[i] = NULL;");
4036 InitId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)\t"+cppName()+"[i]."+initFunction
+"(("+ind
->getName()+")i);");
4040 // generate destroy code
4042 if (!ClassNode
->indexUsedInDestroy
)
4044 DestroyId
.add("uint\ti;");
4045 ClassNode
->indexUsedInDestroy
= true;
4047 DestroyId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)");
4051 DestroyId
.add("if ("+cppName()+"[i] != NULL)");
4053 DestroyId
.add(Type
+"*\t"+objectVariable
+" = "+cppName()+"[i];");
4054 DestroyId
.add(objectVariable
+"->"+destroyFunction
+"();");
4055 DestroyId
.add("delete "+objectVariable
+";");
4060 DestroyId
.add(cppName()+"[i]."+destroyFunction
+"();");
4065 // generate create code
4069 // generate fetch code
4073 if (!ClassNode
->indexUsedInFetch
)
4075 FetchId
.add("uint\ti;");
4076 ClassNode
->indexUsedInFetch
= true;
4078 if (!ClassNode
->tableAndRowIndicesUsedInFetch
)
4080 FetchId
.add(TTableIndexName
+"\ttableIndex;\n"+TRowIndexName
+"\trowIndex;");
4081 ClassNode
->tableAndRowIndicesUsedInFetch
= true;
4083 FetchId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)");
4085 FetchId
.add(cppName()+"[i] = NULL;");
4086 FetchId
.add("// read table and row, create an object, affect to the ref, and fetch it");
4087 FetchId
.add("data.serial(tableIndex, rowIndex);");
4088 FetchId
.add("if (rowIndex != "+INVALID_ROW_INDEXName
+" && tableIndex != "+INVALID_TABLE_INDEXName
+")");
4090 FetchId
.add(cppName()+"[i] = static_cast<"+Type
+"*>("+pdslibFunc("create")+"(tableIndex));");
4091 FetchId
.add(pdslibFunc("setRowIndex")+"(rowIndex, "+cppName()+"[i]);");
4092 FetchId
.add(cppName()+"[i]->"+fetchFunction
+"(data);");
4093 FetchId
.add(cppName()+"[i]->"+setUnnotifiedParentFunction
+"(this);");
4099 if (!ClassNode
->indexUsedInFetch
)
4101 FetchId
.add("uint\ti;");
4102 ClassNode
->indexUsedInFetch
= true;
4104 if (!ClassNode
->tableAndRowIndicesUsedInFetch
)
4106 FetchId
.add(TTableIndexName
+"\ttableIndex;\n"+TRowIndexName
+"\trowIndex;");
4107 ClassNode
->tableAndRowIndicesUsedInFetch
= true;
4109 FetchId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)");
4111 FetchId
.add("// read table and row, create an object, affect to the ref, and fetch it");
4112 FetchId
.add("data.serial(tableIndex, rowIndex);");
4113 FetchId
.add("if (rowIndex != "+INVALID_ROW_INDEXName
+" && tableIndex != "+INVALID_TABLE_INDEXName
+")");
4115 FetchId
.add(pdslibFunc("setRowIndex")+"(rowIndex, &"+cppName()+"[i]);");
4116 FetchId
.add(cppName()+"[i]."+fetchFunction
+"(data);");
4117 FetchId
.add(cppName()+"[i]."+setUnnotifiedParentFunction
+"(this);");
4123 // generate register/unregister code
4127 if (!ClassNode
->indexUsedInRegister
)
4129 RegisterAttributesId
.add("uint\ti;");
4130 ClassNode
->indexUsedInRegister
= true;
4132 RegisterAttributesId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)");
4133 RegisterAttributesId
.add("{");
4134 RegisterAttributesId
.add(cppName()+"[i]."+registerFunction
+"();");
4135 RegisterAttributesId
.add(cppName()+"[i]."+setParentFunction
+"(this);");
4136 RegisterAttributesId
.add("}");
4138 if (!ClassNode
->indexUsedInUnregister
)
4140 UnregisterAttributesId
.add("uint\ti;");
4141 ClassNode
->indexUsedInUnregister
= true;
4143 UnregisterAttributesId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)");
4144 UnregisterAttributesId
.add("{");
4145 UnregisterAttributesId
.add(cppName()+"[i]."+unregisterFunction
+"();");
4146 UnregisterAttributesId
.add("}");
4150 if (!ClassNode
->indexUsedInUnregister
)
4152 UnregisterAttributesId
.add("uint\ti;");
4153 ClassNode
->indexUsedInUnregister
= true;
4155 UnregisterAttributesId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)");
4156 UnregisterAttributesId
.add("{");
4157 UnregisterAttributesId
.add("if ("+cppName()+"[i] != NULL)");
4158 UnregisterAttributesId
.add("{");
4159 UnregisterAttributesId
.add(Type
+"*\t"+objectVariable
+" = "+cppName()+"[i];");
4160 UnregisterAttributesId
.add(objectVariable
+"->"+unregisterFunction
+"();");
4161 UnregisterAttributesId
.add(objectVariable
+"->"+destroyFunction
+"();");
4162 UnregisterAttributesId
.add("delete "+objectVariable
+";");
4163 UnregisterAttributesId
.add("}");
4164 UnregisterAttributesId
.add("}");
4168 // generate init/release notification
4171 if (!ClassNode
->indexUsedInNotifyInit
)
4173 NotifyInitId
.add("uint\ti;");
4174 ClassNode
->indexUsedInNotifyInit
= true;
4176 NotifyInitId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)");
4177 NotifyInitId
.add("{");
4179 if (!ClassNode
->indexUsedInNotifyRelease
)
4181 NotifyReleaseId
.add("uint\ti;");
4182 ClassNode
->indexUsedInNotifyRelease
= true;
4184 NotifyReleaseId
.add("for (i=0; i<"+ind
->getSizeName()+"; ++i)");
4185 NotifyReleaseId
.add("{");
4189 NotifyInitId
.add(cppName()+"[i]."+notifyInitFunction
+"();");
4191 NotifyReleaseId
.add(cppName()+"[i]."+notifyReleaseFunction
+"();");
4195 NotifyInitId
.add("if ("+cppName()+"[i] != NULL)");
4196 NotifyInitId
.add("{");
4197 NotifyInitId
.add(cppName()+"[i]->"+notifyInitFunction
+"();");
4198 NotifyInitId
.add("}");
4200 NotifyReleaseId
.add("if ("+cppName()+"[i] != NULL)");
4201 NotifyReleaseId
.add("{");
4202 NotifyReleaseId
.add(cppName()+"[i]->"+notifyReleaseFunction
+"();");
4203 NotifyReleaseId
.add("}");
4206 NotifyInitId
.add("}");
4207 NotifyReleaseId
.add("}");
4211 // generate unlink code
4215 Gen
.startMethod("void", unlinkFunc(), ind
->getName()+" "+keyVariable
, "internal", false, inlineInternal
);
4216 Gen
.add(cppName()+"["+keyVariable
+"] = NULL;");
4220 // generate clear code
4222 ClearId
.add("for (uint i=0; i<"+ind
->getSizeName()+"; ++i)");
4226 ClearId
.add(cppName()+"[i]."+clearFunction
+"();");
4230 //ClearId.add(cppName()+"[i]->"+setParentFunction+"(NULL);");
4231 ClearId
.add(Type
+"*\t"+objectVariable
+" = "+cppName()+"[i];");
4232 ClearId
.add(objectVariable
+"->"+unregisterFunction
+"();");
4233 ClearId
.add(objectVariable
+"->"+destroyFunction
+"();");
4234 ClearId
.add("delete "+objectVariable
+";");
4245 void CDeclarationNode::generateSetContent(CCallContext
*context
)
4247 setEnv("decltype", "set");
4249 CClassGenerator
&Gen
= ClassNode
->Gen
;
4250 CCppOutput
& DbSummary
= getDbNode()->DbSummary
;
4252 CClassGenerator::SMethodId
&InitId
= ClassNode
->InitId
;
4253 CClassGenerator::SMethodId
&ClearId
= ClassNode
->ClearId
;
4254 CClassGenerator::SMethodId
&DestroyId
= ClassNode
->DestroyId
;
4255 CClassGenerator::SMethodId
&FetchId
= ClassNode
->FetchId
;
4256 CClassGenerator::SMethodId
&RegisterId
= ClassNode
->RegisterId
;
4257 CClassGenerator::SMethodId
&RegisterAttributesId
= ClassNode
->RegisterAttributesId
;
4258 CClassGenerator::SMethodId
&UnregisterId
= ClassNode
->UnregisterId
;
4259 CClassGenerator::SMethodId
&UnregisterAttributesId
= ClassNode
->UnregisterAttributesId
;
4260 CClassGenerator::SMethodId
&SetParentId
= ClassNode
->SetParentId
;
4261 CClassGenerator::SMethodId
&SetUnnotifiedParentId
= ClassNode
->SetUnnotifiedParentId
;
4262 CClassGenerator::SMethodId
&NotifyInitId
= ClassNode
->NotifyInitId
;
4263 CClassGenerator::SMethodId
&NotifyReleaseId
= ClassNode
->NotifyReleaseId
;
4265 CClassNode
*sub
= getClassNode(Type
);
4266 CDeclarationNode
*key
= sub
->getKey();
4267 CTypeNode
*keyType
= getTypeNode(key
->Type
);
4269 bool useReference
= sub
->ForceReference
;
4270 string access
= (useReference
? "->" : ".");
4272 string onChangeUser
= getUserCode("onChange", context
!= NULL
? context
->getUserCodeContext() : "");
4275 string setType
= "std::map<"+keyType
->getName()+", " + Type
+ (useReference
? "*" : "") + ">";
4277 CDeclarationNode
*dnd
= sub
->getDeclarationNode(ForwardRefAttribute
);
4278 XmlNode
+= " type='set' classid='"+toString(sub
->Id
)+"' forwardreferedid='"+toString(dnd
->Id
)+"' key='"+toString(key
->Id
)+"' ";
4280 setEnv("type", Type
);
4281 setEnv("keytype", keyType
->getName());
4282 define(useReference
, "useref");
4287 CClassGenerator::SMethodId
& StoreId
= ClassNode
->StoreId
;
4288 CClassGenerator::SMethodId
& ApplyId
= ClassNode
->ApplyId
;
4290 StoreId
.add("// store "+Name
);
4291 StoreId
.add("__pdr.pushStructBegin("+tokenName()+");");
4292 StoreId
.add("for ("+setType
+"::const_iterator it="+cppName()+".begin(); it!="+cppName()+".end(); ++it)");
4294 StoreId
.add( keyType
->getName()+"\tkey = (*it).first;");
4295 keyType
->generateStoreCode(StoreId
, "__Tok_MapKey", "key");
4296 StoreId
.add( "__pdr.pushStructBegin(__Tok_MapVal);");
4300 generateClassPtrStoreCode("(*it).second");
4304 StoreId
.add("(*it).second.store(__pdr);");
4307 StoreId
.add( "__pdr.pushStructEnd(__Tok_MapVal);");
4309 StoreId
.add("__pdr.pushStructEnd("+tokenName()+");");
4310 StoreId
.add("// end of store "+Name
);
4312 ApplyId
.add("// apply "+Name
);
4313 ApplyId
.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
4315 ApplyId
.add( "__pdr.popStructBegin("+tokenName()+");");
4316 ApplyId
.add( "while (!__pdr.isEndOfStruct())");
4318 ApplyId
.add( keyType
->getName()+"\tkey;");
4319 keyType
->generateApplyCode(ApplyId
, "__Tok_MapKey", "key");
4321 ApplyId
.add( "__pdr.popStructBegin(__Tok_MapVal);");
4324 ApplyId
.add( Type
+"*\tobj;");
4325 generateClassPtrApplyCode("obj");
4326 ApplyId
.add( "if (obj != NULL)");
4328 ApplyId
.add( cppName()+"[key] = obj;");
4333 ApplyId
.add( Type
+"&\tobj = "+cppName()+"[key];");
4334 ApplyId
.add( "obj.apply(__pdr);");
4335 ApplyId
.add( "obj."+setUnnotifiedParentFunction
+"(this);");
4337 ApplyId
.add( "__pdr.popStructEnd(__Tok_MapVal);");
4339 ApplyId
.add( "__pdr.popStructEnd("+tokenName()+");");
4341 ApplyId
.add("// end of apply "+Name
);
4347 // generate read accessor
4349 Gen
.startMethod(Type
+"*", getFunc(), "const "+keyType
->getName()+"& "+keyVariable
, "methods", false, inlineAccessors
);
4350 DbSummary
<< "\t" << getFunc() << "\n";
4351 Gen
.add(setType
+"::iterator _it = "+cppName()+".find("+keyVariable
+");");
4352 Gen
.add("return (_it=="+cppName()+".end() ? NULL : "+(useReference
? "(*_it).second" : "&((*_it).second)")+");");
4354 Gen
.startMethod("const "+Type
+"*", getFunc(), "const "+keyType
->getName()+"& "+keyVariable
, "methods", true, inlineAccessors
);
4355 Gen
.add(setType
+"::const_iterator _it = "+cppName()+".find("+keyVariable
+");");
4356 Gen
.add("return (_it=="+cppName()+".end() ? NULL : "+(useReference
? "(*_it).second" : "&((*_it).second)")+");");
4358 // generate map accessor
4359 string stypedef
= "T"+Name
+"Map";
4360 //Gen.addOther("typedef "+setType+"\t"+stypedef+";");
4361 Gen
.startMethod(setType
+"::iterator", getFunc()+"Begin", "", "methods", false, inlineAccessors
);
4362 Gen
.add("return "+cppName()+".begin();");
4363 DbSummary
<< "\t" << getFunc() << "Begin" << "\n";
4364 Gen
.startMethod(setType
+"::iterator", getFunc()+"End", "", "methods", false, inlineAccessors
);
4365 Gen
.add("return "+cppName()+".end();");
4366 DbSummary
<< "\t" << getFunc() << "End" << "\n";
4367 Gen
.startMethod(setType
+"::const_iterator", getFunc()+"Begin", "", "methods", true, inlineAccessors
);
4368 Gen
.add("return "+cppName()+".begin();");
4369 Gen
.startMethod(setType
+"::const_iterator", getFunc()+"End", "", "methods", true, inlineAccessors
);
4370 Gen
.add("return "+cppName()+".end();");
4371 Gen
.startMethod("const "+setType
+" &", getFunc(), "", "methods", true, inlineAccessors
);
4372 Gen
.add("return "+cppName()+";");
4375 // generate write accessor
4379 Gen
.startMethod("void", setFunc(), Type
+"* "+valueVariable
, "methods", false, inlineAccessors
);
4380 DbSummary
<< "\t" << setFunc() << "\n";
4381 Gen
.add("if ("+valueVariable
+" == NULL)\treturn;");
4382 Gen
.add(keyType
->getName()+"\t"+keyVariable
+" = "+valueVariable
+"->"+sub
->getKey()->getFunc()+"();");
4383 Gen
.add(setType
+"::iterator\t_it = "+cppName()+".find("+keyVariable
+");");
4384 Gen
.add("if (_it != "+cppName()+".end())");
4386 Gen
.add(Type
+"*\t__prev = (*_it).second;");
4387 Gen
.add("if (__prev == "+valueVariable
+")\treturn;");
4388 Gen
.add("__prev->"+setParentFunction
+"(NULL);");
4389 Gen
.add("__prev->"+unregisterFunction
+"();");
4390 Gen
.add("__prev->"+destroyFunction
+"();");
4391 Gen
.add("delete __prev;");
4393 Gen
.add(valueVariable
+"->"+setParentFunction
+"(this);");
4394 Gen
.add(cppName()+"["+keyVariable
+"] = "+valueVariable
+";");
4395 if (!onChangeUser
.empty())
4398 Gen
.add(onChangeUser
);
4403 if (sub
->MapClass
== NULL
&& !sub
->HasInheritance
&& !sub
->DerivatedFlag
)
4405 Gen
.startMethod(Type
+"*", newFunc(), "const "+keyType
->getName()+" &"+keyVariable
, "methods", false, inlineAccessors
);
4406 DbSummary
<< "\t" << newFunc() << "\n";
4407 Gen
.add(setType
+"::iterator\t__it = "+cppName()+".find("+keyVariable
+");");
4408 Gen
.add("if (__it == "+cppName()+".end())");
4410 Gen
.add("__it = "+cppName()+".insert("+setType
+"::value_type("+keyVariable
+", "+(useReference
? toString("new ") : toString(""))+Type
+"())).first;");
4411 Gen
.add(Type
+"*\t"+objectVariable
+" = "+(useReference
? toString("") : toString("&"))+"((*__it).second);");
4412 Gen
.add(objectVariable
+"->"+initFunction
+"("+keyVariable
+");");
4413 Gen
.add(objectVariable
+"->"+registerFunction
+"();");
4414 Gen
.add(objectVariable
+"->"+setParentFunction
+"(this);");
4416 if (!onChangeUser
.empty())
4419 Gen
.add(onChangeUser
);
4422 Gen
.add("return "+(useReference
? toString("") : toString("&"))+"((*__it).second);");
4425 Gen
.startMethod("void", deleteFunc(), "const "+keyType
->getName()+" &"+keyVariable
, "methods", false, inlineAccessors
);
4426 DbSummary
<< "\t" << deleteFunc() << "\n";
4427 Gen
.add(setType
+"::iterator\t__it = "+cppName()+".find("+keyVariable
+");");
4428 Gen
.add("if (__it == "+cppName()+".end())\treturn;");
4431 Gen
.add(Type
+"*\t"+objectVariable
+" = (*__it).second;");
4432 Gen
.add(objectVariable
+"->"+unregisterFunction
+"();");
4433 Gen
.add(objectVariable
+"->"+destroyFunction
+"();");
4434 Gen
.add("delete "+objectVariable
+";");
4438 Gen
.add(Type
+"&\t"+objectVariable
+" = (*__it).second;");
4439 Gen
.add(objectVariable
+"."+unregisterFunction
+"();");
4440 Gen
.add(cppName()+".erase(__it);");
4442 if (!onChangeUser
.empty())
4445 Gen
.add(onChangeUser
);
4450 // generate attribute
4452 Gen
.addAttribute(setType
, cppName(), "attributes");
4459 // generate destroy code
4461 DestroyId
.add("for ("+setType
+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
4463 DestroyId
.add(setType
+"::iterator __itr=__it++;");
4466 DestroyId
.add(Type
+"*\t"+objectVariable
+" = ((*__itr).second);");
4467 DestroyId
.add("if ("+objectVariable
+" != NULL)");
4469 DestroyId
.add(objectVariable
+"->"+destroyFunction
+"();");
4470 DestroyId
.add("delete "+objectVariable
+";");
4475 DestroyId
.add("((*__itr).second)."+destroyFunction
+"();");
4478 DestroyId
.add(cppName()+".clear();");
4481 // generate create code
4485 // generate fetch code
4487 if (!ClassNode
->tableAndRowIndicesUsedInFetch
)
4489 FetchId
.add(TTableIndexName
+"\ttableIndex;\n"+TRowIndexName
+"\trowIndex;");
4490 ClassNode
->tableAndRowIndicesUsedInFetch
= true;
4494 FetchId
.add("// read table and row, create an object, affect to the ref, and fetch it");
4495 FetchId
.add("data.serial(tableIndex, rowIndex);");
4496 FetchId
.add("if (rowIndex == "+INVALID_ROW_INDEXName
+" || tableIndex == "+INVALID_TABLE_INDEXName
+")\tbreak;");
4498 FetchId
.add(keyType
->getName()+"\t"+keyVariable
+";");
4499 if (keyType
->isEnum())
4501 FetchId
.add("data.serialEnum("+keyVariable
+");");
4503 else if (keyType
->CppType
!= keyType
->StorageType
)
4506 FetchId
.add(keyType
->StorageType
+"\t_v;");
4507 FetchId
.add("data.serial(_v);");
4508 FetchId
.add(keyVariable
+" = "+keyType
->castToCpp("_v")+";");
4513 FetchId
.add("data.serial("+keyVariable
+");");
4517 FetchId
.add(Type
+"*\t"+objectVariable
+" = static_cast<"+Type
+"*>("+pdslibFunc("create")+"(tableIndex));");
4518 FetchId
.add(cppName()+".insert(std::make_pair("+keyVariable
+", "+objectVariable
+"));");
4522 FetchId
.add(cppName()+".insert(std::make_pair("+keyVariable
+", "+Type
+"()));");
4523 FetchId
.add(Type
+"*\t"+objectVariable
+" = &("+cppName()+"["+keyVariable
+"]);");
4525 FetchId
.add(pdslibFunc("setRowIndex")+"(rowIndex, "+objectVariable
+");");
4526 FetchId
.add(objectVariable
+"->"+fetchFunction
+"(data);");
4527 FetchId
.add(objectVariable
+"->"+setUnnotifiedParentFunction
+"(this);");
4529 FetchId
.add("while (true);");
4532 // generate register/unregister code
4535 UnregisterAttributesId
.add("for ("+setType
+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
4536 UnregisterAttributesId
.add("{");
4537 UnregisterAttributesId
.add(setType
+"::iterator __itr=__it++;");
4540 UnregisterAttributesId
.add(Type
+"*\t"+objectVariable
+" = (*__itr).second;");
4541 UnregisterAttributesId
.add(objectVariable
+"->"+unregisterFunction
+"();");
4542 UnregisterAttributesId
.add(objectVariable
+"->"+destroyFunction
+"();");
4543 UnregisterAttributesId
.add("delete "+objectVariable
+";");
4547 UnregisterAttributesId
.add(Type
+"&\t"+objectVariable
+" = (*__itr).second;");
4548 UnregisterAttributesId
.add(objectVariable
+"."+unregisterFunction
+"();");
4550 UnregisterAttributesId
.add("}");
4553 // generate init/release notification
4556 NotifyInitId
.add("for ("+setType
+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
4557 NotifyInitId
.add("{");
4558 NotifyInitId
.add(setType
+"::iterator __itr=__it++;");
4560 NotifyReleaseId
.add("for ("+setType
+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
4561 NotifyReleaseId
.add("{");
4562 NotifyReleaseId
.add(setType
+"::iterator __itr=__it++;");
4566 NotifyInitId
.add("(*__itr).second."+notifyInitFunction
+"();");
4567 NotifyReleaseId
.add("(*__itr).second."+notifyReleaseFunction
+"();");
4571 NotifyInitId
.add("(*__itr).second->"+notifyInitFunction
+"();");
4572 NotifyReleaseId
.add("(*__itr).second->"+notifyReleaseFunction
+"();");
4575 NotifyInitId
.add("}");
4576 NotifyReleaseId
.add("}");
4579 // generate unlink code
4583 Gen
.startMethod("void", unlinkFunc(), keyType
->getName()+" "+keyVariable
, "internal", false, inlineInternal
);
4584 Gen
.add(cppName()+".erase("+keyVariable
+");");
4588 // generate clear code
4590 ClearId
.add("for ("+setType
+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
4592 ClearId
.add(setType
+"::iterator __itr=__it++;");
4595 ClearId
.add(Type
+"*\t"+objectVariable
+" = &((*__itr).second);");
4599 ClearId
.add(Type
+"*\t"+objectVariable
+" = (*__itr).second;");
4601 //ClearId.add(objectVariable+"->"+setParentFunction+"(NULL);");
4602 ClearId
.add(objectVariable
+"->"+unregisterFunction
+"();");
4603 ClearId
.add(objectVariable
+"->"+destroyFunction
+"();");
4606 ClearId
.add("delete "+objectVariable
+";");
4609 ClearId
.add(cppName()+".clear();");
4613 string
CDeclarationNode::displayPrintfPrefix()
4615 if (DeclarationType
!= SimpleType
)
4616 error("can't display other declaration than simple type", "internal");
4618 CTypeNode
* type
= getTypeNode(Type
);
4620 if (type
->CppType
== "CEntityId" || type
->CppType
== "CSheetId")
4622 else if (type
->CppType
== "uint64" || type
->CppType
== "sint64")
4623 return "%\"NL_I64\"d";
4624 else if (type
->CppType
== "float" || type
->CppType
== "double")
4630 string
CDeclarationNode::displayCppCode(string replVar
)
4632 if (DeclarationType
!= SimpleType
)
4633 error("can't display other declaration than simple type", "internal");
4635 if (replVar
.empty())
4636 replVar
= cppName();
4638 CTypeNode
* type
= getTypeNode(Type
);
4640 if (type
->CppType
== "CEntityId" || type
->CppType
== "CSheetId")
4641 return replVar
+".toString().c_str()";
4647 string
CDeclarationNode::toUint64(string replVar
)
4649 if (DeclarationType
!= SimpleType
)
4650 error("can't display other declaration than simple type", "internal");
4652 if (replVar
.empty())
4653 replVar
= cppName();
4655 CTypeNode
* type
= getTypeNode(Type
);
4657 if (type
->CppType
== "CEntityId")
4658 return replVar
+".asUint64()";
4659 else if (type
->CppType
== "CSheetId")
4660 return "(uint64)("+replVar
+".asInt())";
4662 return "(uint64)"+replVar
;
4669 bool CLogMsgNode::prolog()
4671 getDbNode()->LogNodes
.push_back(this);
4673 getFileNode()->IncludeDbFile
= true;
4674 getFileNode()->IncludeStandard
= true;
4675 getFileNode()->IncludePDSLib
= true;
4680 void CLogMsgNode::generateContent()
4685 CFunctionGenerator logfunc
;
4686 CClassGenerator logclass
;
4689 CFunctionGenerator
& initDb
= getDbNode()->initDb
;
4692 logfunc
.setType("void");
4693 logfunc
.IsInline
= inlineLogFunctions
;
4695 logclass
.init("Log"+Name
);
4696 logclass
.createPublic("pub");
4697 logclass
.createPrivate("priv");
4699 CClassGenerator::SMethodId startlogid
= logclass
.startMethod("void", logStartFunction
, "", "priv", false, inlineLogFunctions
);
4700 CClassGenerator::SMethodId stoplogid
= logclass
.startMethod("void", logStopFunction
, "", "priv", false, inlineLogFunctions
);
4701 startlogid
.add(pdslibFunc("pushContext")+"();");
4702 stoplogid
.add(pdslibFunc("popContext")+"();");
4704 map
<string
, CParseNode
*> params
;
4706 for (j
=0; j
<Params
.size(); ++j
)
4708 string type
= Params
[j
].first
;
4709 string name
= Params
[j
].second
;
4713 if ( (tnd
= getTypeNode(type
, false)) )
4715 pair
<map
<string
, CParseNode
*>::iterator
, bool> res
= params
.insert(std::pair
<string
, CParseNode
*>(name
, tnd
));
4717 error("log parameter '"+name
+"' already defined");
4719 if (!logfunc
.Proto
.empty())
4720 logfunc
.Proto
+= ", ";
4721 if (!argcall
.empty())
4724 logfunc
.Proto
+= tnd
->getName()+" "+name
;
4727 else if ( (cnd
= getClassNode(type
, false)) )
4729 pair
<map
<string
, CParseNode
*>::iterator
, bool> res
= params
.insert(std::pair
<string
, CParseNode
*>(name
, cnd
));
4731 error("log parameter '"+name
+"' already defined");
4733 if (!logfunc
.Proto
.empty())
4734 logfunc
.Proto
+= ", ";
4735 if (!argcall
.empty())
4738 logfunc
.Proto
+= "const "+type
+"& "+name
;
4741 else if (type
== "string")
4743 CExtLogTypeNode
* extnd
= new CExtLogTypeNode();
4744 extnd
->ExtLogType
= "string";
4745 pair
<map
<string
, CParseNode
*>::iterator
, bool> res
= params
.insert(std::pair
<string
, CParseNode
*>(name
, extnd
));
4747 error("log parameter '"+name
+"' already defined");
4749 if (!logfunc
.Proto
.empty())
4750 logfunc
.Proto
+= ", ";
4751 if (!argcall
.empty())
4754 logfunc
.Proto
+= "const std::string& "+name
;
4759 error("'"+type
+"' not found as a class or a type");
4764 initDb
.add("// Init "+Name
+" log message and parameters");
4766 for (j
=0; j
<Logs
.size(); ++j
)
4770 logfunc
.add(pdslibFunc("log")+"("+toString(logId
)+");");
4771 startlogid
.add(pdslibFunc("log")+"("+toString(logId
)+");");
4773 const char *cptr
= Logs
[j
].c_str();
4778 getDbNode()->xmlDescription
.push_back("<logmsg id='"+toString(logId
)+"' context='"+string(Context
? "true" : "false")+"'>");
4782 initDb
.add(pdslibFunc("initLog")+"("+toString(logId
)+");");
4784 while (*cptr
!= '\0')
4790 error("log format corrupted in line \""+Logs
[j
]+"\"");
4802 while (*cptr
!='\0' && *cptr
!='$' && *cptr
!='.')
4806 error("log format corrupted in line \""+Logs
[j
]+"\"");
4811 while (*cptr
!='\0' && *cptr
!='$')
4816 error("log format corrupted in line \""+Logs
[j
]+"\"");
4820 map
<string
, CParseNode
*>::iterator it
= params
.find(param
);
4822 if (it
== params
.end())
4823 error("'"+param
+"' ot found in prototype, at line \""+Logs
[j
]+"\"");
4825 CTypeNode
*tnd
= NULL
;
4826 CExtLogTypeNode
* extnd
= NULL
;
4831 tnd
= dynamic_cast<CTypeNode
*>((*it
).second
);
4832 extnd
= dynamic_cast<CExtLogTypeNode
*>((*it
).second
);
4835 logfunc
.add(pdslibFunc("logPush")+"("+tnd
->castToPDS(param
)+");");
4836 startlogid
.add(pdslibFunc("logPush")+"("+tnd
->castToPDS(param
)+");");
4838 else if (extnd
!= NULL
&& extnd
->ExtLogType
== "string")
4840 logfunc
.add(pdslibFunc("logPush")+"("+param
+");");
4841 startlogid
.add(pdslibFunc("logPush")+"("+param
+");");
4845 error("misuse of parameter '"+param
+"' at line \""+Logs
[j
]+"\", missing attribute name");
4851 CClassNode
*cnd
= dynamic_cast<CClassNode
*>((*it
).second
);
4853 error("misuse of parameter '"+param
+"' at line \""+Logs
[j
]+"\", should be a class");
4855 CDeclarationNode
*dnd
= cnd
->getDeclaration(var
);
4858 error("attribute '"+var
+"' is not a simple type");
4860 tnd
= getTypeNode(dnd
->Type
);
4862 logfunc
.add(pdslibFunc("logPush")+"("+tnd
->castToPDS(param
+"."+dnd
->getFunc()+"()")+");");
4863 startlogid
.add(pdslibFunc("logPush")+"("+tnd
->castToPDS(param
+"."+dnd
->getFunc()+"()")+");");
4868 getDbNode()->xmlDescription
.push_back("<param id='"+toString(paramNum
)+"' typeid='"+toString(tnd
->Id
)+"'/>");
4869 initDb
.add(pdslibFunc("initLogParam")+"("+toString(logId
)+", "+toString(paramNum
)+", "+toString(tnd
->Size
)+");");
4873 getDbNode()->xmlDescription
.push_back("<param id='"+toString(paramNum
)+"' typeid='"+extnd
->ExtLogType
+"'/>");
4874 initDb
.add(pdslibFunc("initLogParam")+"("+toString(logId
)+", "+toString(paramNum
)+", "+toString(sizeof(uint16
))+");");
4878 log
+= "$"+toString(paramNum
);
4888 getDbNode()->xmlDescription
.push_back("<msg>"+xmlSpecialChars(log
)+"</msg>");
4889 getDbNode()->xmlDescription
.push_back("</logmsg>");
4892 logclass
.get(startlogid
).Proto
= logfunc
.Proto
;
4894 CClassGenerator::SMethodId construct
= logclass
.startConstructor(logfunc
.Proto
, "pub", inlineLogFunctions
, "");
4895 construct
.add(logStartFunction
+"("+argcall
+");");
4896 CClassGenerator::SMethodId destruct
= logclass
.startDestructor("pub", inlineLogFunctions
);
4897 destruct
.add(logStopFunction
+"();");
4899 CFileNode
* file
= getFileNode();
4903 logclass
.flush(file
->hOutput(), file
->cppOutput(), file
->inlineOutput());
4904 file
->hOutput() << "\n";
4908 logfunc
.flush(file
->hOutput(), file
->cppOutput(), file
->inlineOutput());
4909 file
->hOutput() << "\n";