--- /dev/null
+<?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>
--- /dev/null
+<?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>
*/
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,
};
/**
* @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);
}
/**
*
* 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);
}
/**
* @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;
}
/**
* @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;
}
/**
* @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;
}
/**
* @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;
}
/**
* @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;
}
// ------------------
*/
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
}
#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:
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:
--- /dev/null
+/*
+ * 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
m_typeList(""),
m_ixItem(0),
m_ixBag(0),
- m_readPosition(NULL)
-{
+ m_readPosition(NULL) {
}
/**
* @brief Destructor.
*/
-RplContainer::~RplContainer(){
+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;
}
*
* @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));
*
* @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;
}
*
* @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);
*
* @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);
* @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);
* @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;
*
* @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);
*
* @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());
}
/**
*
* @return the next char from the container
*/
-char RplContainer::nextChar(){
+char RplContainer::nextChar() {
nextItem(TAG_CHAR);
char rc = *m_readPosition++;
return rc;
*
* @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;
}
*
* @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;
}
*
* @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;
* 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;
default:
break;
}
- if (! append)
+ if(! append)
data.clear();
data.append((const char*) m_readPosition, length);
m_readPosition += length;
* @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');
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;
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;
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;
/**
* @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 <0> Y -ab34 A long string with an trailing '0' <0><br>
container.startBag();
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();
#include <QByteArray>
#include <QDataStream>
#endif
-class RplContainer
-{
+class RplContainer {
public:
typedef enum {
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:
#include <QHash>
#include <QVector>
#include <QDataStream>
+#include <QMutex>
typedef unsigned char uint8_t;
#include "../rplmodules.hpp"
#include "rplexception.hpp"
#include "rplcontainer.hpp"
#include "rplstring.hpp"
+#include "rplconfigurator.hpp"
#include "rplconfig.hpp"
#include "rplterminator.hpp"
* @param message the reason of the exception
*/
RplException::RplException(const char* message) :
- m_message(message)
-{
+ m_message(message) {
}
/**
* @param message the reason of the exception
*/
RplException::RplException(const QByteArray& message) :
- m_message(message)
-{
+ m_message(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);
}
* @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);
}
* 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);
}
* 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);
}
* @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);
}
* @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);
}
#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;
}
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
*
* @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");
}
/**
* @brief Frees the resources of the global logger.
*/
-void RplLogger::destroyGlobalLogger(){
+void RplLogger::destroyGlobalLogger() {
delete m_globalLogger;
m_globalLogger = NULL;
}
*/
RplAppender::RplAppender(const QByteArray& name) :
m_name(name),
- m_level(LOG_INFO)
-{
+ m_level(LOG_INFO) {
}
/**
* @brief Destructor.
*/
-RplAppender::~RplAppender(){
+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();
}
/**
*
* @param level
*/
-void RplAppender::setLevel(RplLoggerLevel level){
+void RplAppender::setLevel(RplLoggerLevel level) {
m_level = level;
}
/**
*
* @return the level
*/
-RplLoggerLevel RplAppender::getLevel() const{
+RplLoggerLevel RplAppender::getLevel() const {
return m_level;
}
/**
* @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;
}
*
* @param onNotOff the state of the auto deletion
*/
-void RplAppender::setAutoDelete(bool onNotOff){
+void RplAppender::setAutoDelete(bool onNotOff) {
m_autoDelete = onNotOff;
}
*
* @return true: the logger destroys the instance
*/
-bool RplAppender::isAutoDelete() const{
+bool RplAppender::isAutoDelete() const {
return m_autoDelete;
}
* @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;
*/
char RplLogger::getPrefixOfLevel(RplLoggerLevel level) const {
char rc = ' ';
- switch(level){
+ switch(level) {
case LOG_ERROR:
rc = '!';
break;
* @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;
}
*
* @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.
*
* @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;
}
* @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;
}
/**
* @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());
}
* @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());
}
* @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);
* @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);
* @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);
* @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);
}
*
* @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");
* @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);
}
/**
* @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);
*/
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);
}
* @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);
* @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;
}
/**
* @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;
}
* @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);
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() {
}
/**
* @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);
}
*
* @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();
}
*
*/
class RplLogger;
-
+class RplConfig;
/**
* @brief Logging level: for controlling of the logging.
*
LOG_DEBUG = 25 ///< for debug purpose only
};
-class RplAppender
-{
+class RplAppender {
public:
RplAppender(const QByteArray& name);
virtual ~RplAppender();
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);
bool m_autoDelete;
};
-class RplLogger
-{
+class RplLogger {
public:
static RplLogger* globalLogger();
static void destroyGlobalLogger();
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];
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;
/**
* 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"
/**
* 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:
* @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;
}
* 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.
* @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);
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 : '.');
}
}
// 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 : '.');
}
* 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);
}
}
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.
*
* @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.
* @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);
* @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);
}
/**
* @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"));
checkE(2, RplString::count(" a ", " "));
}
- void testCutString(){
+ void testCutString() {
QByteArray source("123");
QByteArray buffer;
checkE(QByteArray("123"), RplString::cutString(source, 4, buffer));
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));
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();
};
#endif
-void testRplString(){
+void testRplString() {
#ifdef RPL_TEST
TestRplString test;
test.run();
#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");
};
*/
RplTerminator::RplTerminator(RplLogger* logger) :
m_stop(false),
- m_logger(logger)
-{
+ m_logger(logger) {
}
/**
* @brief Destructor.
*/
-RplTerminator::~RplTerminator(){
+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,
* @return true: the thread should be stopped.<br>
* false: otherwise
*/
-bool RplTerminator::isStopped() const{
+bool RplTerminator::isStopped() const {
return m_stop;
}
#ifndef RPLTERMINATOR_HPP
#define RPLTERMINATOR_HPP
-class RplTerminator
-{
+class RplTerminator {
public:
RplTerminator(RplLogger* logger = NULL);
virtual ~RplTerminator();
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;
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);
}
/**
* @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--;
/**
* @brief Destructor.
*/
-RplTest::~RplTest(){
+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;
}
* @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);
while(expected[ix] == current[ix] && expected[ix] != '\0')
ix++;
char pointer[12+1];
- char *ptr = pointer;
+ char* ptr = pointer;
int maxIx = ix > 10 ? 10 : ix;
- for (int ii = 0; ii < maxIx - 1; ii++)
+ for(int ii = 0; ii < maxIx - 1; ii++)
*ptr++ = '-';
*ptr++ = '^';
*ptr = '\0';
- if (ix < 10)
+ if(ix < 10)
error("%s-%d: error: diff at index %d\n%s\n%s\n%s",
file, lineNo, ix, expected, current, pointer);
else
* @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());
}
* @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);
}
* @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);
}
* @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;
}
* @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;
}
* @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;
}
* @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;
}
* @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;
}
* @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);
* @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;
}
* @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;
}
#include <QByteArray>
#endif
-class RplTest
-{
+class RplTest {
public:
RplTest(const char* name);
virtual ~RplTest();
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);
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;
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) {
/**
* @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();
}
* 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.
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;
}
/**
* @brief Destructor.
*/
-RplEnigma::~RplEnigma(){
- if (m_ownsRandom){
+RplEnigma::~RplEnigma() {
+ if(m_ownsRandom) {
delete m_random;
m_random = NULL;
}
* @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;
* 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];
* 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];
* @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;
*
* @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;
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;
}
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);
* @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));
}
*
* @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;
}
/**
* @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);
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);
}
printf("%s\n", v.constData());
}
- void testOneBytes(const char* bytes){
+ void testOneBytes(const char* bytes) {
RplEnigma enigma;
enigma.addByteSecret("Hello World");
enigma.setSeed(0x1234);
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();
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * Matrix_test.cpp
+ *
+ * Created on: 29.05.2014
+ * Author: hm
+ */
+
+#include "stdinc.hpp"
+
+namespace rpl {
+
+} /* namespace rpl */
* @brief Constructor.
*/
RplRandom::RplRandom() :
- m_seed(0)
-{
+ m_seed(0) {
}
/**
* @brief Destructor.
*/
-RplRandom::~RplRandom(){
+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;
*
* @param seed the new seed.
*/
-void RplRandom::setSeed(u_int64_t seed){
+void RplRandom::setSeed(u_int64_t seed) {
m_seed = seed;
}
/**
*
* @param seed the XOR operand.
*/
-void RplRandom::xorSeed(u_int64_t seed){
+void RplRandom::xorSeed(u_int64_t seed) {
m_seed ^= 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;
}
* @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;
}
* @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;
* @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;
#define RPLRANDOM_HPP
#include <QtCore>
-class RplRandom
-{
+class RplRandom {
public:
RplRandom();
virtual ~RplRandom();
#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
--- /dev/null
+/*
+ * 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";
--- /dev/null
+/*
+ * 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
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();
}
}
* @brief Returns the peer info.
* @return the peer info
*/
-RplTcpPeer* RplTcpClient::getPeer() const{
+RplTcpPeer* RplTcpClient::getPeer() const {
return m_peer;
}
*
* @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"
/**
* @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;
}
*
* @return the peer
*/
-RplTcpPeer* RplClientThread::getPeer() const{
+RplTcpPeer* RplClientThread::getPeer() const {
return m_client->getPeer();
}
* @brief Returns the logger of the thread.
* @return the logger
*/
-RplLogger* RplClientThread::getLogger() const{
+RplLogger* RplClientThread::getLogger() const {
return m_logger;
}
*
* Calls <code>doIt()</code> for the real things.
*/
-void RplClientThread::run(){
+void RplClientThread::run() {
doIt();
}
#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!
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!
protected:
RplTcpClient* m_client;
RplLogger* m_logger;
+ RplConfigurator& m_configurator;
private:
bool m_ownsLogger;
};
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>
/**
* @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() {
}
* @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;
}
* @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;
* @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();
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);
* 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;
}
*
* @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();
}
/**
*
* @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;
}
/**
*
* @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);
+}
#include "rplnet.hpp"
#endif
-class RplTcpPeer : public QObject
-{
+class RplTcpPeer : public QObject {
Q_OBJECT
public:
enum {
///> 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!
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
#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"
/**
* @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());
+ }
}
/**
*
* @return the thread id
*/
-int RplTcpThread::getThreadId() const{
+int RplTcpThread::getThreadId() const {
return m_threadId;
}
/**
*
* @return the task handler
*/
-RplTaskHandler* RplTcpThread::getTaskHandler() const{
+RplTaskHandler* RplTcpThread::getTaskHandler() const {
return m_taskHandler;
}
/**
*
* @return the socket
*/
-qintptr RplTcpThread::getSocketDescriptor() const{
+qintptr RplTcpThread::getSocketDescriptor() const {
return m_socketDescriptor;
}
/**
* @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){
}
/**
*
* @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.
*/
/**
* @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;
}
/**
*
* @param id the thread id
*/
-void RplTaskHandler::setThreadId(int id){
+void RplTaskHandler::setThreadId(int id) {
m_threadId = 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;
}
+
#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();
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
--- /dev/null
+#-------------------------------------------------
+#
+# 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
+}
--- /dev/null
+/*
+ * 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()
+{
+}
--- /dev/null
+/*
+ * 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