Salome HOME
mergefrom branch BR_V511_PR tag mergeto_trunk_03feb09
[modules/yacs.git] / src / yacsloader / parserBase.cxx
1 //  Copyright (C) 2006-2008  CEA/DEN, EDF R&D
2 //
3 //  This library is free software; you can redistribute it and/or
4 //  modify it under the terms of the GNU Lesser General Public
5 //  License as published by the Free Software Foundation; either
6 //  version 2.1 of the License.
7 //
8 //  This library is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 //  Lesser General Public License for more details.
12 //
13 //  You should have received a copy of the GNU Lesser General Public
14 //  License along with this library; if not, write to the Free Software
15 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include "parserBase.hxx"
20 #include "Exception.hxx"
21 #include "Proc.hxx"
22 #include "Logger.hxx"
23 #include <sstream>
24
25 //#define _DEVDEBUG_
26 #include "YacsTrace.hxx"
27
28 YACS::ENGINE::Proc* currentProc;
29 XML_Parser p ;
30 std::stack<YACS::parser*> sp;
31
32 namespace YACS
33 {
34   parser parser::main_parser;
35
36 parser::~parser()
37 {
38   if(_level==0)
39     {
40       delete _counts;
41     }
42   else
43     {
44       DEBTRACE("Problem with parser: final stack level should be 0 and not " << _level);
45     }
46 }
47
48 std::stack<parser*>& parser::getStack()
49 {
50   return sp;
51 }
52
53 void parser::SetUserDataAndPush(parser* pp)
54 {
55   XML_SetUserData(p,pp);
56   sp.push(pp);
57   DEBTRACE("parser::SetUserDataAndPush, stack size: " << sp.size());
58 }
59
60 void XMLCALL parser::start(void *data, const XML_Char* el, const XML_Char** attr)
61 {
62   DEBTRACE("parser::start, stack size: " << sp.size());
63   parser* pp=static_cast <parser *> (data);
64   pp->incrCount(el);
65   pp->onStart(el,attr);
66 }
67
68 void parser::onEnd(const XML_Char *el,parser* child)
69 {
70   DEBTRACE("parser::onEnd: " << el)
71 }
72
73 void XMLCALL parser::end(void *data, const char *el)
74 {
75   DEBTRACE("parser::end: " << el);
76   parser* child=static_cast <parser *> (data);
77   sp.pop();
78   DEBTRACE("parser::end, stack size: " << sp.size());
79   parser* pp=sp.top();
80   XML_SetUserData(p,pp);
81   pp->onEnd(el,child);
82   child->endParser();
83 }
84
85 void parser::charData(const XML_Char *s, int len)
86 {
87   _content=_content+std::string(s,len);
88 }
89
90 void XMLCALL parser::charac(void *data, const XML_Char *s, int len)
91 {
92   parser* pp=static_cast <parser *> (data);
93   pp->charData(s,len);
94 }
95
96 void parser::endParser()
97 {
98   DEBTRACE("parser::endParser, level: " <<_level);
99   _level=_level-1;
100   if(_level>0)
101     {
102       delete _counts;
103       _counts=_stackCount.top();
104       _orderState=_stackOrder.top();
105       _stackCount.pop();
106       _stackOrder.pop();
107     }
108 }
109
110 void parser::init ()
111 {
112   DEBTRACE("parser::init, level: " <<_level);
113   if(_level>0)
114     {
115       _stackCount.push(_counts);
116       _stackOrder.push(_orderState);
117       _counts=new std::map<std::string,int>;
118     }
119   _level=_level+1;
120   _counts->clear();
121   _orderState=0;
122 }
123
124 void parser::incrCount(const XML_Char *el)
125 {
126   if(_counts->count(el)==0)
127     (*_counts)[el]=1;
128   else
129     (*_counts)[el]=(*_counts)[el]+1;
130 }
131
132 void parser::checkOrder(std::string& el)
133 {
134   if(_orders.count(el)==0)return;
135   if(_orders[el] < _orderState)
136     {
137       std::string msg="unexpected "+el+" element (wrong order)";
138       throw YACS::Exception::Exception(msg);
139     }
140   else if(_orders[el] > _orderState)
141     {
142       _orderState=_orders[el];
143     }
144 }
145
146 void parser::maxcount(std::string name, int max, std::string& el)
147 {
148   if(el!=name)return;
149   if((*_counts)[name]>max)
150     {
151       std::stringstream msg;
152       msg <<"unexpected "+name+" element (count="<<(*_counts)[name];
153       msg <<" > maxOccurs=" << max << ")";
154       throw YACS::Exception::Exception(msg.str());
155     }
156 }
157
158 void parser::mincount(std::string name,int min )
159 {
160   if((*_counts)[name]<min)
161     {
162       std::stringstream msg;
163       msg<<"expected "+name+" element (count="<<(*_counts)[name];
164       msg << " < minOccurs=" << min << ")";
165       throw YACS::Exception::Exception(msg.str());
166     }
167 }
168
169 void parser::maxchoice(std::string *names, int max, std::string& el)
170 {
171   int i=0;
172   int ncount=0;
173   while (names[i]!= "")
174     {
175       ncount=ncount+(*_counts)[names[i]];
176       ++i;
177     }
178   if(ncount>max)
179     {
180       std::stringstream msg;
181       msg<<"unexpected "+el+" element (choice count="<<ncount<<" > maxOccurs=" << max << ")";
182       throw YACS::Exception::Exception(msg.str());
183     }
184 }
185
186 void parser::minchoice(std::string *names, int min)
187 {
188   int i=0;
189   int ncount=0;
190   while (names[i]!= "")
191     {
192       ncount=ncount+(*_counts)[names[i]];
193       ++i;
194     }
195   if(ncount<min)
196     {
197       std::stringstream msg;
198       msg << "expected element ";
199       i=0;
200       while (names[i]!= "")
201         {
202           msg << names[i] << ",";
203           ++i;
204         }
205       msg << "(choice count="<<ncount<<" < minOccurs=" << min << ")";
206       throw YACS::Exception::Exception(msg.str());
207     }
208 }
209
210 void parser::required(const std::string& name, const XML_Char** attr)
211 {
212   for (int i = 0; attr[i]; i += 2) 
213     {
214       if(name == std::string(attr[i]))return;
215     }
216   throw YACS::Exception::Exception("Attribute: "+name+" is required");
217 }
218
219 void parser::buildAttr(const XML_Char** attr)
220 {
221   for (int i = 0; attr[i]; i += 2) 
222     {
223       DEBTRACE(attr[i] << "=" << attr[i + 1]);
224     }
225 }
226
227 void parser::onStart(const XML_Char* el, const XML_Char** attr)
228 {
229   DEBTRACE( "parser::onStart: " << el );
230   SetUserDataAndPush(&main_parser);
231   main_parser.init();
232   main_parser.pre();
233   main_parser.buildAttr(attr);
234 }
235
236 void parser::logError(const std::string& reason)
237 {
238   DEBTRACE( "parser::logError: " << _file );
239   currentProc->getLogger("parser")->error(reason,main_parser._file.c_str(),XML_GetCurrentLineNumber(p));
240 }
241
242 }