~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/include/util/Parser.hpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2003 MySQL AB
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#ifndef CPCD_PARSER_HPP
 
17
#define CPCD_PARSER_HPP
 
18
 
 
19
#include "Vector.hpp"
 
20
#include "Properties.hpp"
 
21
#include "InputStream.hpp"
 
22
#include "NdbOut.hpp"
 
23
 
 
24
class ParserImpl;
 
25
template<class T> struct ParserRow;
 
26
 
 
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
 
34
 
 
35
/**
 
36
 * A generic parser
 
37
 */
 
38
template<class T>
 
39
class Parser {
 
40
public:
 
41
  /**
 
42
   * Status for parser
 
43
   */
 
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
 
58
  };
 
59
 
 
60
  /**
 
61
   * Context for parse
 
62
   */
 
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;
 
72
 
 
73
    Vector<const ParserRow<T> *> m_aliasUsed;
 
74
  };
 
75
  
 
76
  /**
 
77
   * Initialize parser
 
78
   */
 
79
  Parser(const ParserRow<T> rows[], class InputStream & in = Stdin,
 
80
         bool breakOnCommand = false, 
 
81
         bool breakOnEmptyLine = true, 
 
82
         bool breakOnInvalidArg = false);
 
83
  ~Parser();
 
84
  
 
85
  /**
 
86
   * Run parser
 
87
   */
 
88
  bool run(Context &, T &, volatile bool * stop = 0) const;
 
89
 
 
90
  /**
 
91
   * Parse only one entry and return Properties object representing
 
92
   * the message
 
93
   */
 
94
  const Properties *parse(Context &, T &);
 
95
 
 
96
  bool getBreakOnCommand() const;
 
97
  void setBreakOnCommand(bool v);
 
98
  
 
99
  bool getBreakOnEmptyLine() const;
 
100
  void setBreakOnEmptyLine(bool v);
 
101
 
 
102
  bool getBreakOnInvalidArg() const;
 
103
  void setBreakOnInvalidArg(bool v);
 
104
  
 
105
private:
 
106
  ParserImpl * impl;
 
107
};
 
108
 
 
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 };
 
116
  
 
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;
 
129
};
 
130
 
 
131
/**
 
132
 * The void* equivalent implementation
 
133
 */
 
134
class ParserImpl {
 
135
public:
 
136
  class Dummy {};
 
137
  typedef ParserRow<Dummy> DummyRow;
 
138
  typedef Parser<Dummy>::Context Context;
 
139
 
 
140
  
 
141
  ParserImpl(const DummyRow rows[], class InputStream & in,
 
142
             bool b_cmd, bool b_empty, bool b_iarg);
 
143
  ~ParserImpl();
 
144
  
 
145
  bool run(Context *ctx, const class Properties **, volatile bool *) const ;
 
146
  
 
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;
 
157
};
 
158
 
 
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);
 
165
}
 
166
 
 
167
template<class T>
 
168
inline
 
169
Parser<T>::~Parser(){
 
170
  delete impl;
 
171
}
 
172
 
 
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){
 
182
      /**
 
183
       * Should happen if run returns true
 
184
       */
 
185
      abort();
 
186
    }
 
187
 
 
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){
 
191
        /**
 
192
         * Report alias usage with callback (if specified by user)
 
193
         */
 
194
        DEBUG("Alias usage with callback");
 
195
        (t.* alias->function)(ctx, * p);
 
196
      }
 
197
    }
 
198
 
 
199
    if(cmd->function == 0){
 
200
      ctx.m_status = CommandWithoutFunction;
 
201
      DEBUG("CommandWithoutFunction");
 
202
      delete p;
 
203
      return false;
 
204
    }
 
205
    (t.* cmd->function)(ctx, * p); // Call the function
 
206
    delete p;
 
207
    return true;
 
208
  }
 
209
  DEBUG("");
 
210
  return false;
 
211
}
 
212
 
 
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");
 
220
 
 
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){
 
224
      /**
 
225
       * Should happen if run returns true
 
226
       */
 
227
      abort();
 
228
    }
 
229
 
 
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){
 
233
        /**
 
234
         * Report alias usage with callback (if specified by user)
 
235
         */
 
236
        DEBUG("Alias usage with callback");
 
237
        (t.* alias->function)(ctx, * p);
 
238
      }
 
239
    }
 
240
 
 
241
    if(cmd->function == 0){
 
242
      DEBUG("CommandWithoutFunction");
 
243
      ctx.m_status = CommandWithoutFunction;
 
244
      return p;
 
245
    }
 
246
    return p;
 
247
  }
 
248
  DEBUG("");
 
249
  return NULL;
 
250
}
 
251
 
 
252
template<class T>
 
253
inline
 
254
bool 
 
255
Parser<T>::getBreakOnCommand() const{
 
256
  return impl->m_breakOnCmd;
 
257
}
 
258
 
 
259
template<class T>
 
260
inline
 
261
void
 
262
Parser<T>::setBreakOnCommand(bool v){
 
263
  impl->m_breakOnCmd = v;
 
264
}
 
265
 
 
266
template<class T>
 
267
inline
 
268
bool
 
269
Parser<T>::getBreakOnEmptyLine() const{
 
270
  return impl->m_breakOnEmpty;
 
271
}
 
272
template<class T>
 
273
inline
 
274
void
 
275
Parser<T>::setBreakOnEmptyLine(bool v){
 
276
  impl->m_breakOnEmpty = v;
 
277
}
 
278
 
 
279
template<class T>
 
280
inline
 
281
bool
 
282
Parser<T>::getBreakOnInvalidArg() const{
 
283
  return impl->m_breakOnInvalidArg;
 
284
}
 
285
 
 
286
template<class T>
 
287
inline
 
288
void
 
289
Parser<T>::setBreakOnInvalidArg(bool v){
 
290
  impl->m_breakOnInvalidArg = v;
 
291
}
 
292
 
 
293
#endif