From 510698517e115f77adbfc0025c371d0637c7ef4b Mon Sep 17 00:00:00 2001 From: hama Date: Fri, 30 May 2014 21:53:44 +0200 Subject: [PATCH] formatted. +rplmatrix --- .cproject | 51 +++ .project | 27 ++ rplcore/rplconfig.cpp | 240 +++++++------- rplcore/rplconfig.hpp | 13 +- rplcore/rplconfigurator.hpp | 18 ++ rplcore/rplcontainer.cpp | 173 +++++----- rplcore/rplcontainer.hpp | 7 +- rplcore/rplcore.hpp | 2 + rplcore/rplexception.cpp | 77 +++-- rplcore/rplexception.hpp | 22 +- rplcore/rpllogger.cpp | 216 ++++++++----- rplcore/rpllogger.hpp | 41 +-- rplcore/rplstring.cpp | 172 +++++++--- rplcore/rplstring.hpp | 13 +- rplcore/rplterminator.cpp | 13 +- rplcore/rplterminator.hpp | 5 +- rplcore/rpltest.cpp | 96 +++--- rplcore/rpltest.hpp | 15 +- rplcore/testrplexample.cpp | 17 +- rplmath/rplenigma.cpp | 157 +++++---- rplmath/rplmatrix.cpp | 627 ++++++++++++++++++++++++++++++++++++ rplmath/rplmatrix.hpp | 104 ++++++ rplmath/rplmatrix_test.cpp | 12 + rplmath/rplrandom.cpp | 29 +- rplmath/rplrandom.hpp | 3 +- rplnet/rplnet.hpp | 3 + rplnet/rplnetconfig.cpp | 14 + rplnet/rplnetconfig.hpp | 21 ++ rplnet/rpltcpclient.cpp | 80 +++-- rplnet/rpltcpclient.hpp | 16 +- rplnet/rpltcppeer.cpp | 231 ++++++++----- rplnet/rpltcppeer.hpp | 33 +- rplnet/rpltcpserver.cpp | 186 ++++++----- rplnet/rpltcpserver.hpp | 86 ++--- rplstatic/rplstatic.pro | 25 ++ rplstatic/rplstaticlib.cpp | 15 + rplstatic/rplstaticlib.hpp | 21 ++ 37 files changed, 2048 insertions(+), 833 deletions(-) create mode 100644 .cproject create mode 100644 .project create mode 100644 rplcore/rplconfigurator.hpp create mode 100644 rplmath/rplmatrix.cpp create mode 100644 rplmath/rplmatrix.hpp create mode 100644 rplmath/rplmatrix_test.cpp create mode 100644 rplnet/rplnetconfig.cpp create mode 100644 rplnet/rplnetconfig.hpp create mode 100644 rplstatic/rplstatic.pro create mode 100644 rplstatic/rplstaticlib.cpp create mode 100644 rplstatic/rplstaticlib.hpp diff --git a/.cproject b/.cproject new file mode 100644 index 0000000..858efea --- /dev/null +++ b/.cproject @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..aabb6ff --- /dev/null +++ b/.project @@ -0,0 +1,27 @@ + + + rplqt + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/rplcore/rplconfig.cpp b/rplcore/rplconfig.cpp index 3ab4699..536e417 100644 --- a/rplcore/rplconfig.cpp +++ b/rplcore/rplconfig.cpp @@ -22,10 +22,10 @@ */ enum Locations { - LOC_WRITE_1 = RPL_FIRST_OF(RPLMODULE_CONFIG), - LOC_WRITE_2, - LOC_READ_1, - LOC_READ_2, + LOC_WRITE_1 = RPL_FIRST_OF(RPLMODULE_CONFIG), + LOC_WRITE_2, + LOC_READ_1, + LOC_READ_2, }; /** @@ -38,16 +38,16 @@ enum Locations { * @param logger NULL or a logger */ RplConfig::RplConfig(const char* file, bool readOnly, RplLogger* logger) : - m_file(file), - m_lineList(), - m_readOnly(readOnly), - m_logger(logger), - m_ownLogger(logger == NULL){ - if (logger == NULL){ - initLogger(); - } - if (file != NULL) - read(file); + m_file(file), + m_lineList(), + m_readOnly(readOnly), + m_logger(logger), + m_ownLogger(logger == NULL) { + if(logger == NULL) { + initLogger(); + } + if(file != NULL) + read(file); } /** @@ -55,24 +55,24 @@ RplConfig::RplConfig(const char* file, bool readOnly, RplLogger* logger) : * * Frees the resources. */ -RplConfig::~RplConfig(){ - if (m_ownLogger) - delete m_logger; - m_logger = NULL; +RplConfig::~RplConfig() { + if(m_ownLogger) + delete m_logger; + m_logger = NULL; } /** * Inititializes a logger. */ -void RplConfig::initLogger(){ - m_logger = new RplLogger(); - RplMemoryAppender* appender = new RplMemoryAppender(); - appender->setAutoDelete(true); - m_logger->addAppender(appender); - - RplStreamAppender* appender2 = new RplStreamAppender(stdout); - appender2->setAutoDelete(true); - m_logger->addAppender(appender2); +void RplConfig::initLogger() { + m_logger = new RplLogger(); + RplMemoryAppender* appender = new RplMemoryAppender(); + appender->setAutoDelete(true); + m_logger->addAppender(appender); + + RplStreamAppender* appender2 = new RplStreamAppender(stdout); + appender2->setAutoDelete(true); + m_logger->addAppender(appender2); } /** @@ -83,12 +83,12 @@ void RplConfig::initLogger(){ * @return defaultValue: key does not exist * otherwise: the value assigned to key */ -int RplConfig::asInt(const char* key, int defaultValue) const{ - int rc = defaultValue; - if (contains(key)){ - rc = atoi((*this)[key]); - } - return rc; +int RplConfig::asInt(const char* key, int defaultValue) const { + int rc = defaultValue; + if(contains(key)) { + rc = atoi((*this)[key]); + } + return rc; } /** @@ -99,15 +99,15 @@ int RplConfig::asInt(const char* key, int defaultValue) const{ * @return defaultValue: key does not exist * otherwise: the value assigned to key */ -bool RplConfig::asBool(const char* key, bool defaultValue) const{ - bool rc = defaultValue; - if (contains(key)){ - QByteArray value = (*this)[key].toLower(); - rc = value == "1" || value == "y" || value == "yes" || value == "t" - || value == "true"; - } - - return rc; +bool RplConfig::asBool(const char* key, bool defaultValue) const { + bool rc = defaultValue; + if(contains(key)) { + QByteArray value = (*this)[key].toLower(); + rc = value == "1" || value == "y" || value == "yes" || value == "t" + || value == "true"; + } + + return rc; } /** @@ -117,12 +117,12 @@ bool RplConfig::asBool(const char* key, bool defaultValue) const{ * @param defaultValue if the key does not exist this is the result * @return defaultValue: key does not exist */ -QByteArray RplConfig::asString(const char* key, const char* defaultValue){ - QByteArray rc = defaultValue; - if (contains(key)){ - rc = (*this)[key]; - } - return rc; +QByteArray RplConfig::asString(const char* key, const char* defaultValue) { + QByteArray rc = defaultValue; + if(contains(key)) { + rc = (*this)[key]; + } + return rc; } /** @@ -132,34 +132,34 @@ QByteArray RplConfig::asString(const char* key, const char* defaultValue){ * @return true: OK
* false: error occurred */ -bool RplConfig::read(const char* file){ - bool rc = true; - m_lineList.reserve(1024); - FILE* fp = fopen(file, "r"); - if (fp == NULL){ - m_logger->logv(LOG_ERROR, LOC_READ_1, "cannot read: %s", file); - rc = false; - }else{ - char line[64000]; - char* separator; - int lineNo = 0; - while (fgets(line, sizeof line, fp) != NULL){ - lineNo++; - m_lineList.append(line); - if (isalnum(line[0]) && (separator = strchr(line, '=')) != NULL){ - QByteArray key(line, separator - line); - QByteArray value(separator + 1); - key = key.trimmed(); - value = value.trimmed(); - if (contains(key)) - m_logger->logv(LOG_WARNING, LOC_READ_2, - "defined more than once: %s-%d: %s", file, lineNo, line); - else - insert(key, value); - } - } - } - return rc; +bool RplConfig::read(const char* file) { + bool rc = true; + m_lineList.reserve(1024); + FILE* fp = fopen(file, "r"); + if(fp == NULL) { + m_logger->logv(LOG_ERROR, LOC_READ_1, "cannot read: %s", file); + rc = false; + } else { + char line[64000]; + char* separator; + int lineNo = 0; + while(fgets(line, sizeof line, fp) != NULL) { + lineNo++; + m_lineList.append(line); + if(isalnum(line[0]) && (separator = strchr(line, '=')) != NULL) { + QByteArray key(line, separator - line); + QByteArray value(separator + 1); + key = key.trimmed(); + value = value.trimmed(); + if(contains(key)) + m_logger->logv(LOG_WARNING, LOC_READ_2, + "defined more than once: %s-%d: %s", file, lineNo, line); + else + insert(key, value); + } + } + } + return rc; } /** @@ -169,14 +169,14 @@ bool RplConfig::read(const char* file){ * @return true: OK
* false: error occurred */ -bool RplConfig::write(const char* file){ - bool rc = false; - if (m_readOnly) - m_logger->log(LOG_ERROR, LOC_WRITE_1, "cannot write: (readonly"); - else{ - m_logger->log(LOG_ERROR, LOC_WRITE_2, "not implemented: write()"); - } - return rc; +bool RplConfig::write(const char* file) { + bool rc = false; + if(m_readOnly) + m_logger->log(LOG_ERROR, LOC_WRITE_1, "cannot write: (readonly"); + else { + m_logger->log(LOG_ERROR, LOC_WRITE_2, "not implemented: write()"); + } + return rc; } // ------------------ @@ -190,47 +190,47 @@ bool RplConfig::write(const char* file){ */ class TestRplConfig: public RplTest { public: - TestRplConfig() : - RplTest("RplConfig"){ - } + TestRplConfig() : + RplTest("RplConfig") { + } public: - void testBasic(){ - QByteArray fn = getTempFile("test.data", "config"); - RplString::write(fn, "#comment\na=1\nb.1==x\n#=\nB=zzz"); - RplConfig config(fn.constData()); - checkE(3, config.size()); - checkE("1", config["a"]); - checkE("=x", config["b.1"]); - checkE("zzz", config["B"]); - } - void testAsX(){ - QByteArray fn = getTempFile("test.data", "config"); - RplString::write(fn, "i=123\nb=1\nb2=true\nb3=yes\ns=abc"); - RplConfig config(fn.constData()); - checkE(5, config.size()); - checkE(123, config.asInt("i", -1)); - checkE(-1, config.asInt("I", -1)); - checkT(config.asBool("b", false)); - checkT(config.asBool("b2", false)); - checkT(config.asBool("b3", false)); - checkT(config.asBool("-", true)); - checkF(config.asBool("-", false)); - checkE("abc", config.asString("s", "x")); - checkE("x", config.asString("S", "x")); - } - - virtual void doIt(){ - testAsX(); - testBasic(); - - } + void testBasic() { + QByteArray fn = getTempFile("test.data", "config"); + RplString::write(fn, "#comment\na=1\nb.1==x\n#=\nB=zzz"); + RplConfig config(fn.constData()); + checkE(3, config.size()); + checkE("1", config["a"]); + checkE("=x", config["b.1"]); + checkE("zzz", config["B"]); + } + void testAsX() { + QByteArray fn = getTempFile("test.data", "config"); + RplString::write(fn, "i=123\nb=1\nb2=true\nb3=yes\ns=abc"); + RplConfig config(fn.constData()); + checkE(5, config.size()); + checkE(123, config.asInt("i", -1)); + checkE(-1, config.asInt("I", -1)); + checkT(config.asBool("b", false)); + checkT(config.asBool("b2", false)); + checkT(config.asBool("b3", false)); + checkT(config.asBool("-", true)); + checkF(config.asBool("-", false)); + checkE("abc", config.asString("s", "x")); + checkE("x", config.asString("S", "x")); + } + + virtual void doIt() { + testAsX(); + testBasic(); + + } }; #endif -void testRplConfig(){ +void testRplConfig() { #ifdef RPL_TEST - TestRplConfig test; - test.run(); + TestRplConfig test; + test.run(); #endif } diff --git a/rplcore/rplconfig.hpp b/rplcore/rplconfig.hpp index c426c35..46af106 100644 --- a/rplcore/rplconfig.hpp +++ b/rplcore/rplconfig.hpp @@ -8,10 +8,10 @@ #ifndef RPLCONFIG_HPP #define RPLCONFIG_HPP -class RplConfig : public QHash -{ +class RplConfig : public RplConfigurator, public QHash { public: - RplConfig(const char* file = NULL, bool readOnly = true, RplLogger* logger = NULL); + RplConfig(const char* file = NULL, bool readOnly = true, + RplLogger* logger = NULL); virtual ~RplConfig(); public: @@ -19,9 +19,10 @@ public: bool write(const char* file); void clear(); const QVector& getLines() const; - int asInt(const char* key, int defaultValue) const; - bool asBool(const char* key, bool defaultValue) const; - QByteArray asString(const char* key, const char* defaultValue); + + virtual bool asBool(const char* key, bool defaultValue) const; + virtual int asInt(const char* key, int defaultValue) const; + virtual QByteArray asString(const char* key, const char* defaultValue); private: void initLogger(); private: diff --git a/rplcore/rplconfigurator.hpp b/rplcore/rplconfigurator.hpp new file mode 100644 index 0000000..c651800 --- /dev/null +++ b/rplcore/rplconfigurator.hpp @@ -0,0 +1,18 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. + */ +#ifndef RPLCONFIGURATOR_HPP +#define RPLCONFIGURATOR_HPP + +class RplConfigurator { +public: + virtual int asInt(const char* key, int defaultValue) const = 0; + virtual bool asBool(const char* key, bool defaultValue) const = 0; + virtual QByteArray asString(const char* key, const char* defaultValue) = 0; +}; + +#endif // RPLCONFIGURATOR_HPP diff --git a/rplcore/rplcontainer.cpp b/rplcore/rplcontainer.cpp index afe61ea..3137aae 100644 --- a/rplcore/rplcontainer.cpp +++ b/rplcore/rplcontainer.cpp @@ -60,14 +60,13 @@ RplContainer::RplContainer(size_t sizeHint) : m_typeList(""), m_ixItem(0), m_ixBag(0), - m_readPosition(NULL) -{ + m_readPosition(NULL) { } /** * @brief Destructor. */ -RplContainer::~RplContainer(){ +RplContainer::~RplContainer() { } /** @@ -75,17 +74,17 @@ RplContainer::~RplContainer(){ * * @param tag the type tag */ -void RplContainer::addType(type_tag_t tag){ - if (m_countBags == 0) +void RplContainer::addType(type_tag_t tag) { + if(m_countBags == 0) startBag(); - if (m_countBags == 1) + if(m_countBags == 1) m_typeList.append((char) tag); } /** * @brief Starts a new bag. */ -void RplContainer::startBag(){ +void RplContainer::startBag() { m_countBags++; m_ixBag = 0; } @@ -94,7 +93,7 @@ void RplContainer::startBag(){ * * @param value value to insert */ -void RplContainer::addChar(char value){ +void RplContainer::addChar(char value) { addType(TAG_CHAR); //if (m_typeList.at(m_ixBag) != TAG_INT) // RplLogger::logAndThrow(LOG_ERROR, __FILE__, __LINE__, 1, "unexpected type: %c instead of c", m_typeList.at(m_ixBag)); @@ -105,11 +104,11 @@ void RplContainer::addChar(char value){ * * @param value value to add */ -void RplContainer::addInt(int value){ +void RplContainer::addInt(int value) { addType(TAG_INT); char buffer[64]; char* ptr = buffer; - if (value < 0){ + if(value < 0) { *ptr++ = '-'; value = - value; } @@ -121,7 +120,7 @@ void RplContainer::addInt(int value){ * * @param value value to add */ -void RplContainer::addInt(qint64 value){ +void RplContainer::addInt(qint64 value) { addType(TAG_INT); char buffer[128]; snprintf(buffer, sizeof buffer, "%llx ", value); @@ -133,7 +132,7 @@ void RplContainer::addInt(qint64 value){ * * @param value value to add */ -void RplContainer::addString(const char* value){ +void RplContainer::addString(const char* value) { addType(TAG_STRING); // store with trailing '\0' m_data.append(value, strlen(value) + 1); @@ -144,21 +143,21 @@ void RplContainer::addString(const char* value){ * @param value binary data * @param size size of the binary data in bytes */ -void RplContainer::addData(uint8_t* value, size_t size){ - if (size <= 255){ +void RplContainer::addData(uint8_t* value, size_t size) { + if(size <= 255) { addType(TAG_DATA255); m_data.append((char) size); - } else if (size <= 0xffff){ + } else if(size <= 0xffff) { addType(TAG_DATA64K); - m_data.append((char) (size / 256)); - m_data.append((char) (size % 256)); + m_data.append((char)(size / 256)); + m_data.append((char)(size % 256)); m_data.append((const char*) value, size); } else { addType(TAG_DATA4G); - m_data.append((char) (size / 256 / 256 / 256)); - m_data.append((char) (size / 256 / 256 % 256)); - m_data.append((char) (size / 256 % 256)); - m_data.append((char) (size % 256)); + m_data.append((char)(size / 256 / 256 / 256)); + m_data.append((char)(size / 256 / 256 % 256)); + m_data.append((char)(size / 256 % 256)); + m_data.append((char)(size % 256)); m_data.append((const char*) value, size); } addType(TAG_DATA255); @@ -171,12 +170,14 @@ void RplContainer::addData(uint8_t* value, size_t size){ * @return the container as a byte array */ const QByteArray& RplContainer::getData() { - if (m_typeList.length() != 0){ + if(m_typeList.length() != 0) { char buffer[128]; // RPL&1 0a b5[2]cis: !12 - snprintf(buffer, sizeof buffer, "%x[%d]%s:", (unsigned int) m_data.length(), m_countBags, m_typeList.data()); + snprintf(buffer, sizeof buffer, "%x[%d]%s:", (unsigned int) m_data.length(), + m_countBags, m_typeList.data()); char header[128+8]; - snprintf(header, sizeof header, "%s%02x%s", MAGIC_1, (unsigned int) strlen(buffer), buffer); + snprintf(header, sizeof header, "%s%02x%s", MAGIC_1, + (unsigned int) strlen(buffer), buffer); m_data.insert(0, header); } return m_data; @@ -187,26 +188,30 @@ const QByteArray& RplContainer::getData() { * * @param data the container as a byte array */ -void RplContainer::fill(const QByteArray& data){ +void RplContainer::fill(const QByteArray& data) { m_data = data; const char* ptr = m_data.data(); - if (strncmp(ptr, MAGIC_1, strlen(MAGIC_1)) != 0) - throw RplInvalidDataException(LOG_ERROR, LOC_FILL_1, "container has no magic", data.data(), data.length()); + if(strncmp(ptr, MAGIC_1, strlen(MAGIC_1)) != 0) + throw RplInvalidDataException(LOG_ERROR, LOC_FILL_1, "container has no magic", + data.data(), data.length()); ptr += strlen(MAGIC_1); unsigned int headerSize = 0; - if (sscanf(ptr, "%02x", &headerSize) != 1) - throw RplInvalidDataException(LOG_ERROR, LOC_FILL_2, "container has no header size", ptr, 2); + if(sscanf(ptr, "%02x", &headerSize) != 1) + throw RplInvalidDataException(LOG_ERROR, LOC_FILL_2, + "container has no header size", ptr, 2); ptr += 2; unsigned int dataSize = 0; unsigned int countBags = 0; - if (sscanf(ptr, "%x[%x]", &dataSize, &countBags) != 2) - throw RplInvalidDataException(LOG_ERROR, LOC_FILL_2, "container has no data_size[bag_count]", ptr, 16); + if(sscanf(ptr, "%x[%x]", &dataSize, &countBags) != 2) + throw RplInvalidDataException(LOG_ERROR, LOC_FILL_2, + "container has no data_size[bag_count]", ptr, 16); m_countBags = countBags; ptr = strchr(ptr, ']') + 1; const char* end = ptr + strspn(ptr, "cisdDX!"); - if (end == ptr || *end != ':'){ - throw RplInvalidDataException(LOG_ERROR, LOC_FILL_2, "container has no valid typelist", ptr, 16); + if(end == ptr || *end != ':') { + throw RplInvalidDataException(LOG_ERROR, LOC_FILL_2, + "container has no valid typelist", ptr, 16); } m_typeList.clear(); m_typeList.append(ptr, end - ptr); @@ -220,46 +225,48 @@ void RplContainer::fill(const QByteArray& data){ * * @return the number of bags */ -int RplContainer::getCountBags() const{ +int RplContainer::getCountBags() const { return m_countBags; } /** * @brief Sets the begin of the new bag. */ -void RplContainer::nextBag(){ - if (m_ixItem < m_typeList.length() && m_ixItem != -1) +void RplContainer::nextBag() { + if(m_ixItem < m_typeList.length() && m_ixItem != -1) throw RplException(LOG_ERROR, LOC_NEXT_BAG_1, NULL, - "end of bag not reached: remaining items: %s", - m_typeList.data() + m_ixItem); + "end of bag not reached: remaining items: %s", + m_typeList.data() + m_ixItem); m_ixItem = 0; m_ixBag++; - if (m_ixBag >= m_countBags) + if(m_ixBag >= m_countBags) throw RplException(LOG_ERROR, LOC_NEXT_BAG_2, NULL, - "no more bags: %d", m_ixBag); + "no more bags: %d", m_ixBag); } /** * @brief Sets the next item. * * @param expected the expected data type */ -void RplContainer::nextItem(type_tag_t expected){ - if (m_ixBag < 0){ +void RplContainer::nextItem(type_tag_t expected) { + if(m_ixBag < 0) { m_ixBag = 0; m_ixItem = 0; } - if (m_ixItem >= m_typeList.length()) + if(m_ixItem >= m_typeList.length()) throw RplException(LOG_ERROR, LOC_NEXT_ITEM_1, "no more items in the bag"); type_tag_t current = (type_tag_t) m_typeList.at(m_ixItem); // Unify all data types: - if (current == TAG_DATA4G || current == TAG_DATA64K) + if(current == TAG_DATA4G || current == TAG_DATA64K) current = TAG_DATA255; - if (current != expected) - throw RplException(LOG_ERROR, LOC_NEXT_ITEM_2, NULL, "current item is a %c, not a %c", - (char) m_typeList.at(m_ixItem), (char) expected); + if(current != expected) + throw RplException(LOG_ERROR, LOC_NEXT_ITEM_2, NULL, + "current item is a %c, not a %c", + (char) m_typeList.at(m_ixItem), (char) expected); m_ixItem++; - if (m_readPosition > (uint8_t*) (m_data.data() + m_data.length())) - throw RplException(LOG_ERROR, LOC_NEXT_ITEM_3, NULL, "container size too small. Bag: %d of %d Item: %d of %d", - 1 + m_ixBag, m_countBags, 1 + m_ixItem, m_typeList.length()); + if(m_readPosition > (uint8_t*)(m_data.data() + m_data.length())) + throw RplException(LOG_ERROR, LOC_NEXT_ITEM_3, NULL, + "container size too small. Bag: %d of %d Item: %d of %d", + 1 + m_ixBag, m_countBags, 1 + m_ixItem, m_typeList.length()); } /** @@ -267,7 +274,7 @@ void RplContainer::nextItem(type_tag_t expected){ * * @return the next char from the container */ -char RplContainer::nextChar(){ +char RplContainer::nextChar() { nextItem(TAG_CHAR); char rc = *m_readPosition++; return rc; @@ -278,16 +285,17 @@ char RplContainer::nextChar(){ * * @return the next integer from the container */ -int RplContainer::nextInt(){ +int RplContainer::nextInt() { nextItem(TAG_INT); bool isNegativ = *m_readPosition == '-'; - if (isNegativ) + if(isNegativ) m_readPosition++; unsigned int value = 0; - if (sscanf((const char*) m_readPosition, "%x ", &value) != 1) - throw RplInvalidDataException(LOG_ERROR, LOC_NEXT_INT_1, "not a hex_number", m_readPosition, 16); - m_readPosition = (uint8_t*) strchr((const char*) m_readPosition, ' ') + 1; - if (isNegativ) + if(sscanf((const char*) m_readPosition, "%x ", &value) != 1) + throw RplInvalidDataException(LOG_ERROR, LOC_NEXT_INT_1, + "not a hex_number", m_readPosition, 16); + m_readPosition = (uint8_t*) strchr((const char*) m_readPosition, ' ') + 1; + if(isNegativ) value = - value; return value; } @@ -296,16 +304,17 @@ int RplContainer::nextInt(){ * * @return the next integer from the container */ -qint64 RplContainer::nextInt64(){ +qint64 RplContainer::nextInt64() { nextItem(TAG_INT); bool isNegativ = *m_readPosition == '-'; - if (isNegativ) + if(isNegativ) m_readPosition++; qint64 value = 0; - if (sscanf((const char*) m_readPosition, "%llx ", &value) != 1) - throw RplInvalidDataException(LOG_ERROR, LOC_NEXT_INT_1, "not a hex_number", m_readPosition, 16); + if(sscanf((const char*) m_readPosition, "%llx ", &value) != 1) + throw RplInvalidDataException(LOG_ERROR, LOC_NEXT_INT_1, + "not a hex_number", m_readPosition, 16); m_readPosition = (uint8_t*) strchr((const char*) m_readPosition, ' ') + 1; - if (isNegativ) + if(isNegativ) value = - value; return value; } @@ -315,7 +324,7 @@ qint64 RplContainer::nextInt64(){ * * @return the next '\0' delimited string from the container */ -const char* RplContainer::nextString(){ +const char* RplContainer::nextString() { nextItem(TAG_STRING); const char* rc = (const char*) m_readPosition; m_readPosition += strlen(rc) + 1; @@ -330,13 +339,13 @@ const char* RplContainer::nextString(){ * false: data contains the item data only * @return the size of the read data */ -size_t RplContainer::nextData(QByteArray& data, bool append){ +size_t RplContainer::nextData(QByteArray& data, bool append) { nextItem(TAG_DATA255); type_tag_t tag = (type_tag_t) m_typeList.at(m_ixItem - 1); size_t length = 0; - switch(tag){ + switch(tag) { case TAG_DATA4G: - for (int ix = 3; ix >= 0; ix--){ + for(int ix = 3; ix >= 0; ix--) { length = 256 * length + m_readPosition[ix]; } m_readPosition += 4; @@ -351,7 +360,7 @@ size_t RplContainer::nextData(QByteArray& data, bool append){ default: break; } - if (! append) + if(! append) data.clear(); data.append((const char*) m_readPosition, length); m_readPosition += length; @@ -371,8 +380,8 @@ size_t RplContainer::nextData(QByteArray& data, bool append){ * @return a human readable string describing the container */ QByteArray RplContainer::dump(const char* title, - int maxBags, int maxStringLength, int maxBlobLength, - char separatorItems){ + int maxBags, int maxStringLength, int maxBlobLength, + char separatorItems) { QByteArray rc; rc.reserve(64000); rc.append("=== ").append(title).append('\n'); @@ -385,16 +394,16 @@ QByteArray RplContainer::dump(const char* title, m_ixItem = 0; int iValue; QByteArray sValue; - if (maxBags > m_countBags) + if(maxBags > m_countBags) maxBags = m_countBags; - for (int ixBag = 0; ixBag < maxBags; ixBag++){ + for(int ixBag = 0; ixBag < maxBags; ixBag++) { rc.append("--- bag ").append(RplString::toNumber(ixBag)).append(":\n"); nextBag(); QByteArray item; int maxLength; - for (int ixItem; ixItem < m_typeList.length(); ixItem++){ + for(int ixItem; ixItem < m_typeList.length(); ixItem++) { type_tag_t currentType = (type_tag_t) m_typeList.at(ixItem); - switch(currentType){ + switch(currentType) { case TAG_CHAR: rc.append(" c: ").append(nextChar()).append(separatorItems); break; @@ -405,7 +414,7 @@ QByteArray RplContainer::dump(const char* title, break; case TAG_STRING: sValue = nextString(); - if (sValue.length() > maxStringLength) + if(sValue.length() > maxStringLength) sValue = sValue.left(maxStringLength); rc.append(" s: ").append(sValue).append(separatorItems); break; @@ -416,7 +425,8 @@ QByteArray RplContainer::dump(const char* title, rc.append(' ').append((char) currentType).append(": ["); rc.append(RplString::toNumber(item.length())).append("] "); maxLength = item.length() < maxBlobLength ? item.length() : maxBlobLength; - rc.append(RplString::hexDump(item.data(), maxLength, 16)).append(separatorItems); + rc.append(RplString::hexDump(item.data(), maxLength, + 16)).append(separatorItems); break; default: break; @@ -439,13 +449,12 @@ QByteArray RplContainer::dump(const char* title, /** * @brief Unit test for RplContainer */ -class TestRplContainer : public RplTest -{ +class TestRplContainer : public RplTest { public: - TestRplContainer() : RplTest("RplContainer"){} + TestRplContainer() : RplTest("RplContainer") {} public: - void testBasic(){ + void testBasic() { RplContainer container(256); // Rpl&1 09 36[2]cis:!7b Nirwana <0> Y -ab34 A long string with an trailing '0' <0>
container.startBag(); @@ -471,15 +480,15 @@ public: checkE("A long string with an trailing '0'", container2.nextString()); log(("Example: " + data).constData()); - } + } - virtual void doIt(){ + virtual void doIt() { testBasic(); } }; #endif -void testRplContainer(){ +void testRplContainer() { #ifdef RPL_TEST TestRplContainer test; test.run(); diff --git a/rplcore/rplcontainer.hpp b/rplcore/rplcontainer.hpp index 99bc3bc..621a616 100644 --- a/rplcore/rplcontainer.hpp +++ b/rplcore/rplcontainer.hpp @@ -13,8 +13,7 @@ #include #include #endif -class RplContainer -{ +class RplContainer { public: typedef enum { @@ -58,8 +57,8 @@ public: size_t nextData(QByteArray& data, bool append = false); QByteArray dump(const char* title, - int maxBags, int maxStringLength = 80, int maxBlobLength = 16, - char separatorItems = '\n'); + int maxBags, int maxStringLength = 80, int maxBlobLength = 16, + char separatorItems = '\n'); private: void nextItem(type_tag_t expected); private: diff --git a/rplcore/rplcore.hpp b/rplcore/rplcore.hpp index 2938394..a71da62 100644 --- a/rplcore/rplcore.hpp +++ b/rplcore/rplcore.hpp @@ -25,6 +25,7 @@ #include #include #include +#include typedef unsigned char uint8_t; #include "../rplmodules.hpp" @@ -32,6 +33,7 @@ typedef unsigned char uint8_t; #include "rplexception.hpp" #include "rplcontainer.hpp" #include "rplstring.hpp" +#include "rplconfigurator.hpp" #include "rplconfig.hpp" #include "rplterminator.hpp" diff --git a/rplcore/rplexception.cpp b/rplcore/rplexception.cpp index dc7c73a..db0d47e 100644 --- a/rplcore/rplexception.cpp +++ b/rplcore/rplexception.cpp @@ -31,8 +31,7 @@ class RplException; * @param message the reason of the exception */ RplException::RplException(const char* message) : - m_message(message) -{ + m_message(message) { } /** @@ -41,8 +40,7 @@ RplException::RplException(const char* message) : * @param message the reason of the exception */ RplException::RplException(const QByteArray& message) : - m_message(message) -{ + m_message(message) { } /** @@ -56,10 +54,10 @@ RplException::RplException(const QByteArray& message) : * @param message the reason * @param logger if NULL the global logger will be used */ -RplException::RplException(RplLoggerLevel level, int location, const char* message, RplLogger* logger) : - m_message(message) -{ - if (logger == NULL) +RplException::RplException(RplLoggerLevel level, int location, + const char* message, RplLogger* logger) : + m_message(message) { + if(logger == NULL) logger = RplLogger::globalLogger(); logger->log(LOG_ERROR, location, message); } @@ -75,10 +73,10 @@ RplException::RplException(RplLoggerLevel level, int location, const char* messa * @param message the reason * @param logger Nif NULL the global logger will be used */ -RplException::RplException(RplLoggerLevel level, int location, const QByteArray& message, RplLogger* logger) : - m_message(message) -{ - if (logger == NULL) +RplException::RplException(RplLoggerLevel level, int location, + const QByteArray& message, RplLogger* logger) : + m_message(message) { + if(logger == NULL) logger = RplLogger::globalLogger(); logger->log(LOG_ERROR, location, message); } @@ -98,16 +96,16 @@ RplException::RplException(RplLoggerLevel level, int location, const QByteArray& * in format * @param logger if NULL the global logger will be used */ -RplException::RplException(RplLoggerLevel level, int location, RplLogger* logger, const char* format, ...) : - m_message("") -{ +RplException::RplException(RplLoggerLevel level, int location, + RplLogger* logger, const char* format, ...) : + m_message("") { char buffer[64000]; va_list ap; va_start(ap, format); vsnprintf(buffer, sizeof buffer, format, ap); va_end(ap); m_message = buffer; - if (logger == NULL) + if(logger == NULL) logger = RplLogger::globalLogger(); logger->log(LOG_ERROR, location, buffer); } @@ -127,17 +125,17 @@ RplException::RplException(RplLoggerLevel level, int location, RplLogger* logger * in format * @param logger if NULL the global logger will be used */ -RplException::RplException(RplLoggerLevel level, int location, RplLogger* logger, - const QByteArray& format, ...) : - m_message("") -{ +RplException::RplException(RplLoggerLevel level, int location, + RplLogger* logger, + const QByteArray& format, ...) : + m_message("") { char buffer[64000]; va_list ap; va_start(ap, format); vsnprintf(buffer, sizeof buffer, format, ap); va_end(ap); m_message = buffer; - if (logger == NULL) + if(logger == NULL) logger = RplLogger::globalLogger(); logger->log(LOG_ERROR, location, buffer); } @@ -172,17 +170,17 @@ RplException::RplException(RplLoggerLevel level, int location, RplLogger* logger * @param logger if NULL the global logger will be used */ -RplRangeException::RplRangeException(RplLoggerLevel level, int location, size_t current, - size_t lbound, size_t ubound, const char* message, RplLogger* logger) : - RplException("") -{ +RplRangeException::RplRangeException(RplLoggerLevel level, int location, + size_t current, + size_t lbound, size_t ubound, const char* message, RplLogger* logger) : + RplException("") { char buffer[64000]; - if (message == NULL) + if(message == NULL) message = "value outside limits"; snprintf(buffer, sizeof buffer, "%s: %lu [%lu, %lu]", message == NULL ? "" : message, - current, lbound, ubound); - if (logger == NULL) + current, lbound, ubound); + if(logger == NULL) logger = RplLogger::globalLogger(); logger->log(level, location, buffer); } @@ -213,32 +211,33 @@ RplRangeException::RplRangeException(RplLoggerLevel level, int location, size_t * @param dataSize the size of the data which should be dumped * @param logger if NULL the global logger will be used */ -RplInvalidDataException::RplInvalidDataException(RplLoggerLevel level, int location, +RplInvalidDataException::RplInvalidDataException(RplLoggerLevel level, + int location, const char* message, const void* data, size_t dataSize, RplLogger* logger) : - RplException("") -{ + RplException("") { char buffer[64000]; - if (message == NULL) + if(message == NULL) message = "invalid data: "; - if (data == NULL) + if(data == NULL) data = ""; - if (dataSize > 16) + if(dataSize > 16) dataSize = 16; size_t ix; char* ptr = buffer + strlen(buffer); - for (ix = 0; ix < dataSize; ix++){ - snprintf(ptr, sizeof(buffer) - (ptr - buffer) - 1, "%02x ", ((unsigned char*) data)[ix]); + for(ix = 0; ix < dataSize; ix++) { + snprintf(ptr, sizeof(buffer) - (ptr - buffer) - 1, "%02x ", + ((unsigned char*) data)[ix]); ptr += strlen(ptr); } - for (ix = 0; ix < dataSize; ix++){ + for(ix = 0; ix < dataSize; ix++) { char cc = ((char*) data)[ix]; - if (cc > ' ' && cc <= '~') + if(cc > ' ' && cc <= '~') *ptr++ = cc; else *ptr++ = '.'; } - if (logger == NULL) + if(logger == NULL) logger = RplLogger::globalLogger(); logger->log(level, location, buffer); } diff --git a/rplcore/rplexception.hpp b/rplcore/rplexception.hpp index f537223..e3c7d02 100644 --- a/rplcore/rplexception.hpp +++ b/rplcore/rplexception.hpp @@ -12,19 +12,18 @@ #ifndef RPLCORE_HPP #include #endif -class RplException -{ +class RplException { public: RplException(const char* message); RplException(const QByteArray& message); RplException(RplLoggerLevel level, int location, const char* message, - RplLogger* logger = NULL); + RplLogger* logger = NULL); RplException(RplLoggerLevel level, int location, const QByteArray& message, - RplLogger* logger = NULL); + RplLogger* logger = NULL); RplException(RplLoggerLevel level, int location, RplLogger* logger, - const char* message, ...); + const char* message, ...); RplException(RplLoggerLevel level, int location, RplLogger* logger, - const QByteArray& message, ...); + const QByteArray& message, ...); const QByteArray& getMessage() const { return m_message; } @@ -32,16 +31,17 @@ protected: QByteArray m_message; }; -class RplRangeException : public RplException{ +class RplRangeException : public RplException { public: - RplRangeException(RplLoggerLevel level, int location, size_t current, size_t lbound, size_t ubound, - const char* message = NULL, RplLogger* logger = NULL); + RplRangeException(RplLoggerLevel level, int location, size_t current, + size_t lbound, size_t ubound, + const char* message = NULL, RplLogger* logger = NULL); }; -class RplInvalidDataException : public RplException{ +class RplInvalidDataException : public RplException { public: RplInvalidDataException(RplLoggerLevel level, int location, const char* message, - const void* data = NULL, size_t dataSize = 0, RplLogger* logger = NULL); + const void* data = NULL, size_t dataSize = 0, RplLogger* logger = NULL); }; #endif // RPLEXCEPTION_HPP diff --git a/rplcore/rpllogger.cpp b/rplcore/rpllogger.cpp index 02ccc6e..cb7468e 100644 --- a/rplcore/rpllogger.cpp +++ b/rplcore/rpllogger.cpp @@ -22,8 +22,8 @@ RplLogger* RplLogger::m_globalLogger = NULL; * * @return the global logger */ -RplLogger* RplLogger::globalLogger(){ - if (m_globalLogger == NULL){ +RplLogger* RplLogger::globalLogger() { + if(m_globalLogger == NULL) { m_globalLogger = new RplLogger(); m_globalLogger->buildStandardAppender("globallogger"); } @@ -32,7 +32,7 @@ RplLogger* RplLogger::globalLogger(){ /** * @brief Frees the resources of the global logger. */ -void RplLogger::destroyGlobalLogger(){ +void RplLogger::destroyGlobalLogger() { delete m_globalLogger; m_globalLogger = NULL; } @@ -51,14 +51,13 @@ void RplLogger::destroyGlobalLogger(){ */ RplAppender::RplAppender(const QByteArray& name) : m_name(name), - m_level(LOG_INFO) -{ + m_level(LOG_INFO) { } /** * @brief Destructor. */ -RplAppender::~RplAppender(){ +RplAppender::~RplAppender() { } /** @@ -66,8 +65,8 @@ RplAppender::~RplAppender(){ * * @return the name of the instance */ -const char* RplAppender::getName() const{ - return m_name.data(); +const char* RplAppender::getName() const { + return m_name.data(); } /** @@ -75,7 +74,7 @@ const char* RplAppender::getName() const{ * * @param level */ -void RplAppender::setLevel(RplLoggerLevel level){ +void RplAppender::setLevel(RplLoggerLevel level) { m_level = level; } /** @@ -83,7 +82,7 @@ void RplAppender::setLevel(RplLoggerLevel level){ * * @return the level */ -RplLoggerLevel RplAppender::getLevel() const{ +RplLoggerLevel RplAppender::getLevel() const { return m_level; } /** @@ -92,7 +91,7 @@ RplLoggerLevel RplAppender::getLevel() const{ * @param level the level of the location. * @return true: the location level is greater or equals to the appender's level */ -bool RplAppender::isActive(RplLoggerLevel level){ +bool RplAppender::isActive(RplLoggerLevel level) { return level <= m_level; } @@ -101,7 +100,7 @@ bool RplAppender::isActive(RplLoggerLevel level){ * * @param onNotOff the state of the auto deletion */ -void RplAppender::setAutoDelete(bool onNotOff){ +void RplAppender::setAutoDelete(bool onNotOff) { m_autoDelete = onNotOff; } @@ -110,7 +109,7 @@ void RplAppender::setAutoDelete(bool onNotOff){ * * @return true: the logger destroys the instance */ -bool RplAppender::isAutoDelete() const{ +bool RplAppender::isAutoDelete() const { return m_autoDelete; } @@ -137,18 +136,21 @@ bool RplAppender::isAutoDelete() const{ * @brief Constructor. */ RplLogger::RplLogger() : - m_countAppenders(0) -{ + // m_appenders(), + m_countAppenders(0), + m_stdPrefix(), + m_mutex(), + m_withLocking(false) { memset(m_appenders, 0, sizeof m_appenders); } /** * @brief Destructor. */ -RplLogger::~RplLogger(){ - for (size_t ix = 0; ix < m_countAppenders; ix++){ +RplLogger::~RplLogger() { + for(size_t ix = 0; ix < m_countAppenders; ix++) { RplAppender* appender = m_appenders[ix]; - if (appender->isAutoDelete()){ + if(appender->isAutoDelete()) { delete appender; } m_appenders[ix] = NULL; @@ -162,7 +164,7 @@ RplLogger::~RplLogger(){ */ char RplLogger::getPrefixOfLevel(RplLoggerLevel level) const { char rc = ' '; - switch(level){ + switch(level) { case LOG_ERROR: rc = '!'; break; @@ -189,11 +191,11 @@ char RplLogger::getPrefixOfLevel(RplLoggerLevel level) const { * @return false: all appenders are not activated by this level
* true: otherwise */ -bool RplLogger::isActive(RplLoggerLevel level) const{ +bool RplLogger::isActive(RplLoggerLevel level) const { bool rc = false; - for (size_t ix = 0; ix < m_countAppenders; ix++){ + for(size_t ix = 0; ix < m_countAppenders; ix++) { RplAppender* appender = m_appenders[ix]; - if (appender->isActive(level)){ + if(appender->isActive(level)) { rc = true; break; } @@ -206,13 +208,23 @@ bool RplLogger::isActive(RplLoggerLevel level) const{ * * @param level level to set */ -void RplLogger::setLevel(RplLoggerLevel level){ - for (size_t ix = 0; ix < m_countAppenders; ix++){ +void RplLogger::setLevel(RplLoggerLevel level) { + for(size_t ix = 0; ix < m_countAppenders; ix++) { RplAppender* appender = m_appenders[ix]; appender->setLevel(level); } } +/** + * @brief Sets or clears the state "with locking". + * + * @param onNotOff true: the logger is thread save.
+ * false: not thread save + */ +void RplLogger::setWithLocking(bool onNotOff) { + m_withLocking = onNotOff; +} + /** * @brief Returns the standard prefix of a logging line. * @@ -222,8 +234,8 @@ void RplLogger::setLevel(RplLoggerLevel level){ * @param location an unique identifier of the location * @return the standard logging line prefix */ -const QByteArray& RplLogger::getStdPrefix(RplLoggerLevel level, int location){ - if (m_stdPrefix.isEmpty()) +const QByteArray& RplLogger::getStdPrefix(RplLoggerLevel level, int location) { + if(m_stdPrefix.isEmpty()) m_stdPrefix = buildStdPrefix(level, location); return m_stdPrefix; } @@ -236,13 +248,19 @@ const QByteArray& RplLogger::getStdPrefix(RplLoggerLevel level, int location){ * @param message the logging message * @return true: for chaining */ -bool RplLogger::log(RplLoggerLevel level, int location, const char* message){ +bool RplLogger::log(RplLoggerLevel level, int location, const char* message) { m_stdPrefix = ""; - for (size_t ix = 0; ix < m_countAppenders; ix++){ + bool first = true; + for(size_t ix = 0; ix < m_countAppenders; ix++) { RplAppender* appender = m_appenders[ix]; - if (appender->isActive(level)) + if(appender->isActive(level)) { + if(first && m_withLocking) + m_mutex.lock(); appender->log(level, location, message, this); + } } + if(! first && m_withLocking) + m_mutex.unlock(); return true; } /** @@ -253,7 +271,8 @@ bool RplLogger::log(RplLoggerLevel level, int location, const char* message){ * @param message the logging message * @return true: for chaining */ -bool RplLogger::log(RplLoggerLevel level, int location, const QByteArray& message){ +bool RplLogger::log(RplLoggerLevel level, int location, + const QByteArray& message) { return log(level, location, message.data()); } @@ -265,7 +284,8 @@ bool RplLogger::log(RplLoggerLevel level, int location, const QByteArray& messag * @param message the logging message * @return true: for chaining */ -bool RplLogger::log(RplLoggerLevel level, int location, const QString& message){ +bool RplLogger::log(RplLoggerLevel level, int location, + const QString& message) { return log(level, location, message.toUtf8().data()); } @@ -278,7 +298,8 @@ bool RplLogger::log(RplLoggerLevel level, int location, const QString& message){ * @param ... the values of the placeholders (varargs) * @return true: for chaining */ -bool RplLogger::logv(RplLoggerLevel level, int location, const char* format, ...){ +bool RplLogger::logv(RplLoggerLevel level, int location, const char* format, + ...) { char buffer[64000]; va_list ap; va_start(ap, format); @@ -296,7 +317,8 @@ bool RplLogger::logv(RplLoggerLevel level, int location, const char* format, ... * @param ... the values of the placeholders (varargs) * @return true: for chaining */ -bool RplLogger::logv(RplLoggerLevel level, int location, const QByteArray& format, ...){ +bool RplLogger::logv(RplLoggerLevel level, int location, + const QByteArray& format, ...) { char buffer[64000]; va_list ap; va_start(ap, format); @@ -314,7 +336,8 @@ bool RplLogger::logv(RplLoggerLevel level, int location, const QByteArray& forma * @param varlist variable arguments * @return true: for chaining */ -bool RplLogger::log(RplLoggerLevel level, int location, const char* format, va_list& varlist){ +bool RplLogger::log(RplLoggerLevel level, int location, const char* format, + va_list& varlist) { char buffer[64000]; vsnprintf(buffer, sizeof buffer, format, varlist); return log(level, location, buffer); @@ -326,19 +349,19 @@ bool RplLogger::log(RplLoggerLevel level, int location, const char* format, va_l * @param level the level of the location * @param location an unique identifier of the location */ -QByteArray RplLogger::buildStdPrefix(RplLoggerLevel level, int location){ +QByteArray RplLogger::buildStdPrefix(RplLoggerLevel level, int location) { time_t now = time(NULL); struct tm* now2 = localtime(&now); char buffer[64]; snprintf(buffer, sizeof buffer, "%c%d.%02d.%02d %02d:%02d:%02d (%d): ", - getPrefixOfLevel(level), - now2->tm_year + 1900, - now2->tm_mon + 1, - now2->tm_mday, - now2->tm_hour, - now2->tm_min, - now2->tm_sec, - location); + getPrefixOfLevel(level), + now2->tm_year + 1900, + now2->tm_mon + 1, + now2->tm_mday, + now2->tm_hour, + now2->tm_min, + now2->tm_sec, + location); return QByteArray(buffer); } @@ -347,8 +370,8 @@ QByteArray RplLogger::buildStdPrefix(RplLoggerLevel level, int location){ * * @param appender appender to add */ -void RplLogger::addAppender(RplAppender* appender){ - if (m_countAppenders < sizeof m_appenders / sizeof m_appenders[0]){ +void RplLogger::addAppender(RplAppender* appender) { + if(m_countAppenders < sizeof m_appenders / sizeof m_appenders[0]) { m_appenders[m_countAppenders++] = appender; } else { log(LOG_ERROR, LOC_ADD_APPENDER_1, "too many appenders"); @@ -363,16 +386,42 @@ void RplLogger::addAppender(RplAppender* appender){ * @return NULL: no appender with this name is registered
* otherwise: the wanted appender */ -RplAppender* RplLogger::findAppender(const char* name) const{ - RplAppender* rc = NULL; - for (size_t ix = 0; ix < m_countAppenders; ix++){ - RplAppender* current = m_appenders[ix]; - if (strcmp(name, current->getName()) == 0){ - rc = current; - break; - } - } - return rc; +RplAppender* RplLogger::findAppender(const char* name) const { + RplAppender* rc = NULL; + for(size_t ix = 0; ix < m_countAppenders; ix++) { + RplAppender* current = m_appenders[ix]; + if(strcmp(name, current->getName()) == 0) { + rc = current; + break; + } + } + return rc; +} + +/** + * @brief Builds the standard appender configured by a configuration file. + * + * @param config configuration file + */ +void RplLogger::buildStandardAppender(RplConfig* config, + const char* prefix, + const char* defaultLogfilePrefix) { + QByteArray sPrefix(prefix); + QByteArray logFilePrefix = config->asString(sPrefix + "name", + defaultLogfilePrefix); + + int maxSize = config->asInt( + "maxsize", 10100100); + int maxCount = config->asInt(sPrefix + "maxfiles", 5); + buildStandardAppender(logFilePrefix, maxSize, maxCount); + QByteArray sLevel = config->asString(sPrefix + "level", "info"); + RplLoggerLevel level = LOG_INFO; + if (strcasecmp(sLevel.constData(), "error") == 0) + level = LOG_ERROR; + else if (strcasecmp(sLevel, "warning") == 0) + level = LOG_WARNING; + else if (strcasecmp(sLevel, "debug") == 0) + level = LOG_DEBUG; + setLevel(level); } /** @@ -382,7 +431,8 @@ RplAppender* RplLogger::findAppender(const char* name) const{ * @param maxSize the maximum of the file size * @param maxCount the maximal count of files. If neccessary the oldest file will be deleted */ -void RplLogger::buildStandardAppender(const QByteArray& prefix, int maxSize, int maxCount){ +void RplLogger::buildStandardAppender(const QByteArray& prefix, int maxSize, + int maxCount) { RplStreamAppender* streamAppender = new RplStreamAppender(stderr); streamAppender->setAutoDelete(true); addAppender((RplAppender*) streamAppender); @@ -405,14 +455,13 @@ void RplLogger::buildStandardAppender(const QByteArray& prefix, int maxSize, int */ RplStreamAppender::RplStreamAppender(FILE* file, const char* appenderName) : RplAppender(QByteArray(appenderName)), - m_fp(file) -{ + m_fp(file) { } /** * @brief Destructor. */ -RplStreamAppender::~RplStreamAppender(){ +RplStreamAppender::~RplStreamAppender() { fflush(m_fp); } @@ -425,7 +474,8 @@ RplStreamAppender::~RplStreamAppender(){ * @param message the logging message * @param logger the calling logger */ -void RplStreamAppender::log(RplLoggerLevel level, int location, const char* message, RplLogger* logger){ +void RplStreamAppender::log(RplLoggerLevel level, int location, + const char* message, RplLogger* logger) { const QByteArray& prefix = logger->getStdPrefix(level, location); fputs(prefix, m_fp); fputs(message, m_fp); @@ -455,23 +505,23 @@ void RplStreamAppender::log(RplLoggerLevel level, int location, const char* mess * @param maxCount the maximal count of files. If neccessary the oldest file will be deleted * @param appenderName the name of the appender. @see RplLogger::findAppender() */ -RplFileAppender::RplFileAppender(const QByteArray& prefix, int maxSize, int maxCount, const char* appenderName) : +RplFileAppender::RplFileAppender(const QByteArray& prefix, int maxSize, + int maxCount, const char* appenderName) : RplAppender(QByteArray(appenderName)), m_prefix(prefix), m_maxSize(maxSize), m_maxCount(maxCount), m_currentSize(0), m_currentNo(0), - m_fp(NULL) -{ + m_fp(NULL) { open(); } /** * @brief Destructor. */ -RplFileAppender::~RplFileAppender(){ - if (m_fp != NULL){ +RplFileAppender::~RplFileAppender() { + if(m_fp != NULL) { fclose(m_fp); m_fp = NULL; } @@ -480,15 +530,16 @@ RplFileAppender::~RplFileAppender(){ /** * @brief Opens the next log file. */ -void RplFileAppender::open(){ - if (m_fp != NULL) +void RplFileAppender::open() { + if(m_fp != NULL) fclose(m_fp); char fullName[512]; - snprintf(fullName, sizeof fullName, "%s.%03d.log", m_prefix.data(), ++m_currentNo); + snprintf(fullName, sizeof fullName, "%s.%03d.log", m_prefix.data(), + ++m_currentNo); m_fp = fopen(fullName, "a"); - if (m_fp == NULL) + if(m_fp == NULL) fprintf(stderr, "cannot open: %s\n", fullName); - else{ + else { //@ToDo m_currentSize = 0; } @@ -503,10 +554,10 @@ void RplFileAppender::open(){ * @param logger the calling logger */ #pragma GCC diagnostic ignored "-Wunused-parameter" -void RplFileAppender::log(RplLoggerLevel level, int location, const char* message, - RplLogger* logger) -{ - if (m_fp != NULL){ +void RplFileAppender::log(RplLoggerLevel level, int location, + const char* message, + RplLogger* logger) { + if(m_fp != NULL) { const QByteArray& prefix = logger->getStdPrefix(level, location); fputs(prefix, m_fp); fputs(message, m_fp); @@ -533,15 +584,14 @@ void RplFileAppender::log(RplLoggerLevel level, int location, const char* messag RplMemoryAppender::RplMemoryAppender(int maxLines, const char* appenderName) : RplAppender(appenderName), m_lines(), - m_maxLines(maxLines) -{ + m_maxLines(maxLines) { m_lines.reserve(maxLines); } /** * @brief Destructor. */ -RplMemoryAppender::~RplMemoryAppender(){ +RplMemoryAppender::~RplMemoryAppender() { } /** @@ -553,10 +603,10 @@ RplMemoryAppender::~RplMemoryAppender(){ * @param logger the calling logger */ #pragma GCC diagnostic ignored "-Wunused-parameter" -void RplMemoryAppender::log(RplLoggerLevel level, int location, const char* message, - RplLogger* logger) -{ - if (m_lines.size() >= m_maxLines) +void RplMemoryAppender::log(RplLoggerLevel level, int location, + const char* message, + RplLogger* logger) { + if(m_lines.size() >= m_maxLines) m_lines.removeFirst(); m_lines.append(message); } @@ -567,13 +617,13 @@ void RplMemoryAppender::log(RplLoggerLevel level, int location, const char* mess * * @return the line list */ -const QVector& RplMemoryAppender::getLines() const{ +const QVector& RplMemoryAppender::getLines() const { return m_lines; } /** * @brief Deletes all log lines. */ -void RplMemoryAppender::clear(){ +void RplMemoryAppender::clear() { m_lines.clear(); } diff --git a/rplcore/rpllogger.hpp b/rplcore/rpllogger.hpp index 3c0af24..69c8059 100644 --- a/rplcore/rpllogger.hpp +++ b/rplcore/rpllogger.hpp @@ -12,7 +12,7 @@ * */ class RplLogger; - +class RplConfig; /** * @brief Logging level: for controlling of the logging. * @@ -27,8 +27,7 @@ enum RplLoggerLevel { LOG_DEBUG = 25 ///< for debug purpose only }; -class RplAppender -{ +class RplAppender { public: RplAppender(const QByteArray& name); virtual ~RplAppender(); @@ -39,7 +38,7 @@ private: RplAppender& operator =(const RplAppender& source); public: virtual void log(RplLoggerLevel level, int location, const char* message, - RplLogger* logger) = 0; + RplLogger* logger) = 0; bool isActive(RplLoggerLevel level); void setLevel(RplLoggerLevel level); void setAutoDelete(bool onNotOff); @@ -56,8 +55,7 @@ private: bool m_autoDelete; }; -class RplLogger -{ +class RplLogger { public: static RplLogger* globalLogger(); static void destroyGlobalLogger(); @@ -78,15 +76,20 @@ public: bool log(RplLoggerLevel level, int location, const QString& message); bool logv(RplLoggerLevel level, int location, const char* format, ...); bool logv(RplLoggerLevel level, int location, const QByteArray& format, ...); - bool log(RplLoggerLevel level, int location, const char* format, va_list& varlist); + bool log(RplLoggerLevel level, int location, const char* format, + va_list& varlist); void addAppender(RplAppender* appender); RplAppender* findAppender(const char* name) const; - void buildStandardAppender(const QByteArray& prefix, int maxSize = 10*1024*1024, int maxCount = 5); + void buildStandardAppender(RplConfig* config, const char* prefix = "logfile.", + const char* defaultLoggerName = "logger"); + void buildStandardAppender(const QByteArray& prefix, int maxSize = 10*1024*1024, + int maxCount = 5); QByteArray buildStdPrefix(RplLoggerLevel level, int location); const QByteArray& getStdPrefix(RplLoggerLevel level, int location); char getPrefixOfLevel(RplLoggerLevel level) const; bool isActive(RplLoggerLevel level) const; void setLevel(RplLoggerLevel level); + void setWithLocking(bool onNotOff); private: // the assigned appenders: RplAppender* m_appenders[16]; @@ -94,19 +97,20 @@ private: size_t m_countAppenders; // "" or the cache of the prefix of the current logging line: This can be reused by any appender. QByteArray m_stdPrefix; + QMutex m_mutex; + bool m_withLocking; }; /** * Implements an appender which puts the messages to a standard stream: stdout or stderr */ -class RplStreamAppender : public RplAppender -{ +class RplStreamAppender : public RplAppender { public: RplStreamAppender(FILE* stream, const char* appenderName = "FileAppender"); virtual ~RplStreamAppender(); public: virtual void log(RplLoggerLevel level, int location, const char* message, - RplLogger* logger); + RplLogger* logger); private: // stdout or stderr: FILE* m_fp; @@ -115,15 +119,15 @@ private: /** * Implements an appender which puts the messages to a file */ -class RplFileAppender : public RplAppender -{ +class RplFileAppender : public RplAppender { public: - RplFileAppender(const QByteArray& name, int maxSize, int maxCount, const char* appenderName = "FileAppender"); + RplFileAppender(const QByteArray& name, int maxSize, int maxCount, + const char* appenderName = "FileAppender"); virtual ~RplFileAppender(); public: void open(); virtual void log(RplLoggerLevel level, int location, const char* message, - RplLogger* logger); + RplLogger* logger); private: // prefix of the log file name. Will be appended by "..log" @@ -143,13 +147,14 @@ private: /** * Stores the log messages in a list. */ -class RplMemoryAppender : public RplAppender{ +class RplMemoryAppender : public RplAppender { public: - RplMemoryAppender(int maxLines = 1024, const char* appenderName = "MemoryAppender"); + RplMemoryAppender(int maxLines = 1024, + const char* appenderName = "MemoryAppender"); ~RplMemoryAppender(); public: virtual void log(RplLoggerLevel level, int location, const char* message, - RplLogger* logger); + RplLogger* logger); const QVector& getLines() const; void clear(); private: diff --git a/rplcore/rplstring.cpp b/rplcore/rplstring.cpp index d536cd2..40e1308 100644 --- a/rplcore/rplstring.cpp +++ b/rplcore/rplstring.cpp @@ -21,16 +21,16 @@ * @param item this item will be searched * @return the count of occurrences */ -int RplString::count(const char* source, const char* item){ +int RplString::count(const char* source, const char* item) { const char* end = source; int rc = 0; int lengthItem = strlen(item); - while (true){ + while(true) { const char* start = end; end = strstr(start, item); - if (end == NULL) + if(end == NULL) break; - else{ + else { rc++; end += lengthItem; } @@ -50,15 +50,44 @@ int RplString::count(const char* source, const char* item){ * the prefix of source with the given length */ const QByteArray& RplString::cutString(const QByteArray& source, int maxLength, - QByteArray& buffer, const char* appendix){ + QByteArray& buffer, const char* appendix) { QByteArray& rc = source.length() <= maxLength ? (QByteArray&) source : buffer; - if (source.length() > maxLength){ + if(source.length() > maxLength) { buffer = source.left(maxLength); - if (appendix != NULL && appendix[0] != '\0') + if(appendix != NULL && appendix[0] != '\0') buffer.append(appendix); } return rc; } +static char s_fileSeparator = 0; + +/** + * @brief Returns the os specific file path separator. + * @return the file path separator, e.g. "/" for linux + */ +const char* RplString::fileSeparator(){ + return fileSeparatorChar() == '/' ? "/" : "\\"; +} + +/** + * @brief Returns the os specific file path separator. + * @return the file path separator, e.g. '/' for linux + */ +char RplString::fileSeparatorChar(){ + if (s_fileSeparator == 0){ + const char* path = getenv("PATH"); + if (path != NULL){ + s_fileSeparator = strchr(path, ';') != NULL + || strchr(path, '\\') != NULL ? '\\' : '/'; + } else { + if (getenv("windows") != NULL) + s_fileSeparator = '\\'; + else + s_fileSeparator = '/'; + } + } + return s_fileSeparator; +} /** * Builds a hexadecimal dump. @@ -72,7 +101,7 @@ const QByteArray& RplString::cutString(const QByteArray& source, int maxLength, * @param bytesPerLine one line containes so many bytes of data * @return the hex dump */ -QByteArray RplString::hexDump(uint8_t* data, int length, int bytesPerLine){ +QByteArray RplString::hexDump(uint8_t* data, int length, int bytesPerLine) { QByteArray rc; int fullLines = length / bytesPerLine; int expectedLength = (bytesPerLine * 4 + 2) * (fullLines + 1); @@ -80,13 +109,13 @@ QByteArray RplString::hexDump(uint8_t* data, int length, int bytesPerLine){ int ixData = 0; int col; char buffer[16]; - for (int lineNo = 0; lineNo < fullLines; lineNo++){ - for (col = 0; col < bytesPerLine; col++){ + for(int lineNo = 0; lineNo < fullLines; lineNo++) { + for(col = 0; col < bytesPerLine; col++) { snprintf(buffer, sizeof buffer, "%02x ", data[ixData + col]); rc.append(buffer); } rc.append(' '); - for (col = 0; col < bytesPerLine; col++){ + for(col = 0; col < bytesPerLine; col++) { uint8_t cc = data[ixData + col]; rc.append(cc > ' ' && cc < 128 ? (char) cc : '.'); } @@ -95,16 +124,16 @@ QByteArray RplString::hexDump(uint8_t* data, int length, int bytesPerLine){ } // incomplete last line: int restBytes = length - ixData; - if (restBytes > 0){ - for (col = 0; col < restBytes; col++){ + if(restBytes > 0) { + for(col = 0; col < restBytes; col++) { snprintf(buffer, sizeof buffer, "%02x ", data[ixData + col]); rc.append(buffer); } - for (col = restBytes; col < bytesPerLine; col++){ + for(col = restBytes; col < bytesPerLine; col++) { rc.append(" "); } rc.append(' '); - for (col = 0; col < restBytes; col++){ + for(col = 0; col < restBytes; col++) { uint8_t cc = data[ixData + col]; rc.append(cc > ' ' && cc < 128 ? (char) cc : '.'); } @@ -122,17 +151,17 @@ QByteArray RplString::hexDump(uint8_t* data, int length, int bytesPerLine){ * the result will not contain this * @return the file's content */ -QByteArray RplString::read(const char* file, bool removeLastNewline){ +QByteArray RplString::read(const char* file, bool removeLastNewline) { QByteArray rc; struct stat info; size_t size; - if (stat(file, &info) == 0 && (size = info.st_size) > 0){ + if(stat(file, &info) == 0 && (size = info.st_size) > 0) { FILE* fp = fopen(file, "r"); - if (fp != NULL){ + if(fp != NULL) { rc.resize(info.st_size); fread(rc.data(), 1, size, fp); fclose(fp); - if (removeLastNewline && rc.at(size - 1) == '\n'){ + if(removeLastNewline && rc.at(size - 1) == '\n') { rc.resize(size - 1); } } @@ -140,6 +169,21 @@ QByteArray RplString::read(const char* file, bool removeLastNewline){ return rc; } +QByteArray RplString::replaceNode(const char* source, const char* newNode){ + char sep = fileSeparatorChar(); + const char* ptr = strrchr(source, sep); + QByteArray rc; + rc.reserve(strlen(source) + strlen(newNode) + 1); + if (ptr == NULL){ + rc.append(source).append(sep).append(newNode); + } else if (ptr[0] == '\0'){ + rc.append(source).append(newNode); + } else { + rc.append(source, ptr - source + 1).append(newNode); + } + return rc; +} + /** * Converts a string into an array of strings. * @@ -147,24 +191,67 @@ QByteArray RplString::read(const char* file, bool removeLastNewline){ * @param separator the separator between the items to split * @return an array with the splitted source */ -QVector RplString::toArray(const char* source, const char* separator){ +QVector RplString::toArray(const char* source, + const char* separator) { const char* end = source; QVector rc; rc.reserve(count(source, separator) + 1); int lengthItem = strlen(separator); - while (*end != '\0'){ + while(*end != '\0') { const char* start = end; end = strstr(start, separator); - if (end == NULL){ + if(end == NULL) { end = start + strlen(start); } rc.append(QByteArray(start, end - start)); - if (end[0] != '\0') + if(end[0] != '\0') end += lengthItem; } return rc; } +QByteArray RplString::toCString(const char* source, int maxLength){ + if (maxLength <= 0) + maxLength = strlen(source); + int binaries = 0; + int ix; + for (ix = 0; ix < maxLength; ix++) + if (source[ix] < ' '){ + binaries++; + } + QByteArray rc; + rc.reserve(maxLength + 3 * binaries + 1); + char cc; + for (ix = 0; ix < maxLength; ix++) + if ( (cc = source[ix]) >= ' '){ + rc += source[ix]; + } else { + switch(cc){ + case '\0': + // stop looping: + ix = maxLength; + break; + case '\n': + rc += "\\n"; + break; + case '\r': + rc += "\\r"; + break; + case '\t': + rc += "\\t"; + break; + default: + { + char buffer[5]; + snprintf(buffer, sizeof buffer, "\\x%02x", + ((unsigned int) cc) % 0xff); + rc += buffer; + break; + } + } + } + return rc; +} /** * Return an integer as an QByteArray. @@ -173,7 +260,7 @@ QVector RplString::toArray(const char* source, const char* separator * @param format format like in sprintf() * @return the ascii form of the value */ -QByteArray RplString::toNumber(int value, const char* format){ +QByteArray RplString::toNumber(int value, const char* format) { char buffer[128]; snprintf(buffer, sizeof buffer, format, value); return QByteArray(buffer); @@ -188,9 +275,9 @@ QByteArray RplString::toNumber(int value, const char* format){ * @return true: successful
* false: error occurred */ -bool RplString::write(const char* file, const char* content, const char* mode){ +bool RplString::write(const char* file, const char* content, const char* mode) { FILE* fp = fopen(file, mode); - if (fp != NULL){ + if(fp != NULL) { fputs(content, fp); fclose(fp); } @@ -206,13 +293,12 @@ bool RplString::write(const char* file, const char* content, const char* mode){ /** * @brief Unit test for RplString. */ -class TestRplString : public RplTest -{ +class TestRplString : public RplTest { public: - TestRplString() : RplTest("RplString"){} + TestRplString() : RplTest("RplString") {} public: - void testCount(){ + void testCount() { checkE(0, RplString::count("abc", " ")); checkE(1, RplString::count("abc", "b")); checkE(2, RplString::count("axx", "x")); @@ -222,7 +308,7 @@ public: checkE(2, RplString::count(" a ", " ")); } - void testCutString(){ + void testCutString() { QByteArray source("123"); QByteArray buffer; checkE(QByteArray("123"), RplString::cutString(source, 4, buffer)); @@ -231,27 +317,27 @@ public: checkE(QByteArray("12"), RplString::cutString(source, 2, buffer, "")); } - void testHexDump(){ + void testHexDump() { QByteArray data("abc123\nxyz"); checkE(QByteArray("61 62 63 31 abc1\n" - "32 33 0a 78 23.x\n" - "79 7a yz\n"), - RplString::hexDump((uint8_t*) data.constData(), data.length(), 4)); + "32 33 0a 78 23.x\n" + "79 7a yz\n"), + RplString::hexDump((uint8_t*) data.constData(), data.length(), 4)); checkE(QByteArray("61 62 63 31 32 33 0a 78 79 7a abc123.xyz"), - RplString::hexDump((uint8_t*) data.constData(), data.length(), 10)); + RplString::hexDump((uint8_t*) data.constData(), data.length(), 10)); checkE(QByteArray("61 62 63 31 32 33 0a 78 79 7a abc123.xyz"), - RplString::hexDump((uint8_t*) data.constData(), data.length(), 12)); + RplString::hexDump((uint8_t*) data.constData(), data.length(), 12)); } - void testReadWrite(){ + void testReadWrite() { QByteArray fn = getTempFile("test.dat"); const char* content = "Hello world\nLine2\n"; checkT(RplString::write(fn, content)); checkE(content, RplString::read(fn, false)); checkE(content, RplString::read(fn, true) + "\n"); - } + } - void testToArray(){ + void testToArray() { QVector array = RplString::toArray("1 abc 3", " "); checkE(3, array.size()); checkE("1", array.at(0)); @@ -259,13 +345,13 @@ public: checkE("3", array.at(2)); } - void testToNumber(){ + void testToNumber() { checkE("3", RplString::toNumber(3)); checkE("-33", RplString::toNumber(-33)); checkE("003", RplString::toNumber(3, "%03d")); } - virtual void doIt(){ + virtual void doIt() { testCount(); testCutString(); testToNumber(); @@ -276,7 +362,7 @@ public: }; #endif -void testRplString(){ +void testRplString() { #ifdef RPL_TEST TestRplString test; test.run(); diff --git a/rplcore/rplstring.hpp b/rplcore/rplstring.hpp index e83dd63..39b8266 100644 --- a/rplcore/rplstring.hpp +++ b/rplcore/rplstring.hpp @@ -8,20 +8,23 @@ #ifndef RPLSTRING_HPP #define RPLSTRING_HPP -class RplString -{ +class RplString { public: static int count(const char* source, const char* item); static const QByteArray& cutString(const QByteArray& source, int maxLength, - QByteArray& buffer, const char* appendix = "..."); + QByteArray& buffer, const char* appendix = "..."); + static const char* fileSeparator(); + static char fileSeparatorChar(); static QByteArray hexDump(uint8_t* data, int length, int bytesPerLine = 16); - static QByteArray hexDump(const void* data, int length, int bytesPerLine = 16){ + static QByteArray hexDump(const void* data, int length, int bytesPerLine = 16) { return hexDump((uint8_t*) data, length, bytesPerLine); } static QByteArray read(const char* file, bool removeLastNewline = true); + static QByteArray replaceNode(const char* source, const char* newNode); static bool write(const char* file, const char* content = NULL, - const char* mode = "w"); + const char* mode = "w"); static QVector toArray(const char* source, const char* separator); + static QByteArray toCString(const char* source, int maxLength = -1); static QByteArray toNumber(int value, const char* format = "%d"); }; diff --git a/rplcore/rplterminator.cpp b/rplcore/rplterminator.cpp index 41dd99f..6b373aa 100644 --- a/rplcore/rplterminator.cpp +++ b/rplcore/rplterminator.cpp @@ -30,14 +30,13 @@ enum { */ RplTerminator::RplTerminator(RplLogger* logger) : m_stop(false), - m_logger(logger) -{ + m_logger(logger) { } /** * @brief Destructor. */ -RplTerminator::~RplTerminator(){ +RplTerminator::~RplTerminator() { } /** @@ -50,10 +49,10 @@ RplTerminator::~RplTerminator(){ * @param location 0 or the location of the caller */ void RplTerminator::causeTermination(const char* reason, const char* file, - int lineNo, RplLoggerLevel level, int location){ - if (m_logger != NULL){ + int lineNo, RplLoggerLevel level, int location) { + if(m_logger != NULL) { QByteArray message(reason); - if (file != NULL){ + if(file != NULL) { message.append(" [").append(file).append(lineNo).append("]"); } m_logger->log(level, location == 0 ? LOC_CAUSE_TERMINATION_1 : location, @@ -67,7 +66,7 @@ void RplTerminator::causeTermination(const char* reason, const char* file, * @return true: the thread should be stopped.
* false: otherwise */ -bool RplTerminator::isStopped() const{ +bool RplTerminator::isStopped() const { return m_stop; } diff --git a/rplcore/rplterminator.hpp b/rplcore/rplterminator.hpp index 25e5fca..f0e49c1 100644 --- a/rplcore/rplterminator.hpp +++ b/rplcore/rplterminator.hpp @@ -8,8 +8,7 @@ #ifndef RPLTERMINATOR_HPP #define RPLTERMINATOR_HPP -class RplTerminator -{ +class RplTerminator { public: RplTerminator(RplLogger* logger = NULL); virtual ~RplTerminator(); @@ -20,7 +19,7 @@ private: RplTerminator& operator =(const RplTerminator& source); public: void causeTermination(const char* reason, const char* file = NULL, - int lineNo = 0, RplLoggerLevel level = LOG_ERROR, int location = 0); + int lineNo = 0, RplLoggerLevel level = LOG_ERROR, int location = 0); bool isStopped() const; private: bool m_stop; diff --git a/rplcore/rpltest.cpp b/rplcore/rpltest.cpp index 24bfe77..1f538c9 100644 --- a/rplcore/rpltest.cpp +++ b/rplcore/rpltest.cpp @@ -26,8 +26,7 @@ class RplTest; RplTest::RplTest(const char* name) : m_errors(0), m_name(name), - m_logger() -{ + m_logger() { m_logger.buildStandardAppender(getTempDir("rpltest")); log(QByteArray("Start of ") + m_name); } @@ -35,14 +34,14 @@ RplTest::RplTest(const char* name) : /** * @brief Runs all tests of the test class. */ -void RplTest::run(){ +void RplTest::run() { try { doIt(); - } catch (RplException e){ + } catch(RplException e) { error("unexpected RplException: %s", e.getMessage().data()); } - if (m_errors > 0){ + if(m_errors > 0) { error("Unit %s has %d error(s)", m_name.data(), m_errors); // error() increments, we decrement: m_errors--; @@ -52,7 +51,7 @@ void RplTest::run(){ /** * @brief Destructor. */ -RplTest::~RplTest(){ +RplTest::~RplTest() { } /** @@ -66,9 +65,11 @@ RplTest::~RplTest(){ * @param lineNo the line number containing the test * @return true: equal */ -bool RplTest::assertEquals(int expected, int current, const char* file, int lineNo){ - if (expected != current) - error("%s-%d: error: %d != %d / %x != %x)", file, lineNo, expected, current, (unsigned int) expected, (unsigned int) current); +bool RplTest::assertEquals(int expected, int current, const char* file, + int lineNo) { + if(expected != current) + error("%s-%d: error: %d != %d / %x != %x)", file, lineNo, expected, current, + (unsigned int) expected, (unsigned int) current); return expected == current; } @@ -84,10 +85,10 @@ bool RplTest::assertEquals(int expected, int current, const char* file, int line * @return true: equal */ bool RplTest::assertEquals(const char* expected, const char* current, - const char* file, int lineNo){ + const char* file, int lineNo) { bool equal = strcmp(expected, current) == 0; - if (! equal){ - if (strchr(expected, '\n') != NULL || strchr(current, '\n')){ + if(! equal) { + if(strchr(expected, '\n') != NULL || strchr(current, '\n')) { QVector exp = RplString::toArray(expected, "\n"); QVector cur = RplString::toArray(current, "\n"); equal = assertEquals(exp, cur, file, lineNo); @@ -96,13 +97,13 @@ bool RplTest::assertEquals(const char* expected, const char* current, while(expected[ix] == current[ix] && expected[ix] != '\0') ix++; char pointer[12+1]; - char *ptr = pointer; + char* ptr = pointer; int maxIx = ix > 10 ? 10 : ix; - for (int ii = 0; ii < maxIx - 1; ii++) + for(int ii = 0; ii < maxIx - 1; ii++) *ptr++ = '-'; *ptr++ = '^'; *ptr = '\0'; - if (ix < 10) + if(ix < 10) error("%s-%d: error: diff at index %d\n%s\n%s\n%s", file, lineNo, ix, expected, current, pointer); else @@ -128,26 +129,26 @@ bool RplTest::assertEquals(const char* expected, const char* current, * @return true: equal */ bool RplTest::assertEquals(const QVector& expected, - const QVector& current, const char* file, int lineNo){ + const QVector& current, const char* file, int lineNo) { int nMax = expected.size(); bool rc = true; - if (current.size() < nMax) + if(current.size() < nMax) nMax = current.size(); - for (int ix = 0; ix < nMax; ix++){ - if (expected.at(ix) != current.at(ix)){ + for(int ix = 0; ix < nMax; ix++) { + if(expected.at(ix) != current.at(ix)) { error("%s-%d: difference in line %d", file, lineNo, ix+1); m_errors--; assertEquals(expected.at(ix).constData(), current.at(ix).constData(), - file, lineNo); + file, lineNo); rc = false; break; } } - if (rc){ - if (expected.size() > nMax) + if(rc) { + if(expected.size() > nMax) error("%s-%d: less lines than expected (%d):\n%s", file, lineNo, nMax, expected.at(nMax).constData()); - else if (expected.size() < nMax) + else if(expected.size() < nMax) error("%s-%d: more lines than expected (%d):\n%s", file, lineNo, nMax, current.at(nMax).constData()); } @@ -164,7 +165,8 @@ bool RplTest::assertEquals(const QVector& expected, * @param lineNo the line number containing the test * @return true: equal */ -bool RplTest::assertEquals(const QByteArray& expected, const QByteArray& current, const char* file, int lineNo){ +bool RplTest::assertEquals(const QByteArray& expected, + const QByteArray& current, const char* file, int lineNo) { return assertEquals(expected.data(), current.data(), file, lineNo); } @@ -180,7 +182,7 @@ bool RplTest::assertEquals(const QByteArray& expected, const QByteArray& current * @return true: equal */ bool RplTest::assertEquals(const char* expected, const QByteArray& current, - const char* file, int lineNo){ + const char* file, int lineNo) { return assertEquals(expected, current.constData(), file, lineNo); } @@ -194,8 +196,8 @@ bool RplTest::assertEquals(const char* expected, const QByteArray& current, * @param lineNo the line number containing the test * @return condition */ -bool RplTest::assertTrue(bool condition, const char* file, int lineNo){ - if (! condition) +bool RplTest::assertTrue(bool condition, const char* file, int lineNo) { + if(! condition) error("%s-%d: not TRUE", file, lineNo); return condition; } @@ -210,8 +212,8 @@ bool RplTest::assertTrue(bool condition, const char* file, int lineNo){ * @param lineNo the line number containing the test * @return ! condition */ -bool RplTest::assertFalse(bool condition, const char* file, int lineNo){ - if (condition) +bool RplTest::assertFalse(bool condition, const char* file, int lineNo) { + if(condition) error("%s-%d: not FALSE", file, lineNo); return ! condition; } @@ -226,8 +228,8 @@ bool RplTest::assertFalse(bool condition, const char* file, int lineNo){ * @param lineNo the line number containing the test * @return true: ptr is NULL */ -bool RplTest::assertNull(const void* ptr, const char* file, int lineNo){ - if (ptr != NULL) +bool RplTest::assertNull(const void* ptr, const char* file, int lineNo) { + if(ptr != NULL) error("%s-%d: not NULL", file, lineNo); return ptr == NULL; } @@ -242,8 +244,8 @@ bool RplTest::assertNull(const void* ptr, const char* file, int lineNo){ * @param lineNo the line number containing the test * @return true: ptr is not NULL */ -bool RplTest::assertNotNull(const void* ptr, const char* file, int lineNo){ - if (ptr == NULL) +bool RplTest::assertNotNull(const void* ptr, const char* file, int lineNo) { + if(ptr == NULL) error("%s-%d: is NULL", file, lineNo); return ptr != NULL; } @@ -254,7 +256,7 @@ bool RplTest::assertNotNull(const void* ptr, const char* file, int lineNo){ * @param message message to show * @return true (for chaining) */ -bool RplTest::log(const char* message){ +bool RplTest::log(const char* message) { m_logger.log(LOG_INFO, 0, message); return true; } @@ -267,7 +269,7 @@ bool RplTest::log(const char* message){ * @param ... the values for the placeholders in format * @return false (for chaining) */ -bool RplTest::error(const char* format, ...){ +bool RplTest::error(const char* format, ...) { m_errors++; va_list ap; va_start(ap, format); @@ -287,32 +289,32 @@ bool RplTest::error(const char* format, ...){ * @return the name of a existing directory */ QByteArray RplTest::getTempDir(const char* node, const char* parent, - bool withSeparator){ + bool withSeparator) { QByteArray temp("c:\\temp"); struct stat info; const char* ptr; - if ( (ptr = getenv("TMP")) != NULL ) + if((ptr = getenv("TMP")) != NULL) temp = ptr; - else if ( (ptr = getenv("TEMP")) != NULL ) + else if((ptr = getenv("TEMP")) != NULL) temp = ptr; - else if (stat("/tmp", &info) == 0) + else if(stat("/tmp", &info) == 0) temp = "/tmp"; char sep = m_separator = temp.indexOf('/') >= 0 ? '/' : '\\'; - if (temp.at(temp.length() - 1) != sep) + if(temp.at(temp.length() - 1) != sep) temp += sep; - if (parent != NULL){ + if(parent != NULL) { temp += parent; - if (stat(temp.constData(), &info) != 0) + if(stat(temp.constData(), &info) != 0) mkdir(temp.constData(), (-1)); temp += sep; } - if (node != NULL){ + if(node != NULL) { temp += node; temp += sep; - if (stat(temp.data(), &info) != 0) + if(stat(temp.data(), &info) != 0) mkdir(temp.data(), -1); } - if (! withSeparator) + if(! withSeparator) temp.resize(temp.length() - 1); return temp; } @@ -326,11 +328,11 @@ QByteArray RplTest::getTempDir(const char* node, const char* parent, * @return the full name of a temporary file */ QByteArray RplTest::getTempFile(const char* node, const char* parent, - bool deleteIfExists){ + bool deleteIfExists) { QByteArray dir = getTempDir(parent); QByteArray rc = dir + m_separator + node; struct stat info; - if (deleteIfExists && stat(rc.constData(), &info) == 0) + if(deleteIfExists && stat(rc.constData(), &info) == 0) unlink(rc.constData()); return rc; } diff --git a/rplcore/rpltest.hpp b/rplcore/rpltest.hpp index 142459f..4c15120 100644 --- a/rplcore/rpltest.hpp +++ b/rplcore/rpltest.hpp @@ -13,8 +13,7 @@ #include #endif -class RplTest -{ +class RplTest { public: RplTest(const char* name); virtual ~RplTest(); @@ -26,13 +25,13 @@ private: public: bool assertEquals(int expected, int current, const char* file, int lineNo); bool assertEquals(const char* expected, const char* current, - const char* file, int lineNo); + const char* file, int lineNo); bool assertEquals(const QByteArray& expected, const QByteArray& current, - const char* file, int lineNo); + const char* file, int lineNo); bool assertEquals(const char* expected, const QByteArray& current, - const char* file, int lineNo); + const char* file, int lineNo); bool assertEquals(const QVector& expected, - const QVector& current, const char* file, int lineNo); + const QVector& current, const char* file, int lineNo); bool assertTrue(bool condition, const char* file, int lineNo); bool assertFalse(bool condition, const char* file, int lineNo); bool assertNull(const void* ptr, const char* file, int lineNo); @@ -40,9 +39,9 @@ public: bool log(const char* message); bool error(const char* message, ...); QByteArray getTempDir(const char* node, const char* parent = NULL, - bool withSeparator = true); + bool withSeparator = true); QByteArray getTempFile(const char* node, const char* parent = NULL, - bool deleteIfExists = true); + bool deleteIfExists = true); void run(); virtual void doIt() = 0; diff --git a/rplcore/testrplexample.cpp b/rplcore/testrplexample.cpp index 7dc9212..e0c35f4 100644 --- a/rplcore/testrplexample.cpp +++ b/rplcore/testrplexample.cpp @@ -12,7 +12,7 @@ int add(int a, int b) { return a+b; } -QByteArray concat(const char* a, const char* b){ +QByteArray concat(const char* a, const char* b) { return QByteArray(a) + " " + b; } const char* firstDot(const char* s) { @@ -21,31 +21,30 @@ const char* firstDot(const char* s) { /** * @brief Example for usage of the class RplTest. */ -class TestRplExample : public RplTest -{ +class TestRplExample : public RplTest { public: - TestRplExample() : RplTest("RplExample"){} + TestRplExample() : RplTest("RplExample") {} public: - void testInt(){ + void testInt() { log("testing add..."); // compare 2 integers: checkE(2, add(1, 1)); } - void testString(){ + void testString() { // compare 2 strings: checkE("Be good", concat("Be", "good")); // test for not NULL: checkN(firstDot("Hi.")); // test for NULL: checkNN(firstDot("Hi")); - } - virtual void doIt(){ + } + virtual void doIt() { testInt(); testString(); } }; -void testRplExample(){ +void testRplExample() { TestRplExample test; test.run(); } diff --git a/rplmath/rplenigma.cpp b/rplmath/rplenigma.cpp index cd96d7e..1e565ab 100644 --- a/rplmath/rplenigma.cpp +++ b/rplmath/rplenigma.cpp @@ -6,6 +6,14 @@ * The original sources can be found on https://github.com/republib. */ #include "rplmath.hpp" + +/** @class RplEnigma::secret_t rplenigma.hpp "rplmath/rplenigma.hpp" + * + * @brief Stores the internal structure of a secret. + * + * A secret can be a password, a salt, a certificate or simlar + * which makes an encryption individually. + */ /** @class RplEnigma rplenigma.hpp "rplmath/rplenigma.hpp" * * @brief Implements a portable en/decryption engine. @@ -28,25 +36,27 @@ const char* RplEnigma::SET_DECIMALS = "0123456789"; const char* RplEnigma::SET_HEXDIGITS = "0123456789abcdef"; const char* RplEnigma::SET_ALPHANUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz_"; + "abcdefghijklmnopqrstuvwxyz_"; const char* RplEnigma::SET_FILENAME = " !^°$%&=+~#-.0123456789ABCDEFGHIJKLM" - "NOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"; + "NOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"; const char* RplEnigma::SET_32_127 = " !\"#$%&'()*+,-./0123456789:;<=>?@" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f"; const char* RplEnigma::SET_32_255 = " !\"#$%&'()*+,-./0123456789:;<=>?@" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" - "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; -const char* RplEnigma::SET_PRINTABLE_127 = "\t\r\n !\"#$%&'()*+,-./0123456789:;<=>?@" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f"; -const char* RplEnigma::SET_PRINTABLE_255 = "\t\r\n !\"#$%&'()*+,-./0123456789:;<=>?@" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" - "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" - "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; + "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; +const char* RplEnigma::SET_PRINTABLE_127 = + "\t\r\n !\"#$%&'()*+,-./0123456789:;<=>?@" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f"; +const char* RplEnigma::SET_PRINTABLE_255 = + "\t\r\n !\"#$%&'()*+,-./0123456789:;<=>?@" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" + "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; /** * @brief Constructor. @@ -58,10 +68,9 @@ RplEnigma::RplEnigma(RplRandom* random) : m_ownsRandom(false), m_secrets(), m_randomCalls(0), - m_randomSource("4711") -{ + m_randomSource("4711") { m_randomSource.reserve(8096); - if (random == NULL){ + if(random == NULL) { m_random = new RplRandom(); m_ownsRandom = true; } @@ -69,8 +78,8 @@ RplEnigma::RplEnigma(RplRandom* random) : /** * @brief Destructor. */ -RplEnigma::~RplEnigma(){ - if (m_ownsRandom){ +RplEnigma::~RplEnigma() { + if(m_ownsRandom) { delete m_random; m_random = NULL; } @@ -84,18 +93,18 @@ RplEnigma::~RplEnigma(){ * @return empty string: error while reading
* otherwise: the certificate as byte array */ -QByteArray RplEnigma::readCertificate(const char* filename){ +QByteArray RplEnigma::readCertificate(const char* filename) { QByteArray rc; return rc; } -inline void buildBooster(QByteArray& booster, const char* charSet){ +inline void buildBooster(QByteArray& booster, const char* charSet) { int size = 257; booster.fill(0, size); int ix = 0; unsigned char cc; - while( (cc = (unsigned char) *charSet++) != '\0'){ + while((cc = (unsigned char) *charSet++) != '\0') { booster[cc] = ++ix; } booster[0] = ix; @@ -117,15 +126,16 @@ inline void buildBooster(QByteArray& booster, const char* charSet){ * IN: "": not initialized otherwise: ready for work * OUT: ready for work */ -void RplEnigma::encode(char* data, int size, const char* charSet, QByteArray& booster){ - if (booster.length() == 0){ +void RplEnigma::encode(char* data, int size, const char* charSet, + QByteArray& booster) { + if(booster.length() == 0) { buildBooster(booster, charSet); } - int lengthOfCharSet = (int) (unsigned char) booster.at(0); - for (int ii = 0; ii < size; ii++){ + int lengthOfCharSet = (int)(unsigned char) booster.at(0); + for(int ii = 0; ii < size; ii++) { unsigned char cc = (unsigned char) data[ii]; int ix = booster.at(cc); - if (ix != 0){ + if(ix != 0) { int next = nextInt(lengthOfCharSet); int ix2 = (ix - 1 + next) % lengthOfCharSet; data[ii] = charSet[ix2]; @@ -149,15 +159,16 @@ void RplEnigma::encode(char* data, int size, const char* charSet, QByteArray& bo * IN: "": not initialized otherwise: ready for work * OUT: ready for work */ -void RplEnigma::decode(char* data, int size, const char* charSet, QByteArray& booster){ - if (booster.length() == 0){ +void RplEnigma::decode(char* data, int size, const char* charSet, + QByteArray& booster) { + if(booster.length() == 0) { buildBooster(booster, charSet); } - int lengthOfCharSet = (int) (unsigned char) booster.at(0); - for (int ii = 0; ii < size; ii++){ + int lengthOfCharSet = (int)(unsigned char) booster.at(0); + for(int ii = 0; ii < size; ii++) { unsigned char cc = (unsigned char) data[ii]; int ix = booster.at(cc); - if (ix != 0){ + if(ix != 0) { int next = nextInt(lengthOfCharSet); int ix2 = (lengthOfCharSet + ix -1 - next) % lengthOfCharSet; data[ii] = charSet[ix2]; @@ -172,9 +183,9 @@ void RplEnigma::decode(char* data, int size, const char* charSet, QByteArray& bo * @param data IN: data to encode/decoded
* OUT: data encoded/decoded */ -void RplEnigma::change(QByteArray& data){ +void RplEnigma::change(QByteArray& data) { int randomLength = m_randomSource.length(); - for (int ix = data.length() - 1; ix >= 0; ix--){ + for(int ix = data.length() - 1; ix >= 0; ix--) { char item = data.at(ix); item = (item ^ nextInt(0xff) ^ m_randomSource.at(ix % randomLength)); data[ix] = item; @@ -189,21 +200,21 @@ void RplEnigma::change(QByteArray& data){ * * @param byteSecret a byte sequence which influences the random generation */ -void RplEnigma::addByteSecret(QByteArray byteSecret){ +void RplEnigma::addByteSecret(QByteArray byteSecret) { // we expand it to a multiple of 64 bit: int oldSize = byteSecret.length(); int newSize = (oldSize + 7) / 8 * 8; int ix; - if (newSize > oldSize){ + if(newSize > oldSize) { byteSecret.resize(newSize); int sum = 0; int start = oldSize > 8 ? oldSize - 8 : 0; - for (ix = start; ix < oldSize; ix++){ + for(ix = start; ix < oldSize; ix++) { sum += ix + byteSecret.at(ix); } - for (ix = oldSize; ix < newSize; ix++){ + for(ix = oldSize; ix < newSize; ix++) { sum += ix + 7; - byteSecret[ix] = (char) (sum + byteSecret.at(ix-1)); + byteSecret[ix] = (char)(sum + byteSecret.at(ix-1)); } } int count = newSize / 8; @@ -211,9 +222,9 @@ void RplEnigma::addByteSecret(QByteArray byteSecret){ secret->m_count = count; secret->m_list = new u_int64_t[count]; m_secrets.append(secret); - for (ix = 0; ix < count; ix++){ + for(ix = 0; ix < count; ix++) { u_int64_t value = 0; - for (int ix2 = 0; ix2 < 8; ix2++) + for(int ix2 = 0; ix2 < 8; ix2++) value = (value << 8) + byteSecret.at(ix * 8 + ix2); secret->m_list[ix] = value; } @@ -221,7 +232,7 @@ void RplEnigma::addByteSecret(QByteArray byteSecret){ QCryptographicHash hash(QCryptographicHash::Md5); RplRandom rand; hash.addData(m_randomSource.constData(), 4); - for (ix = 0; ix < byteSecret.length(); ix++){ + for(ix = 0; ix < byteSecret.length(); ix++) { hash.addData(byteSecret.constData() + ix, 1); QByteArray current = hash.result(); int ix2 = rand.nextInt(0, m_randomSource.length() - 1); @@ -235,12 +246,12 @@ void RplEnigma::addByteSecret(QByteArray byteSecret){ * @param maxValue * @return */ -int RplEnigma::nextInt(int maxValue){ +int RplEnigma::nextInt(int maxValue) { u_int64_t seed = 0; QList::const_iterator it; int ixSecret = m_randomCalls++; int ix = ixSecret; - for (it = m_secrets.constBegin(); it != m_secrets.constEnd(); ++it){ + for(it = m_secrets.constBegin(); it != m_secrets.constEnd(); ++it) { secret_t* secret = *it; seed |= ((secret->m_list[ixSecret % secret->m_count]) >> (ix % 8)); } @@ -254,7 +265,7 @@ int RplEnigma::nextInt(int maxValue){ * * @param seed the initial state */ -void RplEnigma::setSeed(u_int64_t seed){ +void RplEnigma::setSeed(u_int64_t seed) { m_random->setSeed(seed); m_randomCalls = 0; } @@ -268,13 +279,13 @@ void RplEnigma::setSeed(u_int64_t seed){ /** * @brief Unit test for RplEnigma. */ -class TestRplEnigma : public RplTest -{ +class TestRplEnigma : public RplTest { public: - TestRplEnigma() : RplTest("RplEnigma"){} + TestRplEnigma() : RplTest("RplEnigma") {} public: - void testOneCharset(const char* value, const char* charSet, const char* expected){ + void testOneCharset(const char* value, const char* charSet, + const char* expected) { RplEnigma enigma; enigma.addByteSecret(QByteArray("Geheim")); enigma.setSeed(0); @@ -289,34 +300,34 @@ public: checkE(expected, encoded); } - void printCharSets(){ + void printCharSets() { QByteArray value; value.reserve(256); unsigned char cc; - for (cc = ' '; cc <= 127; cc++){ - if (cc == '"' || cc == '\\') + for(cc = ' '; cc <= 127; cc++) { + if(cc == '"' || cc == '\\') value.append('\\'); value.append(cc); } - printf ("%s\n", value.constData()); + printf("%s\n", value.constData()); value.resize(0); - for (cc = 128; cc >= 128; cc++){ + for(cc = 128; cc >= 128; cc++) { char buf[10]; - if (cc % 32 == 0) + if(cc % 32 == 0) value.append("\n"); sprintf(buf, "\\x%02x", cc); value.append(buf); } - printf ("%s\n", value.constData()); + printf("%s\n", value.constData()); } - void printString(const char* value){ + void printString(const char* value) { QByteArray v; unsigned char cc; - while( (cc = (unsigned char) *value++) != 0){ - if (cc == '\\' || cc == '"'){ + while((cc = (unsigned char) *value++) != 0) { + if(cc == '\\' || cc == '"') { v.append('\\'); v.append(cc); - } else if (cc >= 127) { + } else if(cc >= 127) { char buffer[10]; sprintf(buffer, "\\x%02x", cc); v.append(buffer); @@ -326,7 +337,7 @@ public: } printf("%s\n", v.constData()); } - void testOneBytes(const char* bytes){ + void testOneBytes(const char* bytes) { RplEnigma enigma; enigma.addByteSecret("Hello World"); enigma.setSeed(0x1234); @@ -340,29 +351,33 @@ public: checkE(bytes, decoded); } - void testBytes(){ + void testBytes() { testOneBytes("abcdefg"); testOneBytes("01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); } - void testCharSet(){ + void testCharSet() { //testOneCharset("&()[]{}Weiß der Geier/Kuckuck?", RplEnigma::SET_32_255, "2Kc\x9a\xfeQ\xd7\xa84sx)*\xfb\xd2z\xf4\"W\xb0\xee\xb0\xd1\x84\xace\xf8_u*T"); - testOneCharset("\\Weiß der Geier/Kuckuck?", RplEnigma::SET_32_127, "(Z?hßaZ_#/QZ+Oi|SI^=<,)A"); - testOneCharset("01234567890abcdef", RplEnigma::SET_HEXDIGITS, "c4c25b08735c53a63"); + testOneCharset("\\Weiß der Geier/Kuckuck?", RplEnigma::SET_32_127, + "(Z?hßaZ_#/QZ+Oi|SI^=<,)A"); + testOneCharset("01234567890abcdef", RplEnigma::SET_HEXDIGITS, + "c4c25b08735c53a63"); testOneCharset("data$1%3.^~", RplEnigma::SET_FILENAME, "^voazo-n%$b"); testOneCharset("Weiß der Geier!", RplEnigma::SET_ALPHANUM, "weyß BCk 19NoO!"); - testOneCharset("12345678901234567890", RplEnigma::SET_DECIMALS, "97394833084815683977"); - testOneCharset("000000000000000000000000000", RplEnigma::SET_DECIMALS, "850592651836811261879625929"); + testOneCharset("12345678901234567890", RplEnigma::SET_DECIMALS, + "97394833084815683977"); + testOneCharset("000000000000000000000000000", RplEnigma::SET_DECIMALS, + "850592651836811261879625929"); } - virtual void doIt(){ + virtual void doIt() { testBytes(); testCharSet(); } }; #endif -void testRplEnigma(){ +void testRplEnigma() { #ifdef RPL_TEST TestRplEnigma test; test.run(); diff --git a/rplmath/rplmatrix.cpp b/rplmath/rplmatrix.cpp new file mode 100644 index 0000000..548ceb5 --- /dev/null +++ b/rplmath/rplmatrix.cpp @@ -0,0 +1,627 @@ +/* + * Matrix.cpp + * + * Created on: 29.05.2014 + * Author: hm + */ + +#include "matrixall.hpp" + +namespace rpl { + +MatrixException::MatrixException(const Matrix& matrix, + const char* format, ...) : + m_message() +{ + if (! matrix.getName().empty()) + m_message = matrix.getName() + ": "; + char buffer[16*1024]; + + va_list args; + va_start(args, format); + vsnprintf(buffer, sizeof buffer, format, args); + va_end(args); + m_message += buffer; +} +MatrixException::MatrixException(const char* format, ...) +{ + char buffer[16*1024]; + + va_list args; + va_start(args, format); + vsnprintf(buffer, sizeof buffer, format, args); + va_end(args); + m_message = buffer; +} + +/** + * Constructor. + */ +Matrix::Matrix(const char* name) : + m_rows(0), + m_cols(0), + m_values(NULL), + m_name(name) +{ +} + +/** + * Constructor. + * + * @param rows number of rows + * @param cols number of columns + */ +Matrix::Matrix(int rows, int cols, const char* name): + m_rows(rows), + m_cols(cols), + m_values(new MatVal[rows*cols]), + m_name(name) +{ +} +/** + * Destructor. + */ +Matrix::~Matrix() { + delete m_values; + m_values = NULL; +} + +/** + * Copy constructor. + * + * @param source source to copy + */ +Matrix::Matrix(const Matrix& source) : + m_rows(0), + m_cols(), + m_values(NULL), + m_name(source.m_name + std::string("-copy")) +{ + resize(source.m_rows, source.m_cols, source.m_values); +} + +/** + * Checks the validity of the definition parameters. + * + * @param rows the row number + * @param cols the column number + * @trows MatrixException + */ +void Matrix::checkDefinition(int rows, int cols) const +{ + if (rows < 0) + throw MatrixException(*this, "row number negative: %d", rows); + if (cols < 0) + throw MatrixException(*this, "column number negative: %d", cols); + if (double(rows) * cols > 1.0*1000*1000) + throw MatrixException(*this, "too many elements: %d*%d", rows, cols); +} + +/** + * Checks the validity of the indexes. + * + * @param row the matrix row number: 0..N-1 + * @param col the matrix column number: 0..M-1 + * @throws MatrixException + */ +void Matrix::check(int row, int col) const +{ + if (row < 0 || row >= m_rows) + throw MatrixException(*this, "invalid row: %d not in [0,%d[", row, + m_rows); + if (col < 0 || col >= m_cols) + throw MatrixException(*this, "invalid column: %d not in [0,%d[", col, + m_cols); +} +/** + * Checks whether a given matrix has the same dimensions. + * + * @param operand matrix to compare + * @throws MatrixException + */ +void Matrix::checkSameDimension(const Matrix& operand) const +{ + if (m_rows != operand.getRows()) + throw MatrixException(*this, + "Matrix %s has different row count: %d / %d", + operand.getName().c_str(), m_rows, operand.getRows()); + if (m_cols != operand.getCols()) + throw MatrixException(*this, + "Matrix %s has different column count: %d / %d", + operand.getName().c_str(), m_cols, operand.getCols()); +} + +/** + * Assignment operator. + * + * @param source the source to copy + */ +Matrix& Matrix::operator =(const Matrix& source) +{ + resize(source.m_rows, source.m_cols, source.m_values); + return *this; +} +/** + * Adds a matrix to the instance. + * + * @param operand matrix to add + * @return the instance itself + */ +Matrix& Matrix::operator +=(const Matrix& operand) +{ + checkSameDimension(operand); + for (int ix = m_rows * m_cols - 1; ix >= 0; ix--){ + m_values[ix] += operand.m_values[ix]; + } + return *this; +} +/** + * Subtracts a matrix from the instance. + * + * @param operand matrix to subtract + * @return the instance itself + */ +Matrix& Matrix::operator -=(const Matrix& operand) +{ + checkSameDimension(operand); + for (int ix = m_rows * m_cols - 1; ix >= 0; ix--){ + m_values[ix] -= operand.m_values[ix]; + } + return *this; +} +/** + * Builds the sum of the instance and a given matrix. + * + * @param operand matrix to add + * @return a new matrix with the sum + */ +Matrix Matrix::operator +(const Matrix& operand) +{ + Matrix rc(*this); + rc += operand; + return rc; +} +/** + * Builds the difference of the instance and a given matrix. + * + * @param operand matrix to subtract + * @return a new matrix with the difference + */ +Matrix Matrix::operator -(const Matrix& operand) +{ + Matrix rc(*this); + rc -= operand; + return rc; +} +/** + * Adds a scalar to the instance. + * + * @param scalar scalar to add + * @return the instance itself + */ +Matrix& Matrix::operator +=(MatVal scalar) +{ + for (int ix = m_rows * m_cols - 1; ix >= 0; ix--){ + m_values[ix] += scalar; + } + return *this; +} +/** + * Adds a scalar to the instance. + * + * @param scalar scalar to add + * @return the instance itself + */ +Matrix& Matrix::operator -=(MatVal scalar) +{ + for (int ix = m_rows * m_cols - 1; ix >= 0; ix--){ + m_values[ix] -= scalar; + } + return *this; +} +/** + * Builds the sum of the instance and a given scalar. + * + * @param scalar scalar to add + * @return a new matrix with the sum + */ +Matrix Matrix::operator +(MatVal scalar) +{ + Matrix rc(*this); + rc += scalar; + return rc; +} +/** + * Builds the difference of the instance and a given scalar. + * + * @param scalar scalar to subtract + * @return a new matrix with the sum + */ +Matrix Matrix::operator -(MatVal scalar) +{ + Matrix rc(*this); + rc -= scalar; + return rc; +} +/** + * Tests the equiness of the instance with a given matrix. + * + * @param operand the matrix to compare + * @return true: the matrices are equal
+ * false: otherwise + */ +bool Matrix::operator ==(const Matrix& operand) const +{ + checkSameDimension(operand); + bool rc = true; + for (int ix = m_rows * m_cols - 1; ix >= 0; ix--){ + if (m_values[ix] != operand.m_values[ix]){ + rc = false; + break; + } + } + return rc; +} +/** + * Compares the instance with a given scalar. + * + * @param operand the scalar to compare + * @return true: all elements are equal to the scalar
+ * false: otherwise + */ +bool Matrix::operator ==(MatVal scalar) const +{ + bool rc = true; + for (int ix = m_rows * m_cols - 1; ix >= 0; ix--){ + if (m_values[ix] != scalar){ + rc = false; + break; + } + } + return rc; +} +/** + * Sets a new row-column pair. + */ +Matrix& Matrix::resize(int rows, int cols, const MatVal values[], + MatVal defaultValue) +{ + checkDefinition(rows, cols); + if (rows != m_rows || cols != m_cols){ + delete m_values; + m_values = new MatVal[rows * cols]; + } + int ix = -1; + if (values == NULL) + { + for (int row = 0; row < m_rows; row++){ + for (int col = 0; row < m_cols; col++) + m_values[++ix] = defaultValue; + } + } else { + for (int row = 0; row < m_rows; row++){ + for (int col = 0; row < m_cols; col++){ + ix++; + m_values[ix] = values[ix]; + } + } + } + return *this; +} +/** + * Returns the minimum and the maximum of the instance. + * + * @return a tuple with the minimum and the maximum + */ +Tuple2 Matrix::minMax() const +{ + Tuple2 rc(DBL_MAX, DBL_MIN); + + for (int ix = m_rows*m_cols - 1; ix >= 0; ix--){ + MatVal x; + if ( (x = m_values[ix]) < rc.m_value1) + rc.m_value1 = x; + if (x > rc.m_value2) + rc.m_value2 = x; + } + return rc; +} + +/** + * Builds a matrix with exchanged rows and cols. + * + * @return the transposed matrix + */ +Matrix Matrix::transpose() const +{ + Matrix rc(m_cols, m_rows); + + for (int row = 0; row < m_rows; row++){ + for (int col = 0; col < m_cols; col++){ + rc.m_values[m_rows*col + row] = m_values[row * m_cols + col]; + } + } + return rc; +} +std::string Matrix::toString(const char* prefix, const char* format, + const char* rowSeparator, const char* colSeparator) const +{ + char buffer[128]; + Tuple2 minMaxi(minMax()); + std::string rc; + snprintf(buffer, sizeof buffer, format, minMaxi.m_value1); + int length = strlen(buffer); + snprintf(buffer, sizeof buffer, format, minMaxi.m_value2); + int length2 = strlen(buffer); + if (length < length2) + length = length2; + snprintf(buffer, sizeof buffer, format, + (minMaxi.m_value1 + minMaxi.m_value2) / 2); + length2 = strlen(buffer); + if (length < length2) + length = length2; + if (prefix == NULL) + prefix = ""; + length = m_rows * m_cols * (length + strlen(colSeparator)) + + m_rows * strlen(rowSeparator) + strlen(prefix) + 20; + rc.reserve(length); + rc += prefix; + rc += "["; + for (int row = 0; row < m_rows; row++){ + for (int col; col < m_cols; col++){ + snprintf(buffer, sizeof buffer, format, m_values[m_cols*row + col]); + rc += buffer; + rc += colSeparator; + } + rc += rowSeparator; + } + rc += "]"; + return rc; +} +/** + * Returns the length of the number string. + * + * @param text a text to inspect + * @return 0: not a number
+ * otherwise: the length of the number string + */ +static int lengthOfNumber(const char* text){ + int rc = 0; + bool found = false; + const char* ptr = text; + while(isspace(*ptr)) + ptr++; + if ( (*ptr == '+' || *ptr == '-')) + ptr++; + found = isdigit(*ptr); + while(isdigit(*ptr)) + text++; + if (*ptr == '.'){ + ptr++; + found = isdigit(*ptr); + if (found){ + while(isdigit(*ptr)) + ptr++; + } + } + if (found && toupper(*ptr) == 'E'){ + ptr++; + if (*ptr == '+' || *ptr == '-') + ptr++; + found = isdigit(*ptr); + if (found){ + while(isdigit(*ptr)) + ptr++; + } + } + if (found){ + while(isspace(*ptr)){ + ptr++; + } + } + rc = found ? 0 : ptr - text; + return rc; +} +/** + * Finds the length of a column. + * + * @param text the text to inspect + * @param separator the column separator + * @return the count of chars between start and the next separator + */ +static int lengthOfColumn(const char* text, char separator){ + const char* ptr = text; + while(*ptr == ' ') + ptr++; + char delimiter = 0; + if (*ptr == '"' || *ptr == '\''){ + delimiter = *ptr++; + } + while(*ptr){ + if (*ptr == '\\'){ + ptr++; + if (*ptr != '\0') + ptr++; + } else if (*ptr == separator) + break; + else if (*ptr != delimiter){ + ptr++; + while(*ptr && *ptr != separator) + ptr++; + } + } + int rc = ptr - text; + return rc; +} +/** + * Counts the occurrences of a given char in a string. + * + * @param line the text to inspect + * @param cc the char to count + * @return the number of cc in the text + */ +static int countChar(const char* line, char cc) +{ + const char* ptr = line; + int rc = 0; + while( (ptr = strchr(ptr, cc)) != NULL){ + rc++; + ptr++; + } + return rc; +} +/** + * Adds the count of the possible separators. + * + * @param countTab IN/OUT: number of tabulators + * @param countCommas IN/OUT: number of ',' + * @param countSemicolons IN/OUT: number of ';' + * @param countPipes IN/OUT: number of '|' + * @param countBlanks IN/OUT: number of ' ' + */ +static void addSeparators(const char* line, int& commas, int& semicolons, + int& pipes, int& blanks) +{ + commas += countChar(line, ','); + semicolons += countChar(line, ';'); + pipes += countChar(line, '|'); + blanks += countChar(line, ' '); +} +/** + * Finds the separator of the CSV file. + * + * Inspects the first 5 lines and counts the possible separators. + * The most found separator will be returned. + * + * @param fp CSV file + * @param buffer a line buffer + * @param bufferSize the size of buffer[] + */ +static char findSeparator(FILE* fp, char* buffer, size_t bufferSize){ + char rc = '\0'; + int ix = 0; + int maxLines = 5; + const char* line; + int commas = 0; + int semicolons = 0; + int pipes = 0; + int blanks = 0; + while(++ix < maxLines && (line = fgets(buffer, bufferSize, fp)) != NULL){ + if (strchr(line, '\t') != NULL){ + rc = '\t'; + break; + } + addSeparators(line, commas, semicolons, pipes, blanks); + } + fseek(fp, 0, SEEK_SET); + if (commas + semicolons + pipes == 0) { + rc = blanks > 0 ? ' ' : '\0'; + } else if (semicolons > commas && semicolons > pipes) + rc = ','; + else if (commas > semicolons && commas > pipes) + rc = ','; + else if (pipes > commas && pipes > semicolons) + rc = '|'; + return rc; +} +/** + * Skips all columns with a content other than a numeric value. + * + * @param line the text line + * @param separator the column separator + * @return the start of a number or "" + */ +static const char* skipNonNumbers(const char* line, char separator) +{ + int len1, len2 = 0; + + while ( (len1 = lengthOfNumber(line)) == 0 + && (len2 = lengthOfColumn(line, separator)) > 0) + line += len2; + return line; +} +/** + * Returns the count of numeric numbers in a CSV line. + * + * @param line the line from a CSV file + * @return 0: not only numbers are in the line
+ * otherwise: the count of numeric columns in the line + */ +static int countNumbers(char* line, char separator){ + skipNonNumbers(line, separator); + bool again = true; + int rc = 0; + while(again && *line != '\0'){ + int length = lengthOfNumber(line); + if (length == 0){ + rc = 0; + again = false; + } else { + line += lengthOfNumber(line); + rc++; + if (*line == separator) + line++; + } + } + return rc; +} +/** + * Reads a file with the CSV (comma separated values) format + * into the instance. + */ +void Matrix::readFromCvs(const char* filename, int maxLineLength) +{ + FILE* fp = fopen(filename, "r"); + if (fp == NULL) + throw MatrixException(*this, "Cannot open %s (%d)", filename, errno); + char* buffer = new char[maxLineLength]; + char* line; + char separator = findSeparator(fp, buffer, maxLineLength); + int rows = 0; + int cols = 0; + // find the count of rows and columns: + while( (line = fgets(buffer, sizeof buffer, fp)) != NULL) + { + int nCols; + if ( (nCols = countNumbers(line, separator)) > 0){ + rows++; + if (nCols > cols) + cols = nCols; + } + } + resize(rows, cols); + // find the values + fseek(fp, 0, SEEK_SET); + int row = -1; + while( (line = fgets(buffer, sizeof buffer, fp)) != NULL) + { + int nCols; + if ( (nCols = countNumbers(line, separator)) > 0){ + row++; + skipNonNumbers(line, separator); + int col = -1; + int length; + char* ptr; + while( (length = lengthOfNumber(ptr)) > 0){ + while(*ptr == ' ') + ptr++; + MatVal value = atof(ptr); + m_values[m_cols*row + col] = value; + ptr += length; + if (*ptr) + ptr++; + } + } + } + + fclose(fp); + delete buffer; +} +void readFromXml(const char* filename, const char* tagCol, + const char* tagRow, const char* tagTable, + int maxLineLength = 1024*1024) +{ + +} + +} /* namespace rpl */ diff --git a/rplmath/rplmatrix.hpp b/rplmath/rplmatrix.hpp new file mode 100644 index 0000000..9bf89f8 --- /dev/null +++ b/rplmath/rplmatrix.hpp @@ -0,0 +1,104 @@ +/* + * Matrix.hpp + * + * Created on: 29.05.2014 + * Author: hm + */ + +#ifndef MATRIX_HPP_ +#define MATRIX_HPP_ + + +namespace rpl { + +class Matrix; +/** + * Implements a matrix specific exception. + */ +class MatrixException +{ +public: + MatrixException(const Matrix& matrix, const char* format, ...); + MatrixException(const char* format, ...); +private: + const std::string getMessage() const + { return m_message; } +private: + std::string m_message; +}; + +/** + * The type of a matrix element. + */ +typedef double MatVal; + +class Tuple2 { +public: + Tuple2(MatVal value1, MatVal value2) : + m_value1(value1), + m_value2(value2) + {} +public: + MatVal m_value1; + MatVal m_value2; +}; +/** + * Implements a matrix with 2 dimensions. + */ +class Matrix { +public: + Matrix(const char* name = NULL); + Matrix(int rows, int cols, const char* name = NULL); + virtual ~Matrix(); + Matrix(const Matrix& source); + Matrix& operator =(const Matrix& source); +public: + Matrix& operator +=(const Matrix& operand); + Matrix& operator -=(const Matrix& operand); + Matrix operator +(const Matrix& operand); + Matrix operator -(const Matrix& operand); + Matrix& operator +=(MatVal scalar); + Matrix& operator -=(MatVal scalar); + Matrix operator +(MatVal scalar); + Matrix operator -(MatVal scalar); + bool operator ==(const Matrix& operand) const; + bool operator ==(MatVal scalar) const; + inline bool operator !=(const Matrix& operand) const + { return ! (*this == operand); } + inline bool operator !=(MatVal operand) + { return ! (*this == operand); } +public: + inline const std::string& getName() const + { return m_name; } + inline MatVal get(int row, int col) const + { check(row, col); return m_values[row*m_cols + col]; } + inline Matrix& set(int row, int col, MatVal value) + { check(row, col); m_values[row*m_cols + col] = value; return *this; } + inline int getRows() const + { return m_rows; } + inline int getCols() const + { return m_cols; } +public: + void checkDefinition(int rows, int cols) const; + void check(int row, int col) const; + void checkSameDimension(const Matrix& operand) const; + Matrix& resize(int rows, int cols, const MatVal values[] = NULL, + MatVal defaultValue = 0.0); + Tuple2 minMax() const; + Matrix transpose() const; + std::string toString(const char* prefix = NULL, + const char* format = "%f", + const char* rowSeparator = "\n", + const char* colSeparator = ",") const; + void readFromCvs(const char* filename, int maxLineLength = 1024*1024); + void readFromXml(const char* filename, const char* tagCol, + const char* tagRow, const char* tagTable, + int maxLineLength = 1024*1024); +protected: + int m_rows; + int m_cols; + MatVal* m_values; + std::string m_name; +}; +} // namespace rpl +#endif /* MATRIX_HPP_ */ diff --git a/rplmath/rplmatrix_test.cpp b/rplmath/rplmatrix_test.cpp new file mode 100644 index 0000000..dbc6c7d --- /dev/null +++ b/rplmath/rplmatrix_test.cpp @@ -0,0 +1,12 @@ +/* + * Matrix_test.cpp + * + * Created on: 29.05.2014 + * Author: hm + */ + +#include "stdinc.hpp" + +namespace rpl { + +} /* namespace rpl */ diff --git a/rplmath/rplrandom.cpp b/rplmath/rplrandom.cpp index dc5eb90..6bf00d5 100644 --- a/rplmath/rplrandom.cpp +++ b/rplmath/rplrandom.cpp @@ -17,14 +17,13 @@ * @brief Constructor. */ RplRandom::RplRandom() : - m_seed(0) -{ + m_seed(0) { } /** * @brief Destructor. */ -RplRandom::~RplRandom(){ +RplRandom::~RplRandom() { } /** @@ -32,7 +31,7 @@ RplRandom::~RplRandom(){ * * @return the next random number. */ -u_int64_t RplRandom::nextInt64(){ +u_int64_t RplRandom::nextInt64() { // Donald Knuth recommands (for 64-Bit): m_seed = m_seed * 6364136223846793005L + 1442695040888963407L; return m_seed; @@ -42,7 +41,7 @@ u_int64_t RplRandom::nextInt64(){ * * @param seed the new seed. */ -void RplRandom::setSeed(u_int64_t seed){ +void RplRandom::setSeed(u_int64_t seed) { m_seed = seed; } /** @@ -50,7 +49,7 @@ void RplRandom::setSeed(u_int64_t seed){ * * @param seed the XOR operand. */ -void RplRandom::xorSeed(u_int64_t seed){ +void RplRandom::xorSeed(u_int64_t seed) { m_seed ^= seed; } @@ -59,10 +58,10 @@ void RplRandom::xorSeed(u_int64_t seed){ * * @return a pseudo random value 0..255 */ -quint8 RplRandom::nextByte(){ +quint8 RplRandom::nextByte() { u_int64_t value = nextInt64(); // forget the last 3 bits: - quint8 rc = (quint8) (value >> 3) % 256; + quint8 rc = (quint8)(value >> 3) % 256; return rc; } @@ -73,14 +72,14 @@ quint8 RplRandom::nextByte(){ * @param maxValue the maximal result (includeing) * @return the next integer */ -int RplRandom::nextInt(int minValue, int maxValue){ +int RplRandom::nextInt(int minValue, int maxValue) { u_int64_t value = nextInt64(); u_int64_t diff = maxValue - minValue; int rc; - if (diff <= 0) + if(diff <= 0) rc = minValue; else - rc = (int) (minValue + value % diff); + rc = (int)(minValue + value % diff); return rc; } @@ -92,10 +91,10 @@ int RplRandom::nextInt(int minValue, int maxValue){ * @param maxChar all characters of the result are lower or equal than this value * @return a random string */ -QByteArray RplRandom::nextString(int length, char minChar, char maxChar){ +QByteArray RplRandom::nextString(int length, char minChar, char maxChar) { QByteArray rc; rc.resize(length); - for (int ii = 0; ii < length; ii++){ + for(int ii = 0; ii < length; ii++) { rc[ii] = nextInt(minChar, maxChar); } return rc; @@ -108,11 +107,11 @@ QByteArray RplRandom::nextString(int length, char minChar, char maxChar){ * @param charSet a string with all allowed characters * @return a random string with characters from the given set */ -QByteArray RplRandom::nextString(int length, char* charSet){ +QByteArray RplRandom::nextString(int length, char* charSet) { QByteArray rc; rc.resize(length); int ubound = strlen(charSet) - 1; - for (int ii = 0; ii < length; ii++){ + for(int ii = 0; ii < length; ii++) { rc[ii] = charSet[nextInt(0, ubound)]; } return rc; diff --git a/rplmath/rplrandom.hpp b/rplmath/rplrandom.hpp index e90a020..a041fb6 100644 --- a/rplmath/rplrandom.hpp +++ b/rplmath/rplrandom.hpp @@ -2,8 +2,7 @@ #define RPLRANDOM_HPP #include -class RplRandom -{ +class RplRandom { public: RplRandom(); virtual ~RplRandom(); diff --git a/rplnet/rplnet.hpp b/rplnet/rplnet.hpp index 2f2fe11..f9c4731 100644 --- a/rplnet/rplnet.hpp +++ b/rplnet/rplnet.hpp @@ -13,11 +13,14 @@ #include #include #include +#include +#include //includes implicite rplcore.hpp: #include "../rplmath/rplmath.hpp" #include "rpltcppeer.hpp" #include "rpltcpserver.hpp" #include "rpltcpclient.hpp" +#include "rplnetconfig.hpp" #endif // RPLNET_HPP diff --git a/rplnet/rplnetconfig.cpp b/rplnet/rplnetconfig.cpp new file mode 100644 index 0000000..bdb28d5 --- /dev/null +++ b/rplnet/rplnetconfig.cpp @@ -0,0 +1,14 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ + + +#include "rplnetconfig.hpp" + +const char* RplNetConfig::IP = "connection.ip"; +const char* RplNetConfig::PORT = "connection.port"; +const char* RplNetConfig::SLEEP_MILLISEC = "connection.sleepmillisec"; diff --git a/rplnet/rplnetconfig.hpp b/rplnet/rplnetconfig.hpp new file mode 100644 index 0000000..4d58ef0 --- /dev/null +++ b/rplnet/rplnetconfig.hpp @@ -0,0 +1,21 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ + + +#ifndef RPLNETCONFIG_HPP +#define RPLNETCONFIG_HPP + +class RplNetConfig +{ +public: + static const char* IP; + static const char* PORT; + static const char* SLEEP_MILLISEC; +}; + +#endif // RPLNETCONFIG_HPP diff --git a/rplnet/rpltcpclient.cpp b/rplnet/rpltcpclient.cpp index 167fc21..981ab5a 100644 --- a/rplnet/rpltcpclient.cpp +++ b/rplnet/rpltcpclient.cpp @@ -10,51 +10,63 @@ enum { LOC_1 = RPL_FIRST_OF(RPLMODULE_TCPCLIENT), // 701 LOC_HANDLE_ERROR_1, + LOC_SET_REMOTE_ADDRESS_1, }; /** @class RplTcpClient rpltcpclient.hpp "rplnet/rpltcpclient.hpp" * - * Implements a TCP client. + * @brief Implements a TCP client. * * Use the protocol defined at RplTcpServer. */ /** * @brief Constructor. * - * @param ip server ip - * @param port server port + * @param configurator some parameters will be get from this configurator * @param thread current thread. Used for sleep() * @param terminator NULL or for controlled termination * @param logger a logger */ -RplTcpClient::RplTcpClient(const char* ip, int port, QThread* thread, - RplTerminator* terminator, RplLogger* logger) : - m_peer(new RplTcpPeer(ip, port, thread, terminator, logger)), - m_logger(logger) -{ - if (ip != NULL && port != 0) - setRemoteAddress(ip, port); +RplTcpClient::RplTcpClient(RplConfigurator& configurator, QThread* thread, + RplTerminator* terminator, + RplLogger* logger) : + m_peer(new RplTcpPeer(configurator, thread, terminator, false, logger)), + m_logger(logger), + m_configurator(configurator){ + QByteArray ip = configurator.asString(RplNetConfig::IP, "localhost"); + int port = configurator.asInt(RplNetConfig::PORT, 12345); + if(! ip.isEmpty() && port != 0) + setRemoteAddress(ip.constData(), port); } /** * @brief Destructor. */ -RplTcpClient::~RplTcpClient(){ +RplTcpClient::~RplTcpClient() { delete m_peer; m_peer = NULL; } -void RplTcpClient::setRemoteAddress(const char* ip, int port){ +/** + * @brief Defines the remote address for a client. + * @param ip NULL or the ip to connect + * @param port 0 or the port to connect + */ +void RplTcpClient::setRemoteAddress(const char* ip, int port) { QTcpSocket* socket = (QTcpSocket*) m_peer->getSocket(); delete socket; - if (ip == NULL || port == 0) + if(ip == NULL || port == 0) m_peer->setSocket(NULL); - else{ + else { socket = new QTcpSocket(); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(handleError(QAbstractSocket::SocketError))); m_peer->setSocket(socket); + m_peer->setAddress(ip, port); + m_logger->logv(LOG_INFO, LOC_SET_REMOTE_ADDRESS_1, + "connect with %s:%d", ip, port); socket->connectToHost(QString(ip), port); + socket->waitForConnected(); } } @@ -62,7 +74,7 @@ void RplTcpClient::setRemoteAddress(const char* ip, int port){ * @brief Returns the peer info. * @return the peer info */ -RplTcpPeer* RplTcpClient::getPeer() const{ +RplTcpPeer* RplTcpClient::getPeer() const { return m_peer; } @@ -71,9 +83,10 @@ RplTcpPeer* RplTcpClient::getPeer() const{ * * @param socketError the error code */ -void RplTcpClient::handleError(QAbstractSocket::SocketError socketError){ - m_logger->logv(LOG_ERROR, LOC_HANDLE_ERROR_1, "Network error %d", - socketError); +void RplTcpClient::handleError(QAbstractSocket::SocketError socketError) { + if (m_logger != NULL) + m_logger->logv(LOG_ERROR, LOC_HANDLE_ERROR_1, "Network error %d", + socketError); } /** @class RplClientThread rpltcpclient.hpp "rplnet/rpltcpclient.hpp" @@ -87,29 +100,26 @@ void RplTcpClient::handleError(QAbstractSocket::SocketError socketError){ /** * @brief Constructor. * - * @param ip NULL or the ip of the server, e.g. "localhost" or "127.0.0.1" - * @param port 0 or the port of the server - * @param logger the logger. If NULL a default logger will be used + * @param configurator delivers some connection parameters + * @param port 0 or the port of the server + * @param sleepMilliSec duration of a busy wait + * @param logger the logger. If NULL a default logger will be used */ -RplClientThread::RplClientThread(const char* ip, int port, RplLogger* logger) : +RplClientThread::RplClientThread(RplConfigurator& configurator, + RplLogger* logger) : m_client(NULL), m_logger(logger), - m_ownsLogger(logger == NULL) -{ - if (logger == NULL){ - m_logger = new RplLogger(); - m_logger->buildStandardAppender("client"); - m_logger->setLevel(LOG_DEBUG); - } - m_client = new RplTcpClient(ip, port, this, NULL, logger); + m_configurator(configurator), + m_ownsLogger(false) { + m_client = new RplTcpClient(configurator, this, NULL, logger); } /** * @brief Destructor. */ -RplClientThread::~RplClientThread(){ +RplClientThread::~RplClientThread() { delete m_client; m_client = NULL; - if (m_ownsLogger){ + if(m_ownsLogger) { delete m_logger; m_logger = NULL; } @@ -119,7 +129,7 @@ RplClientThread::~RplClientThread(){ * * @return the peer */ -RplTcpPeer* RplClientThread::getPeer() const{ +RplTcpPeer* RplClientThread::getPeer() const { return m_client->getPeer(); } @@ -127,7 +137,7 @@ RplTcpPeer* RplClientThread::getPeer() const{ * @brief Returns the logger of the thread. * @return the logger */ -RplLogger* RplClientThread::getLogger() const{ +RplLogger* RplClientThread::getLogger() const { return m_logger; } @@ -136,6 +146,6 @@ RplLogger* RplClientThread::getLogger() const{ * * Calls doIt() for the real things. */ -void RplClientThread::run(){ +void RplClientThread::run() { doIt(); } diff --git a/rplnet/rpltcpclient.hpp b/rplnet/rpltcpclient.hpp index 1421072..7ba45a5 100644 --- a/rplnet/rpltcpclient.hpp +++ b/rplnet/rpltcpclient.hpp @@ -13,12 +13,13 @@ #endif class RplTcpPeer; -class RplTcpClient : public QObject -{ - Q_OBJECT + +class RplTcpClient : public QObject { + Q_OBJECT public: - RplTcpClient(const char* ip, int port, QThread* thread, - RplTerminator* terminator, RplLogger* logger = NULL); + RplTcpClient(RplConfigurator& configurator, QThread* thread, + RplTerminator* terminator, + RplLogger* logger = NULL); virtual ~RplTcpClient(); private: // No copy constructor: no implementation! @@ -34,11 +35,13 @@ public slots: private: RplTcpPeer* m_peer; RplLogger* m_logger; + RplConfigurator& m_configurator; }; class RplClientThread : public QThread { public: - RplClientThread(const char* ip, int port, RplLogger* logger = NULL); + RplClientThread(RplConfigurator& configurator, + RplLogger* logger = NULL); virtual ~RplClientThread(); private: // No copy constructor: no implementation! @@ -61,6 +64,7 @@ private: protected: RplTcpClient* m_client; RplLogger* m_logger; + RplConfigurator& m_configurator; private: bool m_ownsLogger; }; diff --git a/rplnet/rpltcppeer.cpp b/rplnet/rpltcppeer.cpp index fcfbe20..207c36b 100644 --- a/rplnet/rpltcppeer.cpp +++ b/rplnet/rpltcppeer.cpp @@ -12,14 +12,16 @@ enum { LOC_READ_BYTES_1, LOC_READ_BYTES_2, LOC_READ_BYTES_3, + LOC_READ_BYTES_4, LOC_HANDLE_ERROR_1, + LOC_SEND_2, }; static int s_dummy = 0; -/** @class rpltcppeer rpltcppeer.hpp "rplnet/rpltcppeer.hpp" +/** @class RplTcpPeer rpltcppeer.hpp "rplnet/rpltcppeer.hpp" * - * @brief Implement the common things for TCP server and client. + * @brief Implements the common things for TCP server and client. * * The communication is done with the following protocol: *
    @@ -42,45 +44,51 @@ static int s_dummy = 0; /** * @brief Creates an instance of a RplTcpPeer. * - * @param ip NULL or the ip address, e.g. "localhost" or "192.168.2.1" - * @param port 0 or port - * @param thread the current thread. Used for sleep() + * @param configurator delivers some connection parameters + * @param thread the current thread. Used for sleep() * @param terminator NULL or for controlled thread termination - * @param logger logger. If Null the global logger will be taken (not thread safe!) - * @return a instance of RplTcpPeer + * @param logger logger. If Null the global logger will be taken (not thread safe!) + * @return a instance of RplTcpPeer */ -RplTcpPeer* RplTcpPeer::createPeer(const char* ip, int port, QThread* thread, - RplTerminator* terminator, RplLogger* logger){ - return new RplTcpPeer(ip, port, thread, terminator, logger); +RplTcpPeer* RplTcpPeer::createPeer(RplConfigurator& configurator, + QThread* thread, + RplTerminator* terminator, + RplLogger* logger) { + return new RplTcpPeer(configurator, thread, terminator, logger); } /** * @brief Constructor. * - * @param ip NULL or the ip address, e.g. "localhost" or "192.168.2.1" - * @param port 0 or port + * @param configurator delivers some connection parameters * @param thread the current thread. Used for sleep() * @param terminator NULL or for controlled thread termination + * @param isServer true: the receiving does have a timeout * @param logger logger. If Null the global logger will be taken (not thread safe!) */ -RplTcpPeer::RplTcpPeer(const char* ip, int port, QThread* thread, - RplTerminator* terminator, RplLogger* logger) : - m_ip(ip), - m_port(port), - m_socket(NULL), - m_logger(logger == NULL ? RplLogger::globalLogger() : logger), - m_thread(thread), - m_random(), - m_terminator(terminator) -{ +RplTcpPeer::RplTcpPeer(RplConfigurator& configurator, QThread* thread, + RplTerminator* terminator, + bool isServer, + RplLogger* logger) : + m_socket(NULL), + m_logger(logger == NULL ? RplLogger::globalLogger() : logger), + m_thread(thread), + m_random(), + m_timeout(isServer ? 0 : configurator.asInt("connection.timeout", 60)), + m_terminator(terminator), + m_configurator(configurator), + m_isServer(isServer), + m_dataLocker(QMutex::NonRecursive), + m_waitForData() { // Simulate a true random with time, and addresses from stack and code segment: - m_random.setSeed(time(NULL) + ((qint64) this << 8) + ((qint64) &s_dummy << 16) + ((qint64) &createPeer << 24)); + m_random.setSeed(time(NULL) + ((qint64) this << 8) + ((qint64) &s_dummy << 16) + + ((qint64) &createPeer << 24)); } /** * @brief Destructor. */ -RplTcpPeer::~RplTcpPeer(){ +RplTcpPeer::~RplTcpPeer() { } @@ -93,47 +101,52 @@ RplTcpPeer::~RplTcpPeer(){ * @return true: success
    * false: error occurred */ -bool RplTcpPeer::send(qint8 flags, const char* command, const QByteArray& data){ +bool RplTcpPeer::send(qint8 flags, const char* command, + const QByteArray& data) { bool rc = false; QByteArray header; + QByteArray data2 = RplString::toCString(data.constData(), 20); + m_logger->logv(LOG_INFO, LOC_SEND_1, "send: flags: %x %s %s (%d)", + flags, command, data2.constData(), data.length()); header.reserve(16); header.append((char) flags); - if (flags & FLAG_ENCRYPT){ + if(flags & FLAG_ENCRYPT) { header.append((char) m_random.nextByte()); header.append((char) m_random.nextByte()); header.append((char) m_random.nextByte()); header.append((char) m_random.nextByte()); } unsigned int length = data.length(); - header.append(char (length % 256)); - header.append(char ((length >> 8) % 256)); - if (flags & FLAG_4_BYTE_SIZE){ - header.append(char ((length >> 16) % 256)); - header.append(char ((length >> 24) % 256)); + header.append(char(length % 256)); + header.append(char((length >> 8) % 256)); + if(flags & FLAG_4_BYTE_SIZE) { + header.append(char((length >> 16) % 256)); + header.append(char((length >> 24) % 256)); } length = strlen(command); header.append(command, length < 5 ? length : 5); - while (length++ < 5){ + while(length++ < 5) { header.append(' '); } qint64 written = m_socket->write(header.constData(), header.length()); qint64 written2 = m_socket->write(data); + m_socket->flush(); int count = 0; - if (written != header.length() || written2 != data.length()){ + if(written != header.length() || written2 != data.length()) { int endTime = time(NULL) + m_timeout; // wait until the data are sent or timeout or external termination: - while(m_socket->bytesToWrite() > 0){ + while(m_socket->bytesToWrite() > 0) { m_thread->msleep(1); - if (++count % 20 == 0){ - if (m_terminator == NULL || m_terminator->isStopped() + if(++count % 20 == 0) { + if(m_terminator == NULL || m_terminator->isStopped() || time(NULL) > endTime) break; } } } - if (m_logger->isActive(LOG_DEBUG)) - m_logger->logv(LOG_DEBUG, LOC_SEND_1, "send %s-%d: %s len=%d loops=%d %s", - m_ip.constData(), m_port, command, data.length(), count, + if(m_logger->isActive(LOG_DEBUG)) + m_logger->logv(LOG_DEBUG, LOC_SEND_1, "send %s: %s len=%d loops=%d %s", + m_address.constData(), command, data.length(), count, RplString::hexDump((const void*) data.constData(), 16, 16).constData()); return rc; } @@ -148,39 +161,52 @@ bool RplTcpPeer::send(qint8 flags, const char* command, const QByteArray& data){ * @return "": read not successful: timeout or termination or error
    * otherwise: the read bytes */ -QByteArray RplTcpPeer::readBytes(int bytes, time_t maxTime, int& loops){ +QByteArray RplTcpPeer::readBytes(int bytes, time_t maxTime, int& loops) { QAbstractSocket* socket = getSocket(); bool success = true; - qint64 bytes64 = bytes; - while(socket->bytesAvailable() < bytes64){ - if (loops == 0) - maxTime = time(NULL) + m_timeout; - if (++loops % 20 == 0){ - if (time(NULL) > maxTime){ - m_logger->logv(LOG_ERROR, LOC_READ_BYTES_1, "receive: timeout (%d)", m_timeout); - success = false; - break; - } else if (m_terminator != NULL && m_terminator->isStopped()){ - m_logger->log(LOG_ERROR, LOC_READ_BYTES_2, "receive: stopped"); - success = false; - break; - } - } + qint64 available; + long msec = m_configurator.asInt(RplNetConfig::SLEEP_MILLISEC, 1); + int divider = 1000L / (msec == 0 ? 1 : msec); + if (divider < 1) + divider = 1; + QMutexLocker locker(&m_dataLocker); + m_dataLocker.lock(); + + while(! m_waitForData.wait(&m_dataLocker, 1000L)){ + if(loops == 0 && ! m_isServer) + maxTime = time(NULL) + m_timeout; + if(++loops % divider == 0 && ! m_isServer) { + if(time(NULL) > maxTime) { + m_logger->logv(LOG_ERROR, LOC_READ_BYTES_1, + "receive: timeout (%d)", m_timeout); + success = false; + break; + } + } + if(m_terminator != NULL && m_terminator->isStopped()) { + m_logger->log(LOG_ERROR, LOC_READ_BYTES_2, "receive: stopped"); + success = false; + break; + } } + available = socket->bytesAvailable(); + m_logger->logv(LOG_DEBUG, LOC_READ_BYTES_4, + "readBytes(): available: %ld/%ld", available, bytes); QByteArray rc; - if (success){ + if(success) { rc = socket->read(bytes); - if (rc.length() != bytes){ - m_logger->logv(LOG_ERROR, LOC_READ_BYTES_3, "receive: too few bytes: %d of %d", - rc.length(), bytes); + if(rc.length() != bytes) { + m_logger->logv(LOG_ERROR, LOC_READ_BYTES_3, + "receive: too few bytes: %d of %d", + rc.length(), bytes); } } return rc; } -int getInt(const QByteArray& data, int offset, int size){ +int getInt(const QByteArray& data, int offset, int size) { int rc = ((int)(unsigned char) data.at(offset++)); - while (--size > 0){ + while(--size > 0) { rc = rc * 256 + (unsigned char) data.at(offset++); } return rc; @@ -194,7 +220,7 @@ int getInt(const QByteArray& data, int offset, int size){ * @return true: success
    * false: error occurred */ -bool RplTcpPeer::receive(QByteArray& command, QByteArray& data){ +bool RplTcpPeer::receive(QByteArray& command, QByteArray& data) { bool rc = true; command.clear(); data.clear(); @@ -205,23 +231,24 @@ bool RplTcpPeer::receive(QByteArray& command, QByteArray& data){ time_t maxTime = 0; quint8 flags = 0; header = readBytes(minHeaderSize, maxTime, loops); - if (header.length() > 0){ + if(header.length() > 0) { flags = header.at(0); int headerSize = minHeaderSize; - if ((flags & FLAG_4_BYTE_SIZE) != 0) + if((flags & FLAG_4_BYTE_SIZE) != 0) headerSize += 2; - if ((flags & FLAG_ENCRYPT) != 0) + if((flags & FLAG_ENCRYPT) != 0) headerSize += 4; - if (headerSize != minHeaderSize){ - QByteArray restHeader = readBytes(headerSize - minHeaderSize, maxTime, loops); - if (restHeader.length() == 0) + if(headerSize != minHeaderSize) { + QByteArray restHeader = readBytes(headerSize - minHeaderSize, + maxTime, loops); + if(restHeader.length() == 0) header.clear(); else header.append(restHeader); } } rc = header.length() > 0; - if (rc){ + if(rc) { int offset = (flags & FLAG_ENCRYPT) == 0 ? 6 : 8; int size = (flags & FLAG_4_BYTE_SIZE) == 0 ? 4 : 2; int dataLength = getInt(header, offset, size); @@ -245,11 +272,12 @@ bool RplTcpPeer::receive(QByteArray& command, QByteArray& data){ * false: error occurred */ bool RplTcpPeer::sendAndReceive(quint8 flags, char command [4], - QByteArray* data, QByteArray& answer, QByteArray& answerData){ + QByteArray* data, QByteArray& answer, + QByteArray& answerData) { answer.clear(); answerData.clear(); bool rc = send(flags, command, data == NULL ? QByteArray("") : *data); - if (rc) + if(rc) rc = receive(answer, answerData); return rc; } @@ -259,14 +287,17 @@ bool RplTcpPeer::sendAndReceive(quint8 flags, char command [4], * * @param socket the socket to set */ -void RplTcpPeer::setSocket(QAbstractSocket* socket){ +void RplTcpPeer::setSocket(QAbstractSocket* socket) { m_socket = socket; - //if (socket != NULL) - //connect( m_socket, SIGNAL(readyRead()), SLOT(readTcpData()) ); + if (socket != NULL) + connect( m_socket, SIGNAL(readyRead()), SLOT(readTcpData()) ); } -void RplTcpPeer::readTcpData(){ - +/** + * @brief Reads the (ready) data from the socket. + */ +void RplTcpPeer::readTcpData() { + m_waitForData.wakeOne(); } /** @@ -274,9 +305,22 @@ void RplTcpPeer::readTcpData(){ * * @param socketError the error code */ -void RplTcpPeer::handleError(QTcpSocket::SocketError socketError){ - m_logger->logv(LOG_ERROR, LOC_HANDLE_ERROR_1, "Network error %d", - socketError); +void RplTcpPeer::handleError(QTcpSocket::SocketError socketError) { + m_logger->logv(LOG_ERROR, LOC_HANDLE_ERROR_1, "Network error %d", + socketError); +} + +/** + * @brief Returns a human readable peer address. + * @return a string with the peer address: e.g. "192.16.2.3:44335" + */ +QByteArray RplTcpPeer::getPeerAddress() { + QByteArray rc; + if(m_socket == NULL) + rc = ""; + else + rc = m_socket->peerAddress().toString().toUtf8(); + return rc; } /** @@ -284,6 +328,33 @@ void RplTcpPeer::handleError(QTcpSocket::SocketError socketError){ * * @return the socket */ -QAbstractSocket* RplTcpPeer::getSocket() const{ +QAbstractSocket* RplTcpPeer::getSocket() const { return m_socket; } + +/** + * @brief Returns the port. + * @return the port of the peer. + */ +int RplTcpPeer::getPort(){ + int port = m_configurator.asInt(RplNetConfig::PORT, 12345); + return port; +} +/** + * @brief Returns the ip address. + * @return "": all addresses (for listening)
    + * otherwise: the address (e.g. 127.0.0.1) + */ +QByteArray RplTcpPeer::getIp(){ + QByteArray ip = m_configurator.asString(RplNetConfig::IP, ""); + return ip; +} +/** + * @brief Sets the address (ip:port). + * @param ip the ip address + * @param port the port + */ +void RplTcpPeer::setAddress(const char* ip, int port) +{ + m_address = QByteArray(ip) + ":" + QByteArray::number(port); +} diff --git a/rplnet/rpltcppeer.hpp b/rplnet/rpltcppeer.hpp index 0784de6..d040496 100644 --- a/rplnet/rpltcppeer.hpp +++ b/rplnet/rpltcppeer.hpp @@ -12,8 +12,7 @@ #include "rplnet.hpp" #endif -class RplTcpPeer : public QObject -{ +class RplTcpPeer : public QObject { Q_OBJECT public: enum { @@ -29,10 +28,15 @@ public: ///> connection initialization of } flag_t; public: - static RplTcpPeer* createPeer(const char* ip, int port, QThread* thread, - RplTerminator* terminator, RplLogger* logger = NULL); + static RplTcpPeer* createPeer(RplConfigurator& configurator, + QThread* thread, + RplTerminator* terminator, + RplLogger* logger = NULL); public: - RplTcpPeer(const char* ip, int port, QThread* thread, RplTerminator* terminator, RplLogger* logger = NULL); + RplTcpPeer(RplConfigurator& configurator, QThread* thread, + RplTerminator* terminator, + bool isServer, + RplLogger* logger = NULL); virtual ~RplTcpPeer(); private: // No copy constructor: no implementation! @@ -43,33 +47,38 @@ public: virtual bool send(qint8 flags, const char* command, const QByteArray& data); virtual bool receive(QByteArray& command, QByteArray& data); virtual bool sendAndReceive(quint8 flags, char command [4], - QByteArray* data, QByteArray& answer, QByteArray& answerData); + QByteArray* data, QByteArray& answer, QByteArray& answerData); void setSocket(QAbstractSocket* socket); QAbstractSocket* getSocket() const; - + QByteArray getPeerAddress(); void handleError(QTcpSocket::SocketError socketError); + int getPort(); + QByteArray getIp(); + void setAddress(const char* ip, int port); private: QByteArray readBytes(int bytes, time_t maxTime, int& loops); -public: +public slots: void readTcpData(); private: - QByteArray m_ip; - int m_port; QAbstractSocket* m_socket; + // : + QByteArray m_address; RplLogger* m_logger; QByteArray m_received; int m_expected; QThread* m_thread; // Only used for salt generation: RplRandom m_random; - ///> true: the read/write operation is done - bool m_ready; ///> maximum allowed time (in seconds) for sending/receiving one info unit int m_timeout; ///> for controlled termination RplTerminator* m_terminator; + RplConfigurator& m_configurator; + bool m_isServer; + QMutex m_dataLocker; + QWaitCondition m_waitForData; }; #endif // RPLTCPPEER_HPP diff --git a/rplnet/rpltcpserver.cpp b/rplnet/rpltcpserver.cpp index 65e86df..e4533d9 100644 --- a/rplnet/rpltcpserver.cpp +++ b/rplnet/rpltcpserver.cpp @@ -8,7 +8,10 @@ #include "rplnet.hpp" enum { - LOC_1 = RPL_FIRST_OF(RPLMODULE_TCPSERVER), // 601 + LOC_RUN_1 = RPL_FIRST_OF(RPLMODULE_TCPSERVER), // 601 + LOC_TCP_TREAD_RUN_1, + LOC_TCP_TREAD_RUN_2, + LOC_TCP_INCOMING_CONNECTION_1, }; /** @class RplTcpThread rpltcpserver.hpp "rplcore/rpltcpserver.hpp" @@ -21,34 +24,50 @@ enum { /** * @brief Constructor. * + * @param configurator delivers some connection parameters * @param socketDescriptor socket of the connection to handle * @param threadId an unique id for the thread * @param handler does the work */ -RplTcpThread::RplTcpThread(qintptr socketDescriptor, int threadId, RplTaskHandler* handler) : +RplTcpThread::RplTcpThread(RplConfigurator& configurator, + qintptr socketDescriptor, int threadId, + RplTaskHandler* handler) : m_threadId(threadId), m_taskHandler(handler), - m_socketDescriptor(socketDescriptor) -{ + m_socketDescriptor(socketDescriptor), + m_configurator(configurator){ } /** * @brief Destructor. */ -RplTcpThread::~RplTcpThread(){ +RplTcpThread::~RplTcpThread() { } -void RplTcpThread::run(){ - QTcpSocket tcpSocket; - if (!tcpSocket.setSocketDescriptor(getSocketDescriptor())) { - emit error(tcpSocket.error()); +/** + * @brief Does the proper thread task. + * + * Initializes the socket and loops for incoming commands. + */ +void RplTcpThread::run() { + QTcpSocket socket; + if(!socket.setSocketDescriptor(getSocketDescriptor())) { + emit error(socket.error()); } else { - while(m_taskHandler->handle(&tcpSocket)){ + RplTcpPeer peer(m_configurator, this, m_taskHandler->getTerminator(), + true, m_taskHandler->getLogger()); + peer.setSocket(&socket); + QByteArray addr = peer.getPeerAddress(); + m_taskHandler->getLogger()->logv(LOG_DEBUG, LOC_TCP_TREAD_RUN_1, + "RplTcpThread::run(): start Peer: %s", addr.constData()); + while(m_taskHandler->handle(&peer)) { // do nothing } - tcpSocket.disconnectFromHost(); - tcpSocket.waitForDisconnected(); - } + socket.disconnectFromHost(); + socket.waitForDisconnected(); + m_taskHandler->getLogger()->logv(LOG_DEBUG, LOC_TCP_TREAD_RUN_1, + "RplTcpThread::run(): end Peer: %s", addr.constData()); + } } /** @@ -56,7 +75,7 @@ void RplTcpThread::run(){ * * @return the thread id */ -int RplTcpThread::getThreadId() const{ +int RplTcpThread::getThreadId() const { return m_threadId; } /** @@ -64,7 +83,7 @@ int RplTcpThread::getThreadId() const{ * * @return the task handler */ -RplTaskHandler* RplTcpThread::getTaskHandler() const{ +RplTaskHandler* RplTcpThread::getTaskHandler() const { return m_taskHandler; } /** @@ -72,7 +91,7 @@ RplTaskHandler* RplTcpThread::getTaskHandler() const{ * * @return the socket */ -qintptr RplTcpThread::getSocketDescriptor() const{ +qintptr RplTcpThread::getSocketDescriptor() const { return m_socketDescriptor; } @@ -84,25 +103,22 @@ qintptr RplTcpThread::getSocketDescriptor() const{ /** * @brief Constructor. * - * @param taskHandler this handler reads from the tcp and interprets the content - * @param thread the current thread. Used for sleeping - * @param logger NULL or logger - * @param parent NULL or the parent which deletes the childen - */ -RplTcpServer::RplTcpServer(RplTaskHandler* taskHandler, QThread* thread, RplLogger* logger, QObject *parent) : + * @param configurator some parameters will be get from this configurator + * @param taskHandler this handler reads from the tcp and interprets the content + * @param threadFacctory creates a thread for a new connection + * @param logger NULL or logger + * @param parent NULL or the parent which deletes the childen + */ +RplTcpServer::RplTcpServer(RplConfigurator& configurator, + RplTaskHandler* taskHandler, + RplThreadFactory& threadFactory, + RplLogger* logger, + QObject* parent) : QTcpServer(parent), m_taskHandler(taskHandler), m_threadId(0), - m_peer(NULL) -{ -} - -/** - * @brief Returns the peer info. - * @return the peer info - */ -RplTcpPeer* RplTcpServer::getPeer() const{ - return m_peer; + m_threadFactory(threadFactory), + m_configurator(configurator){ } /** @@ -110,13 +126,21 @@ RplTcpPeer* RplTcpServer::getPeer() const{ * * @param socketDescriptor the tcp socket */ -void RplTcpServer::incomingConnection(qintptr socketDescriptor) -{ - RplTcpThread *thread = createThread(socketDescriptor, ++m_threadId, m_taskHandler); +void RplTcpServer::incomingConnection(qintptr socketDescriptor) { + RplTcpThread* thread = m_threadFactory.create(m_configurator, + socketDescriptor, ++m_threadId, m_taskHandler); + m_taskHandler->getLogger()->log(LOG_DEBUG, LOC_TCP_INCOMING_CONNECTION_1, + "Connection detected"); QTcpServer::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); } +/** @class RplTcpThread rpltcpserver.hpp "rplcore/rpltcpserver.hpp" + * + * @brief Defines a function pointer type to create a RplTcpThread instance. + * + */ + /** @class RplTaskHandler rpltcpserver.hpp "rplcore/rpltcpserver.hpp" * * @brief An abstract base class for an handler processing an data unit. @@ -125,25 +149,45 @@ void RplTcpServer::incomingConnection(qintptr socketDescriptor) */ /** * @brief Constructor + * + * @param configurator delivers some connection parameters + * @param terminator external controller for thread termination + * @param logger the logger */ -RplTaskHandler::RplTaskHandler(){ +RplTaskHandler::RplTaskHandler(RplConfigurator& configurator, + RplTerminator* terminator, RplLogger* logger) : + m_answerFlags(0), + m_logger(logger), + m_terminator(terminator), + m_configurator(configurator){ } /** * @brief Destructor. */ -RplTaskHandler::~RplTaskHandler(){ +RplTaskHandler::~RplTaskHandler() { } /** - * @brief Reads a data unit, processes it and sends the answer. + * @brief Reads one data unit, processes it and sends the answer. * - * @param socket the communication socket - * @return true: the application should stop
    - * false: processing remains + * @param peer the communication partner + * @return false: the application should stop
    + * true: processing remains */ -bool RplTaskHandler::handle(QAbstractSocket* socket){ - return true; +bool RplTaskHandler::handle(RplTcpPeer* peer) { + QByteArray command; + QByteArray data; + QByteArray answer; + QByteArray answerData; + bool rc = true; + if(peer->receive(command, data)) { + rc = process(command, data, answer, answerData); + if(answer.length() > 0) { + peer->send(m_answerFlags, answer, answerData); + } + } + return rc; } /** @@ -151,7 +195,7 @@ bool RplTaskHandler::handle(QAbstractSocket* socket){ * * @param id the thread id */ -void RplTaskHandler::setThreadId(int id){ +void RplTaskHandler::setThreadId(int id) { m_threadId = id; } @@ -160,55 +204,25 @@ void RplTaskHandler::setThreadId(int id){ * * @return the thread id */ -int RplTaskHandler::getThreadId() const{ +int RplTaskHandler::getThreadId() const { return m_threadId; } -/** @class RplCryptoTaskHandler rpltcpserver.hpp "rplcore/rpltcpserver.hpp" - * - * @brief An abstract base class for an handler processing an encrypted data unit. - * - * The handler knows the stucture of the data unit and can interpret this. - * The data unit contains some authentification and encryption information. - * The embedded data are encrypted. - * - * Structure of the exchanged data units: - * - * The data unit (further named "envelope") is a RplContainer. - * It contains 1 bag with the following items: - *
      - *
    • string user: the login will be done for this user. - *
    • integer current_salt: the random generator must be initialized by this value. - * Then the embedded data can be decrypted. - * Note: other user specific data (certificate) affects the encryption as well.
    • - *
    • integer salt": this is the encrypted version of the current salt: - * Only if the sender knows the user's credentials this value can be calculated correctly. - * This is the authentification. - * The encryption is done in the 'hexadecimal mode': input of hex digits produses output of hex digits.
    • - *
    • string application_command. 2 characters for application, 2 characters for the command. - * Encrpyted in 'ASCII mode': input of chr(32)-chr(127) produces chr(32)-chr(127).
    • - *
    • container embeddedInfo: not encrypted: contains 1 bag with one item: the encrypted data.
      - * The encryption is done by the "byte stream mode". Each info-byte is "xor-ed" by an byte value of the random generator.
    • - *
    - */ -/** - * @brief Constructor. - */ -RplCryptoTaskHandler::RplCryptoTaskHandler(){ -} /** - * @brief Destructor. + * @brief Returns the logger. + * + * @return the logger */ -RplCryptoTaskHandler::~RplCryptoTaskHandler(){ +RplLogger* RplTaskHandler::getLogger() const { + return m_logger; } + /** - * @brief Processes an (partitionally) encrypted data unit. - * - * Reads one data unit, decrypts it and calls another task handler to process the unencrypted data. + * @brief Returns the termination controller. * - * @param socket the socket for reading and writing - * @return true: the process must be finished. + * @return the termination controller */ -bool RplCryptoTaskHandler::handle(QAbstractSocket* socket){ - return false; +RplTerminator* RplTaskHandler::getTerminator() const { + return m_terminator; } + diff --git a/rplnet/rpltcpserver.hpp b/rplnet/rpltcpserver.hpp index 84e2246..2683346 100644 --- a/rplnet/rpltcpserver.hpp +++ b/rplnet/rpltcpserver.hpp @@ -13,55 +13,52 @@ #include "rplnet.hpp" #endif -class RplTaskHandler -{ +class RplTcpPeer; +class RplTaskHandler { public: - RplTaskHandler(); + RplTaskHandler(RplConfigurator& configurator, + RplTerminator* terminator, + RplLogger* logger); virtual ~RplTaskHandler(); public: - virtual bool handle(QAbstractSocket* socket); + virtual bool handle(RplTcpPeer* peer); /** * @brief Processes one data unit from the socket. * - * @param application this application is responsible - * @param command determines the meaning of the information unit - * @param size the length of the data - * @param info the data unit - * @param answerCode OUT: 0: success. Otherwise: error code - * @param answerSize OUT: 0 or the size of the answer data - * @param answerData OUT: NULL or the answer data - * @return true: the answer must be put to the socket
    - * false: no answer will be sent + * @param command defines the meaning of the information unit + * @param data "" or the data of the information unit + * @param answer OUT: "" or the answer to send back + * @param answerData OUT: "" or the answer data to send back + * @return true: the receiving loop should be continued
    + * false: the process should be stopped */ - virtual bool process(char application, int command, int size, const void* info, - int answerCode, int& answerSize, void*& answerData) = 0; + virtual bool process(const QByteArray& command, const QByteArray& data, + QByteArray& answer, QByteArray& answerData) = 0; void setThreadId(int id); int getThreadId() const; + RplLogger* getLogger() const; + RplTerminator* getTerminator() const; +protected: + quint8 m_answerFlags; private: int m_threadId; + RplLogger* m_logger; + RplTerminator* m_terminator; + RplConfigurator& m_configurator; }; -class RplCryptoTaskHandler -{ -public: - RplCryptoTaskHandler(); - virtual ~RplCryptoTaskHandler(); -public: - - virtual bool handle(QAbstractSocket* socket); -}; - - class RplTcpThread : public QThread { Q_OBJECT public: - RplTcpThread(qintptr socketDescriptor, int threadId, RplTaskHandler* handler); + RplTcpThread(RplConfigurator& m_configurator, + qintptr socketDescriptor, int threadId, + RplTaskHandler* handler); virtual ~RplTcpThread(); private: // No copy constructor: no implementation! RplTcpThread(const RplTcpThread& source); - // No assignment operator: no implementation! + // No assignment operator: no implementation! RplTcpThread& operator=(const RplTcpThread& source); public: void run(); @@ -79,35 +76,42 @@ private: RplTaskHandler* m_taskHandler; // the assigned socket qintptr m_socketDescriptor; + RplConfigurator& m_configurator; +}; +class RplThreadFactory { +public: + virtual RplTcpThread* create(RplConfigurator& configurator, + qintptr socketDescriptor, + int threadId, + RplTaskHandler* handler) = 0; }; class RplTcpPeer; -class RplTcpServer : public QTcpServer, public RplTerminator -{ +class RplTcpServer : public QTcpServer, public RplTerminator { Q_OBJECT public: - explicit RplTcpServer(RplTaskHandler* taskHandler, QThread* thread, RplLogger* logger = NULL, QObject *parent = 0); + explicit RplTcpServer(RplConfigurator& configurator, + RplTaskHandler* taskHandler, + RplThreadFactory& threadFactory, + RplLogger* logger = NULL, QObject* parent = 0); private: // No copy constructor: no implementation! RplTcpServer(const RplTcpServer& source); - // No assignment operator: no implementation! + // No assignment operator: no implementation! RplTcpServer& operator=(const RplTcpServer& source); public: RplTcpPeer* getPeer() const; bool handleTask(); - /** - * Creates a thread derived from RplTcpThread. - * @return a new thread - */ - virtual RplTcpThread* createThread(qintptr socketDescriptor, int threadId, RplTaskHandler* taskHandler) = 0; protected slots: - void incomingConnection(qintptr socketDescriptor); + void incomingConnection(qintptr socketDescriptor); private: - RplTaskHandler* m_taskHandler; - int m_threadId; - RplTcpPeer* m_peer; + RplTaskHandler* m_taskHandler; + int m_threadId; + RplTcpPeer* m_peer; + RplThreadFactory& m_threadFactory; + RplConfigurator& m_configurator; }; #endif // RPLTCPSERVER_HPP diff --git a/rplstatic/rplstatic.pro b/rplstatic/rplstatic.pro new file mode 100644 index 0000000..a2352f0 --- /dev/null +++ b/rplstatic/rplstatic.pro @@ -0,0 +1,25 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-05-30T21:36:15 +# +#------------------------------------------------- + +QT += network testlib + +QT -= gui + +TARGET = rplstatic +TEMPLATE = lib +CONFIG += staticlib + +SOURCES += rplstaticlib.cpp ../rplmath/rplmatrix.cpp ../rplmath/rplenigma.cpp + +HEADERS += rplstaticlib.hpp ../rplmath/rplmatrix.hpp ../rplmath/rplenigma.hpp +unix:!symbian { + maemo5 { + target.path = /opt/usr/lib + } else { + target.path = /usr/lib + } + INSTALLS += target +} diff --git a/rplstatic/rplstaticlib.cpp b/rplstatic/rplstaticlib.cpp new file mode 100644 index 0000000..e4c28bf --- /dev/null +++ b/rplstatic/rplstaticlib.cpp @@ -0,0 +1,15 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ + + +#include "rplstaticlib.hpp" + + +RplStaticLib::RplStaticLib() +{ +} diff --git a/rplstatic/rplstaticlib.hpp b/rplstatic/rplstaticlib.hpp new file mode 100644 index 0000000..80a926b --- /dev/null +++ b/rplstatic/rplstaticlib.hpp @@ -0,0 +1,21 @@ +/* + * Licence: + * You can use and modify this file without any restriction. + * There is no warranty. + * You also can use the licence from http://www.wtfpl.net/. + * The original sources can be found on https://github.com/republib. +*/ + + +#ifndef RPLSTATICLIB_HPP +#define RPLSTATICLIB_HPP + + +class RplStaticLib +{ + +public: + RplStaticLib(); +}; + +#endif // RPLSTATICLIB_HPP -- 2.39.5