Salome HOME
Updated copyright comment
[modules/hexablock.git] / src / HEXABLOCK / HexXmlTree.cxx
1
2 // C++ : ParserXml
3
4 // Copyright (C) 2009-2024  CEA, EDF
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "HexXmlTree.hxx"
24
25 BEGIN_NAMESPACE_HEXA
26
27 enum { HEND_FILE = -2, HEND_LINE = -1, CRLF = 13 };
28
29 // ====================================================== Constructeur
30 XmlTree::XmlTree (const std::string& nom, XmlTree* dad)
31 {
32    item_name     = nom;
33    item_vide     = "";
34    xml_parent    = dad;
35    nbr_attributs = 0;
36    nbr_items     = 0;
37
38    fic_buffer  = "";
39    len_buffer  = 0;
40    xml_file    = NULL;
41    nro_ligne   = 0;
42    fic_pos     = 1988;
43
44    xml_flow  = NULL;
45    pos_flow  = 0;
46    xml_ended = true;
47 }
48 // ====================================================== Destructeur
49 XmlTree::~XmlTree ()
50 {
51 }
52 // ====================================================== findChild
53 XmlTree* XmlTree::findChild (const std::string& nom)
54 {
55    for (int nro = 0 ; nro<nbr_items ; nro++)
56        {
57        if (nom == tab_items [nro]->item_name)
58            return tab_items [nro];
59        }
60    return NULL;
61 }
62 // ====================================================== findAttribute
63 int XmlTree::findAttribute (const std::string& nom)
64 {
65    for (int nro = 0 ; nro<nbr_attributs ; nro++)
66        {
67        if (nom == tab_attributs [nro])
68           return nro;
69        }
70    return NOTHING;
71 }
72 // ====================================================== findValue
73 const std::string& XmlTree::findValue (const std::string& nom)
74 {
75    for (int nro = 0 ; nro<nbr_attributs ; nro++)
76        {
77        if (nom == tab_attributs [nro])
78           return  tab_values    [nro];
79        }
80    return item_vide;
81 }
82 // ====================================================== findInteger
83 int XmlTree::findInteger (const std::string& nom)
84 {
85    int   val = 0;
86    const std::string chnum = findValue (nom);
87    if (chnum==item_vide)
88       return val;
89
90    int lg = chnum.size();
91    for (int nc=0 ; nc<lg ; ++nc)
92        {
93        char car = chnum[nc];
94        if (car >= '0' && car <= '9')
95            val  = 10*val + car - '0';
96        }
97    return val;
98 }
99 // ====================================================== parseFile
100 int XmlTree::parseFile (const std::string& ficnom)
101 {
102    fic_buffer  = "";
103    len_buffer  = 0;
104    nro_ligne   = 0;
105    fic_pos     = 1988;
106    xml_flow    = NULL;
107    pos_flow    = 0;
108    xml_ended   = true;
109
110    xml_file = fopen (ficnom.c_str(), "r");
111    if (xml_file==NULL)
112       {
113       std::cout << " **** Fichier XML '" << ficnom << "' inaccessible"
114            << std::endl;
115       return HERR;
116       }
117
118    int ier = parseXml ();
119    return ier;
120 }
121 // ====================================================== parseStream
122 int XmlTree::parseStream (cpchar flux, int& posit)
123 {
124    fic_buffer  = "";
125    len_buffer  = 0;
126    nro_ligne   = 0;
127    fic_pos     = 1988;
128
129    xml_flow = flux;
130    pos_flow = posit;
131
132    int ier  = parseXml ();
133    posit    = pos_flow;
134    return ier;
135 }
136 // ====================================================== parseXml
137 int XmlTree::parseXml ()
138 {
139    xml_ended  = false;
140
141    enum EnumEtat { M_PREMS, M_BALISE_OUVERTE, M_NEUTRE };
142    EnumEtat etat =  M_PREMS;
143
144    XmlTree* node = this;
145    EnumItem item_lu;
146    std::string   nom, valeur, foo;
147    while ((item_lu=readItem (nom)) != M_NONE)
148       {
149       switch (item_lu)
150          {
151          case M_BEGIN :
152               item_lu = getItem (nom, M_IDENT);
153               if (etat==M_PREMS)
154                  setName (nom);
155               else
156                  node = node -> addChild  (nom);
157               etat = M_BALISE_OUVERTE;
158               break;
159
160          case M_END   :
161               if (etat != M_BALISE_OUVERTE)
162                  putError (" balise ouverte");
163               etat = M_NEUTRE;
164               break;
165
166          case M_BEGIN_CLOSE :
167               if (etat == M_BALISE_OUVERTE)
168                  putError (" balise ouverte");
169               getItem (nom, M_IDENT);
170               getItem (foo, M_END);
171               node = node -> getParent ();
172               if (node==NULL)
173                  return HOK;
174               break;
175
176          case M_CLOSE :
177               if (etat != M_BALISE_OUVERTE)
178                  putError (" balise deja fermee");
179               node = node -> getParent ();
180               etat = M_NEUTRE;
181               break;
182
183          case M_IDENT :
184               getItem (valeur, M_EQUALS);
185               getItem (valeur, M_STRING);
186               node -> addAttribut (nom, valeur);
187               break;
188
189          case M_COMMENT : goTo ("-->");
190               break;
191
192          case M_PROLOG  : goTo ("?>");
193               break;
194
195          default :
196          case M_EQUALS :
197          case M_STRING :
198          case M_END_COMMENT :
199          case M_END_PROLOG :
200               putError ("Item incorrect");
201          }
202       }
203    return HOK;
204 }
205 // ====================================================== getItem
206 EnumItem XmlTree::getItem (std::string& value, EnumItem waited)
207 {
208    EnumItem item = readItem (value);
209
210    if (item == waited)
211       return item;
212    putError ("Erreur de sequence");
213    return item;
214 }
215 // ====================================================== readItem
216 EnumItem XmlTree::readItem (std::string& value)
217 {
218    value  = "";
219
220    while (true)
221          {
222          if (fic_pos>=len_buffer)
223             {
224             int ier=readLine ();
225             if (ier==HEND_FILE)
226                return M_NONE;
227             }
228          else
229             {
230             char  car = fic_buffer [fic_pos++];
231
232             if (car=='=')
233                return M_EQUALS;
234             else if (car=='>')
235                return M_END;
236             else if (car=='"')
237                {
238                getString (value);
239                return M_STRING;
240                }
241             else if (isalpha (car))
242                {
243                getIdent (value);
244                return M_IDENT;
245                }
246
247             char ncar = fic_pos >= len_buffer ? ' ' : fic_buffer [fic_pos];
248             if (car=='/' && ncar == '>')
249                {
250                fic_pos++;
251                return M_CLOSE;
252                }
253             else if (car=='<')
254                {
255                if (ncar=='/')
256                   {
257                   fic_pos++;
258                   return M_BEGIN_CLOSE;
259                   }
260                else if (ncar=='?')
261                   {
262                   fic_pos++;
263                   return M_PROLOG;
264                   }
265                else if (ncar=='!')
266                   {
267                   fic_pos++;
268                   return M_COMMENT;
269                   }
270                else
271                   return M_BEGIN;
272                }
273             }
274          }
275 }
276 // ====================================================== getIdent
277 int XmlTree::getIdent (std::string& ident)
278 {
279    ident = "";
280
281    for (int nc=fic_pos-1; nc<len_buffer ; nc++)
282        {
283        char car = fic_buffer[nc];
284        if (isalnum (car) || car =='_')
285            {
286            ident.push_back (car);
287            }
288        else
289            {
290            fic_pos = nc;
291            return HOK;
292            }
293        }
294
295    fic_pos = len_buffer;
296    return HOK;
297 }
298 // ====================================================== goTo
299 int XmlTree::goTo (cpchar ouca)
300 {
301    int nbc = strlen (ouca) - 1;
302    int pos = 0;
303    int car = ' ';
304
305    while ((car = getChar ()) != EOF)
306        {
307        if (car!=ouca[pos])
308           pos = 0;
309        else if (pos<nbc)
310           pos++;
311        else
312           return HOK;
313        }
314
315    return HERR;
316 }
317 // ====================================================== getString
318 int XmlTree::getString (std::string& chaine)
319 {
320    chaine  = "";
321    int car = ' ';
322
323    while ((car = getChar ()) != EOF)
324        {
325        if (car=='"')
326           return HOK;
327        chaine.push_back (car);
328        }
329
330    return HERR;
331 }
332 // ====================================================== getChar
333 int XmlTree::getChar ()
334 {
335    while (true)
336          {
337          if (fic_pos<len_buffer)
338             {
339             fic_pos++;
340             return fic_buffer [fic_pos-1];
341             }
342          int ier = readLine ();
343          if (ier==HEND_FILE)
344             return EOF;
345          else
346             return EOL;
347          }
348 }
349 // ====================================================== readLine
350 int XmlTree::readLine ()
351 {
352    nro_ligne++;
353    fic_buffer = "";
354    fic_pos    = 0;
355
356    if (xml_ended)
357        return HEND_FILE;
358
359    len_buffer = 0;
360    int ier = HEND_LINE;
361    while (ier==HEND_LINE)
362          {
363          int carac = xml_flow != NULL ? xml_flow [pos_flow++]
364                                       : fgetc (xml_file);
365
366          if (carac==EOL || carac==CRLF)
367             {
368             ier = HOK;
369             }
370          else if (carac!=EOF && carac!=EOS)
371             {
372             fic_buffer.push_back (carac);
373             len_buffer ++;
374             }
375          else if (len_buffer > 0)
376             {
377             xml_ended = true;
378             ier = HOK;
379             }
380          else
381             {
382             xml_ended = true;
383             ier = HEND_FILE;
384             }
385          }
386    return HOK;
387 }
388 // ====================================================== putError
389 void XmlTree::putError (cpchar mess)
390 {
391      printf (" ***** Erreur : %s\n", mess);
392      printf (" +++ Derniere ligne lue : nro %d, %deme caractere\n",
393                nro_ligne, fic_pos);
394      printf ("%s\n", fic_buffer.c_str());
395      //  exit (102);
396 }
397 // ====================================================== addChild
398 XmlTree* XmlTree::addChild (const std::string& nom)
399 {
400    XmlTree* child = new XmlTree (nom, this);
401    tab_items.push_back (child);
402    nbr_items ++;
403    return child;
404 }
405 // ====================================================== addAttribut
406 void XmlTree::addAttribut (const std::string& nom, const std::string& value)
407 {
408    tab_attributs.push_back (nom);
409    tab_values   .push_back (value);
410    nbr_attributs ++;
411    // printf (" %s = %s\n", nom.c_str(), value.c_str());
412 }
413 // ====================================================== dump
414 void XmlTree::dump (int niveau)
415 {
416    std::string marge = "";
417    for (int niv=0 ; niv<niveau ; niv++)
418        marge += " | ";
419
420    std::cout << marge << item_name << std::endl;
421
422    for (int nc=0 ; nc<nbr_attributs ; nc++)
423        {
424        std::cout << marge  << " : "
425             << tab_attributs [nc] << " = '" << tab_values [nc]
426             << "'" << std::endl;
427        }
428
429    for (int nc=0 ; nc<nbr_items ; nc++)
430        {
431        tab_items [nc]->dump (niveau+1);
432        }
433
434 }
435 END_NAMESPACE_HEXA