]> gitweb.hamatoma.de Git - reqt/commitdiff
formatted. +rplmatrix
authorhama <hama@siduction.net>
Fri, 30 May 2014 19:53:44 +0000 (21:53 +0200)
committerhama <hama@siduction.net>
Fri, 30 May 2014 19:53:44 +0000 (21:53 +0200)
37 files changed:
.cproject [new file with mode: 0644]
.project [new file with mode: 0644]
rplcore/rplconfig.cpp
rplcore/rplconfig.hpp
rplcore/rplconfigurator.hpp [new file with mode: 0644]
rplcore/rplcontainer.cpp
rplcore/rplcontainer.hpp
rplcore/rplcore.hpp
rplcore/rplexception.cpp
rplcore/rplexception.hpp
rplcore/rpllogger.cpp
rplcore/rpllogger.hpp
rplcore/rplstring.cpp
rplcore/rplstring.hpp
rplcore/rplterminator.cpp
rplcore/rplterminator.hpp
rplcore/rpltest.cpp
rplcore/rpltest.hpp
rplcore/testrplexample.cpp
rplmath/rplenigma.cpp
rplmath/rplmatrix.cpp [new file with mode: 0644]
rplmath/rplmatrix.hpp [new file with mode: 0644]
rplmath/rplmatrix_test.cpp [new file with mode: 0644]
rplmath/rplrandom.cpp
rplmath/rplrandom.hpp
rplnet/rplnet.hpp
rplnet/rplnetconfig.cpp [new file with mode: 0644]
rplnet/rplnetconfig.hpp [new file with mode: 0644]
rplnet/rpltcpclient.cpp
rplnet/rpltcpclient.hpp
rplnet/rpltcppeer.cpp
rplnet/rpltcppeer.hpp
rplnet/rpltcpserver.cpp
rplnet/rpltcpserver.hpp
rplstatic/rplstatic.pro [new file with mode: 0644]
rplstatic/rplstaticlib.cpp [new file with mode: 0644]
rplstatic/rplstaticlib.hpp [new file with mode: 0644]

diff --git a/.cproject b/.cproject
new file mode 100644 (file)
index 0000000..858efea
--- /dev/null
+++ b/.cproject
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?>
+
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+       <storageModule moduleId="org.eclipse.cdt.core.settings">
+               <cconfiguration id="0.800691153">
+                       <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.800691153" moduleId="org.eclipse.cdt.core.settings" name="Default">
+                               <externalSettings/>
+                               <extensions>
+                                       <extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                               </extensions>
+                       </storageModule>
+                       <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+                               <configuration buildProperties="" description="" id="0.800691153" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg">
+                                       <folderInfo id="0.800691153." name="/" resourcePath="">
+                                               <toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.295364492" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
+                                                       <targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.295364492.978176953" name=""/>
+                                                       <builder id="org.eclipse.cdt.build.core.settings.default.builder.1827277458" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
+                                                       <tool id="org.eclipse.cdt.build.core.settings.holder.libs.247202732" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
+                                                       <tool id="org.eclipse.cdt.build.core.settings.holder.1313807664" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
+                                                               <inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1190613361" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
+                                                       </tool>
+                                                       <tool id="org.eclipse.cdt.build.core.settings.holder.814499006" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
+                                                               <inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1978993617" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
+                                                       </tool>
+                                                       <tool id="org.eclipse.cdt.build.core.settings.holder.1957234262" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
+                                                               <inputType id="org.eclipse.cdt.build.core.settings.holder.inType.151373444" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
+                                                       </tool>
+                                               </toolChain>
+                                       </folderInfo>
+                               </configuration>
+                       </storageModule>
+                       <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+               </cconfiguration>
+       </storageModule>
+       <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+               <project id="rplqt.null.1220808761" name="rplqt"/>
+       </storageModule>
+       <storageModule moduleId="scannerConfiguration">
+               <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+               <scannerConfigBuildInfo instanceId="0.800691153">
+                       <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+               </scannerConfigBuildInfo>
+       </storageModule>
+       <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+</cproject>
diff --git a/.project b/.project
new file mode 100644 (file)
index 0000000..aabb6ff
--- /dev/null
+++ b/.project
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>rplqt</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+                       <triggers>clean,full,incremental,</triggers>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+                       <triggers>full,incremental,</triggers>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.cdt.core.cnature</nature>
+               <nature>org.eclipse.cdt.core.ccnature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+       </natures>
+</projectDescription>
index 3ab4699e1146431621fd1266206fb7417494829c..536e41762f7a65dae82c7cdcf3b97791a913926c 100644 (file)
  */
 
 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<br>
  *              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<br>
  *              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
 }
index c426c35f695a2a855565ece5d0b0461b2d5599cf..46af10682a258e6737dcb9b2ed4b1c79d5a0a233 100644 (file)
@@ -8,10 +8,10 @@
 #ifndef RPLCONFIG_HPP
 #define RPLCONFIG_HPP
 
