Integrated new Lexer and Parser class into Client class.
This commit is contained in:
parent
ac876e196e
commit
12df269ae0
|
|
@ -41,16 +41,17 @@ namespace QRedis
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Emitted when a bulk reply is received
|
* @brief Emitted when a status reply is received
|
||||||
* @param value the value as a byte array
|
* @param message a descriptive status message
|
||||||
*/
|
*/
|
||||||
void bulk(const QByteArray & value);
|
void status(const QString & message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Emitted when an error reply is received
|
* @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
|
* @brief Emitted when an integer reply is received
|
||||||
|
|
@ -58,6 +59,12 @@ namespace QRedis
|
||||||
*/
|
*/
|
||||||
void integer(qlonglong value);
|
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
|
* @brief Emitted when a multi-bulk reply is received
|
||||||
* @param a list of bulk values
|
* @param a list of bulk values
|
||||||
|
|
@ -69,12 +76,6 @@ namespace QRedis
|
||||||
*/
|
*/
|
||||||
void reply();
|
void reply();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Emitted when a status reply is received
|
|
||||||
* @param message a descriptive status message
|
|
||||||
*/
|
|
||||||
void status(const QString & message);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const QScopedPointer<RequestPrivate> d;
|
const QScopedPointer<RequestPrivate> d;
|
||||||
|
|
|
||||||
121
src/client.cpp
121
src/client.cpp
|
|
@ -4,124 +4,41 @@
|
||||||
using namespace QRedis;
|
using namespace QRedis;
|
||||||
|
|
||||||
ClientPrivate::ClientPrivate(Client * client)
|
ClientPrivate::ClientPrivate(Client * client)
|
||||||
: q(client)
|
: lexer(&socket), parser(&lexer)
|
||||||
{
|
{
|
||||||
connect(&socket, &QTcpSocket::connected, q, &Client::connected);
|
connect(&socket, SIGNAL(connected()), client, SIGNAL(connected()));
|
||||||
connect(&socket, &QTcpSocket::disconnected, q, &Client::disconnected);
|
connect(&socket, SIGNAL(disconnected()), client, SIGNAL(disconnected()));
|
||||||
connect(&socket, &QTcpSocket::disconnected, this, &ClientPrivate::reset);
|
|
||||||
connect(&socket, &QTcpSocket::readyRead, this, &ClientPrivate::readReply);
|
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");
|
emit queue.dequeue()->status(message);
|
||||||
if(pos != -1)
|
|
||||||
{
|
|
||||||
value = buffer.mid(0, pos).toLongLong();
|
|
||||||
buffer.remove(0, pos + 2);
|
|
||||||
}
|
|
||||||
return pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void ClientPrivate::sendError(const QString & generic, const QString & specific)
|
||||||
* Note: error replies actually contain a type and then the error description
|
|
||||||
* but we just combine them here for simplicity.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool ClientPrivate::readStatusOrErrorReply()
|
|
||||||
{
|
{
|
||||||
/* Check if the reply contains \r\n. */
|
emit queue.dequeue()->error(generic, specific);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientPrivate::readIntegerReply()
|
void ClientPrivate::sendInteger(qlonglong value)
|
||||||
{
|
{
|
||||||
/* Check if the reply contains \r\n. */
|
emit queue.dequeue()->integer(value);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientPrivate::readBulkReply()
|
void ClientPrivate::sendBulk(const QByteArray & value)
|
||||||
{
|
{
|
||||||
/* Check if the reply contains \r\n. */
|
emit queue.dequeue()->bulk(value);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientPrivate::readMultiBulkReply()
|
void ClientPrivate::sendMultiBulk(const QVariantList & values)
|
||||||
{
|
{
|
||||||
return false;
|
emit queue.dequeue()->multiBulk(values);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::Client(QObject * parent)
|
Client::Client(QObject * parent)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
#include <qredis/client.h>
|
#include <qredis/client.h>
|
||||||
#include <qredis/request.h>
|
#include <qredis/request.h>
|
||||||
|
#include "lexer.h"
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
namespace QRedis
|
namespace QRedis
|
||||||
{
|
{
|
||||||
|
|
@ -18,27 +20,19 @@ namespace QRedis
|
||||||
|
|
||||||
ClientPrivate(Client *);
|
ClientPrivate(Client *);
|
||||||
|
|
||||||
/* Utility methods for reading items from the buffer. */
|
|
||||||
int readInteger(qlonglong &);
|
|
||||||
|
|
||||||
bool readStatusOrErrorReply();
|
|
||||||
bool readIntegerReply();
|
|
||||||
bool readBulkReply();
|
|
||||||
bool readMultiBulkReply();
|
|
||||||
|
|
||||||
QTcpSocket socket;
|
QTcpSocket socket;
|
||||||
|
|
||||||
QQueue<Request *> queue;
|
QQueue<Request *> queue;
|
||||||
QByteArray buffer;
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
Lexer lexer;
|
||||||
|
Parser parser;
|
||||||
|
|
||||||
void reset();
|
private Q_SLOTS:
|
||||||
void readReply();
|
|
||||||
|
|
||||||
private:
|
void sendStatus(const QString &);
|
||||||
|
void sendError(const QString &, const QString &);
|
||||||
Client * const q;
|
void sendInteger(qlonglong);
|
||||||
|
void sendBulk(const QByteArray &);
|
||||||
|
void sendMultiBulk(const QVariantList &);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ Request::Request(QObject * parent)
|
||||||
* Each of these signals also causes the generic reply() signal to be emitted.
|
* Each of these signals also causes the generic reply() signal to be emitted.
|
||||||
*/
|
*/
|
||||||
connect(this, SIGNAL(bulk(QByteArray)), SIGNAL(reply()));
|
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(integer(qlonglong)), SIGNAL(reply()));
|
||||||
connect(this, SIGNAL(multiBulk(QVariantList)), SIGNAL(reply()));
|
connect(this, SIGNAL(multiBulk(QVariantList)), SIGNAL(reply()));
|
||||||
connect(this, SIGNAL(status(QString)), SIGNAL(reply()));
|
connect(this, SIGNAL(status(QString)), SIGNAL(reply()));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue