From 12df269ae0005e1cc94c7a37fdb5fe2e30d58bae Mon Sep 17 00:00:00 2001 From: Nathan Osman Date: Mon, 15 Jul 2013 22:19:40 -0700 Subject: [PATCH] Integrated new Lexer and Parser class into Client class. --- include/qredis/request.h | 23 ++++---- src/client.cpp | 121 ++++++--------------------------------- src/client_p.h | 26 ++++----- src/request.cpp | 2 +- 4 files changed, 42 insertions(+), 130 deletions(-) diff --git a/include/qredis/request.h b/include/qredis/request.h index 2f0e803..82564b7 100644 --- a/include/qredis/request.h +++ b/include/qredis/request.h @@ -41,16 +41,17 @@ namespace QRedis Q_SIGNALS: /** - * @brief Emitted when a bulk reply is received - * @param value the value as a byte array + * @brief Emitted when a status reply is received + * @param message a descriptive status message */ - void bulk(const QByteArray & value); + void status(const QString & message); /** * @brief Emitted when an error reply is received - * @param message a descriptive error message + * @param generic a generic error identifer + * @param specific a more specific error message */ - void error(const QString & message); + void error(const QString & generic, const QString & specific); /** * @brief Emitted when an integer reply is received @@ -58,6 +59,12 @@ namespace QRedis */ void integer(qlonglong value); + /** + * @brief Emitted when a bulk reply is received + * @param value the value as a byte array + */ + void bulk(const QByteArray & value); + /** * @brief Emitted when a multi-bulk reply is received * @param a list of bulk values @@ -69,12 +76,6 @@ namespace QRedis */ void reply(); - /** - * @brief Emitted when a status reply is received - * @param message a descriptive status message - */ - void status(const QString & message); - private: const QScopedPointer d; diff --git a/src/client.cpp b/src/client.cpp index d31b433..bd503a6 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -4,124 +4,41 @@ using namespace QRedis; ClientPrivate::ClientPrivate(Client * client) - : q(client) + : lexer(&socket), parser(&lexer) { - connect(&socket, &QTcpSocket::connected, q, &Client::connected); - connect(&socket, &QTcpSocket::disconnected, q, &Client::disconnected); - connect(&socket, &QTcpSocket::disconnected, this, &ClientPrivate::reset); - connect(&socket, &QTcpSocket::readyRead, this, &ClientPrivate::readReply); + connect(&socket, SIGNAL(connected()), client, SIGNAL(connected())); + connect(&socket, SIGNAL(disconnected()), client, SIGNAL(disconnected())); + + connect(&parser, SIGNAL(status(QString)), SLOT(sendStatus(QString))); + connect(&parser, SIGNAL(error(QString,QString)), SLOT(sendError(QString,QString))); + connect(&parser, SIGNAL(integer(qlonglong)), SLOT(sendInteger(qlonglong))); + connect(&parser, SIGNAL(bulk(QByteArray)), SLOT(sendBulk(QByteArray))); + connect(&parser, SIGNAL(multiBulk(QVariantList)), SLOT(sendMultiBulk(QVariantList))); } -int ClientPrivate::readInteger(qlonglong & value) +void ClientPrivate::sendStatus(const QString & message) { - int pos = buffer.indexOf("\r\n"); - if(pos != -1) - { - value = buffer.mid(0, pos).toLongLong(); - buffer.remove(0, pos + 2); - } - return pos; + emit queue.dequeue()->status(message); } -/* - * Note: error replies actually contain a type and then the error description - * but we just combine them here for simplicity. - */ - -bool ClientPrivate::readStatusOrErrorReply() +void ClientPrivate::sendError(const QString & generic, const QString & specific) { - /* Check if the reply contains \r\n. */ - int pos = buffer.indexOf("\r\n"); - if(pos != -1) - { - Request * request = queue.dequeue(); - - if(buffer[0] == '+') - emit request->status(buffer.mid(1, pos - 1)); - else - emit request->error(buffer.mid(1, pos - 1)); - - buffer.remove(0, pos + 2); - return true; - } - - return false; + emit queue.dequeue()->error(generic, specific); } -bool ClientPrivate::readIntegerReply() +void ClientPrivate::sendInteger(qlonglong value) { - /* Check if the reply contains \r\n. */ - int pos = buffer.indexOf("\r\n"); - if(pos != -1) - { - emit queue.dequeue()->integer(buffer.mid(1, pos -1).toLongLong()); - - buffer.remove(0, pos + 2); - return true; - } - - return false; + emit queue.dequeue()->integer(value); } -bool ClientPrivate::readBulkReply() +void ClientPrivate::sendBulk(const QByteArray & value) { - /* Check if the reply contains \r\n. */ - int pos = buffer.indexOf("\r\n"); - if(pos != -1) - { - int length = buffer.mid(1, pos -1).toInt(); - if(buffer.size() >= pos + length + 4) - { - emit queue.dequeue()->bulk(buffer.mid(pos + 2, length)); - - buffer.remove(0, pos + length + 4); - return true; - } - } - - return false; + emit queue.dequeue()->bulk(value); } -bool ClientPrivate::readMultiBulkReply() +void ClientPrivate::sendMultiBulk(const QVariantList & values) { - return false; -} - -void ClientPrivate::reset() -{ - foreach(Request * request, queue) - request->deleteLater(); - queue.clear(); -} - -// TODO: unrecognized replies in the switch should be handled. - -void ClientPrivate::readReply() -{ - buffer.append(socket.readAll()); - while(!buffer.isEmpty()) - { - bool finished; - switch(buffer[0]) - { - case '+': - case '-': - finished = readStatusOrErrorReply(); - break; - case ':': - finished = readIntegerReply(); - break; - case '$': - finished = readBulkReply(); - break; - case '*': - finished = readMultiBulkReply(); - break; - } - - if(!finished) - break; - } + emit queue.dequeue()->multiBulk(values); } Client::Client(QObject * parent) diff --git a/src/client_p.h b/src/client_p.h index 5d72511..7bc7074 100644 --- a/src/client_p.h +++ b/src/client_p.h @@ -7,6 +7,8 @@ #include #include +#include "lexer.h" +#include "parser.h" namespace QRedis { @@ -18,27 +20,19 @@ namespace QRedis ClientPrivate(Client *); - /* Utility methods for reading items from the buffer. */ - int readInteger(qlonglong &); - - bool readStatusOrErrorReply(); - bool readIntegerReply(); - bool readBulkReply(); - bool readMultiBulkReply(); - QTcpSocket socket; - QQueue queue; - QByteArray buffer; - public Q_SLOTS: + Lexer lexer; + Parser parser; - void reset(); - void readReply(); + private Q_SLOTS: - private: - - Client * const q; + void sendStatus(const QString &); + void sendError(const QString &, const QString &); + void sendInteger(qlonglong); + void sendBulk(const QByteArray &); + void sendMultiBulk(const QVariantList &); }; } diff --git a/src/request.cpp b/src/request.cpp index fa8177a..8342f5e 100644 --- a/src/request.cpp +++ b/src/request.cpp @@ -17,7 +17,7 @@ Request::Request(QObject * parent) * Each of these signals also causes the generic reply() signal to be emitted. */ connect(this, SIGNAL(bulk(QByteArray)), SIGNAL(reply())); - connect(this, SIGNAL(error(QString)), SIGNAL(reply())); + connect(this, SIGNAL(error(QString,QString)), SIGNAL(reply())); connect(this, SIGNAL(integer(qlonglong)), SIGNAL(reply())); connect(this, SIGNAL(multiBulk(QVariantList)), SIGNAL(reply())); connect(this, SIGNAL(status(QString)), SIGNAL(reply()));