-class RplConfig : public QHash<QByteArray, QByteArray>
-{
+class RplConfig : public RplConfigurator, public QHash<QByteArray, QByteArray> {
 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<QByteArray>& 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 (file)
index 0000000..c651800
--- /dev/null
@@ -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
index afe61eaae4af8765321d31b9436a6bda86bf5e38..3137aaeff2bf0d083aec1893595f997072ea2606 100644 (file)
@@ -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<blank>", 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<blank>", 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<blank>", m_readPosition, 16);
+    if(sscanf((const char*) m_readPosition, "%llx ", &value) != 1)
+        throw RplInvalidDataException(LOG_ERROR, LOC_NEXT_INT_1,
+                                      "not a hex_number<blank>", 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 <code>RplContainer</code>
  */
-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 &lt;0&gt; Y -ab34 A long string with an trailing '0' &lt;0&gt<br>
         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();
index 99bc3bc25de34cefd1cce1efa690f6ae1225a313..621a61603afb7f1481a170cb95325aa41da2ba32 100644 (file)
@@ -13,8 +13,7 @@
 #include <QByteArray>
 #include <QDataStream>
 #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:
index 29383941d8c60f82add5f1bee5485acaea25d455..a71da6257236df5a9b2dca5bca9e845ca6bb18ec 100644 (file)
@@ -25,6 +25,7 @@
 #include <QHash>
 #include <QVector>
 #include <QDataStream>
+#include <QMutex>
 
 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"
 
index dc7c73a96f0d9194bbe3537f1daa87332da863e2..db0d47eb9ea2070de92f7b419639329fd9352cbe 100644 (file)
@@ -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 <code>format</code>
  * @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 <code>format</code>
  * @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);
 }
index f5372232c39959098b83d524dc8df74041a14c2f..e3c7d02d526252134687b184a56633bb34d3fa09 100644 (file)
 #ifndef RPLCORE_HPP
 #include <QByteArray>
 #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
index 02ccc6edd38702e54a47ad995c0a39cc46a247b6..cb7468ec17749034859cab2c2bf614ee7710ac74 100644 (file)
@@ -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<br>
  *                  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.<br>
+ *                   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<br>
  *              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<QByteArray>& RplMemoryAppender::getLines() const{
+const QVector<QByteArray>& RplMemoryAppender::getLines() const {
     return m_lines;
 }
 
 /**
  * @brief Deletes all log lines.
  */
-void RplMemoryAppender::clear(){
+void RplMemoryAppender::clear() {
     m_lines.clear();
 }
index 3c0af244cff71475ce25edf17ee15e040c9ca8c7..69c8059ba93bff6df0d291f084fdfc7f96aea20d 100644 (file)
@@ -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 ".<no>.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<QByteArray>& getLines() const;
     void clear();
 private:
index d536cd2a61d3fc26360c5c5aae4906f5c9cbf0ca..40e130824c94088b77c30ee0ea8e19102e0d7791 100644 (file)
  * @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<QByteArray> RplString::toArray(const char* source, const char* separator){
+QVector<QByteArray> RplString::toArray(const char* source,
+                                       const char* separator) {
     const char* end = source;
     QVector<QByteArray> 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<QByteArray> 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<br>
  *                  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 <code>RplString</code>.
  */
-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<QByteArray> 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();
index e83dd638e9f0ff232c6aa3025197e1e6cf412124..39b82665be60b12261928b1359ea5ca55bbe5ff2 100644 (file)
@@ -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<QByteArray> 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");
 };
 
index 41dd99f66c789133f8674b883c3a7bf06bee078c..6b373aa253108def79772f761e035840fa983e6c 100644 (file)
@@ -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.<br>
  *          false: otherwise
  */
-bool RplTerminator::isStopped() const{
+bool RplTerminator::isStopped() const {
     return m_stop;
 }
 
index 25e5fca6043a1ea20108bbcd662b6b9811f65e04..f0e49c1476f7585388356279a99122a02a823931 100644 (file)
@@ -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;
index 24bfe7718ff491c44d01a34dd222610c7a977d33..1f538c94e71df31ff7759092d7fd51b924599326 100644 (file)
@@ -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<QByteArray> exp = RplString::toArray(expected, "\n");
             QVector<QByteArray> 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;
+            charptr = 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<QByteArray>& expected,
-        const QVector<QByteArray>& current, const char* file, int lineNo){
+                           const QVector<QByteArray>& 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<QByteArray>& 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              <code>condition</code>
  */
-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              <code>! condition</code>
  */
-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 <code>format</code>
  * @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;
 }
index 142459f878690a69073746562f5703a49efde111..4c15120ce2461eb0d590b5625708b2fdd54a5106 100644 (file)
@@ -13,8 +13,7 @@
 #include <QByteArray>
 #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<QByteArray>& expected,
-        const QVector<QByteArray>& current, const char* file, int lineNo);
+                      const QVector<QByteArray>& 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;
 
index 7dc921237c95984c25aef2f159d4994a21b440d9..e0c35f44b1ac05068396ca30fbad7cf63d36ba96 100644 (file)
@@ -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();
 }
index cd96d7e3651963257db4457ff9ca8c21bb02a90e..1e565ab9c0a3b2777ccd43e4c5754fb953ccb7fe 100644 (file)
@@ -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 <b>secret</b>.
+ *
+ * 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.
 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<br>
  *                      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<br>
  *                  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<secret_t*>::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 <code>RplEnigma</code>.
  */
-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 (file)
index 0000000..548ceb5
--- /dev/null
@@ -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<br>
+ *                                     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<br>
+ *                                     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<br>
+ *                             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 <code>buffer[]</code>
+ */
+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<br>
+ *                             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 (file)
index 0000000..9bf89f8
--- /dev/null
@@ -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 (file)
index 0000000..dbc6c7d
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Matrix_test.cpp
+ *
+ *  Created on: 29.05.2014
+ *      Author: hm
+ */
+
+#include "stdinc.hpp"
+
+namespace rpl {
+
+} /* namespace rpl */
index dc5eb904f206efe4e27e5c658440956fe3904800..6bf00d52adacbd51bc63c68e35bc0a491e4dcd99 100644 (file)
  * @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;
index e90a020dd460ea56eec7611ee2a843d77130556a..a041fb6344653bd35bd3873d4cb58bf942e59a63 100644 (file)
@@ -2,8 +2,7 @@
 #define RPLRANDOM_HPP
 
 #include <QtCore>
-class RplRandom
-{
+class RplRandom {
 public:
     RplRandom();
     virtual ~RplRandom();
index 2f2fe11e50f324176f49825865918ef50b72c254..f9c4731ead4045c13efd8c3bfa0afa96cc2193ba 100644 (file)
 #include <QTcpSocket>
 #include <QTcpServer>
 #include <QThread>
+#include <QWaitCondition>
+#include <QMutexLocker>
 
 //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 (file)
index 0000000..bdb28d5
--- /dev/null
@@ -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 (file)
index 0000000..4d58ef0
--- /dev/null
@@ -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
index 167fc21b4df6aa377069419081b5fd47781ece21..981ab5a09dcb902ca290931ffc1dd172dccea2b4 100644 (file)
 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 <code>RplTcpServer</code>.
  */
 /**
  * @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 <code>sleep()</code>
  * @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 <code>doIt()</code> for the real things.
  */
-void RplClientThread::run(){
+void RplClientThread::run() {
     doIt();
 }
index 1421072eba1217b2125c34b7752f312d86e25bd1..7ba45a58fd610bf4793651d2054a1eb706aeabe7 100644 (file)
 #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;
 };
index fcfbe208149d9aaa21172d064db95d14d6fd6327..207c36b08b5c8cc48c6b65f608beb9b7898e10a6 100644 (file)
@@ -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:
  * <ul>
@@ -42,45 +44,51 @@ static int s_dummy = 0;
 /**
  * @brief Creates an instance of a <code>RplTcpPeer</code>.
  *
- * @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 <code>RplTcpPeer</code>
+ * @param logger        logger. If Null the global logger will be taken (not thread safe!)
+ * @return              a instance of <code>RplTcpPeer</code>
  */
-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<br>
  *                  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<br>
  *                  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<br>
  *                  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 = "<not connected>";
+    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)<br>
+ *          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);
+}
index 0784de68df9c9f2d4f5f35647f44fde6d23e1f14..d04049622b7eddb4c85ad29d2d03300e44c80312 100644 (file)
@@ -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;
+    // <ip>:<port>
+    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
index 65e86dffbe3753d898e32e8443d3f685304a3aa4..e4533d9dd529ed2c8709e0f59a685448c66e9661 100644 (file)
@@ -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 <code>RplTcpThread</code> 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<br>
- *                  false: processing remains
+ * @param peer      the communication partner
+ * @return          false: the application should stop<br>
+ *                  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 <code>RplContainer</code>.
- * It contains 1 bag with the following items:
- * <ul>
- * <li>string user: the login will be done for this user.
- * <li>integer current_salt: the random generator must be initialized by this value.
- *      Then the embedded data can be decrypted.
- *      <b>Note:</b> other user specific data (certificate) affects the encryption as well.</li>
- * <li>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.</li>
- * <li>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).</li>
- * <li>container embeddedInfo: not encrypted: contains 1 bag with one item: the encrypted data.<br>
- *     The encryption is done by the "byte stream mode". Each info-byte is "xor-ed" by an byte value of the random generator. </li>
- * </ul>
- */
-/**
- * @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;
 }
+
index 84e2246d7d92cf00743642aa6b1471c8d0aea20f..268334660882b82adec7f70b237c7221454fcbae 100644 (file)
 #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<br>
-     *                      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<br>
+     *                      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 (file)
index 0000000..a2352f0
--- /dev/null
@@ -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 (file)
index 0000000..e4c28bf
--- /dev/null
@@ -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 (file)
index 0000000..80a926b
--- /dev/null
@@ -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