Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / nel / src / georges / form_elm.cpp
blob3dac9b5a0d3d707426d0c439a62c6c2e5401eb8b
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "stdgeorges.h"
24 #include "nel/misc/o_xml.h"
25 #include "nel/misc/i_xml.h"
27 #include "nel/georges/form.h"
28 #include "nel/georges/form_elm.h"
29 #include "nel/georges/form_loader.h"
30 #include "nel/georges/type.h"
32 #ifdef DEBUG_NEW
33 #define new DEBUG_NEW
34 #endif
36 using namespace NLMISC;
37 using namespace std;
39 namespace NLGEORGES
42 // ***************************************************************************
43 // class CFormElm
44 // ***************************************************************************
46 // ***************************************************************************
48 void warning (bool exception, const char *format, ... );
50 // ***************************************************************************
52 bool CFormElm::isArray () const
54 return false;
57 // ***************************************************************************
59 bool CFormElm::getArraySize (uint &/* size */) const
61 warning (false, "getArraySize", "This node is not an array.");
62 return false;
65 // ***************************************************************************
67 bool CFormElm::getArrayNode (const UFormElm ** /* result */, uint /* arrayIndex */) const
69 warning (false, "getArrayNode", "This node is not an array.");
70 return false;
73 // ***************************************************************************
75 bool CFormElm::getArrayNode (UFormElm ** /* result */, uint /* arrayIndex */)
77 warning (false, "getArrayNode", "This node is not an array.");
78 return false;
81 // ***************************************************************************
83 bool CFormElm::getArrayNodeName (std::string &/* result */, uint /* arrayIndex */) const
85 warning (false, "getArrayNodeName", "This node is not an array.");
86 return false;
89 // ***************************************************************************
91 bool CFormElm::getArrayValue (std::string &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
93 warning (false, "getArrayNode", "This node is not an array.");
94 return false;
97 // ***************************************************************************
99 bool CFormElm::getArrayValue (sint8 &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
101 warning (false, "getArrayValue", "This node is not an array.");
102 return false;
105 // ***************************************************************************
107 bool CFormElm::getArrayValue (uint8 &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
109 warning (false, "getArrayValue", "This node is not an array.");
110 return false;
113 // ***************************************************************************
115 bool CFormElm::getArrayValue (sint16 &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
117 warning (false, "getArrayValue", "This node is not an array.");
118 return false;
121 // ***************************************************************************
123 bool CFormElm::getArrayValue (uint16 &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
125 warning (false, "getArrayValue", "This node is not an array.");
126 return false;
129 // ***************************************************************************
131 bool CFormElm::getArrayValue (sint32 &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
133 warning (false, "getArrayValue", "This node is not an array.");
134 return false;
137 // ***************************************************************************
139 bool CFormElm::getArrayValue (uint32 &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
141 warning (false, "getArrayValue", "This node is not an array.");
142 return false;
145 // ***************************************************************************
147 bool CFormElm::getArrayValue (float &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
149 warning (false, "getArrayValue", "This node is not an array.");
150 return false;
153 // ***************************************************************************
155 bool CFormElm::getArrayValue (double &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
157 warning (false, "getArrayValue", "This node is not an array.");
158 return false;
161 // ***************************************************************************
163 bool CFormElm::getArrayValue (bool &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
165 warning (false, "getArrayValue", "This node is not an array.");
166 return false;
169 // ***************************************************************************
171 bool CFormElm::getArrayValue (NLMISC::CRGBA &/* result */, uint /* arrayIndex */, TEval /* evaluate */, TWhereIsValue * /* where */) const
173 warning (false, "getArrayValue", "This node is not an array.");
174 return false;
177 // ***************************************************************************
179 bool CFormElm::isStruct () const
181 return false;
184 // ***************************************************************************
186 bool CFormElm::isVirtualStruct () const
188 return false;
191 // ***************************************************************************
193 bool CFormElm::getDfnName (std::string &/* dfnName */ ) const
195 return false;
198 // ***************************************************************************
200 bool CFormElm::getStructSize (uint &/* size */) const
202 warning (false, "getStructSize", "This node is not a struct.");
203 return false;
206 // ***************************************************************************
208 bool CFormElm::getStructNodeName (uint /* element */, string &/* result */) const
210 warning (false, "getStructNodeName", "This node is not a struct.");
211 return false;
214 // ***************************************************************************
216 bool CFormElm::getStructNode (uint /* element */, const UFormElm ** /* result */) const
218 warning (false, "getStructNode", "This node is not a struct.");
219 return false;
222 // ***************************************************************************
224 bool CFormElm::getStructNode (uint /* element */, UFormElm ** /* result */)
226 warning (false, "getStructNode", "This node is not a struct.");
227 return false;
230 // ***************************************************************************
232 bool CFormElm::isAtom () const
234 return false;
237 // ***************************************************************************
239 const CType* CFormElm::getType ()
241 warning (false, "getType", "This node is not an atom.");
242 return NULL;
245 // ***************************************************************************
247 bool CFormElm::getValue (string &/* result */, TEval /* evaluate */) const
249 warning (false, "getValue", "This node is not an atom.");
250 return false;
253 // ***************************************************************************
255 bool CFormElm::getValue (sint8 &/* result */, TEval /* evaluate */) const
257 warning (false, "getValue", "This node is not an atom.");
258 return false;
261 // ***************************************************************************
263 bool CFormElm::getValue (uint8 &/* result */, TEval /* evaluate */) const
265 warning (false, "getValue", "This node is not an atom.");
266 return false;
269 // ***************************************************************************
271 bool CFormElm::getValue (sint16 &/* result */, TEval /* evaluate */) const
273 warning (false, "getValue", "This node is not an atom.");
274 return false;
277 // ***************************************************************************
279 bool CFormElm::getValue (uint16 &/* result */, TEval /* evaluate */) const
281 warning (false, "getValue", "This node is not an atom.");
282 return false;
285 // ***************************************************************************
287 bool CFormElm::getValue (sint32 &/* result */, TEval /* evaluate */) const
289 warning (false, "getValue", "This node is not an atom.");
290 return false;
293 // ***************************************************************************
295 bool CFormElm::getValue (uint32 &/* result */, TEval /* evaluate */) const
297 warning (false, "getValue", "This node is not an atom.");
298 return false;
301 // ***************************************************************************
303 bool CFormElm::getValue (float &/* result */, TEval /* evaluate */) const
305 warning (false, "getValue", "This node is not an atom.");
306 return false;
309 // ***************************************************************************
311 bool CFormElm::getValue (double &/* result */, TEval /* evaluate */) const
313 warning (false, "getValue", "This node is not an atom.");
314 return false;
317 // ***************************************************************************
319 bool CFormElm::getValue (bool &/* result */, TEval /* evaluate */) const
321 warning (false, "getValue", "This node is not an atom.");
322 return false;
325 // ***************************************************************************
327 bool CFormElm::getValue (NLMISC::CRGBA &/* result */, TEval /* evaluate */) const
329 warning (false, "getValue", "This node is not an atom.");
330 return false;
333 // ***************************************************************************
335 CFormElm::CFormElm (CForm *form, CFormElm *parentNode, const CFormDfn *parentDfn, uint parentIndex)
337 Form = form;
338 ParentNode = parentNode;
339 ParentDfn = parentDfn;
340 ParentIndex = parentIndex;
341 Round = 0xffffffff;
344 // ***************************************************************************
346 CFormElm::~CFormElm ()
348 clean(); // it's virtual
351 // ***************************************************************************
353 bool CFormElm::isUsed (const CForm *form) const
355 return form == Form;
358 // ***************************************************************************
360 CForm *CFormElm::getForm () const
362 return Form;
365 // ***************************************************************************
367 bool CFormElm::getNodeByName (UFormElm **result, const std::string &name, TWhereIsNode *where, bool verbose, uint32 round)
369 const UFormElm *resultConst = NULL;
370 if (((const UFormElm*)this)->getNodeByName (&resultConst, name, where, verbose, round))
372 *result = const_cast<UFormElm*> (resultConst);
373 return true;
375 return false;
378 // ***************************************************************************
380 bool CFormElm::getNodeByName (const UFormElm **result, const std::string &name, TWhereIsNode *where, bool verbose, uint32 round) const
382 // The parent Dfn
383 const CFormDfn *parentDfn;
384 const CFormDfn *nodeDfn;
385 const CType *nodeType;
386 CFormElm *node;
387 uint indexDfn;
388 bool array;
389 bool parentVDfnArray;
390 UFormDfn::TEntryType type;
392 // Search for the node
393 if (getNodeByName (name, &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, array, parentVDfnArray, verbose, round))
395 // Set the result
396 *result = node;
398 // Where ?
399 if (where && node)
401 *where = (node->getForm () == Form) ? NodeForm : NodeParentForm;
404 // Ok
405 return true;
408 return false;
411 // ***************************************************************************
413 bool CFormElm::getValueByName (string& result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
415 // The parent Dfn
416 const CFormDfn *parentDfn;
417 const CFormDfn *nodeDfn;
418 const CType *nodeType;
419 CFormElm *node;
420 uint parentIndex;
421 bool array;
422 bool parentVDfnArray;
423 UFormDfn::TEntryType type;
425 // Search for the node
426 if (getNodeByName (name, &parentDfn, parentIndex, &nodeDfn, &nodeType, &node, type, array, parentVDfnArray, true, round))
428 // End, return the current index
429 if (type == UFormDfn::EntryType)
431 // The atom
432 const CFormElmAtom *atom = node ? safe_cast<const CFormElmAtom*> (node) : NULL;
434 // Evale
435 nlassert (nodeType);
436 return (nodeType->getValue (result, Form, atom, *parentDfn, parentIndex, evaluate, (uint32*)where, round, name));
438 else
440 // Error message
441 warning (false, "getValueByName", "The node (%s) is not an atom element. Can't return a value.", name.c_str());
444 else
446 // Error message
447 warning (false, "getValueByName", "Can't find the node (%s).", name.c_str());
450 // Error
451 return false;
454 // ***************************************************************************
456 bool CFormElm::getValueByName (sint8 &result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
458 // Get the string value
459 string value;
460 if (getValueByName (value, name, evaluate, where, round))
462 return convertValue (result, value);
465 return false;
468 // ***************************************************************************
470 bool CFormElm::getValueByName (uint8 &result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
472 // Get the string value
473 string value;
474 if (getValueByName (value, name, evaluate, where, round))
476 return convertValue (result, value);
479 return false;
482 // ***************************************************************************
484 bool CFormElm::getValueByName (sint16 &result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
486 // Get the string value
487 string value;
488 if (getValueByName (value, name, evaluate, where, round))
490 return convertValue (result, value);
493 return false;
496 // ***************************************************************************
498 bool CFormElm::getValueByName (uint16 &result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
500 // Get the string value
501 string value;
502 if (getValueByName (value, name, evaluate, where, round))
504 return convertValue (result, value);
507 return false;
510 // ***************************************************************************
512 bool CFormElm::getValueByName (sint32 &result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
514 // Get the string value
515 string value;
516 if (getValueByName (value, name, evaluate, where, round))
518 return convertValue (result, value);
521 return false;
524 // ***************************************************************************
526 bool CFormElm::getValueByName (uint32 &result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
528 // Get the string value
529 string value;
530 if (getValueByName (value, name, evaluate, where, round))
532 return convertValue (result, value);
535 return false;
538 // ***************************************************************************
540 bool CFormElm::getValueByName (float &result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
542 // Get the string value
543 string value;
544 if (getValueByName (value, name, evaluate, where, round))
546 return convertValue (result, value);
549 return false;
552 // ***************************************************************************
554 bool CFormElm::getValueByName(double &result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
556 // Get the string value
557 string value;
558 if (getValueByName (value, name, evaluate, where, round))
560 return convertValue (result, value);
563 return false;
566 // ***************************************************************************
568 bool CFormElm::getValueByName (bool &result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
570 // Get the string value
571 string value;
572 if (getValueByName (value, name, evaluate, where, round))
574 return convertValue (result, value);
577 return false;
580 // ***************************************************************************
582 bool CFormElm::getValueByName (NLMISC::CRGBA &result, const std::string &name, TEval evaluate, TWhereIsValue *where, uint32 round) const
584 // Get the string value
585 string value;
586 if (getValueByName (value, name, evaluate, where, round))
588 return convertValue (result, value);
591 return false;
594 // ***************************************************************************
596 UFormElm *CFormElm::getParent () const
598 return ParentNode;
601 // ***************************************************************************
603 bool CFormElm::createNodeByName (const std::string &name, const CFormDfn **parentDfn, uint &indexDfn,
604 const CFormDfn **nodeDfn, const CType **nodeType,
605 CFormElm **node, UFormDfn::TEntryType &type,
606 bool &array, bool &created)
608 *parentDfn = ParentDfn;
609 indexDfn = ParentIndex;
610 *nodeDfn = NULL;
611 *nodeType = NULL;
612 *node = this;
613 bool parentVDfnArray;
614 return getInternalNodeByName (Form, name, parentDfn, indexDfn, nodeDfn, nodeType, node, type, array, Create, created, parentVDfnArray, true, NLGEORGES_FIRST_ROUND);
617 // ***************************************************************************
619 bool CFormElm::deleteNodeByName (const std::string &name, const CFormDfn **parentDfn, uint &indexDfn,
620 const CFormDfn **nodeDfn, const CType **nodeType,
621 CFormElm **node, UFormDfn::TEntryType &type,
622 bool &array)
624 *parentDfn = ParentDfn;
625 indexDfn = ParentIndex;
626 *nodeDfn = NULL;
627 *nodeType = NULL;
628 *node = this;
629 bool created;
630 bool parentVDfnArray;
631 return getInternalNodeByName (Form, name, parentDfn, indexDfn, nodeDfn, nodeType, node, type, array, Delete, created, parentVDfnArray, true, NLGEORGES_FIRST_ROUND);
634 // ***************************************************************************
636 bool CFormElm::getNodeByName (const std::string &name, const CFormDfn **parentDfn, uint &indexDfn,
637 const CFormDfn **nodeDfn, const CType **nodeType,
638 CFormElm **node, UFormDfn::TEntryType &type,
639 bool &array, bool &parentVDfnArray, bool verbose, uint32 round) const
641 *parentDfn = ParentDfn;
642 indexDfn = ParentIndex;
643 *nodeDfn = NULL;
644 *nodeType = NULL;
645 *node = (CFormElm*)this;
646 bool created;
647 return getInternalNodeByName (Form, name, parentDfn, indexDfn, nodeDfn, nodeType, node, type, array, Return, created, parentVDfnArray, verbose, round);
650 // ***************************************************************************
652 bool CFormElm::arrayInsertNodeByName (const std::string &name, const CFormDfn **parentDfn, uint &indexDfn,
653 const CFormDfn **nodeDfn, const CType **nodeType,
654 CFormElm **node, UFormDfn::TEntryType &type,
655 bool &array, bool verbose, uint arrayIndex) const
657 // Get the node by name
658 *parentDfn = ParentDfn;
659 indexDfn = ParentIndex;
660 *nodeDfn = NULL;
661 *nodeType = NULL;
662 *node = (CFormElm*)this;
663 bool created;
664 bool parentVDfnArray;
665 if (getInternalNodeByName (Form, name, parentDfn, indexDfn, nodeDfn, nodeType, node, type, array, Create, created, parentVDfnArray, verbose, NLGEORGES_FIRST_ROUND))
667 // Must be in the same form
668 nlassert ((*node) && ((*node)->Form == Form));
670 // Get its parent
671 CFormElm *parentNode = (*node)->ParentNode;
672 if (parentNode->isArray ())
674 // Cast pointer
675 CFormElmArray *array = safe_cast<CFormElmArray*>(parentNode);
677 // Valid index ?
678 if (arrayIndex<array->Elements.size ())
680 // Insert the element
681 array->Elements.insert (array->Elements.begin() + arrayIndex, CFormElmArray::CElement());
683 // Create a new element
685 // The new element
686 CFormElm *newelm = NULL;
687 switch (type)
689 case UFormDfn::EntryType:
691 // Create an atom
692 CFormElmAtom *atom = new CFormElmAtom (Form, array, *parentDfn, indexDfn);
693 newelm = atom;
695 break;
696 case UFormDfn::EntryDfn:
698 CFormElmStruct *_struct = new CFormElmStruct (Form, array, *parentDfn, indexDfn);
699 _struct->build (*nodeDfn);
700 newelm = _struct;
702 break;
703 case UFormDfn::EntryVirtualDfn:
704 // todo array of virtual struct
705 //newelm = new CFormElmVirtualStruct (Form, array, *parentDfn, indexDfn);
706 break;
707 default:
708 nlstop;
711 nlassert (newelm);
713 // Set the element pointer
714 array->Elements[arrayIndex].Element = newelm;
716 // Ok
717 return true;
721 return false;
724 // ***************************************************************************
726 bool CFormElm::arrayDeleteNodeByName (const std::string &name, const CFormDfn **parentDfn, uint &indexDfn,
727 const CFormDfn **nodeDfn, const CType **nodeType,
728 CFormElm **node, UFormDfn::TEntryType &type,
729 bool &array, bool verbose, uint arrayIndex) const
731 // Get the node by name
732 *parentDfn = ParentDfn;
733 indexDfn = ParentIndex;
734 *nodeDfn = NULL;
735 *nodeType = NULL;
736 *node = (CFormElm*)this;
737 bool created;
738 bool parentVDfnArray;
739 if (getInternalNodeByName (Form, name, parentDfn, indexDfn, nodeDfn, nodeType, node, type, array, Create, created, parentVDfnArray, verbose, NLGEORGES_FIRST_ROUND))
741 // Must be in the same form
742 nlassert ((*node) && ((*node)->Form == Form));
744 // Get its parent
745 CFormElm *parentNode = (*node)->ParentNode;
746 if (parentNode->isArray ())
748 // Cast pointer
749 CFormElmArray *array = safe_cast<CFormElmArray*>(parentNode);
751 // Valid index ?
752 if (arrayIndex<array->Elements.size ())
754 // Insert the element
755 if (array->Elements[arrayIndex].Element)
756 delete array->Elements[arrayIndex].Element;
758 // Erase the entry
759 array->Elements.erase (array->Elements.begin () + arrayIndex);
761 // Ok
762 return true;
766 return false;
769 // ***************************************************************************
771 bool CFormElm::getInternalNodeByName (CForm *form, const std::string &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)
773 // *** Init output variables
774 created = false;
775 parentVDfnArray = false;
777 // ParentDfn or Node..
778 nlassert ( (*parentDfn) || (*node) );
780 // Error message
781 char error[512];
783 // Parent exist ?
784 if (*parentDfn)
786 // Get the entry
787 const CFormDfn::CEntry &theEntry = (*parentDfn)->getEntry (indexDfn);
789 // Get the type
790 type = theEntry.getType ();
791 *nodeType = theEntry.getTypePtr ();
792 if (type == UFormDfn::EntryVirtualDfn)
794 if (*node)
795 *nodeDfn = safe_cast <CFormElmVirtualStruct*> (*node)->FormDfn;
796 else
797 *nodeDfn = NULL;
799 else
800 *nodeDfn = theEntry.getDfnPtr ();
801 array = theEntry.getArrayFlag ();
803 else if (*node)
805 nlassert (!(*node)->isArray ());
806 indexDfn = 0xffffffff;
807 *nodeType = (*node)->isAtom () ? safe_cast<CFormElmAtom*>(*node)->Type : NULL;
808 *nodeDfn = (*node)->isStruct () ? (const CFormDfn *)(safe_cast<CFormElmStruct*>(*node)->FormDfn) : NULL;
809 type = (*node)->isAtom () ? UFormDfn::EntryType : (*node)->isVirtualStruct () ? UFormDfn::EntryVirtualDfn : UFormDfn::EntryDfn;
810 array = false;
813 // Check node pointer
814 if (action == Create)
816 nlassert (*node);
817 nlassert ((*node)->getForm () == form);
820 // Backup current node
821 CFormElm *backupFirstElm = *node;
823 // *** Parsing variables
825 // Current token start and end
826 const char *startToken = name.c_str();
827 const char *endToken;
829 // Current token start
830 string token;
832 // Current form name
833 string currentName;
834 if (*node)
835 (*node)->getFormName (currentName);
837 // Error
838 uint errorIndex;
840 // Token code
841 uint code;
843 // Are we parsing an array ?
844 bool inArrayIndex = false;
846 // Index in the array
847 uint arrayIndex = 0;
849 // Bool next token must be an array index
850 bool wantArrayIndex = false;
852 // Last struct elm
853 CFormElmStruct *lastStructElm = ((*node)->ParentNode && (*node)->ParentNode->isStruct ()) ? safe_cast<CFormElmStruct*> ((*node)->ParentNode) : NULL;
854 uint lastStructIndex = 0;
855 if (lastStructElm)
857 // Look for node in the parent
858 for (; lastStructIndex<lastStructElm->Elements.size (); lastStructIndex++)
860 // The same node ?
861 if (lastStructElm->Elements[lastStructIndex].Element == (*node))
862 break;
865 // Must have been found
866 nlassert (lastStructIndex<lastStructElm->Elements.size ());
869 // While there is tokens
870 while ((endToken = tokenize (startToken, token, errorIndex, code)))
872 // Ready an array index ?
873 if (!inArrayIndex)
875 // For each code
876 switch (code)
878 case TokenString:
880 // Need an array index array ?
881 if (wantArrayIndex)
883 // Error message
884 smprintf (error, 512, "Token (%s) should be an array index.", token.c_str());
885 goto exit;
888 // Are we a struct ?
889 if ( ((type == UFormDfn::EntryDfn) || (type == UFormDfn::EntryVirtualDfn)) /*&& (!array)*/ )
891 // Check the virtual DFN is not empty..
892 if ( (type == UFormDfn::EntryVirtualDfn) && (*nodeDfn == NULL) )
894 // Is it a parent virtual DFN ?
895 if ( (type == UFormDfn::EntryVirtualDfn) && (*node == NULL) )
896 parentVDfnArray = true;
898 // Create mode ?
899 if (action == Create)
901 // Should have a valid node
902 nlassert (*node && lastStructElm);
904 // Get the current virtual dfn
905 CFormElmVirtualStruct *vStruct = safe_cast<CFormElmVirtualStruct*> (*node);
907 // Get the form name of the current node
908 string formName;
909 vStruct->getFormName (formName, NULL);
911 // Get the parent node if available
912 for (uint parent=0; parent<form->getParentCount (); parent++)
914 // Get the parent
915 CForm *parentPtr = form->getParent (parent);
916 nlassert (parentPtr);
918 // Get the virtual node by name
919 UFormElm *uelm;
920 if (parentPtr->getRootNode ().getNodeByName (&uelm, formName, NULL, verbose, round+1) && uelm)
922 // Value node ?
923 if (uelm->isVirtualStruct ())
925 // Get a virtual struct pointer
926 CFormElmVirtualStruct *vStructParent = safe_cast<CFormElmVirtualStruct*> (uelm);
928 // Copy the DFN filename
929 vStruct->DfnFilename = vStructParent->DfnFilename;
931 // Build it
932 vStruct->build (vStructParent->FormDfn);
934 // Set the current DFN
935 *nodeDfn = vStruct->FormDfn;
937 // Stop looking for parent
938 break;
940 else
942 // Error message
943 smprintf (error, 512, "Internal node parsing error.");
944 goto exit;
950 // Still no DFN ?
951 if (*nodeDfn == NULL)
953 // Error message
954 smprintf (error, 512, "Empty virtual struct element. Can't look into it while it is not defined.");
955 goto exit;
959 // Must have a nodeDfn here
960 nlassert (*nodeDfn);
962 // Look for the element
963 // uint elementCount = (*nodeDfn)->getNumEntry ();
965 // Get the parents
966 vector<const CFormDfn*> arrayDfn;
967 arrayDfn.reserve ((*nodeDfn)->countParentDfn ());
968 (*nodeDfn)->getParentDfn (arrayDfn);
970 // For each parent
971 uint i;
972 uint formElm = 0;
973 for (i=0; i<arrayDfn.size(); i++)
975 // The dfn
976 const CFormDfn &dfn = *(arrayDfn[i]);
978 // For each elements
979 uint element;
980 for (element=0; element<dfn.Entries.size(); element++)
982 // Good name ?
983 if (dfn.Entries[element].Name == token)
985 // Good one.
986 *parentDfn = &dfn;
987 indexDfn = element;
988 *nodeDfn = dfn.Entries[element].Dfn;
989 *nodeType = dfn.Entries[element].Type;
990 type = dfn.Entries[element].TypeElement;
991 array = dfn.Entries[element].Array;
992 wantArrayIndex = array;
994 // Next node
995 if (*node)
997 // Get next node
998 CFormElmStruct *nodeStruct = safe_cast<CFormElmStruct*> (*node);
999 CFormElm *nextElt = nodeStruct->Elements[formElm].Element;
1001 // If no next node, watch for parent node
1002 *node = nextElt;
1004 // Create node
1005 if ( (action == Create) && (*node == NULL) )
1007 // Is an array ?
1008 if (array)
1010 // Create an atom
1011 CFormElmArray *atom = new CFormElmArray (form, *nodeDfn, *nodeType, nodeStruct, *parentDfn, indexDfn);
1012 *node = atom;
1014 else
1016 // What kind of node ?
1017 switch (type)
1019 case UFormDfn::EntryType:
1021 // Create an atom
1022 CFormElmAtom *atom = new CFormElmAtom (form, nodeStruct, *parentDfn, indexDfn);
1023 *node = atom;
1025 break;
1026 case UFormDfn::EntryDfn:
1028 CFormElmStruct *_struct = new CFormElmStruct (form, nodeStruct, *parentDfn, indexDfn);
1029 _struct->build (*nodeDfn);
1030 *node = _struct;
1032 break;
1033 case UFormDfn::EntryVirtualDfn:
1034 *node = new CFormElmVirtualStruct (form, nodeStruct, *parentDfn, indexDfn);
1035 break;
1036 default:
1037 nlstop;
1041 // Node created
1042 created = true;
1044 // Set the node in parent
1045 nodeStruct->Elements[formElm].Element = *node;
1048 // Is a virtual DFN ?
1049 if ((*node) && (*node)->isVirtualStruct ())
1051 // Should be NULL
1052 nlassert (*nodeDfn == NULL);
1054 // Set the current dfn
1055 *nodeDfn = safe_cast<const CFormElmVirtualStruct*> (*node)->FormDfn;
1058 // Save last struct
1059 lastStructElm = nodeStruct;
1060 lastStructIndex = formElm;
1062 else
1064 // Save last struct
1065 // CFormElmStruct *lastStructElm = NULL;
1066 //uint lastStructIndex = 0xffffffff;
1068 *node = NULL;
1071 break;
1073 formElm++;
1076 // Breaked ?
1077 if (element!=dfn.Entries.size())
1078 break;
1081 // Breaked ?
1082 if (i==arrayDfn.size())
1084 // Not found
1085 smprintf (error, 512, "Struct does not contain element named (%s).", token.c_str());
1086 goto exit;
1089 else
1091 // Error message
1092 smprintf (error, 512, "Not a struct element. Can't open the node (%s).", token.c_str());
1093 goto exit;
1096 break;
1097 case TokenPoint:
1099 // Need an array index array ?
1100 if (wantArrayIndex)
1102 // Error message
1103 smprintf (error, 512, "Token (%s) should be an array index.", token.c_str());
1104 goto exit;
1107 // Are we a struct ?
1108 if ((type != UFormDfn::EntryDfn) && (type != UFormDfn::EntryVirtualDfn))
1110 // Error message
1111 smprintf (error, 512, "Not a struct element. Can't open the node (%s).", token.c_str());
1112 goto exit;
1115 break;
1116 case TokenArrayBegin:
1118 // Are we an array ?
1119 if (!array)
1121 // Error message
1122 smprintf (error, 512, "Not an array element. Can't open the node (%s).", token.c_str());
1123 goto exit;
1125 inArrayIndex = true;
1126 arrayIndex = 0xffffffff;
1128 break;
1129 default:
1131 // Error message
1132 smprintf (error, 512, "Syntax error at keyword (%s).", token.c_str ());
1133 goto exit;
1135 break;
1138 else
1140 switch (code)
1142 case TokenString:
1144 // To int
1145 if (!fromString(token, arrayIndex))
1147 // Error message
1148 smprintf (error, 512, "Keyword (%s) is not an array index.", token.c_str());
1149 goto exit;
1152 // Is it a parent virtual DFN ?
1153 if (*node == NULL)
1154 parentVDfnArray = true;
1156 // Should have an array defined
1157 if (*node)
1159 // Check index
1160 uint arraySize;
1161 nlverify ((*node)->getArraySize (arraySize));
1162 if (arrayIndex>=arraySize)
1164 // Create mode ?
1165 if (action == Create)
1167 // Must be in the same form
1168 nlassert ((*node)->Form == form);
1170 // The array pointer
1171 CFormElmArray *array = safe_cast<CFormElmArray*>(*node);
1172 uint oldSize = (uint)array->Elements.size ();
1173 array->Elements.resize (arrayIndex+1);
1175 // Insert empty element
1176 uint i;
1177 for (i=oldSize; i<array->Elements.size (); i++)
1179 // The new element
1180 CFormElm *newelm = NULL;
1181 switch (type)
1183 case UFormDfn::EntryType:
1185 // Create an atom
1186 CFormElmAtom *atom = new CFormElmAtom (form, array, *parentDfn, indexDfn);
1187 newelm = atom;
1189 break;
1190 case UFormDfn::EntryDfn:
1192 CFormElmStruct *_struct = new CFormElmStruct (form, array, *parentDfn, indexDfn);
1193 _struct->build (*nodeDfn);
1194 newelm = _struct;
1196 break;
1197 case UFormDfn::EntryVirtualDfn:
1198 // todo array of virtual struct
1199 //newelm = new CFormElmVirtualStruct (form, array, *parentDfn, indexDfn);
1200 break;
1201 default:
1202 nlstop;
1205 nlassert (newelm);
1207 // Node created
1208 created = true;
1210 // Set the element pointer
1211 array->Elements[i].Element = newelm;
1214 else
1216 // Error message
1217 smprintf (error, 512, "Out of array bounds (%d >= %d).", arrayIndex, arraySize);
1218 goto exit;
1222 else
1224 // Error message
1225 smprintf (error, 512, "Array is not defined.");
1226 goto exit;
1229 break;
1230 case TokenArrayEnd:
1232 // No need of an array index any more
1233 wantArrayIndex = false;
1235 // Index found ?
1236 if (arrayIndex == 0xffffffff)
1238 // Error message
1239 smprintf (error, 512, "Missing array index.");
1241 else
1243 // Let the parent DFN
1244 nlassert (*parentDfn);
1246 // New current node
1247 CFormElmArray *parentNode = safe_cast<CFormElmArray*> (*node);
1249 // Get the element
1250 *node = parentNode->Elements[arrayIndex].Element;
1252 // Is a dfn ?
1253 *nodeDfn = (*parentDfn)->getEntry (indexDfn).getDfnPtr ();
1255 // Is a type ?
1256 *nodeType = (*parentDfn)->getEntry (indexDfn).getTypePtr ();
1258 // Type ?
1259 type = (*parentDfn)->getEntry (indexDfn).getType ();
1261 // Can't be an array of array
1262 array = false;
1264 // Not any more in index
1265 inArrayIndex = false;
1267 // What kind of node ?
1268 if ( (action == Create) && ( *node == NULL) )
1270 switch (type)
1272 case UFormDfn::EntryType:
1274 // Create an atom
1275 CFormElmAtom *atom = new CFormElmAtom (form, parentNode, *parentDfn, indexDfn);
1276 *node = atom;
1278 break;
1279 case UFormDfn::EntryDfn:
1281 CFormElmStruct *_struct = new CFormElmStruct (form, parentNode, *parentDfn, indexDfn);
1282 _struct->build (*nodeDfn);
1283 *node = _struct;
1285 break;
1286 case UFormDfn::EntryVirtualDfn:
1287 // todo array of virtual struct
1288 // *node = new CFormElmVirtualStruct (form, parentNode, *parentDfn, indexDfn);
1289 break;
1290 default:
1291 nlstop;
1294 nlassert (*node);
1296 // Node created
1297 created = true;
1299 // Set the element pointer
1300 parentNode->Elements[arrayIndex].Element = *node;
1303 // Is a virtual DFN ?
1304 if ((*node) && (*node)->isVirtualStruct ())
1306 // Should be NULL
1307 nlassert (*nodeDfn == NULL);
1309 // Set the current dfn
1310 *nodeDfn = safe_cast<const CFormElmVirtualStruct*> (*node)->FormDfn;
1314 break;
1315 default:
1317 // Error message
1318 smprintf (error, 512, "Keyword (%s) is not an array index.", token.c_str());
1319 goto exit;
1324 // Concat current address
1325 currentName += token;
1326 startToken = endToken;
1328 exit:;
1330 // Error ?
1331 bool errorAppend = endToken != NULL;
1333 // Continue ?
1334 if (!errorAppend)
1336 // Delete the node ?
1337 if ( (action == Delete) && (*node) )
1339 // Get its parent
1340 CFormElm *parent = safe_cast<CFormElm*> ((*node)->getParent ());
1342 // Don't erase the root structure
1343 if (parent && !parent->isArray ())
1345 // Unlink the primitive from its parent
1346 parent->unlink (*node);
1348 // Erase the node
1349 delete (*node);
1350 *node = parent;
1351 parent = (CFormElm*) (parent->getParent ());
1353 // For each parent
1354 while (parent && !(*node)->isUsed (form) && !parent->isArray ())
1356 // Unlink the primitive from its parent
1357 parent->unlink (*node);
1359 // Erase it and get next parent
1360 delete (*node);
1361 *node = parent;
1362 parent = (CFormElm*) (parent->getParent ());
1365 // No more node
1366 *node = NULL;
1371 // Node not found in get node ? Look in parents !
1372 if ( ((*node) == NULL) && (action == Return) && backupFirstElm )
1374 // Get the path name
1375 string formName;
1376 backupFirstElm->getFormName (formName);
1377 uint formNameSize = (uint)formName.size ();
1378 if ((formNameSize > 0) && (formName[formNameSize-1] != '.') && (formName[formNameSize-1] != '['))
1379 formName += ".";
1380 formName += name;
1382 // Backup first parent default value
1383 bool defaultValue = false;
1384 const CFormDfn *defaultParentDfnParent=0;
1385 uint defaultIndexDfnParent=0;
1386 const CFormDfn *defaultNodeDfnParent=0;
1387 const CType *defaultNodeTypeParent=0;
1388 CFormElm *defaultNodeParent=0;
1389 UFormDfn::TEntryType defaultTypeParent = UFormDfn::EntryType;
1390 bool defaultArrayParent=false;
1391 bool defaultCreatedParent=false;
1392 bool defaultParentVDfnArray=false;
1394 // Look in parent form
1395 for (uint parent=0; parent<form->getParentCount (); parent++)
1397 // Get the parent
1398 CForm *parentPtr = form->getParent (parent);
1399 nlassert (parentPtr);
1401 if (parentPtr->getFilename() == form->getFilename())
1403 nlerror("parent is identical to current sheet %s!", form->getFilename().c_str());
1404 return false;
1407 // Get the node by name in the parent
1408 const CFormDfn *parentDfnParent = NULL;
1409 uint indexDfnParent = 0xffffffff;
1410 const CFormDfn *nodeDfnParent = NULL;
1411 const CType *nodeTypeParent = NULL;
1412 CFormElm *nodeParent = (CFormElm*)&parentPtr->getRootNode ();
1413 UFormDfn::TEntryType typeParent;
1414 bool arrayParent;
1415 bool createdParent;
1416 bool parentVDfnArray;
1417 if (getInternalNodeByName (parentPtr, formName, &parentDfnParent, indexDfnParent, &nodeDfnParent, &nodeTypeParent, &nodeParent, typeParent, arrayParent, action, createdParent, parentVDfnArray, false, round+1))
1419 // Node found ?
1420 if (nodeParent)
1422 // Found copy return values
1423 *parentDfn = parentDfnParent;
1424 indexDfn = indexDfnParent;
1425 *nodeDfn = nodeDfnParent;
1426 *nodeType = nodeTypeParent;
1427 *node = nodeParent;
1428 type = typeParent;
1429 array = arrayParent;
1430 created = createdParent;
1432 return true;
1434 else
1436 // Backup the first parent default value found
1437 if (!defaultValue)
1439 defaultParentDfnParent = parentDfnParent;
1440 defaultIndexDfnParent = indexDfnParent;
1441 defaultNodeDfnParent = nodeDfnParent;
1442 defaultNodeTypeParent = nodeTypeParent;
1443 defaultNodeParent = nodeParent;
1444 defaultTypeParent = typeParent;
1445 defaultArrayParent = arrayParent;
1446 defaultCreatedParent = createdParent;
1447 defaultParentVDfnArray = parentVDfnArray;
1448 defaultValue = true;
1454 // Default value available ?
1455 if (defaultValue)
1457 *parentDfn = defaultParentDfnParent;
1458 indexDfn = defaultIndexDfnParent;
1459 *nodeDfn = defaultNodeDfnParent;
1460 *nodeType = defaultNodeTypeParent;
1461 *node = defaultNodeParent;
1462 type = defaultTypeParent;
1463 array = defaultArrayParent;
1464 created = defaultCreatedParent;
1465 return true;
1469 // Recurse warning !
1470 if (*node)
1472 if (round > NLGEORGES_MAX_RECURSION)
1474 // Turn around..
1475 string formName;
1476 (*node)->getFormName (formName);
1477 warning (false, formName, form->getFilename (), "getInternalNodeByName", "Recursive call on the same node (%s), look for loop references or inheritances.", name.c_str());
1478 return false;
1482 if (verbose && errorAppend)
1484 nlassert (*error);
1486 // Get the best form name
1487 warning (false, currentName, form->getFilename (), "getInternalNodeByName", "Getting the node (%s) : %s", name.c_str(), error);
1490 return !errorAppend;
1493 // ***************************************************************************
1495 const char* CFormElm::tokenize (const char *name, string &str, uint &/* errorIndex */, uint &code)
1497 if (*name == 0)
1499 return NULL;
1502 if (*name == '[')
1504 code = TokenArrayBegin;
1505 str = "[";
1506 return name+1;
1509 if (*name == ']')
1511 code = TokenArrayEnd;
1512 str = "]";
1513 return name+1;
1516 if (*name == '.')
1518 code = TokenPoint;
1519 str = ".";
1520 return name+1;
1523 str.clear();
1524 while ( (*name != '.') && (*name != '[') && (*name != ']') && (*name != 0) )
1526 // Add a char
1527 str += *name;
1528 name++;
1531 code = TokenString;
1532 return name;
1535 // ***************************************************************************
1537 void CFormElm::unlink (CFormElm * /* child */)
1539 // No children
1540 nlstop;
1543 // ***************************************************************************
1545 bool CFormElm::setValueByName(const std::string &value, const std::string &name, bool *created)
1547 // The parent Dfn
1548 const CFormDfn *parentDfn;
1549 const CFormDfn *nodeDfn;
1550 const CType *nodeType;
1551 CFormElm *node;
1552 uint indexDfn;
1553 bool array;
1554 bool _created;
1555 UFormDfn::TEntryType type;
1557 // Search for the node
1558 if (createNodeByName (name, &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, array, _created))
1560 // Is this a type ?
1561 if (type == UFormDfn::EntryType)
1563 // The atom
1564 CFormElmAtom *atom = node ? safe_cast<CFormElmAtom*> (node) : NULL;
1566 // Evale
1567 nlassert (nodeType);
1568 atom->setValue (value);
1570 // Created flag
1571 if (created)
1572 *created = _created;
1573 return true;
1575 else
1577 // Error message
1578 warning (false, "setValueByName", "The node (%s) is not an atom element. Can't set the value.", name.c_str());
1581 else
1583 // Error message
1584 warning (false, "setValueByName", "Can't created / set the node (%s).", name.c_str());
1586 // Created flag
1587 if (created)
1588 *created = false;
1591 // Error
1592 return false;
1595 // ***************************************************************************
1597 bool CFormElm::setValueByName (sint8 value, const std::string &name, bool *created)
1599 return setValueByName (toString (value), name, created);
1602 // ***************************************************************************
1604 bool CFormElm::setValueByName (uint8 value, const std::string &name, bool *created)
1606 return setValueByName (toString (value), name, created);
1609 // ***************************************************************************
1611 bool CFormElm::setValueByName (sint16 value, const std::string &name, bool *created)
1613 return setValueByName (toString (value), name, created);
1616 // ***************************************************************************
1618 bool CFormElm::setValueByName (uint16 value, const std::string &name, bool *created)
1620 return setValueByName (toString (value), name, created);
1623 // ***************************************************************************
1625 bool CFormElm::setValueByName(sint32 value, const std::string &name, bool *created)
1627 return setValueByName (toString (value), name, created);
1630 // ***************************************************************************
1632 bool CFormElm::setValueByName (uint32 value, const std::string &name, bool *created)
1634 return setValueByName (toString (value), name, created);
1637 // ***************************************************************************
1639 bool CFormElm::setValueByName (float value, const std::string &name, bool *created)
1641 return setValueByName (toString (value), name, created);
1644 // ***************************************************************************
1646 bool CFormElm::setValueByName (double value, const std::string &name, bool *created)
1648 return setValueByName (toString (value), name, created);
1651 // ***************************************************************************
1653 bool CFormElm::setValueByName (bool value, const std::string &name, bool *created)
1655 return setValueByName (toString (value), name, created);
1658 // ***************************************************************************
1660 bool CFormElm::setValueByName (NLMISC::CRGBA value, const std::string &name, bool *created)
1662 char tmp[512];
1663 smprintf (tmp, 512, "%d,%d,%d", value.R, value.G, value.B);
1664 return setValueByName(std::string(tmp), name, created);
1667 // ***************************************************************************
1669 void CFormElm::warning (bool exception, const std::string &formName, const std::string &formFileName, const std::string &function, const char *format, ... )
1671 // Make a buffer string
1672 va_list args;
1673 va_start( args, format );
1674 char buffer[1024];
1675 vsnprintf( buffer, 1024, format, args );
1676 va_end( args );
1678 // Set the warning
1679 NLGEORGES::warning (exception, "(CFormElm::%s) on node (%s) in form (%s) : %s", function.c_str(), formName.c_str(), formFileName.c_str(), buffer);
1682 // ***************************************************************************
1684 void CFormElm::warning (bool exception, const std::string &function, const char *format, ... ) const
1686 va_list args;
1687 va_start( args, format );
1689 string formName;
1690 getFormName (formName);
1691 warning (exception, formName, getForm ()->getFilename (), function, format, args);
1693 va_end( args );
1696 // ***************************************************************************
1697 // class CFormElmStruct
1698 // ***************************************************************************
1700 CFormElmStruct::CFormElmStruct (CForm *form, CFormElm *parentNode, const CFormDfn *parentDfn, uint parentIndex) : CFormElm (form, parentNode, parentDfn, parentIndex)
1702 FormDfn = NULL;
1705 // ***************************************************************************
1707 CFormElmStruct::~CFormElmStruct ()
1709 // Job done in clean()
1710 clean();
1713 // ***************************************************************************
1715 void CFormElmStruct::clean ()
1717 // For each element of the array
1718 uint elm;
1719 for (elm =0; elm<Elements.size(); elm++)
1721 delete Elements[elm].Element;
1722 Elements[elm].Element = NULL;
1724 Elements.clear();
1727 // ***************************************************************************
1729 bool CFormElmStruct::isStruct () const
1731 return true;
1734 // ***************************************************************************
1736 bool CFormElmStruct::getStructSize (uint &size) const
1738 size = (uint)Elements.size();
1739 return true;
1742 // ***************************************************************************
1744 bool CFormElmStruct::getStructNodeName (uint element, string &result) const
1746 if (element<Elements.size())
1748 result = Elements[element].Name;
1749 return true;
1751 else
1753 warning (false, "getStructNodeName", "Index (%u) out of bound (%u).", element, (uint)Elements.size() );
1754 return false;
1758 // ***************************************************************************
1760 bool CFormElmStruct::getStructNode (uint element, const UFormElm **result) const
1762 if (element<Elements.size())
1764 *result = Elements[element].Element;
1765 return true;
1767 else
1769 warning (false, "getStructNode", "Index (%u) out of bound (%u).", element, (uint)Elements.size() );
1770 return false;
1774 // ***************************************************************************
1776 UFormDfn *CFormElmStruct::getStructDfn ()
1778 return (CFormDfn*)FormDfn;
1781 // ***************************************************************************
1783 bool CFormElmStruct::getStructNode (uint element, UFormElm **result)
1785 if (element<Elements.size())
1787 *result = Elements[element].Element;
1788 return true;
1790 else
1792 warning (false, "getStructNode", "Index (%u) out of bound (%u).", element, (uint)Elements.size() );
1793 return false;
1797 // ***************************************************************************
1799 xmlNodePtr CFormElmStruct::write (xmlNodePtr root, const CForm *form, const std::string &structName, bool forceWrite) const
1801 // Is used ?
1802 if (isUsed (form) || forceWrite)
1804 // *** Header
1805 xmlNodePtr node = xmlNewChild ( root, NULL, (const xmlChar*)"STRUCT", NULL);
1807 // Element name
1808 if (!structName.empty())
1810 // Struct name
1811 xmlSetProp (node, (const xmlChar*)"Name", (const xmlChar*)structName.c_str());
1814 // For each elements of the structure
1815 uint elm;
1816 for (elm=0; elm<Elements.size(); elm++)
1818 // Create a node if it exist
1819 if (Elements[elm].Element)
1820 Elements[elm].Element->write (node, form, Elements[elm].Name);
1823 // Return the new node
1824 return node;
1826 return NULL;
1829 // ***************************************************************************
1831 void CFormElmStruct::read (xmlNodePtr node, CFormLoader &loader, const CFormDfn *dfn, CForm *form)
1833 // Get the smart pointer on the dfn
1834 FormDfn = (CFormDfn*)dfn;
1836 // Build the Form
1837 build (dfn);
1839 // Count parent
1840 uint dfnCount = dfn->countParentDfn ();
1842 // Array of Dfn
1843 std::vector<const CFormDfn*> dfnArray;
1844 dfnArray.reserve (dfnCount);
1845 dfn->getParentDfn (dfnArray);
1847 // For each Dfn
1848 uint dfnId;
1849 uint elmIndex=0;
1850 for (dfnId=0; dfnId<dfnCount; dfnId++)
1852 // Lookup for the name in the DFN
1853 uint elm;
1854 for (elm=0; elm<dfnArray[dfnId]->Entries.size(); elm++)
1856 // Found ?
1857 // bool found = false;
1859 // Read the struct
1860 xmlNodePtr child = NULL;
1862 // Node can be NULL
1863 if (node)
1864 child = node->children;
1866 while (child)
1868 // Good node ?
1869 const char *name = (const char*)xmlGetProp (child, (xmlChar*)"Name");
1870 if (name && (dfnArray[dfnId]->Entries[elm].getName () == name) )
1872 // Type
1873 bool atom=false;
1874 bool array=false;
1875 bool _struct=false;
1876 bool vStruct=false;
1878 // Is an atom ?
1879 if (strcmp ((const char*)child->name, "ATOM") == 0)
1881 atom = true;
1883 // Is a struct ?
1884 else if (strcmp ((const char*)child->name, "STRUCT") == 0)
1886 _struct = true;
1888 // Is a struct ?
1889 else if (strcmp ((const char*)child->name, "VSTRUCT") == 0)
1891 vStruct = true;
1893 // Is an array ?
1894 else if (strcmp ((const char*)child->name, "ARRAY") == 0)
1896 array = true;
1899 // Continue ?
1900 if (atom || _struct || vStruct || array)
1902 // Same type ?
1903 if (
1904 (atom && (dfnArray[dfnId]->Entries[elm].getType ()==UFormDfn::EntryType) && (!dfnArray[dfnId]->Entries[elm].getArrayFlag ()) ) ||
1905 (array && dfnArray[dfnId]->Entries[elm].getArrayFlag () && ( (dfnArray[dfnId]->Entries[elm].getType () == UFormDfn::EntryType) || (dfnArray[dfnId]->Entries[elm].getType () == UFormDfn::EntryDfn) ) ) ||
1906 (_struct && (dfnArray[dfnId]->Entries[elm].getType () == UFormDfn::EntryDfn) && (!dfnArray[dfnId]->Entries[elm].getArrayFlag ()) ) ||
1907 (vStruct && (dfnArray[dfnId]->Entries[elm].getType () == UFormDfn::EntryVirtualDfn) && (!dfnArray[dfnId]->Entries[elm].getArrayFlag ()) )
1910 // Ok keep it
1911 xmlFree((void*) name);
1912 break;
1914 else
1916 // Make a warning message
1917 warning (false, "read", "In block line %u, node (%s) type in DFN have changed.",
1918 (uint)child->line, child->name);
1921 else
1923 if (name)
1925 // Delete the value
1926 xmlFree ((void*)name);
1929 // Throw exception
1930 warning (true, "read", "XML Syntax error in block line %u, node (%s) name should be STRUCT, ATOM or ARRAY.",
1931 (uint)child->line, child->name);
1935 if (name)
1937 // Delete the value
1938 xmlFree ((void*)name);
1941 // Next child
1942 child = child->next;
1945 // Found ?
1946 if (child)
1948 // Create a new element
1949 if (dfnArray[dfnId]->Entries[elm].getArrayFlag ())
1951 // Array of type
1952 CFormElmArray *newElm = NULL;
1953 if (dfnArray[dfnId]->Entries[elm].getType () == UFormDfn::EntryType)
1955 // Load the new element
1956 newElm = new CFormElmArray (form, NULL, dfnArray[dfnId]->Entries[elm].getTypePtr (), this, dfnArray[dfnId], elm);
1958 // Array of struct
1959 else if (dfnArray[dfnId]->Entries[elm].getType () == UFormDfn::EntryDfn)
1961 newElm = new CFormElmArray (form, dfnArray[dfnId]->Entries[elm].getDfnPtr (), NULL, this, dfnArray[dfnId], elm);
1964 // Should be created
1965 nlassert (newElm);
1966 Elements[elmIndex].Element = newElm;
1967 newElm->read (child, loader, form);
1969 else if (dfnArray[dfnId]->Entries[elm].getType () == UFormDfn::EntryType)
1971 // Load the new element
1972 CFormElmAtom *newElm = new CFormElmAtom (form, this, dfnArray[dfnId], elm);
1973 Elements[elmIndex].Element = newElm;
1974 newElm->read (child, loader, dfnArray[dfnId]->Entries[elm].getTypePtr (), form);
1976 else if (dfnArray[dfnId]->Entries[elm].getType () == UFormDfn::EntryDfn)
1978 // Load the new element
1979 CFormElmStruct *newElm = new CFormElmStruct (form, this, dfnArray[dfnId], elm);
1980 Elements[elmIndex].Element = newElm;
1981 newElm->read (child, loader, dfnArray[dfnId]->Entries[elm].getDfnPtr (), form);
1983 else // if dfnArray[dfnId]->Entries[elm].getType () == CFormDfn::CEntry::EntryVirtualDfn)
1985 // Should be a struct
1986 nlassert (dfnArray[dfnId]->Entries[elm].getType () == UFormDfn::EntryVirtualDfn);
1988 // Load the new element
1989 CFormElmVirtualStruct *newElm = new CFormElmVirtualStruct (form, this, dfnArray[dfnId], elm);
1990 Elements[elmIndex].Element = newElm;
1991 newElm->read (child, loader, form);
1994 else
1995 Elements[elmIndex].Element = NULL;
1997 elmIndex++;
2002 // ***************************************************************************
2004 bool CFormElmStruct::isUsed (const CForm *form) const
2006 for (uint i=0; i<Elements.size(); i++)
2008 if (Elements[i].Element && Elements[i].Element->isUsed (form))
2009 return true;
2011 return false;
2014 // ***************************************************************************
2016 void CFormElmStruct::build (const CFormDfn *dfn)
2018 // Clean the form
2019 clean ();
2021 // Set the DFN
2022 FormDfn = (CFormDfn*)dfn;
2024 // Get the parents
2025 vector<const CFormDfn*> arrayDfn;
2026 arrayDfn.reserve (dfn->countParentDfn ());
2027 dfn->getParentDfn (arrayDfn);
2029 // Count element
2030 uint elementCount = 0;
2031 uint dfnIndex;
2032 for (dfnIndex=0; dfnIndex<arrayDfn.size(); dfnIndex++)
2034 elementCount += arrayDfn[dfnIndex]->getNumEntry();
2037 // Resize the element array
2038 Elements.resize (elementCount);
2040 elementCount = 0;
2041 for (dfnIndex=0; dfnIndex<arrayDfn.size(); dfnIndex++)
2043 // For each element
2044 for (uint elm=0; elm<arrayDfn[dfnIndex]->Entries.size(); elm++)
2046 // Copy the name
2047 Elements[elementCount].Name = arrayDfn[dfnIndex]->Entries[elm].Name;
2048 elementCount++;
2053 // ***************************************************************************
2055 void CFormElmStruct::unlink (CFormElm *child)
2057 uint i;
2058 for (i=0; i<Elements.size (); i++)
2060 if (Elements[i].Element == child)
2062 Elements[i].Element = NULL;
2063 break;
2067 // Element not found!
2068 nlassert (i != Elements.size ());
2071 // ***************************************************************************
2073 void CFormElmStruct::getFormName (std::string &result, const CFormElm *child) const
2075 // Reset the result
2076 if (child == NULL)
2078 result.clear();
2079 result.reserve (50);
2082 // Get parent form name
2083 if (ParentNode)
2084 ParentNode->getFormName (result, this);
2086 // Get node name
2087 if (child)
2089 // Look for the child
2090 uint i;
2091 for (i=0; i<Elements.size (); i++)
2093 // This one ?
2094 if (Elements[i].Element == child)
2096 // Add the field name
2097 result += ".";
2098 result += Elements[i].Name;
2099 break;
2103 // Draw some warning
2104 if (i==Elements.size ())
2106 warning (false, "getFormName", "Child node not found.");
2111 // ***************************************************************************
2113 void CFormElmStruct::warning (bool exception, const std::string &function, const char *format, ... ) const
2115 // Make a buffer string
2116 va_list args;
2117 va_start( args, format );
2118 char buffer[1024];
2119 vsnprintf( buffer, 1024, format, args );
2120 va_end( args );
2122 // Set the warning
2123 string formName;
2124 getFormName (formName, NULL);
2125 NLGEORGES::warning (exception, "(CFormElmStruct::%s) on node (%s) in form (%s) : %s", function.c_str(), formName.c_str (), Form->getFilename ().c_str (), buffer);
2128 // ***************************************************************************
2130 void CFormElmStruct::getDependencies (std::set<std::string> &dependencies) const
2132 // Visit the dfn
2133 if (FormDfn)
2134 FormDfn->getDependencies (dependencies);
2136 // Visit elements
2137 for (uint i=0; i<Elements.size (); i++)
2139 if (Elements[i].Element)
2140 Elements[i].Element->getDependencies (dependencies);
2144 // ***************************************************************************
2145 // class CFormElmVirtualStruct
2146 // ***************************************************************************
2148 CFormElmVirtualStruct::CFormElmVirtualStruct (CForm *form, CFormElm *parentNode, const CFormDfn *parentDfn, uint parentIndex) : CFormElmStruct (form, parentNode, parentDfn, parentIndex)
2152 // ***************************************************************************
2154 xmlNodePtr CFormElmVirtualStruct::write (xmlNodePtr root, const CForm *form, const std::string &structName, bool forceWrite) const
2156 // Is used ?
2157 if (isUsed (form) || forceWrite)
2159 // *** Header
2160 xmlNodePtr node = xmlNewChild ( root, NULL, (const xmlChar*)"VSTRUCT", NULL);
2162 // Write the DFN filename in the node
2163 xmlSetProp (node, (const xmlChar*)"DfnName", (const xmlChar*)DfnFilename.c_str());
2165 // Element name
2166 if (!structName.empty())
2168 // Struct name
2169 xmlSetProp (node, (const xmlChar*)"Name", (const xmlChar*)structName.c_str());
2172 // For each elements of the structure
2173 uint elm;
2174 for (elm=0; elm<Elements.size(); elm++)
2176 // Create a node if it exist
2177 if (Elements[elm].Element)
2178 Elements[elm].Element->write (node, form, Elements[elm].Name);
2181 // Return the new node
2182 return node;
2184 return NULL;
2187 // ***************************************************************************
2189 void CFormElmVirtualStruct::read (xmlNodePtr node, CFormLoader &loader, CForm *form)
2191 // Get the DFN filename
2192 const char *filename = (const char*)xmlGetProp (node, (xmlChar*)"DfnName");
2193 if (filename)
2195 // Set the name
2196 DfnFilename = filename;
2198 // Delete the value
2199 xmlFree ((void*)filename);
2201 // Load the dfn
2202 FormDfn = loader.loadFormDfn (DfnFilename, false);
2203 if (!FormDfn)
2205 // Throw exception
2206 warning (true, "read", "Can't find DFN filename (%s).", DfnFilename.c_str ());
2209 else
2211 // Throw exception
2212 warning (true, "read", "XML Syntax error in virtual struct in block line %u, should have a DfnName property.",
2213 (uint)node->line);
2216 // Read the parent
2217 CFormElmStruct::read (node, loader, FormDfn, form);
2220 // ***************************************************************************
2222 bool CFormElmVirtualStruct::isVirtualStruct () const
2224 return true;
2227 // ***************************************************************************
2229 bool CFormElmVirtualStruct::getDfnName (std::string &dfnName ) const
2231 dfnName = DfnFilename;
2232 return true;
2235 // ***************************************************************************
2237 bool CFormElmVirtualStruct::isUsed (const CForm * /* form */) const
2239 return true;
2242 // ***************************************************************************
2244 void CFormElmVirtualStruct::warning (bool exception, const std::string &function, const char *format, ... ) const
2246 // Make a buffer string
2247 va_list args;
2248 va_start( args, format );
2249 char buffer[1024];
2250 vsnprintf( buffer, 1024, format, args );
2251 va_end( args );
2253 // Set the warning
2254 string formName;
2255 getFormName (formName, NULL);
2256 NLGEORGES::warning (exception, "(CFormElmVirtualStruct::%s) on node (%s) in form (%s) : %s", function.c_str(), formName.c_str (), Form->getFilename ().c_str (), buffer);
2259 // ***************************************************************************
2260 // class CFormElmArray
2261 // ***************************************************************************
2263 CFormElmArray::CFormElmArray (CForm *form, const CFormDfn *formDfn, const CType *type, CFormElm *parentNode, const CFormDfn *parentDfn, uint parentIndex) : CFormElm (form, parentNode, parentDfn, parentIndex)
2265 FormDfn = (CFormDfn*)formDfn;
2266 Type = type;
2269 // ***************************************************************************
2271 CFormElmArray::~CFormElmArray ()
2273 // Job done in clean()
2274 clean();
2277 // ***************************************************************************
2279 void CFormElmArray::clean ()
2281 // For each element of the array
2282 uint elm;
2283 for (elm =0; elm<Elements.size(); elm++)
2285 delete Elements[elm].Element;
2286 Elements[elm].Element = NULL;
2288 Elements.clear ();
2291 // ***************************************************************************
2293 bool CFormElmArray::isArray () const
2295 return true;
2298 // ***************************************************************************
2300 bool CFormElmArray::getArraySize (uint &size) const
2302 size = (uint)Elements.size ();
2303 return true;
2306 // ***************************************************************************
2308 bool CFormElmArray::getArrayNode (const UFormElm **result, uint arrayIndex) const
2310 if (arrayIndex<Elements.size())
2312 *result = Elements[arrayIndex].Element;
2313 return true;
2315 else
2317 warning (false, "getArrayNode", "Index (%u) out of bound (%u).", arrayIndex, (uint)Elements.size() );
2318 return false;
2322 // ***************************************************************************
2324 bool CFormElmArray::getArrayNodeName (std::string &result, uint arrayIndex) const
2326 if (arrayIndex<Elements.size())
2328 if (Elements[arrayIndex].Name.empty ())
2329 result = "#" + toString (arrayIndex);
2330 else
2331 result = Elements[arrayIndex].Name;
2332 return true;
2334 else
2336 warning (false, "getArrayNodeName", "Index (%u) out of bound (%u).", arrayIndex, (uint)Elements.size() );
2337 return false;
2341 // ***************************************************************************
2343 bool CFormElmArray::getArrayNode (UFormElm **result, uint arrayIndex)
2345 if (arrayIndex<Elements.size())
2347 *result = Elements[arrayIndex].Element;
2348 return true;
2350 else
2352 warning (false, "getArrayNode", "Index (%u) out of bound (%u).", arrayIndex, (uint)Elements.size() );
2353 return false;
2358 // ***************************************************************************
2360 bool CFormElmArray::getArrayValue (std::string &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2362 if (arrayIndex >= Elements.size())
2364 warning (false, "getArrayValue", "Access out of bound, trying to access array index %u, array size is %u.", arrayIndex, (uint)Elements.size());
2366 else if (Type)
2368 return (Type->getValue (result, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""));
2370 else
2372 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2375 return false;
2378 // ***************************************************************************
2380 bool CFormElmArray::getArrayValue (sint8 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2382 if (Type)
2384 string str;
2385 if (Type->getValue (str, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""))
2387 return convertValue (result, str);
2390 else
2392 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2395 return false;
2398 // ***************************************************************************
2400 bool CFormElmArray::getArrayValue (uint8 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2402 if (Type)
2404 string str;
2405 if (Type->getValue (str, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""))
2407 return convertValue (result, str);
2410 else
2412 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2415 return false;
2418 // ***************************************************************************
2420 bool CFormElmArray::getArrayValue (sint16 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2422 if (Type)
2424 string str;
2425 if (Type->getValue (str, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""))
2427 return convertValue (result, str);
2430 else
2432 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2435 return false;
2438 // ***************************************************************************
2440 bool CFormElmArray::getArrayValue (uint16 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2442 if (Type)
2444 string str;
2445 if (Type->getValue (str, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""))
2447 return convertValue (result, str);
2450 else
2452 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2455 return false;
2458 // ***************************************************************************
2460 bool CFormElmArray::getArrayValue (sint32 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2462 if (Type)
2464 string str;
2465 if (Type->getValue (str, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""))
2467 return convertValue (result, str);
2470 else
2472 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2475 return false;
2478 // ***************************************************************************
2480 bool CFormElmArray::getArrayValue (uint32 &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2482 if (Type)
2484 string str;
2485 if (Type->getValue (str, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""))
2487 return convertValue (result, str);
2490 else
2492 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2495 return false;
2498 // ***************************************************************************
2500 bool CFormElmArray::getArrayValue (float &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2502 if (Type)
2504 string str;
2505 if (Type->getValue (str, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""))
2507 return convertValue (result, str);
2510 else
2512 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2515 return false;
2518 // ***************************************************************************
2520 bool CFormElmArray::getArrayValue (double &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2522 if (Type)
2524 string str;
2525 if (Type->getValue (str, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""))
2527 return convertValue (result, str);
2530 else
2532 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2535 return false;
2538 // ***************************************************************************
2540 bool CFormElmArray::getArrayValue (bool &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2542 if (Type)
2544 string str;
2545 if (Type->getValue (str, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""))
2547 return convertValue (result, str);
2550 else
2552 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2555 return false;
2558 // ***************************************************************************
2560 bool CFormElmArray::getArrayValue (NLMISC::CRGBA &result, uint arrayIndex, TEval evaluate, TWhereIsValue *where) const
2562 if (Type)
2564 string str;
2565 if (Type->getValue (str, Form, safe_cast<const CFormElmAtom*> (Elements[arrayIndex].Element), *ParentDfn, ParentIndex, evaluate, (uint32*)where, NLGEORGES_FIRST_ROUND, ""))
2567 return convertValue (result, str);
2570 else
2572 warning (false, "getArrayValue", "This array is not an array of atom. This is an array of structure.");
2575 return false;
2578 // ***************************************************************************
2580 xmlNodePtr CFormElmArray::write (xmlNodePtr root, const CForm *form, const std::string &structName, bool forceWrite) const
2582 // Arrau is used ?
2583 if (isUsed (form) || forceWrite)
2585 // *** Header
2586 xmlNodePtr node = xmlNewChild ( root, NULL, (const xmlChar*)"ARRAY", NULL);
2588 // Element name
2589 if (!structName.empty())
2591 // Struct name
2592 xmlSetProp (node, (const xmlChar*)"Name", (const xmlChar*)structName.c_str());
2595 // For each elements of the structure
2596 uint elm;
2597 for (elm=0; elm<Elements.size(); elm++)
2599 // Create a node
2600 if (Elements[elm].Element)
2601 Elements[elm].Element->write (node, form, Elements[elm].Name, true);
2604 // Return the new node
2605 return node;
2608 return NULL;
2611 // ***************************************************************************
2613 void CFormElmArray::read (xmlNodePtr node, CFormLoader &loader, CForm *form)
2615 // Clean the form
2616 clean ();
2618 // Count child
2619 if (node)
2621 // Type of DFN array
2622 if (Type)
2624 nlassert (FormDfn == NULL);
2626 // Count children
2627 uint childCount = CIXml::countChildren (node, "ATOM");
2629 // Resize the table
2630 Elements.resize (childCount);
2632 // For each children
2633 uint childNum=0;
2634 xmlNodePtr child = CIXml::getFirstChildNode (node, "ATOM");
2635 while (child)
2637 // Get node name
2638 const char *name = (const char*)xmlGetProp (child, (xmlChar*)"Name");
2640 // Create a new node
2641 CFormElmAtom *newElt = new CFormElmAtom (form, this, ParentDfn, ParentIndex);
2642 Elements[childNum].Element = newElt;
2643 if (name)
2645 Elements[childNum].Name = name;
2646 xmlFree ((void*)name);
2648 newElt->read (child, loader, Type, form);
2650 // Next child
2651 child = CIXml::getNextChildNode (child, "ATOM");
2652 childNum++;
2655 else
2657 nlassert (FormDfn);
2658 nlassert (Type == NULL);
2660 // Count children
2661 uint childCount = CIXml::countChildren (node, "STRUCT");
2663 // Resize the table
2664 Elements.resize (childCount);
2666 // For each children
2667 uint childNum=0;
2668 xmlNodePtr child = CIXml::getFirstChildNode (node, "STRUCT");
2669 while (child)
2671 // Get node name
2672 const char *name = (const char*)xmlGetProp (child, (xmlChar*)"Name");
2674 // Create a new node
2675 CFormElmStruct *newElt = new CFormElmStruct (form, this, ParentDfn, ParentIndex);
2676 Elements[childNum].Element = newElt;
2677 if (name)
2679 Elements[childNum].Name = name;
2680 xmlFree ((void*)name);
2682 newElt->read (child, loader, FormDfn, form);
2684 // Next child
2685 child = CIXml::getNextChildNode (child, "STRUCT");
2686 childNum++;
2692 // ***************************************************************************
2694 bool CFormElmArray::setParent (CFormElm * /* parent */)
2696 return true;
2699 // ***************************************************************************
2701 void CFormElmArray::unlink (CFormElm *child)
2703 uint i;
2704 for (i=0; i<Elements.size (); i++)
2706 if (Elements[i].Element == child)
2708 Elements[i].Element = NULL;
2709 break;
2713 // Element not found!
2714 nlassert (i != Elements.size ());
2717 // ***************************************************************************
2719 bool CFormElmArray::isUsed (const CForm *form) const
2721 /*for (uint i=0; i<Elements.size(); i++)
2723 if (Elements[i] && Elements[i]->isUsed (form))
2724 return true;
2726 return form == Form;
2729 // ***************************************************************************
2731 void CFormElmArray::getFormName (std::string &result, const CFormElm *child) const
2733 // Reset the result
2734 if (child == NULL)
2736 result.clear();
2737 result.reserve (50);
2740 // Get parent form name
2741 if (ParentNode)
2742 ParentNode->getFormName (result, this);
2744 // Get node name
2745 if (child)
2747 // Look for the child
2748 uint i;
2749 for (i=0; i<Elements.size (); i++)
2751 // This one ?
2752 if (Elements[i].Element == child)
2754 char name[512];
2755 smprintf (name, 512, "[%d]", i);
2757 // Add the field name
2758 result += name;
2759 break;
2763 // Draw some warning
2764 if (i==Elements.size ())
2766 warning (false, "getFormName", "Child node not found.");
2771 // ***************************************************************************
2773 void CFormElmArray::warning (bool exception, const std::string &function, const char *format, ... ) const
2775 // Make a buffer string
2776 va_list args;
2777 va_start( args, format );
2778 char buffer[1024];
2779 vsnprintf( buffer, 1024, format, args );
2780 va_end( args );
2782 // Set the warning
2783 string formName;
2784 getFormName (formName, NULL);
2785 NLGEORGES::warning (exception, "(CFormElmArray::%s) on node (%s) in form (%s) : %s", function.c_str(), formName.c_str (), Form->getFilename ().c_str (), buffer);
2788 // ***************************************************************************
2790 void CFormElmArray::getDependencies (std::set<std::string> &dependencies) const
2792 if (FormDfn)
2794 // Add the dfn
2795 FormDfn->getDependencies (dependencies);
2797 // Add each elements
2798 for (uint i=0; i<Elements.size (); i++)
2800 Elements[i].Element->getDependencies (dependencies);
2804 if (Type)
2806 // Add the type
2807 Type->getDependencies (dependencies);
2811 // ***************************************************************************
2812 // CFormElmAtom
2813 // ***************************************************************************
2815 CFormElmAtom::CFormElmAtom (CForm *form, CFormElm *parentNode, const CFormDfn *parentDfn, uint parentIndex) : CFormElm (form, parentNode, parentDfn, parentIndex)
2817 Type = NULL;
2820 // ***************************************************************************
2822 bool CFormElmAtom::isAtom () const
2824 return true;
2827 // ***************************************************************************
2829 const CType* CFormElmAtom::getType ()
2831 return Type;
2834 // ***************************************************************************
2836 void CFormElmAtom::getDependencies (std::set<std::string> &/* dependencies */) const
2840 // ***************************************************************************
2842 bool CFormElmAtom::getValue (string &result, TEval evaluate) const
2844 nlassert (Type);
2846 // Evale
2847 return Type->getValue (result, Form, this, *ParentDfn, ParentIndex, evaluate, NULL, NLGEORGES_FIRST_ROUND, "");
2850 // ***************************************************************************
2852 bool CFormElmAtom::getValue (sint8 &result, TEval evaluate) const
2854 // Get the string value
2855 string value;
2856 if (getValue (value, evaluate))
2858 return convertValue (result, value.c_str ());
2861 return false;
2864 // ***************************************************************************
2866 bool CFormElmAtom::getValue (uint8 &result, TEval evaluate) const
2868 // Get the string value
2869 string value;
2870 if (getValue (value, evaluate))
2872 return convertValue (result, value.c_str ());
2875 return false;
2878 // ***************************************************************************
2880 bool CFormElmAtom::getValue (sint16 &result, TEval evaluate) const
2882 // Get the string value
2883 string value;
2884 if (getValue (value, evaluate))
2886 return convertValue (result, value.c_str ());
2889 return false;
2892 // ***************************************************************************
2894 bool CFormElmAtom::getValue (uint16 &result, TEval evaluate) const
2896 // Get the string value
2897 string value;
2898 if (getValue (value, evaluate))
2900 return convertValue (result, value.c_str ());
2903 return false;
2906 // ***************************************************************************
2908 bool CFormElmAtom::getValue (sint32 &result, TEval evaluate) const
2910 // Get the string value
2911 string value;
2912 if (getValue (value, evaluate))
2914 return convertValue (result, value.c_str ());
2917 return false;
2920 // ***************************************************************************
2922 bool CFormElmAtom::getValue (uint32 &result, TEval evaluate) const
2924 // Get the string value
2925 string value;
2926 if (getValue (value, evaluate))
2928 return convertValue (result, value.c_str ());
2931 return false;
2934 // ***************************************************************************
2936 bool CFormElmAtom::getValue (float &result, TEval evaluate) const
2938 // Get the string value
2939 string value;
2940 if (getValue (value, evaluate))
2942 return convertValue (result, value.c_str ());
2945 return false;
2948 // ***************************************************************************
2950 bool CFormElmAtom::getValue (double &result, TEval evaluate) const
2952 // Get the string value
2953 string value;
2954 if (getValue (value, evaluate))
2956 return convertValue (result, value.c_str ());
2959 return false;
2962 // ***************************************************************************
2964 bool CFormElmAtom::getValue (bool &result, TEval evaluate) const
2966 // Get the string value
2967 string value;
2968 if (getValue (value, evaluate))
2970 return convertValue (result, value.c_str ());
2973 return false;
2976 // ***************************************************************************
2978 bool CFormElmAtom::getValue (NLMISC::CRGBA &result, TEval evaluate) const
2980 // Get the string value
2981 string value;
2982 if (getValue (value, evaluate))
2984 return convertValue (result, value.c_str ());
2987 return false;
2990 // ***************************************************************************
2992 xmlNodePtr CFormElmAtom::write (xmlNodePtr root, const CForm *form, const std::string &structName, bool forceWrite) const
2994 // Atom is used ?
2995 if (isUsed (form) || forceWrite)
2997 // *** Header
2998 xmlNodePtr node = xmlNewChild ( root, NULL, (const xmlChar*)"ATOM", NULL);
3000 // Element name
3001 if (!structName.empty())
3003 // Struct name
3004 xmlSetProp (node, (const xmlChar*)"Name", (const xmlChar*)structName.c_str());
3007 // The value
3008 if (!Value.empty ())
3010 if (COXml::isStringValidForProperties (Value))
3011 xmlSetProp (node, (const xmlChar*)"Value", (const xmlChar*)Value.c_str());
3012 else
3014 xmlNodePtr textNode = xmlNewText ((const xmlChar *)Value.c_str ());
3015 xmlAddChild (node, textNode);
3019 // Return the new node
3020 return node;
3022 return NULL;
3025 // ***************************************************************************
3027 void CFormElmAtom::read (xmlNodePtr node, CFormLoader &/* loader */, const CType *type, CForm * /* form */)
3029 // Set the type
3030 Type = type;
3032 // Set the value ?
3033 if (node)
3035 // Get the value
3036 const char *value = (const char*)xmlGetProp (node, (xmlChar*)"Value");
3037 if (value)
3039 // Active value
3040 setValue (value);
3042 // Delete the value
3043 xmlFree ((void*)value);
3045 else
3047 // Get content
3048 const char *valueText = (const char*)xmlNodeGetContent (node);
3049 if (valueText)
3051 setValue (valueText);
3053 // Delete the value
3054 xmlFree ((void*)valueText);
3060 // ***************************************************************************
3062 void CFormElmAtom::setValue (const std::string &value)
3064 Value = value;
3067 // ***************************************************************************
3069 void CFormElmAtom::getValue (std::string &result) const
3071 result = Value;
3074 // ***************************************************************************
3076 void CFormElmAtom::getFormName (std::string &result, const CFormElm *child) const
3078 // Must be NULL
3079 nlassert (child == NULL);
3080 result.clear();
3081 result.reserve (50);
3083 // Get parent form name
3084 if (ParentNode)
3085 ParentNode->getFormName (result, this);
3088 // ***************************************************************************
3090 void CFormElmAtom::warning (bool exception, const std::string &function, const char *format, ... ) const
3092 // Make a buffer string
3093 va_list args;
3094 va_start( args, format );
3095 char buffer[1024];
3096 vsnprintf( buffer, 1024, format, args );
3097 va_end( args );
3099 // Set the warning
3100 string formName;
3101 getFormName (formName, NULL);
3102 NLGEORGES::warning (exception, "(CFormElmAtom::%s) on node (%s) in form (%s) : %s", function.c_str(), formName.c_str (), Form->getFilename ().c_str (), buffer);
3105 // ***************************************************************************
3107 } // NLGEORGES