// 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 . #ifndef NL_FORM_ELM_H #define NL_FORM_ELM_H #include "nel/georges/u_form_elm.h" #include "nel/misc/smart_ptr.h" #include "nel/misc/rgba.h" #include "form_dfn.h" #define NLGEORGES_FIRST_ROUND 0 #define NLGEORGES_MAX_RECURSION 100 namespace NLGEORGES { class CType; class CFormDfn; class CForm; /** * Base class of form elements */ class CFormElm : public UFormElm { friend class CForm; friend class CType; friend class CFormDfn; public: // Contructor CFormElm (CForm *form, CFormElm *parentNode, const CFormDfn *parentDfn, uint parentIndex); // Destructor virtual ~CFormElm (); /// Reset contents virtual void clean() {} // Get the form pointer CForm *getForm () const; // Is the element used by this form ? virtual bool isUsed (const CForm *form) const; // Get the form name of the element virtual void getFormName (std::string &result, const CFormElm *child=NULL) const = 0; // From UFormElm virtual bool getNodeByName (const UFormElm **result, const char *name, TWhereIsNode *where, bool verbose, uint32 round=0) const; virtual bool getNodeByName (UFormElm **result, const char *name, TWhereIsNode *where, bool verbose, uint32 round=0); virtual bool getValueByName (std::string &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool getValueByName (sint8 &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool getValueByName (uint8 &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool getValueByName (sint16 &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool getValueByName (uint16 &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool getValueByName (sint32 &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool getValueByName (uint32 &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool getValueByName (float &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool getValueByName (double &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool getValueByName (bool &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool getValueByName (NLMISC::CRGBA &result, const char *name, TEval evaluate, TWhereIsValue *where, uint32 round=0) const; virtual bool setValueByName (const char *value, const char *name, bool *created); virtual bool setValueByName (sint8 value, const char *name, bool *created); virtual bool setValueByName (uint8 value, const char *name, bool *created); virtual bool setValueByName (sint16 value, const char *name, bool *created); virtual bool setValueByName (uint16 value, const char *name, bool *created); virtual bool setValueByName (sint32 value, const char *name, bool *created); virtual bool setValueByName (uint32 value, const char *name, bool *created); virtual bool setValueByName (float value, const char *name, bool *created); virtual bool setValueByName (double value, const char *name, bool *created); virtual bool setValueByName (bool value, const char *name, bool *created); virtual bool setValueByName (NLMISC::CRGBA value, const char *name, bool *created); virtual UFormElm *getParent () const; virtual const CType *getType (); virtual bool isArray () const; virtual bool getArraySize (uint &size) const; virtual bool getArrayNode (const UFormElm **result, uint arrayIndex) const; virtual bool getArrayNode (UFormElm **result, uint arrayIndex); virtual bool getArrayNodeName (std::string &result, uint arrayIndex) const; virtual bool getArrayValue (std::string &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool getArrayValue (sint8 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool getArrayValue (uint8 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool getArrayValue (sint16 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool getArrayValue (uint16 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool getArrayValue (sint32 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool getArrayValue (uint32 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool getArrayValue (float &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool getArrayValue (double &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool getArrayValue (bool &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool getArrayValue (NLMISC::CRGBA &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; virtual bool isStruct () const; virtual bool isVirtualStruct () const; virtual bool getDfnName (std::string &dfnName ) const; virtual bool getStructSize (uint &size) const; virtual bool getStructNodeName (uint element, std::string &result) const; virtual bool getStructNode (uint element, const UFormElm **result) const; virtual bool getStructNode (uint element, UFormElm **result); virtual bool isAtom () const; virtual bool getValue (std::string &resultname, TEval evaluate) const; virtual bool getValue (sint8 &resultname, TEval evaluate) const; virtual bool getValue (uint8 &resultname, TEval evaluate) const; virtual bool getValue (sint16 &resultname, TEval evaluate) const; virtual bool getValue (uint16 &resultname, TEval evaluate) const; virtual bool getValue (sint32 &resultname, TEval evaluate) const; virtual bool getValue (uint32 &resultname, TEval evaluate) const; virtual bool getValue (float &resultname, TEval evaluate) const; virtual bool getValue (double &resultname, TEval evaluate) const; virtual bool getValue (bool &resultname, TEval evaluate) const; virtual bool getValue (NLMISC::CRGBA &resultname, TEval evaluate) const; virtual UFormDfn *getStructDfn () { return NULL; } // ** Convert functions inline bool convertValue (sint8 &result, const char *value) const; inline bool convertValue (uint8 &result, const char *value) const; inline bool convertValue (sint16 &result, const char *value) const; inline bool convertValue (uint16 &result, const char *value) const; inline bool convertValue (sint32 &result, const char *value) const; inline bool convertValue (uint32 &result, const char *value) const; inline bool convertValue (float &result, const char *value) const; inline bool convertValue (double &result, const char *value) const; inline bool convertValue (bool &result, const char *value) const; inline bool convertValue (NLMISC::CRGBA &result, const char *value) const; // ** Get dependencies virtual void getDependencies (std::set &dependencies) const = 0; // ** Internal node access // Create a node by name. If the node already exists, return it bool createNodeByName (const char *name, const CFormDfn **parentDfn, uint &indexDfn, const CFormDfn **nodeDfn, const CType **nodeType, CFormElm **node, UFormDfn::TEntryType &type, bool &array, bool &created); /** * Delete a node by name. If the node already exists, return it *Delete its parent if not used */ bool deleteNodeByName (const char *name, const CFormDfn **parentDfn, uint &indexDfn, const CFormDfn **nodeDfn, const CType **nodeType, CFormElm **node, UFormDfn::TEntryType &type, bool &array); // Search for a node by name bool getNodeByName (const char *name, const CFormDfn **parentDfn, uint &indexDfn, const CFormDfn **nodeDfn, const CType **nodeType, CFormElm **node, UFormDfn::TEntryType &type, bool &array, bool &parentVDfnArray, bool verbose, uint32 round) const; /** * Insert an array node by name * The index asked must be < the size of the array. */ bool arrayInsertNodeByName (const char *name, const CFormDfn **parentDfn, uint &indexDfn, const CFormDfn **nodeDfn, const CType **nodeType, CFormElm **node, UFormDfn::TEntryType &type, bool &array, bool verbose, uint arrayIndex) const; /** * Delete an array node by name * The index asked must be < the size of the array. */ bool arrayDeleteNodeByName (const char *name, const CFormDfn **parentDfn, uint &indexDfn, const CFormDfn **nodeDfn, const CType **nodeType, CFormElm **node, UFormDfn::TEntryType &type, bool &array, bool verbose, uint arrayIndex) const; protected: // Action to perform enum TNodeAction { Return, Create, Delete, }; /** * Is createNode == Create, (*node)->Form must be == to the form argument. * Is createNode == Return, form argument is not used, can be undefined. * * Only form, name, and action, must be defined. * Then, else (*parentDfn / indexDfn ) or *node must be defined. * Other values are for result only. */ static bool getInternalNodeByName (CForm *form, const char *name, const CFormDfn **parentDfn, uint &indexDfn, const CFormDfn **nodeDfn, const CType **nodeType, CFormElm **node, UFormDfn::TEntryType &type, bool &array, TNodeAction action, bool &created, bool &parentVDfnArray, bool verbose, uint32 round); /** * Unlink a child */ virtual void unlink (CFormElm *child); public: // Get next token, return NULL if last token static const char* tokenize (const char *name, std::string &str, uint &errorIndex, uint &code); // ** IO functions virtual xmlNodePtr write (xmlNodePtr node, const CForm *form, const char *structName = NULL, bool forceWrite = false) const = 0; protected: // The form of this node CForm *Form; // The parent node of this node CFormElm *ParentNode; // The parent DFN of this node const CFormDfn *ParentDfn; // The index in the parent DFN for this node uint ParentIndex; // Recurce Tag uint32 Round; // Error handling static void warning (bool exception, const char *formName, const char *formFileName, const char *function, const char *format, ... ); virtual void warning (bool exception, const char *function, const char *format, ... ) const; private: // Tokens enum TToken { TokenString = 0, TokenPoint, TokenArrayBegin, TokenArrayEnd, }; }; /** * Define a structure of elements * * This structure has pointers on named sub structures in Elements. * If a sub structure is empty, its pointer is NULL. */ class CFormElmStruct : public CFormElm { public: // Default constructor CFormElmStruct (CForm *form, CFormElm *parentNode, const CFormDfn *parentDfn, uint parentIndex); virtual ~CFormElmStruct (); // Clear sub elements void clean (); // Smart pointer on the form definition for this structure NLMISC::CSmartPtr FormDfn; // Pointer on the parent element //CFormElmStruct *Parent; // A struct element class CFormElmStructElm { public: CFormElmStructElm () { Element = NULL; } std::string Name; CFormElm* Element; }; // Build form a DFN void build (const CFormDfn *dfn); // From UFormElm bool isStruct () const; bool getStructSize (uint &size) const; bool getStructNodeName (uint element, std::string &result) const; bool getStructNode (uint element, const UFormElm **result) const; bool getStructNode (uint element, UFormElm **result); UFormDfn *getStructDfn (); // From CFormElm bool isUsed (const CForm *form) const; xmlNodePtr write (xmlNodePtr node, const CForm *form, const char *structName, bool forceWrite = false) const; void unlink (CFormElm *child); void getFormName (std::string &result, const CFormElm *child) const; void getDependencies (std::set &dependencies) const; // Call by CFormLoader void read (xmlNodePtr node, CFormLoader &loader, const CFormDfn *dfn, CForm *form); // Sub Elements std::vector Elements; // Error handling virtual void warning (bool exception, const char *function, const char *format, ... ) const; }; /** * Define an array of elements */ class CFormElmVirtualStruct : public CFormElmStruct { public: CFormElmVirtualStruct (CForm *form, CFormElm *parentNode, const CFormDfn *parentDfn, uint parentIndex); virtual ~CFormElmVirtualStruct() { } // The Dfn filename used by this struct std::string DfnFilename; // From UFormElm bool isVirtualStruct () const; bool getDfnName (std::string &dfnName ) const; // From CFormElm bool isUsed (const CForm *form) const; xmlNodePtr write (xmlNodePtr node, const CForm *form, const char *structName, bool forceWrite = false) const; // Call by CFormLoader void read (xmlNodePtr node, CFormLoader &loader, CForm *form); // Error handling virtual void warning (bool exception, const char *function, const char *format, ... ) const; }; /** * Define an array of elements */ class CFormElmArray : public CFormElm { public: // Default constructor CFormElmArray (CForm *form, const CFormDfn *formDfn, const CType *type, CFormElm *parentNode, const CFormDfn *parentDfn, uint parentIndex); virtual ~CFormElmArray (); void clean (); // Smart pointer on the form definition for this structure NLMISC::CSmartPtr FormDfn; // Pointer on the type (the smart pointer in hold by CFormDfn) const CType *Type; // From UFormElm bool isArray () const; bool getArraySize (uint &size) const; bool getArrayNode (const UFormElm **result, uint arrayIndex) const; bool getArrayNode (UFormElm **result, uint arrayIndex); bool getArrayNodeName (std::string &result, uint arrayIndex) const; bool getArrayValue (std::string &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; bool getArrayValue (sint8 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; bool getArrayValue (uint8 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; bool getArrayValue (sint16 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; bool getArrayValue (uint16 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; bool getArrayValue (sint32 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; bool getArrayValue (uint32 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; bool getArrayValue (float &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; bool getArrayValue (double &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; bool getArrayValue (bool &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; bool getArrayValue (NLMISC::CRGBA &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const; // From CFormElm xmlNodePtr write (xmlNodePtr node, const CForm *form, const char *structName, bool forceWrite = false) const; bool setParent (CFormElm *parent); void unlink (CFormElm *child); bool isUsed (const CForm *form) const; void getFormName (std::string &result, const CFormElm *child) const; void getDependencies (std::set &dependencies) const; // Call by CFormLoader // Read an array void read (xmlNodePtr node, CFormLoader &loader, CForm *form); // A struct element class CElement { public: CElement () { Element = NULL; } std::string Name; CFormElm* Element; }; // Array of elements std::vector Elements; // Error handling virtual void warning (bool exception, const char *function, const char *format, ... ) const; }; /** * Signed integer element */ class CFormElmAtom : public CFormElm { friend class CForm; friend class CFormElm; friend class CType; public: // Default constructor CFormElmAtom (CForm *form, CFormElm *parentNode, const CFormDfn *parentDfn, uint parentIndex); virtual ~CFormElmAtom() { } // Pointer on the parent element //CFormElmAtom *Parent; // Pointer on the type (the smart pointer in hold by CFormDfn) const CType *Type; // From CFormElm xmlNodePtr write (xmlNodePtr node, const CForm *form, const char *structName, bool forceWrite = false) const; bool setParent (CFormElm *parent); void getFormName (std::string &result, const CFormElm *child) const; void getDependencies (std::set &dependencies) const; const CType* getType (); // Call by CFormLoader void read (xmlNodePtr node, CFormLoader &loader, const CType *type, CForm *form); // From UFormElm bool isAtom () const; bool getValue (std::string &resultname, TEval evaluate) const; bool getValue (sint8 &resultname, TEval evaluate) const; bool getValue (uint8 &resultname, TEval evaluate) const; bool getValue (sint16 &resultname, TEval evaluate) const; bool getValue (uint16 &resultname, TEval evaluate) const; bool getValue (sint32 &resultname, TEval evaluate) const; bool getValue (uint32 &resultname, TEval evaluate) const; bool getValue (float &resultname, TEval evaluate) const; bool getValue (double &resultname, TEval evaluate) const; bool getValue (bool &resultname, TEval evaluate) const; bool getValue (NLMISC::CRGBA &resultname, TEval evaluate) const; // Set the value, the elt been used void setValue (const char *value); private: // The value std::string Value; // Error handling virtual void warning (bool exception, const char *function, const char *format, ... ) const; }; // *************************************************************************** // CFormElm inlines // *************************************************************************** inline bool CFormElm::convertValue (sint8 &result, const char *value) const { float tmp; if (NLMISC::fromString(value, tmp)) { NLMISC::clamp (tmp, -128.f, 127.f); result = (sint8)tmp; return true; } else { // Error message warning (false, "convertValue", "Can't convert the string \"%s\" in sint8.", value); } return false; } // *************************************************************************** inline bool CFormElm::convertValue (uint8 &result, const char *value) const { float tmp; if (NLMISC::fromString(value, tmp)) { NLMISC::clamp (tmp, 0.f, 255.f); result = (uint8)tmp; return true; } else { // Error message warning (false, "convertValue", "Can't convert the string \"%s\" in uint8.", value); } return false; } // *************************************************************************** inline bool CFormElm::convertValue (sint16 &result, const char *value) const { float tmp; if (NLMISC::fromString(value, tmp)) { NLMISC::clamp (tmp, -32768.f, 32767.f); result = (sint16)tmp; return true; } else { // Error message warning (false, "convertValue", "Can't convert the string \"%s\" in sint16.", value); } return false; } // *************************************************************************** inline bool CFormElm::convertValue (uint16 &result, const char *value) const { float tmp; if (NLMISC::fromString(value, tmp)) { NLMISC::clamp (tmp, 0.f, 65535.f); result = (uint16)tmp; return true; } else { // Error message warning (false, "convertValue", "Can't convert the string \"%s\" in uint16.", value); } return false; } // *************************************************************************** inline bool CFormElm::convertValue (sint32 &result, const char *value) const { float tmp; if (NLMISC::fromString(value, tmp)) { NLMISC::clamp (tmp, -2147483648.f, 2147483647.f); result = (sint32)tmp; return true; } else { // Error message warning (false, "convertValue", "Can't convert the string \"%s\" in sint32.", value); } return false; } // *************************************************************************** inline bool CFormElm::convertValue (uint32 &result, const char *value) const { float tmp; if (NLMISC::fromString(value, tmp)) { NLMISC::clamp (tmp, 0.f, 4294967295.f); result = (sint32)tmp; return true; } else { // Error message warning (false, "convertValue", "Can't convert the string \"%s\" in uint32.", value); } return false; } // *************************************************************************** inline bool CFormElm::convertValue (float &result, const char *value) const { if (NLMISC::fromString(value, result)) { return true; } else { // Error message warning (false, "convertValue", "Can't convert the string \"%s\" in float.", value); } return false; } // *************************************************************************** inline bool CFormElm::convertValue (double &result, const char *value) const { float tmp; if (NLMISC::fromString(value, tmp)) { result = tmp; return true; } else { // Error message warning (false, "convertValue", "Can't convert the string \"%s\" in double.", value); } return false; } // *************************************************************************** inline bool CFormElm::convertValue (bool &result, const char *value) const { int tmp; if (NLMISC::fromString(value, tmp)) { result = tmp != 0; return true; } else { std::string temp = NLMISC::toLower(std::string(value)); if (strcmp (temp.c_str (), "true") == 0) { result = true; return true; } if (strcmp (temp.c_str (), "false") == 0) { result = false; return true; } } // Error message warning (false, "convertValue", "Can't convert the string \"%s\" in boolean.", value); return false; } // *************************************************************************** inline bool CFormElm::convertValue (NLMISC::CRGBA &result, const char *value) const { float r, g, b; if (sscanf (value, "%f,%f,%f", &r, &g, &b) == 3) { NLMISC::clamp (r, 0.f, 255.f); NLMISC::clamp (g, 0.f, 255.f); NLMISC::clamp (b, 0.f, 255.f); result.R = (uint8)r; result.G = (uint8)g; result.B = (uint8)b; return true; } // Error message warning (false, "convertValue", "Can't convert the string \"%s\" in RGB color.", value); return false; } // *************************************************************************** } // NLGEORGES #endif // NL_FORM_ELM_H