// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdgeorges.h" #include "nel/misc/i_xml.h" #include "nel/misc/path.h" #include "form_dfn.h" #include "form_loader.h" #include "form_elm.h" using namespace NLMISC; using namespace std; #ifndef NL_OS_WINDOWS #define stricmp strcasecmp #endif namespace NLGEORGES { // *************************************************************************** void warning (bool exception, const char *format, ... ); // *************************************************************************** void CFormDfn::write (xmlDocPtr doc, const char *filename, bool georges4CVS) { // Save filename _Filename = CFile::getFilename (filename); // Create the first node xmlNodePtr node = xmlNewDocNode (doc, NULL, (const xmlChar*)"DFN", NULL); xmlDocSetRootElement (doc, node); // Write elements uint parent; for (parent=0; parentname == NULL) || (strcmp ((const char*)root->name, "DFN") != 0) ) { // Throw exception warning (true, "read", "XML Syntax error in block line %d, node (%s) should be DFN.", (ptrdiff_t)root->content, root->name); } // Count the parent uint parentCount = CIXml::countChildren (root, "PARENT"); Parents.resize (parentCount); // For each element entry uint parentNumber = 0; xmlNodePtr parent = CIXml::getFirstChildNode (root, "PARENT"); while (parentNumbername, (ptrdiff_t)parent->content); } // Next parent parent = CIXml::getNextChildNode (parent, "PARENT"); parentNumber++; } // Count the element children uint childCount = CIXml::countChildren (root, "ELEMENT"); // Resize the element table Entries.resize (childCount); // For each element entry uint childNumber = 0; xmlNodePtr child = CIXml::getFirstChildNode (root, "ELEMENT"); while (childNumbername, (ptrdiff_t)child->content, Entries[childNumber].Filename.c_str ()); } // Read the default value const char *defaultName = (const char*)xmlGetProp (child, (xmlChar*)"Default"); if (defaultName) { Entries[childNumber].Default = defaultName; // Delete the value xmlFree ((void*)defaultName); } } else { // Throw exception warning (true, "read", "XML In block (%s) line %d, no filename found for the .typ file.", child->name, (ptrdiff_t)child->content, Entries[childNumber].Filename.c_str ()); } } else if (stricmp (typeName, "Dfn") == 0) { Entries[childNumber].TypeElement = UFormDfn::EntryDfn; dfn = true; // Load the filename if (!Entries[childNumber].Filename.empty ()) { // Load the filename Entries[childNumber].Dfn = loader.loadFormDfn (Entries[childNumber].Filename.c_str (), forceLoad); if ((Entries[childNumber].Dfn == NULL) && !forceLoad) { // Throw exception warning (true, "read", "XML In block (%s) line %d, file not found %s.", child->name, (ptrdiff_t)child->content, Entries[childNumber].Filename.c_str ()); } } else { // Throw exception warning (true, "read", "XML In block (%s) line %d, no filename found for the .typ file.", child->name, (ptrdiff_t)child->content, Entries[childNumber].Filename.c_str ()); } } else if (stricmp (typeName, "DfnPointer") == 0) { Entries[childNumber].TypeElement = UFormDfn::EntryVirtualDfn; } else { // Throw exception warning (true, "read", "XML Syntax error in block (%s) line %d, element has not a valid type name attribut \"Type = %s\".", child->name, (ptrdiff_t)child->content, typeName); } // Delete the value xmlFree ((void*)typeName); } else { // Throw exception warning (true, "read", "XML Syntax error in block (%s) line %d, element has no type name attribut \"Type = [Type][Dfn][DfnPointer]\".", child->name, (ptrdiff_t)child->content); } // Get the array attrib Entries[childNumber].Array = false; const char* arrayFlag = (const char*)xmlGetProp (child, (xmlChar*)"Array"); if (arrayFlag) { Entries[childNumber].Array = (stricmp (arrayFlag, "true") == 0); // Delete the value xmlFree ((void*)arrayFlag); } } else { // Throw exception warning (true, "read", "XML Syntax error in block (%s) line %d, aguments Name not found.", root->name, (ptrdiff_t)root->content); } // Next child child = CIXml::getNextChildNode (child, "ELEMENT"); childNumber++; } // Read the header Header.read (root); } // *************************************************************************** uint CFormDfn::countParentDfn (uint32 round) const { // Checkout recursive calls if (round > NLGEORGES_MAX_RECURSION) { // Turn around.. warning (false, "countParentDfn", "Recursive call on the same DFN, look for loop inheritances."); return 0; } uint count = 0; uint i; for (i=0; icountParentDfn (round+1); } return count+1; } // *************************************************************************** void CFormDfn::getParentDfn (std::vector &array, uint32 round) { // Checkout recursive calls if (round > NLGEORGES_MAX_RECURSION) { // Turn around.. warning (false, "getParentDfn", "Recursive call on the same DFN, look for loop inheritances."); return; } //uint count = 0; uint i; for (i=0; igetParentDfn (array, round+1); } array.push_back (this); } // *************************************************************************** void CFormDfn::getParentDfn (std::vector &array, uint32 round) const { // Checkout recursive calls if (round > NLGEORGES_MAX_RECURSION) { // Turn around.. warning (false, "getParentDfn", "Recursive call on the same DFN, look for loop inheritances."); return; } //uint count = 0; uint i; for (i=0; igetParentDfn (array, round+1); } array.push_back (this); } // *************************************************************************** uint CFormDfn::getNumParent () const { return Parents.size (); } // *************************************************************************** CFormDfn *CFormDfn::getParent (uint parent) const { return Parents[parent].Parent; } // *************************************************************************** const string& CFormDfn::getParentFilename (uint parent) const { return Parents[parent].ParentFilename; } // *************************************************************************** uint CFormDfn::getNumEntry () const { return Entries.size(); } // *************************************************************************** void CFormDfn::setNumEntry (uint size) { Entries.resize (size); } // *************************************************************************** const CFormDfn::CEntry &CFormDfn::getEntry (uint entry) const { return Entries[entry]; } // *************************************************************************** CFormDfn::CEntry &CFormDfn::getEntry (uint entry) { return Entries[entry]; } // *************************************************************************** void CFormDfn::setNumParent (uint size) { Parents.resize (size); } // *************************************************************************** void CFormDfn::setParent (uint parent, CFormLoader &loader, const char *filename) { if (strcmp (filename, "")==0) Parents[parent].Parent = NULL; else Parents[parent].Parent = loader.loadFormDfn (filename, false); Parents[parent].ParentFilename = filename; } // *************************************************************************** void CFormDfn::CEntry::setType (CFormLoader &loader, const char *filename) { TypeElement = EntryType; Dfn = NULL; Filename = filename; Type = loader.loadType (filename); } // *************************************************************************** void CFormDfn::CEntry::setDfn (CFormLoader &loader, const char *filename) { TypeElement = EntryDfn; Filename = filename; Type = NULL; Dfn = loader.loadFormDfn (filename, false); } // *************************************************************************** void CFormDfn::CEntry::setDfnPointer () { TypeElement = EntryVirtualDfn; Filename = ""; Type = NULL; Dfn = NULL; } // *************************************************************************** const std::string &CFormDfn::CEntry::getName () const { return Name; } // *************************************************************************** void CFormDfn::CEntry::setName (const char *name) { Name = name; } // *************************************************************************** const std::string &CFormDfn::CEntry::getDefault () const { return Default; } // *************************************************************************** void CFormDfn::CEntry::setDefault (const char *def) { Default = def; } // *************************************************************************** void CFormDfn::CEntry::setArrayFlag (bool flag) { Array = flag; } // *************************************************************************** bool CFormDfn::CEntry::getArrayFlag () const { return Array; } // *************************************************************************** UFormDfn::TEntryType CFormDfn::CEntry::getType () const { return TypeElement; } // *************************************************************************** const std::string &CFormDfn::CEntry::getFilename() const { return Filename; } // *************************************************************************** void CFormDfn::CEntry::setFilename (const char *def) { Filename = def; } // *************************************************************************** CType *CFormDfn::CEntry::getTypePtr () { return Type; } // *************************************************************************** CFormDfn *CFormDfn::CEntry::getDfnPtr () { return Dfn; } // *************************************************************************** const CType *CFormDfn::CEntry::getTypePtr () const { return Type; } // *************************************************************************** const CFormDfn *CFormDfn::CEntry::getDfnPtr () const { return Dfn; } // *************************************************************************** CFormDfn *CFormDfn::getSubDfn (uint index, uint &dfnIndex) { // Get the sub DFN vector parentDfn; parentDfn.reserve (countParentDfn ()); getParentDfn (parentDfn); // For each parent uint dfn; dfnIndex = index; uint parentSize = parentDfn.size(); for (dfn=0; dfnEntries.size (); if (dfnIndex parentDfn; parentDfn.reserve (countParentDfn ()); getParentDfn (parentDfn); // For each parent uint dfn; dfnIndex = index; uint parentSize = parentDfn.size(); for (dfn=0; dfnEntries.size (); if (dfnIndex=0) { CEntry *entryPtr=&Entries[entryIndex]; if (entryPtr->getName()==name) { *entry=entryPtr; return true; } entryIndex--; } *entry=NULL; return false; } bool CFormDfn::getEntryDfnByName (const std::string &name, UFormDfn **dfn) { CFormDfn::CEntry *entry; if (getEntryByName (name, &entry)) { *dfn=entry->getDfnPtr(); return true; } *dfn=NULL; return false; } bool CFormDfn::isAnArrayEntryByName (const std::string &name) const { CFormDfn::CEntry *entry; if (const_cast(this)->getEntryByName (name, &entry)) { return entry->getArrayFlag(); } return false; } // *************************************************************************** bool CFormDfn::getEntryType (uint entry, UType **type) { if (entry < Entries.size ()) { if (Entries[entry].TypeElement == EntryType) { *type = Entries[entry].Type; return true; } else warning (false, "getEntryType", "This entry is not a type."); } warning (false, "getEntryType", "Wrong entry ID."); return false; } // *************************************************************************** uint CFormDfn::getNumParents () const { return Parents.size (); } // *************************************************************************** bool CFormDfn::getParent (uint parent, UFormDfn **parentRet) { if (parent < Parents.size ()) { *parentRet = Parents[parent].Parent; return true; } warning (false, "getParent", "Wrong parent ID."); return false; } // *************************************************************************** bool CFormDfn::getParentFilename (uint parent, std::string &filename) const { if (parent < Parents.size ()) { filename = Parents[parent].ParentFilename; return true; } warning (false, "getParentFilename", "Wrong parent ID."); return false; } // *************************************************************************** const std::string& CFormDfn::getComment () const { return Header.Comments; } // *************************************************************************** const std::string &CFormDfn::CEntry::getFilenameExt() const { return FilenameExt; } // *************************************************************************** void CFormDfn::CEntry::setFilenameExt (const char *ext) { FilenameExt = ext; } // *************************************************************************** void CFormDfn::warning (bool exception, const char *function, const char *format, ... ) const { // Make a buffer string va_list args; va_start( args, format ); char buffer[1024]; vsnprintf( buffer, 1024, format, args ); va_end( args ); // Set the warning NLGEORGES::warning (exception, "(CFormDfn::%s) in form DFN (%s) : %s", function, _Filename.c_str (), buffer); } // *************************************************************************** void CFormDfn::getDependencies (std::set &dependencies) const { // Scan only if not already inserted if (dependencies.insert (toLower(CFile::getFilename (_Filename))).second) { // Add parents uint i; for (i=0; igetDependencies (dependencies); } // Add entries for (i=0; igetDependencies (dependencies); if (Entries[i].getTypePtr ()) { dependencies.insert (toLower(CFile::getFilename (Entries[i].getFilename()))); } } } } // *************************************************************************** } // NLGEORGES