mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / ndb / include / util / Parser.hpp
blob366384621bf35efb1fa7fc864b96974314bfea40
1 /* Copyright (c) 2003-2006 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 #ifndef CPCD_PARSER_HPP
17 #define CPCD_PARSER_HPP
19 #include "Vector.hpp"
20 #include "Properties.hpp"
21 #include "InputStream.hpp"
22 #include "NdbOut.hpp"
24 class ParserImpl;
25 template<class T> struct ParserRow;
27 //#define PARSER_DEBUG
28 #ifdef PARSER_DEBUG
29 #define DEBUG(x) \
30 ndbout_c("%s:%d:%s", __FILE__, __LINE__, x);
31 #else
32 #define DEBUG(x)
33 #endif
35 /**
36 * A generic parser
38 template<class T>
39 class Parser {
40 public:
41 /**
42 * Status for parser
44 enum ParserStatus {
45 Ok = 0,
46 Eof = 1,
47 NoLine = 2,
48 EmptyLine = 3,
49 UnknownCommand = 4,
50 UnknownArgument = 5,
51 TypeMismatch = 6,
52 InvalidArgumentFormat = 7,
53 UnknownArgumentType = 8,
54 CommandWithoutFunction = 9,
55 ArgumentGivenTwice = 10,
56 ExternalStop = 11,
57 MissingMandatoryArgument = 12
60 /**
61 * Context for parse
63 class Context {
64 public:
65 Context() { m_mutex= NULL; };
66 ParserStatus m_status;
67 const ParserRow<T> * m_currentCmd;
68 const ParserRow<T> * m_currentArg;
69 char * m_currentToken;
70 char m_tokenBuffer[512];
71 NdbMutex *m_mutex;
73 Vector<const ParserRow<T> *> m_aliasUsed;
76 /**
77 * Initialize parser
79 Parser(const ParserRow<T> rows[], class InputStream & in = Stdin,
80 bool breakOnCommand = false,
81 bool breakOnEmptyLine = true,
82 bool breakOnInvalidArg = false);
83 ~Parser();
85 /**
86 * Run parser
88 bool run(Context &, T &, volatile bool * stop = 0) const;
90 /**
91 * Parse only one entry and return Properties object representing
92 * the message
94 const Properties *parse(Context &, T &);
96 bool getBreakOnCommand() const;
97 void setBreakOnCommand(bool v);
99 bool getBreakOnEmptyLine() const;
100 void setBreakOnEmptyLine(bool v);
102 bool getBreakOnInvalidArg() const;
103 void setBreakOnInvalidArg(bool v);
105 private:
106 ParserImpl * impl;
109 template<class T>
110 struct ParserRow {
111 public:
112 enum Type { Cmd, Arg, CmdAlias, ArgAlias };
113 enum ArgType { String, Int, Properties };
114 enum ArgRequired { Mandatory, Optional };
115 enum ArgMinMax { CheckMinMax, IgnoreMinMax };
117 const char * name;
118 const char * realName;
119 Type type;
120 ArgType argType;
121 ArgRequired argRequired;
122 ArgMinMax argMinMax;
123 int minVal;
124 int maxVal;
125 void (T::* function)(typename Parser<T>::Context & ctx,
126 const class Properties& args);
127 const char * description;
128 void *user_value;
132 * The void* equivalent implementation
134 class ParserImpl {
135 public:
136 class Dummy {};
137 typedef ParserRow<Dummy> DummyRow;
138 typedef Parser<Dummy>::Context Context;
141 ParserImpl(const DummyRow rows[], class InputStream & in,
142 bool b_cmd, bool b_empty, bool b_iarg);
143 ~ParserImpl();
145 bool run(Context *ctx, const class Properties **, volatile bool *) const ;
147 static const DummyRow* matchCommand(Context*, const char*, const DummyRow*);
148 static const DummyRow* matchArg(Context*, const char *, const DummyRow *);
149 static bool parseArg(Context*, char*, const DummyRow*, Properties*);
150 static bool checkMandatory(Context*, const Properties*);
151 private:
152 const DummyRow * const m_rows;
153 class ParseInputStream & input;
154 bool m_breakOnEmpty;
155 bool m_breakOnCmd;
156 bool m_breakOnInvalidArg;
159 template<class T>
160 inline
161 Parser<T>::Parser(const ParserRow<T> rows[], class InputStream & in,
162 bool b_cmd, bool b_empty, bool b_iarg){
163 impl = new ParserImpl((ParserImpl::DummyRow *)rows, in,
164 b_cmd, b_empty, b_iarg);
167 template<class T>
168 inline
169 Parser<T>::~Parser(){
170 delete impl;
173 template<class T>
174 inline
175 bool
176 Parser<T>::run(Context & ctx, T & t, volatile bool * stop) const {
177 const Properties * p;
178 DEBUG("Executing Parser<T>::run");
179 if(impl->run((ParserImpl::Context*)&ctx, &p, stop)){
180 const ParserRow<T> * cmd = ctx.m_currentCmd; // Cast to correct type
181 if(cmd == 0){
183 * Should happen if run returns true
185 abort();
188 for(unsigned i = 0; i<ctx.m_aliasUsed.size(); i++){
189 const ParserRow<T> * alias = ctx.m_aliasUsed[i];
190 if(alias->function != 0){
192 * Report alias usage with callback (if specified by user)
194 DEBUG("Alias usage with callback");
195 (t.* alias->function)(ctx, * p);
199 if(cmd->function == 0){
200 ctx.m_status = CommandWithoutFunction;
201 DEBUG("CommandWithoutFunction");
202 delete p;
203 return false;
205 (t.* cmd->function)(ctx, * p); // Call the function
206 delete p;
207 return true;
209 DEBUG("");
210 return false;
213 template<class T>
214 inline
215 const Properties *
216 Parser<T>::parse(Context &ctx, T &t) {
217 const Properties * p;
218 volatile bool stop = false;
219 DEBUG("Executing Parser<T>::parse");
221 if(impl->run((ParserImpl::Context*)&ctx, &p, &stop)){
222 const ParserRow<T> * cmd = ctx.m_currentCmd; // Cast to correct type
223 if(cmd == 0){
225 * Should happen if run returns true
227 abort();
230 for(unsigned i = 0; i<ctx.m_aliasUsed.size(); i++){
231 const ParserRow<T> * alias = ctx.m_aliasUsed[i];
232 if(alias->function != 0){
234 * Report alias usage with callback (if specified by user)
236 DEBUG("Alias usage with callback");
237 (t.* alias->function)(ctx, * p);
241 if(cmd->function == 0){
242 DEBUG("CommandWithoutFunction");
243 ctx.m_status = CommandWithoutFunction;
244 return p;
246 return p;
248 DEBUG("");
249 return NULL;
252 template<class T>
253 inline
254 bool
255 Parser<T>::getBreakOnCommand() const{
256 return impl->m_breakOnCmd;
259 template<class T>
260 inline
261 void
262 Parser<T>::setBreakOnCommand(bool v){
263 impl->m_breakOnCmd = v;
266 template<class T>
267 inline
268 bool
269 Parser<T>::getBreakOnEmptyLine() const{
270 return impl->m_breakOnEmpty;
272 template<class T>
273 inline
274 void
275 Parser<T>::setBreakOnEmptyLine(bool v){
276 impl->m_breakOnEmpty = v;
279 template<class T>
280 inline
281 bool
282 Parser<T>::getBreakOnInvalidArg() const{
283 return impl->m_breakOnInvalidArg;
286 template<class T>
287 inline
288 void
289 Parser<T>::setBreakOnInvalidArg(bool v){
290 impl->m_breakOnInvalidArg = v;
293 #endif