mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Initial revision of NDB Cluster files
BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted
This commit is contained in:
290
ndb/include/util/Parser.hpp
Normal file
290
ndb/include/util/Parser.hpp
Normal file
@ -0,0 +1,290 @@
|
||||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifndef CPCD_PARSER_HPP
|
||||
#define CPCD_PARSER_HPP
|
||||
|
||||
#include "Vector.hpp"
|
||||
#include "Properties.hpp"
|
||||
#include "InputStream.hpp"
|
||||
#include "NdbOut.hpp"
|
||||
|
||||
class ParserImpl;
|
||||
template<class T> class ParserRow;
|
||||
|
||||
//#define PARSER_DEBUG
|
||||
#ifdef PARSER_DEBUG
|
||||
#define DEBUG(x) \
|
||||
ndbout_c("%s:%d:%s", __FILE__, __LINE__, x);
|
||||
#else
|
||||
#define DEBUG(x)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A generic parser
|
||||
*/
|
||||
template<class T>
|
||||
class Parser {
|
||||
public:
|
||||
/**
|
||||
* Status for parser
|
||||
*/
|
||||
enum ParserStatus {
|
||||
Ok = 0,
|
||||
Eof = 1,
|
||||
NoLine = 2,
|
||||
EmptyLine = 3,
|
||||
UnknownCommand = 4,
|
||||
UnknownArgument = 5,
|
||||
TypeMismatch = 6,
|
||||
InvalidArgumentFormat = 7,
|
||||
UnknownArgumentType = 8,
|
||||
CommandWithoutFunction = 9,
|
||||
ArgumentGivenTwice = 10,
|
||||
ExternalStop = 11,
|
||||
MissingMandatoryArgument = 12
|
||||
};
|
||||
|
||||
/**
|
||||
* Context for parse
|
||||
*/
|
||||
struct Context {
|
||||
ParserStatus m_status;
|
||||
const ParserRow<T> * m_currentCmd;
|
||||
const ParserRow<T> * m_currentArg;
|
||||
char * m_currentToken;
|
||||
char m_tokenBuffer[512];
|
||||
|
||||
Vector<const ParserRow<T> *> m_aliasUsed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize parser
|
||||
*/
|
||||
Parser(const ParserRow<T> rows[], class InputStream & in = Stdin,
|
||||
bool breakOnCommand = false,
|
||||
bool breakOnEmptyLine = true,
|
||||
bool breakOnInvalidArg = false);
|
||||
~Parser();
|
||||
|
||||
/**
|
||||
* Run parser
|
||||
*/
|
||||
bool run(Context &, T &, volatile bool * stop = 0) const;
|
||||
|
||||
/**
|
||||
* Parse only one entry and return Properties object representing
|
||||
* the message
|
||||
*/
|
||||
const Properties *parse(Context &, T &);
|
||||
|
||||
bool getBreakOnCommand() const;
|
||||
void setBreakOnCommand(bool v);
|
||||
|
||||
bool getBreakOnEmptyLine() const;
|
||||
void setBreakOnEmptyLine(bool v);
|
||||
|
||||
bool getBreakOnInvalidArg() const;
|
||||
void setBreakOnInvalidArg(bool v);
|
||||
|
||||
private:
|
||||
ParserImpl * impl;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct ParserRow {
|
||||
public:
|
||||
enum Type { Cmd, Arg, CmdAlias, ArgAlias };
|
||||
enum ArgType { String, Int, Properties };
|
||||
enum ArgRequired { Mandatory, Optional };
|
||||
enum ArgMinMax { CheckMinMax, IgnoreMinMax };
|
||||
|
||||
const char * name;
|
||||
const char * realName;
|
||||
Type type;
|
||||
ArgType argType;
|
||||
ArgRequired argRequired;
|
||||
ArgMinMax argMinMax;
|
||||
int minVal;
|
||||
int maxVal;
|
||||
void (T::* function)(typename Parser<T>::Context & ctx,
|
||||
const class Properties& args);
|
||||
const char * description;
|
||||
void *user_value;
|
||||
};
|
||||
|
||||
/**
|
||||
* The void* equivalent implementation
|
||||
*/
|
||||
class ParserImpl {
|
||||
class Dummy {};
|
||||
typedef ParserRow<Dummy> DummyRow;
|
||||
typedef Parser<Dummy>::Context Context;
|
||||
template<class T> friend class Parser;
|
||||
private:
|
||||
|
||||
ParserImpl(const DummyRow rows[], class InputStream & in,
|
||||
bool b_cmd, bool b_empty, bool b_iarg);
|
||||
~ParserImpl();
|
||||
|
||||
bool run(Context *ctx, const class Properties **, volatile bool *) const ;
|
||||
|
||||
static const DummyRow* matchCommand(Context*, const char*, const DummyRow*);
|
||||
static const DummyRow* matchArg(Context*, const char *, const DummyRow *);
|
||||
static bool parseArg(Context*, char*, const DummyRow*, Properties*);
|
||||
static bool checkMandatory(Context*, const Properties*);
|
||||
private:
|
||||
const DummyRow * const m_rows;
|
||||
class ParseInputStream & input;
|
||||
bool m_breakOnEmpty;
|
||||
bool m_breakOnCmd;
|
||||
bool m_breakOnInvalidArg;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
Parser<T>::Parser(const ParserRow<T> rows[], class InputStream & in,
|
||||
bool b_cmd, bool b_empty, bool b_iarg){
|
||||
impl = new ParserImpl((ParserImpl::DummyRow *)rows, in,
|
||||
b_cmd, b_empty, b_iarg);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
Parser<T>::~Parser(){
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool
|
||||
Parser<T>::run(Context & ctx, T & t, volatile bool * stop) const {
|
||||
const Properties * p;
|
||||
DEBUG("Executing Parser<T>::run");
|
||||
if(impl->run((ParserImpl::Context*)&ctx, &p, stop)){
|
||||
const ParserRow<T> * cmd = ctx.m_currentCmd; // Cast to correct type
|
||||
if(cmd == 0){
|
||||
/**
|
||||
* Should happen if run returns true
|
||||
*/
|
||||
abort();
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i<ctx.m_aliasUsed.size(); i++){
|
||||
const ParserRow<T> * alias = ctx.m_aliasUsed[i];
|
||||
if(alias->function != 0){
|
||||
/**
|
||||
* Report alias usage with callback (if specified by user)
|
||||
*/
|
||||
DEBUG("Alias usage with callback");
|
||||
(t.* alias->function)(ctx, * p);
|
||||
}
|
||||
}
|
||||
|
||||
if(cmd->function == 0){
|
||||
ctx.m_status = CommandWithoutFunction;
|
||||
DEBUG("CommandWithoutFunction");
|
||||
delete p;
|
||||
return false;
|
||||
}
|
||||
(t.* cmd->function)(ctx, * p); // Call the function
|
||||
delete p;
|
||||
return true;
|
||||
}
|
||||
DEBUG("");
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
const Properties *
|
||||
Parser<T>::parse(Context &ctx, T &t) {
|
||||
const Properties * p;
|
||||
volatile bool stop = false;
|
||||
DEBUG("Executing Parser<T>::parse");
|
||||
|
||||
if(impl->run((ParserImpl::Context*)&ctx, &p, &stop)){
|
||||
const ParserRow<T> * cmd = ctx.m_currentCmd; // Cast to correct type
|
||||
if(cmd == 0){
|
||||
/**
|
||||
* Should happen if run returns true
|
||||
*/
|
||||
abort();
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i<ctx.m_aliasUsed.size(); i++){
|
||||
const ParserRow<T> * alias = ctx.m_aliasUsed[i];
|
||||
if(alias->function != 0){
|
||||
/**
|
||||
* Report alias usage with callback (if specified by user)
|
||||
*/
|
||||
DEBUG("Alias usage with callback");
|
||||
(t.* alias->function)(ctx, * p);
|
||||
}
|
||||
}
|
||||
|
||||
if(cmd->function == 0){
|
||||
DEBUG("CommandWithoutFunction");
|
||||
ctx.m_status = CommandWithoutFunction;
|
||||
return p;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
DEBUG("");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool
|
||||
Parser<T>::getBreakOnCommand() const{
|
||||
return impl->m_breakOnCmd;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
void
|
||||
Parser<T>::setBreakOnCommand(bool v){
|
||||
impl->m_breakOnCmd = v;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool
|
||||
Parser<T>::getBreakOnEmptyLine() const{
|
||||
return impl->m_breakOnEmpty;
|
||||
}
|
||||
template<class T>
|
||||
inline
|
||||
void
|
||||
Parser<T>::setBreakOnEmptyLine(bool v){
|
||||
impl->m_breakOnEmpty = v;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool
|
||||
Parser<T>::getBreakOnInvalidArg() const{
|
||||
return impl->m_breakOnInvalidArg;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
void
|
||||
Parser<T>::setBreakOnInvalidArg(bool v){
|
||||
impl->m_breakOnInvalidArg;
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user