From 959f82eba1fc423da6f1947a50800fbf59d82a2b Mon Sep 17 00:00:00 2001 From: vincent <vincent@groupe-sa.fr> Date: Mon, 21 Dec 2015 17:35:32 +0100 Subject: [PATCH] New class QCronField. --- src/CMakeLists.txt | 1 + src/qcron.cpp | 187 ++++---------------------------------------- src/qcron.hpp | 82 +++---------------- src/qcronfield.cpp | 165 ++++++++++++++++++++++++++++++++++++++ src/qcronfield.hpp | 84 ++++++++++++++++++++ test/qcron_test.cpp | 7 +- 6 files changed, 282 insertions(+), 244 deletions(-) create mode 100644 src/qcronfield.cpp create mode 100644 src/qcronfield.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd3564a..65ad75f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,6 @@ set(${PROJECT}_SRC_FILES qcron.cpp + qcronfield.cpp ) set(${PROJECT}_HEADERS diff --git a/src/qcron.cpp b/src/qcron.cpp index e0bb6da..27d6cfe 100644 --- a/src/qcron.cpp +++ b/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(); +} diff --git a/src/qcron.hpp b/src/qcron.hpp index 6d2b6d3..d0f999d 100644 --- a/src/qcron.hpp +++ b/src/qcron.hpp @@ -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); diff --git a/src/qcronfield.cpp b/src/qcronfield.cpp new file mode 100644 index 0000000..d1912aa --- /dev/null +++ b/src/qcronfield.cpp @@ -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; + } +} + +/******************************************************************************/ diff --git a/src/qcronfield.hpp b/src/qcronfield.hpp new file mode 100644 index 0000000..27faef1 --- /dev/null +++ b/src/qcronfield.hpp @@ -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 diff --git a/test/qcron_test.cpp b/test/qcron_test.cpp index a780bbe..6b26631 100644 --- a/test/qcron_test.cpp +++ b/test/qcron_test.cpp @@ -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!"); } /******************************************************************************/