New class QCronField.
This commit is contained in:
parent
c8a21f4eeb
commit
959f82eba1
@ -1,5 +1,6 @@
|
||||
set(${PROJECT}_SRC_FILES
|
||||
qcron.cpp
|
||||
qcronfield.cpp
|
||||
)
|
||||
|
||||
set(${PROJECT}_HEADERS
|
||||
|
187
src/qcron.cpp
187
src/qcron.cpp
@ -35,173 +35,12 @@ QCron::
|
||||
_init()
|
||||
{
|
||||
_is_valid = true;
|
||||
_fields[0].field = MINUTE;
|
||||
_fields[1].field = HOUR;
|
||||
_fields[2].field = DOM;
|
||||
_fields[3].field = MONTH;
|
||||
_fields[4].field = DOW;
|
||||
_fields[5].field = YEAR;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
QString
|
||||
QCron::
|
||||
_validCharacters(EField field)
|
||||
{
|
||||
Q_UNUSED(field);
|
||||
return "0123456789*-/,";
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
QCron::IntNode *
|
||||
QCron::
|
||||
QCronField::parseInt(QString & str)
|
||||
{
|
||||
IntNode * node = new IntNode();
|
||||
int value = 0;
|
||||
int char_idx = 0;
|
||||
QChar c = str[char_idx];
|
||||
while (c.isDigit())
|
||||
{
|
||||
value = value * 10 + c.digitValue();
|
||||
c = str[++char_idx];
|
||||
}
|
||||
if (char_idx == 0)
|
||||
{
|
||||
throw 42;
|
||||
}
|
||||
str.remove(0, char_idx);
|
||||
node->value = value;
|
||||
//qDebug() << "Parsing an Int :" << value;
|
||||
switch (field)
|
||||
{
|
||||
case MINUTE: if (value < 0 || 59 < value) throw 42; break;
|
||||
case HOUR: if (value < 0 || 23 < value) throw 42; break;
|
||||
case DOM: if (value < 1 || 31 < value) throw 42; break;
|
||||
case MONTH: if (value < 1 || 12 < value) throw 42; break;
|
||||
case DOW: if (value < 1 || 7 < value) throw 42; break;
|
||||
case YEAR: if (value < 2016 || 2099 < value) throw 42; break;
|
||||
default: throw 42; break;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
QCron::RangeNode*
|
||||
QCron::
|
||||
QCronField::parseRange(QString & str)
|
||||
{
|
||||
// qDebug() << "Parsing a Range";
|
||||
if (last_node == NULL)
|
||||
{
|
||||
throw 42;
|
||||
}
|
||||
RangeNode * range = new RangeNode();
|
||||
IntNode * begin = dynamic_cast<IntNode *>(last_node);
|
||||
if (begin == NULL)
|
||||
{
|
||||
throw 42;
|
||||
}
|
||||
range->begin = begin;
|
||||
str.remove(0, 1);
|
||||
IntNode * end = dynamic_cast<IntNode *>(parseInt(str));
|
||||
if (end == NULL)
|
||||
{
|
||||
throw 42;
|
||||
}
|
||||
range->end = end;
|
||||
if (range->begin->value > range->end->value)
|
||||
{
|
||||
throw 42;
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
QCron::EveryNode*
|
||||
QCron::
|
||||
QCronField::parseEvery(QString & str)
|
||||
{
|
||||
// qDebug() << "Parsing an Every";
|
||||
EveryNode * every = new EveryNode();
|
||||
every->what = last_node;
|
||||
str.remove(0, 1);
|
||||
every->freq = parseInt(str);
|
||||
return every;
|
||||
}
|
||||
|
||||
QCron::ListNode*
|
||||
QCron::
|
||||
QCronField::parseList(QString & str)
|
||||
{
|
||||
// qDebug() << "Parsing a List";
|
||||
ListNode * list = new ListNode();
|
||||
list->nodes << last_node;
|
||||
last_node = list;
|
||||
while (str[0] == ',')
|
||||
{
|
||||
str.remove(0, 1);
|
||||
Node * node = parseNode(str);
|
||||
list->nodes << node;
|
||||
last_node = node;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
QCron::Node *
|
||||
QCron::
|
||||
QCronField::
|
||||
parseNode(QString & str)
|
||||
{
|
||||
//qDebug() << "Parsing a node";
|
||||
QChar c = str[0];
|
||||
if (c.isDigit())
|
||||
{
|
||||
return parseInt(str);
|
||||
}
|
||||
else if ("-" == c)
|
||||
{
|
||||
return parseRange(str);
|
||||
}
|
||||
else if ("/" == c)
|
||||
{
|
||||
return parseEvery(str);
|
||||
}
|
||||
else if ("*" == c)
|
||||
{
|
||||
return new AllNode;
|
||||
}
|
||||
else if ("," == c)
|
||||
{
|
||||
return parseList(str);
|
||||
}
|
||||
throw 42;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
void
|
||||
QCron::
|
||||
QCronField::
|
||||
parse(QString & str)
|
||||
{
|
||||
try
|
||||
{
|
||||
last_node = NULL;
|
||||
Node * root = parseNode(str);
|
||||
if (!str.isEmpty())
|
||||
{
|
||||
last_node = root;
|
||||
root = parseNode(str);
|
||||
}
|
||||
is_valid = true;
|
||||
}
|
||||
catch (int)
|
||||
{
|
||||
is_valid = false;
|
||||
}
|
||||
_fields[0].setField(MINUTE);
|
||||
_fields[1].setField(HOUR);
|
||||
_fields[2].setField(DOM);
|
||||
_fields[3].setField(MONTH);
|
||||
_fields[4].setField(DOW);
|
||||
_fields[5].setField(YEAR);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -224,13 +63,17 @@ _parsePattern(QString & pattern)
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
_fields[i].parse(fields[i]);
|
||||
_is_valid &= _fields[i].is_valid;
|
||||
_is_valid &= _fields[i].isValid();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
|
||||
|
||||
*/
|
||||
QDateTime
|
||||
QCron::
|
||||
next(int n) const
|
||||
{
|
||||
Q_UNUSED(n);
|
||||
//QCronField seconds = _fields[0];
|
||||
return QDateTime::currentDateTime();
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
#define _QCRON_HPP
|
||||
|
||||
#include <QObject>
|
||||
#include <QDateTime>
|
||||
#include "qcronfield.hpp"
|
||||
|
||||
class QCron : public QObject
|
||||
{
|
||||
@ -12,87 +14,25 @@ public:
|
||||
QCron(QString & pattern);
|
||||
~QCron();
|
||||
|
||||
// Features.
|
||||
// Accessors.
|
||||
void setBeginning(const QDateTime & date_time)
|
||||
{ _beginning = date_time; }
|
||||
|
||||
bool isValid() const
|
||||
{ return _is_valid; }
|
||||
|
||||
// Features.
|
||||
|
||||
QDateTime next(int n = 1) const;
|
||||
|
||||
signals:
|
||||
void activated();
|
||||
void deactivated();
|
||||
|
||||
private:
|
||||
enum EField
|
||||
{
|
||||
MINUTE,
|
||||
HOUR,
|
||||
DOM,
|
||||
MONTH,
|
||||
DOW,
|
||||
YEAR
|
||||
};
|
||||
|
||||
|
||||
struct Node
|
||||
{
|
||||
virtual ~Node() {}
|
||||
};
|
||||
|
||||
struct ValueNode : public Node
|
||||
{
|
||||
};
|
||||
|
||||
struct IntNode : public ValueNode
|
||||
{
|
||||
int value;
|
||||
};
|
||||
|
||||
struct StrNode : public ValueNode
|
||||
{
|
||||
};
|
||||
|
||||
struct AllNode : public ValueNode
|
||||
{
|
||||
};
|
||||
|
||||
struct RangeNode : public Node
|
||||
{
|
||||
IntNode * begin;
|
||||
IntNode * end;
|
||||
};
|
||||
|
||||
struct EveryNode : public Node
|
||||
{
|
||||
Node * what;
|
||||
IntNode * freq;
|
||||
};
|
||||
|
||||
struct ListNode : public Node
|
||||
{
|
||||
QList<Node*> nodes;
|
||||
};
|
||||
|
||||
struct QCronField
|
||||
{
|
||||
EField field;
|
||||
bool is_valid;
|
||||
Node * last_node;
|
||||
Node * root;
|
||||
|
||||
QCronField()
|
||||
: is_valid(false)
|
||||
{}
|
||||
|
||||
IntNode * parseInt(QString & str);
|
||||
RangeNode* parseRange(QString & str);
|
||||
EveryNode* parseEvery(QString & str);
|
||||
ListNode * parseList(QString & str);
|
||||
Node * parseNode(QString & str);
|
||||
void parse(QString&);
|
||||
|
||||
};
|
||||
|
||||
bool _is_valid;
|
||||
QCronField _fields[6];
|
||||
QDateTime _beginning;
|
||||
|
||||
void _init();
|
||||
void _parsePattern(QString & pattern);
|
||||
|
165
src/qcronfield.cpp
Normal file
165
src/qcronfield.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
#include "qcronfield.hpp"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
QCronField::
|
||||
QCronField()
|
||||
: _is_valid(false)
|
||||
{}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
IntNode *
|
||||
QCronField::
|
||||
_parseInt(QString & str)
|
||||
{
|
||||
IntNode * node = new IntNode();
|
||||
int value = 0;
|
||||
int char_idx = 0;
|
||||
QChar c = str[char_idx];
|
||||
while (c.isDigit())
|
||||
{
|
||||
value = value * 10 + c.digitValue();
|
||||
c = str[++char_idx];
|
||||
}
|
||||
if (char_idx == 0)
|
||||
{
|
||||
throw 42;
|
||||
}
|
||||
str.remove(0, char_idx);
|
||||
node->value = value;
|
||||
//qDebug() << "Parsing an Int :" << value;
|
||||
switch (_field)
|
||||
{
|
||||
case MINUTE: if (value < 0 || 59 < value) throw 42; break;
|
||||
case HOUR: if (value < 0 || 23 < value) throw 42; break;
|
||||
case DOM: if (value < 1 || 31 < value) throw 42; break;
|
||||
case MONTH: if (value < 1 || 12 < value) throw 42; break;
|
||||
case DOW: if (value < 1 || 7 < value) throw 42; break;
|
||||
case YEAR: if (value < 2016 || 2099 < value) throw 42; break;
|
||||
default: throw 42; break;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
RangeNode*
|
||||
QCronField::
|
||||
_parseRange(QString & str)
|
||||
{
|
||||
// qDebug() << "Parsing a Range";
|
||||
if (_last_node == NULL)
|
||||
{
|
||||
throw 42;
|
||||
}
|
||||
RangeNode * range = new RangeNode();
|
||||
IntNode * begin = dynamic_cast<IntNode *>(_last_node);
|
||||
if (begin == NULL)
|
||||
{
|
||||
throw 42;
|
||||
}
|
||||
range->begin = begin;
|
||||
str.remove(0, 1);
|
||||
IntNode * end = dynamic_cast<IntNode *>(_parseInt(str));
|
||||
if (end == NULL)
|
||||
{
|
||||
throw 42;
|
||||
}
|
||||
range->end = end;
|
||||
if (range->begin->value > range->end->value)
|
||||
{
|
||||
throw 42;
|
||||
}
|
||||
return range;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
EveryNode*
|
||||
QCronField::
|
||||
_parseEvery(QString & str)
|
||||
{
|
||||
// qDebug() << "Parsing an Every";
|
||||
EveryNode * every = new EveryNode();
|
||||
every->what = _last_node;
|
||||
str.remove(0, 1);
|
||||
every->freq = _parseInt(str);
|
||||
return every;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
ListNode*
|
||||
QCronField::
|
||||
_parseList(QString & str)
|
||||
{
|
||||
// qDebug() << "Parsing a List";
|
||||
ListNode * list = new ListNode();
|
||||
list->nodes << _last_node;
|
||||
_last_node = list;
|
||||
while (str[0] == ',')
|
||||
{
|
||||
str.remove(0, 1);
|
||||
Node * node = _parseNode(str);
|
||||
list->nodes << node;
|
||||
_last_node = node;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
Node *
|
||||
QCronField::
|
||||
_parseNode(QString & str)
|
||||
{
|
||||
//qDebug() << "Parsing a node";
|
||||
QChar c = str[0];
|
||||
if (c.isDigit())
|
||||
{
|
||||
return _parseInt(str);
|
||||
}
|
||||
else if ("-" == c)
|
||||
{
|
||||
return _parseRange(str);
|
||||
}
|
||||
else if ("/" == c)
|
||||
{
|
||||
return _parseEvery(str);
|
||||
}
|
||||
else if ("*" == c)
|
||||
{
|
||||
return new AllNode;
|
||||
}
|
||||
else if ("," == c)
|
||||
{
|
||||
return _parseList(str);
|
||||
}
|
||||
throw 42;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
QCronField::
|
||||
parse(QString & str)
|
||||
{
|
||||
try
|
||||
{
|
||||
_last_node = NULL;
|
||||
Node * _root = _parseNode(str);
|
||||
if (!str.isEmpty())
|
||||
{
|
||||
_last_node = _root;
|
||||
_root = _parseNode(str);
|
||||
}
|
||||
_is_valid = true;
|
||||
}
|
||||
catch (int)
|
||||
{
|
||||
_is_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
84
src/qcronfield.hpp
Normal file
84
src/qcronfield.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
#ifndef _QCRONFIELD_HPP
|
||||
#define _QCRONFIELD_HPP
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
enum EField
|
||||
{
|
||||
MINUTE,
|
||||
HOUR,
|
||||
DOM,
|
||||
MONTH,
|
||||
DOW,
|
||||
YEAR
|
||||
};
|
||||
|
||||
struct Node
|
||||
{
|
||||
virtual ~Node() {}
|
||||
};
|
||||
|
||||
struct ValueNode : public Node
|
||||
{
|
||||
};
|
||||
|
||||
struct IntNode : public ValueNode
|
||||
{
|
||||
int value;
|
||||
};
|
||||
|
||||
struct StrNode : public ValueNode
|
||||
{
|
||||
};
|
||||
|
||||
struct AllNode : public ValueNode
|
||||
{
|
||||
};
|
||||
|
||||
struct RangeNode : public Node
|
||||
{
|
||||
IntNode * begin;
|
||||
IntNode * end;
|
||||
};
|
||||
|
||||
struct EveryNode : public Node
|
||||
{
|
||||
Node * what;
|
||||
IntNode * freq;
|
||||
};
|
||||
|
||||
struct ListNode : public Node
|
||||
{
|
||||
QList<Node*> nodes;
|
||||
};
|
||||
|
||||
class QCronField
|
||||
{
|
||||
public:
|
||||
QCronField();
|
||||
|
||||
// Accessors.
|
||||
void setField(EField field)
|
||||
{ _field = field; }
|
||||
|
||||
// Features.
|
||||
void parse(QString & str);
|
||||
|
||||
bool isValid() const
|
||||
{ return _is_valid; }
|
||||
|
||||
private:
|
||||
EField _field;
|
||||
bool _is_valid;
|
||||
Node * _last_node;
|
||||
Node * _root;
|
||||
|
||||
IntNode * _parseInt(QString & str);
|
||||
RangeNode* _parseRange(QString & str);
|
||||
EveryNode* _parseEvery(QString & str);
|
||||
ListNode * _parseList(QString & str);
|
||||
Node * _parseNode(QString & str);
|
||||
};
|
||||
|
||||
#endif
|
@ -8,7 +8,12 @@ void
|
||||
QCronTest::
|
||||
basics()
|
||||
{
|
||||
QFAIL("Nothing here.");
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
QCron c("* * * * * *");
|
||||
c.setBeginning(now);
|
||||
QDateTime next = c.next();
|
||||
qDebug() << next;
|
||||
QFAIL("Nope!");
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
Loading…
x
Reference in New Issue
Block a user