+++ /dev/null
-Subproject commit 0000000000000000000000000000000000000000
--- /dev/null
+++ b/appl/refind
+Subproject commit 0000000000000000000000000000000000000000
/*
* ReContainer.cpp
- *
+ *
* License: Public Domain
* You can use and modify this file without any restriction.
* Do what you want.
m_ixItem = 0;
}
if (m_ixItem >= m_typeList.length())
- throw ReException(LOG_ERROR, LOC_NEXT_ITEM_1, "no more items in the bag");
+ throw ReException(LOG_ERROR, LOC_NEXT_ITEM_1, ReLogger::globalLogger(),
+ "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)
+++ /dev/null
-/*
- * ReQString.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-/** @file
- * @brief Missed operation for <code>ReString</code>s.
- */
-/** @file rplcore/rplqstring.hpp
- *
- * @brief Definitions for missed operation for <code>ReString</code>s.
- */
-#include "base/rebase.hpp"
-
-/**
- * @brief Determines the length and vlaue of an integer.
- *
- * @param text the number as text
- * @param start the first index to inspect
- * @param radix the base of the number sytem: 8 (octal), 10 or 16
- * @param pValue OUT: the value of the integer. May be NULL
- *
- * @return <=0: no integer found
- * otherwise: the length of the integer
- */
-int ReQString::lengthOfUInt64(const ReString& text, int start, int radix,
- quint64* pValue){
- int inputLength = text.size();
- int64_t value = 0;
- int ix = start;
- int cc;
- if (radix == 10){
- while (ix < inputLength){
- if ((cc = text[ix].unicode()) >= '0' && cc <= '9')
- value = value * 10 + cc - '0';
- else
- break;
- ix++;
- }
- }else if (radix == 16){
- while (ix < inputLength){
- if ((cc = text[ix].unicode()) >= '0' && cc <= '9')
- value = value * 16 + cc - '0';
- else if (cc >= 'A' && cc <= 'F')
- value = value * 16 + cc - 'A' + 10;
- else if (cc >= 'a' && cc <= 'f')
- value = value * 16 + cc - 'a' + 10;
- else
- break;
- ix++;
- }
- }else if (radix == 8){
- while (ix < inputLength){
- if ((cc = text[ix].unicode()) >= '0' && cc <= '7')
- value = value * 8 + cc - '0';
- else
- break;
- ix++;
- }
- }else{
- throw ReException("ReQString::lengthOfInt(): wrong radix: %d", radix);
- }
- if (pValue != NULL)
- *pValue = value;
- return ix - start;
-}
-/**
- * @brief Determines the length and value of an unsigned integer.
- *
- * @param text the number as text
- * @param start the first index to inspect
- * @param radix the base of the number sytem: 8 (octal), 10 or 16
- * @param pValue OUT: the value of the integer. May be NULL
- *
- * @return 0: no integer found
- * otherwise: the length of the integer
- */
-int ReQString::lengthOfUInt(const ReString& text, int start, int radix,
- uint* pValue){
- quint64 value;
- int rc = lengthOfUInt64(text, start, radix, &value);
- if (pValue != NULL)
- *pValue = (uint) value;
- return rc;
-}
-
-/**
- * @brief Determines the length and value of a floting point number.
- *
- * @param text the number as text
- * @param start the first index to inspect
- * @param pValue OUT: the value of the integer. May be NULL
- *
- * @return <=0: no real number found
- * otherwise: the length of the floating point number
- */
-int ReQString::lengthOfReal(const ReString& text, int start, qreal* pValue){
- int inputLength = text.size();
- qreal value = 0.0;
- int cc;
- int ix = start;
- while (ix < inputLength){
- if ((cc = text[ix].unicode()) >= '0' && cc <= '9')
- value = value * 10 + (cc - '0');
- else
- break;
- ix++;
- }
- // found: a digit has been found (in front of or behind the '.'
- bool found = ix > start;
- if (ix < inputLength && text[ix].unicode() == '.'){
- ix++;
- }
- if (ix < inputLength && text[ix].isDigit()){
- found = true;
- qreal divisor = 1;
- qreal precision = 0;
- while (ix < inputLength && (cc = text[ix].unicode()) >= '0' && cc <= '9'){
- divisor *= 10;
- precision = precision * 10 + cc - '0';
- ix++;
- }
- value += precision / divisor;
- }else if (!found){
- ix = start;
- }
- if (found && ix + 1 < inputLength && toupper(text[ix].unicode()) == 'E'){
- int savePoint = ix;
- ix++;
- bool negative = false;
- if ((cc = text[ix].unicode()) == '+')
- ix++;
- else if (cc == '-'){
- ix++;
- negative = true;
- }
- if (ix >= inputLength || !text[ix].isDigit())
- ix = savePoint;
- else{
- int exponent = 0;
- while (ix < inputLength && text[ix].isDigit()){
- exponent = exponent * 10 + text[ix].unicode() - '0';
- ix++;
- }
- if (negative)
- value /= qPow(10, exponent);
- else
- value *= qPow(10, exponent);
- }
- }
- if (pValue)
- *pValue = value;
- return found ? ix - start : 0;
-}
-
-/**
- * @brief Converts a ReString into an utf-8 string
- *
- * The expression <code>qstring.toUtf8().constData()</code> is not allowed
- * in a variable argument list like sprintf. This is a thread save workaround.
- *
- * @param source string to convert
- * @param buffer OUT: target buffer
- * @param bufferSize size of the target buffer
- * @return <code>buffer</code>
- */
-char*ReQString::utf8(const ReString& source, char buffer[], size_t bufferSize){
- QByteArray val = source.toUtf8();
- if (val.length() < (int) bufferSize)
- bufferSize = val.length() + 1;
- memcpy(buffer, val.constData(), bufferSize - 1);
- buffer[bufferSize - 1] = '\0';
- return buffer;
-}
--- /dev/null
+/*
+ * ReQStringUtil.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+/** @file
+ * @brief Missed operation for <code>ReString</code>s.
+ */
+/** @file rplcore/rplqstring.hpp
+ *
+ * @brief Definitions for missed operation for <code>ReString</code>s.
+ */
+#include "base/rebase.hpp"
+#include <QtCore/qmath.h>
+/**
+ * @brief Determines the length and vlaue of an integer.
+ *
+ * @param text the number as text
+ * @param start the first index to inspect
+ * @param radix the base of the number sytem: 8 (octal), 10 or 16
+ * @param pValue OUT: the value of the integer. May be NULL
+ *
+ * @return <=0: no integer found
+ * otherwise: the length of the integer
+ */
+int ReQStringUtil::lengthOfUInt64(const ReString& text, int start, int radix,
+ quint64* pValue){
+ int inputLength = text.size();
+ int64_t value = 0;
+ int ix = start;
+ int cc;
+ if (radix == 10){
+ while (ix < inputLength){
+ if ((cc = text[ix].unicode()) >= '0' && cc <= '9')
+ value = value * 10 + cc - '0';
+ else
+ break;
+ ix++;
+ }
+ }else if (radix == 16){
+ while (ix < inputLength){
+ if ((cc = text[ix].unicode()) >= '0' && cc <= '9')
+ value = value * 16 + cc - '0';
+ else if (cc >= 'A' && cc <= 'F')
+ value = value * 16 + cc - 'A' + 10;
+ else if (cc >= 'a' && cc <= 'f')
+ value = value * 16 + cc - 'a' + 10;
+ else
+ break;
+ ix++;
+ }
+ }else if (radix == 8){
+ while (ix < inputLength){
+ if ((cc = text[ix].unicode()) >= '0' && cc <= '7')
+ value = value * 8 + cc - '0';
+ else
+ break;
+ ix++;
+ }
+ }else{
+ throw ReException("ReQStringUtil::lengthOfInt(): wrong radix: %d", radix);
+ }
+ if (pValue != NULL)
+ *pValue = value;
+ return ix - start;
+}
+/**
+ * @brief Determines the length and value of an unsigned integer.
+ *
+ * @param text the number as text
+ * @param start the first index to inspect
+ * @param radix the base of the number sytem: 8 (octal), 10 or 16
+ * @param pValue OUT: the value of the integer. May be NULL
+ *
+ * @return 0: no integer found
+ * otherwise: the length of the integer
+ */
+int ReQStringUtil::lengthOfUInt(const ReString& text, int start, int radix,
+ uint* pValue){
+ quint64 value;
+ int rc = lengthOfUInt64(text, start, radix, &value);
+ if (pValue != NULL)
+ *pValue = (uint) value;
+ return rc;
+}
+
+/**
+ * @brief Determines the length and value of a floting point number.
+ *
+ * @param text the number as text
+ * @param start the first index to inspect
+ * @param pValue OUT: the value of the integer. May be NULL
+ *
+ * @return <=0: no real number found
+ * otherwise: the length of the floating point number
+ */
+int ReQStringUtil::lengthOfReal(const ReString& text, int start, qreal* pValue){
+ int inputLength = text.size();
+ qreal value = 0.0;
+ int cc;
+ int ix = start;
+ while (ix < inputLength){
+ if ((cc = text[ix].unicode()) >= '0' && cc <= '9')
+ value = value * 10 + (cc - '0');
+ else
+ break;
+ ix++;
+ }
+ // found: a digit has been found (in front of or behind the '.'
+ bool found = ix > start;
+ if (ix < inputLength && text[ix].unicode() == '.'){
+ ix++;
+ }
+ if (ix < inputLength && text[ix].isDigit()){
+ found = true;
+ qreal divisor = 1;
+ qreal precision = 0;
+ while (ix < inputLength && (cc = text[ix].unicode()) >= '0' && cc <= '9'){
+ divisor *= 10;
+ precision = precision * 10 + cc - '0';
+ ix++;
+ }
+ value += precision / divisor;
+ }else if (!found){
+ ix = start;
+ }
+ if (found && ix + 1 < inputLength && toupper(text[ix].unicode()) == 'E'){
+ int savePoint = ix;
+ ix++;
+ bool negative = false;
+ if ((cc = text[ix].unicode()) == '+')
+ ix++;
+ else if (cc == '-'){
+ ix++;
+ negative = true;
+ }
+ if (ix >= inputLength || !text[ix].isDigit())
+ ix = savePoint;
+ else{
+ int exponent = 0;
+ while (ix < inputLength && text[ix].isDigit()){
+ exponent = exponent * 10 + text[ix].unicode() - '0';
+ ix++;
+ }
+ if (negative)
+ value /= qPow(10, exponent);
+ else
+ value *= qPow(10, exponent);
+ }
+ }
+ if (pValue)
+ *pValue = value;
+ return found ? ix - start : 0;
+}
+
+/**
+ * @brief Converts a ReString into an utf-8 string
+ *
+ * The expression <code>qstring.toUtf8().constData()</code> is not allowed
+ * in a variable argument list like sprintf. This is a thread save workaround.
+ *
+ * @param source string to convert
+ * @param buffer OUT: target buffer
+ * @param bufferSize size of the target buffer
+ * @return <code>buffer</code>
+ */
+char*ReQStringUtil::utf8(const ReString& source, char buffer[],
+ size_t bufferSize){
+ QByteArray val = source.toUtf8();
+ if (val.length() < (int) bufferSize)
+ bufferSize = val.length() + 1;
+ memcpy(buffer, val.constData(), bufferSize - 1);
+ buffer[bufferSize - 1] = '\0';
+ return buffer;
+}
+
+class ReParserException : public ReException {
+public:
+ ReParserException(const QString& message) :
+ ReException(),
+ m_message(message){
+ }
+public:
+ QString m_message;
+};
+/**
+ * Constructor.
+ *
+ * @param expr an expression, e.g. "10*1024kByte+5MiByte"
+ * @param unitList description of the allowed units with its factor<br>
+ * example: "kibyte:1024;kbyte:1000;mibyte:1048576;mbyte:1000000"
+ */
+ReUnitParser::ReUnitParser(const QString& expr, const char* unitList) :
+ m_result(0), m_expr(expr), m_message(), m_unitList(unitList){
+ // Replace the '-' operator by '+' as operator and '-' as sign:
+ // This makes the syntax easier to parse: only one sum operator ('+').
+ for (int ii = m_expr.length() - 1; ii > 0; ii--){
+ if (m_expr[ii] == '-' && m_expr[ii -1] != '+' && m_expr[ii - 1] != '*'){
+ m_expr.insert(ii, '+');
+ }
+ }
+ parse();
+}
+/**
+ * Returns whether the given expression is valid.
+ *
+ * @return <code>true</code>: the expression is valid, a result was calculated
+ */
+bool ReUnitParser::isValid() const{
+ return m_message.isEmpty();
+}
+/**
+ * Returns an empty string or the error message.
+ *
+ * @return "": no error occurred<br>
+ * otherwise: the error message
+ */
+const QString& ReUnitParser::errorMessage() const{
+ return m_message;
+}
+/**
+ * Returns the result of the expression as a 64 bit integer.
+ *
+ * @param defaultValue the result if the expression was not valid
+ * @return <code>defaultValue</code>: the result was not valid<br>
+ * the result as a 64 bit integer
+ */
+int64_t ReUnitParser::asInt64(int64_t defaultValue){
+ return m_message.isEmpty() ? m_result : defaultValue;
+}
+/**
+ * Returns the result of the expression as an integer.
+ *
+ * @param defaultValue the result if the expression was not valid
+ * @return <code>defaultValue</code>: the result was not valid<br>
+ * the result as an integer
+ */
+int ReUnitParser::asInt(int defaultValue){
+ return m_message.isEmpty() ? (int) m_result : defaultValue;
+}
+/**
+ * Returns the result of the expression as floating point number.
+ *
+ * @param defaultValue the result if the expression was not valid
+ * @return <code>defaultValue</code>: the result was not valid<br>
+ * the result as a floating point
+ */
+real_t ReUnitParser::asReal(real_t defaultValue){
+ return m_message.isEmpty() ? (real_t) m_result : defaultValue;
+}
+
+/**
+ * Calculates the value of a number or a (number, unit) pair.
+ *
+ * @param value a non negative number or a number followed by a unit<br>
+ * only units defined in m_unitList are allowed<br>
+ * examples: "4kByte" returns 4000, "4kibyte" returns 4096
+ * @return the value of the number multiplied by the factor given by the unit
+ * @throws ReParserException
+ */
+uint64_t ReUnitParser::valueOf(const QString& value) const{
+ uint64_t rc = 0;
+ int ix = ReQStringUtil::lengthOfUInt64(value, 0, 10, &rc);
+ if (ix == 0)
+ throw ReParserException(QObject::tr("number expected: ") + value);
+ QString unit = value.mid(ix);
+ if (! unit.isEmpty()){
+ QStringList units = QString(m_unitList).split(";");
+ QStringList::const_iterator it;
+ bool found = false;
+ for (it = units.begin(); it != units.end(); ++it){
+ QStringList pair = it->split(":");
+ if (pair.count() == 0)
+ throw ReParserException(QObject::tr("missing ':' in unit definition, e.g. 'k:1000': ") + *it);
+ if (pair.count() > 2)
+ throw ReParserException(QObject::tr("too many ':' in unit definition: ") + *it);
+ bool ok = false;
+ QString unit2 = *pair.begin();
+ QString factor = *++pair.begin();
+ uint64_t nFactor = factor.toLongLong(&ok);
+ if (! ok)
+ throw ReParserException(QObject::tr("not a number: ") + factor);
+ if (unit2.startsWith(unit)){
+ rc *= nFactor;
+ found = true;
+ break;
+ }
+ }
+ if (! found)
+ throw ReParserException(QObject::tr("unknown unit, allowed: ") + QString(m_unitList));
+ }
+ return rc;
+}
+/**
+ * Evaluate the expression.
+ */
+void ReUnitParser::parse(){
+ QStringList addends = m_expr.split("+");
+ QStringList::const_iterator it;
+ try{
+ m_result = 0;
+ for (it = addends.begin(); it != addends.end(); ++it){
+ QStringList factors = it->split("*");
+ QStringList::const_iterator it2;
+ int64_t product = 1;
+ for (it2 = factors.begin(); it2 != factors.end(); ++it2){
+ QStringList powerOperands = it2->split("^");
+ if (powerOperands.count() > 2)
+ throw ReParserException(QObject::tr("more than 2 power operators, e.g. '2^3^4'"));
+ QStringList::const_iterator it3 = powerOperands.begin();
+ QString op = *it3;
+ bool isNeg = op.startsWith("-");
+ if (isNeg)
+ op = op.mid(1);
+ uint64_t value = valueOf(op);
+ if (powerOperands.count() > 1){
+ uint64_t fac = value;
+ uint64_t exponent = valueOf(*++it3);
+ if (qLn(value) * qLn(exponent) >= qLn(qPow(2.0, 64)))
+ throw ReParserException(QObject::tr("number overflow while power operation"));
+ for (int ii = 1; ii < (int) exponent; ii++)
+ value = value * fac;
+ }
+ product *= value;
+ if (isNeg)
+ product = -product;
+ }
+ m_result += product;
+ }
+
+ } catch (ReParserException& e){
+ m_message = e.m_message;
+ }
+}
+
+/**
+ * Constructor.
+ *
+ * @param expr an expression, e.g. "10*1024kByte+5MiByte"
+ */
+ReSizeParser::ReSizeParser(const QString& expr) :
+ ReUnitParser(expr, "byte:1;kbyte:1000;kibyte:1024;"
+ "mbyte:1000000;mibyte:1048576;"
+ "gbyte:1000000000;gibyte:1073741824;"
+ "tbyte:1000000000000;tibyte:1099511627776"){
+}
+/**
+ * Constructor.
+ *
+ * @param expr an expression, e.g. "3*3days-5min+3weeks"
+ */
+ReDateTimeParser::ReDateTimeParser(const QString& expr) :
+ ReUnitParser(expr, "minutes:60;hours:3600;days:86400;weeks:604800"){
+}
--- /dev/null
+/*
+ * ReQtring.hpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+#ifndef RPLQSTRING_HPP
+#define RPLQSTRING_HPP
+
+class ReQStringUtil {
+public:
+ static int lengthOfUInt64(const ReString& text, int start = 0,
+ int radix = 10, uint64_t* value = NULL);
+ static int lengthOfUInt(const ReString& text, int start, int radix,
+ uint* pValue);
+ static int lengthOfReal(const ReString& text, int start = 0, qreal* value =
+ NULL);
+ /**
+ * @brief Returns the value of a hexadecimal digit.
+ *
+ * @param digit a (unicode) character
+ * @return -1: not a hexadecimal digit<br>
+ * otherwise: the value, e.g. 10 for 'a'
+ */
+ inline static int valueOfHexDigit(int digit){
+ return digit >= '0' && digit <= '9' ? digit - '0' :
+ digit >= 'A' && digit <= 'F' ? digit - 'A' + 10 :
+ digit >= 'a' && digit <= 'f' ? digit - 'a' + 10 : -1;
+ }
+ static char* utf8(const ReString& source, char buffer[], size_t bufferSize);
+};
+
+class ReUnitParser {
+public:
+ ReUnitParser(const QString& expr, const char* unitList);
+public:
+ bool isValid() const;
+ const QString& errorMessage() const;
+ int64_t asInt64(int64_t defaultValue = -1ll);
+ int asInt(int defaultValue = -1);
+ real_t asReal(real_t defaultValue = -1.0);
+private:
+ void parse();
+ uint64_t valueOf(const QString& value) const;
+private:
+ int64_t m_result;
+ QString m_expr;
+ QString m_message;
+ const char* m_unitList;
+};
+
+class ReSizeParser : public ReUnitParser {
+public:
+ ReSizeParser(const QString& expr);
+};
+
+class ReDateTimeParser : public ReUnitParser {
+public:
+ ReDateTimeParser(const QString& expr);
+};
+
+#endif // RPLQSTRING_HPP
+++ /dev/null
-/*
- * ReQtring.hpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-#ifndef RPLQSTRING_HPP
-#define RPLQSTRING_HPP
-
-class ReQString {
-public:
- static int lengthOfUInt64(const ReString& text, int start = 0,
- int radix = 10, quint64* value = NULL);
- static int lengthOfUInt(const ReString& text, int start, int radix,
- uint* pValue);
- static int lengthOfReal(const ReString& text, int start = 0, qreal* value =
- NULL);
- /**
- * @brief Returns the value of a hexadecimal digit.
- *
- * @param digit a (unicode) character
- * @return -1: not a hexadecimal digit<br>
- * otherwise: the value, e.g. 10 for 'a'
- */
- inline static int valueOfHexDigit(int digit){
- return digit >= '0' && digit <= '9' ? digit - '0' :
- digit >= 'A' && digit <= 'F' ? digit - 'A' + 10 :
- digit >= 'a' && digit <= 'f' ? digit - 'a' + 10 : -1;
- }
- static char* utf8(const ReString& source, char buffer[], size_t bufferSize);
-};
-
-#endif // RPLQSTRING_HPP
/*
* ReTerminator.hpp
- *
+ *
* License: Public Domain
* You can use and modify this file without any restriction.
* Do what you want.
/*
* ReTest.cpp
- *
+ *
* License: Public Domain
* You can use and modify this file without any restriction.
* Do what you want.
m_logger.buildStandardAppender(getTempDir("rpltest"));
log(QByteArray("Start of ") + m_name);
m_memoryLogger.addAppender(&m_memoryAppender);
- try{
- run();
- } catch (ReException e){
- error("unexpected RplException: %s", e.getMessage().constData());
- } catch (...){
- error("unknown Exception");
- }
+}
+void ReTest::doIt(){
+ try{
+ run();
+ } catch (ReException e){
+ error("unexpected RplException: %s", e.getMessage().constData());
+ } catch (...){
+ error("unknown Exception");
+ }
- if (m_errors > 0){
- error("Unit %s has %d error(s)", m_name.data(), m_errors);
- // error() increments, we decrement:
- m_errors--;
- }
+ if (m_errors > 0){
+ error("Unit %s has %d error(s)", m_name.data(), m_errors);
+ // error() increments, we decrement:
+ m_errors--;
+ }
}
/**
/*
* ReTest.hpp
- *
+ *
* License: Public Domain
* You can use and modify this file without any restriction.
* Do what you want.
ReTest(const ReTest& source);
// Prohibits assignment operator: no implementation!
ReTest& operator =(const ReTest& source);
+protected:
+ void doIt();
public:
bool assertEquals(int expected, int current, const char* file, int lineNo);
bool assertEquals(int64_t expected, int64_t current, const char* file,
* You also can use this license: http://www.wtfpl.net
* The latest sources: https://github.com/republib
*/
-#ifndef RECORE_HPP
-#define RECORE_HPP
+#ifndef REBASE_HPP
+#define REBASE_HPP
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
-#include <QAbstractSocket>
-#include <QTcpSocket>
-#include <QTcpServer>
#include <QThread>
#include <QIODevice>
#include <QTextStream>
#include <QMutex>
#include <QRegularExpression>
#include <QtCore/qmath.h>
-
+#include <QTranslator>
typedef unsigned char uint8_t;
//typedef qint64 int64_t;
typedef quint64 uint64_t;
#include "base/ReException.hpp"
#include "base/ReContainer.hpp"
#include "base/ReStringUtil.hpp"
-#include "base/ReQtring.hpp"
+#include "ReQStringUtil.hpp"
#include "base/ReConfigurator.hpp"
#include "base/ReConfig.hpp"
#include "base/ReTerminator.hpp"
#include "base/ReTest.hpp"
-#endif // RECORE_HPP
+#endif // REBASE_HPP
/*
* testrplexample.cpp
- *
+ *
* License: Public Domain
* You can use and modify this file without any restriction.
* Do what you want.
*/
include "project.hpp"
-#include "base/base.hpp"
+#include "base/rebase.hpp"
// Code to test:
int add(int a, int b){
return a+b;
--- /dev/null
+/*
+ * allTests.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use the license from http://www.wtfpl.net/.
+ * The latest sources: https://github.com/republib
+ */
+#include "base/rebase.hpp"
+#include "math/remath.hpp"
+#include "net/renet.hpp"
+//#include "os/reos.hpp"
+
+static bool s_allTest = true;
+
+static void testBase(){
+ void testReByteStorage();
+ void testReCharPtrMap();
+ void testReConfig();
+ void testReContainer();
+ void testReException();
+ void testReQStringUtil();
+ void testReStringUtil();
+ void testReWriter();
+
+ testReQStringUtil();
+ if (s_allTest){
+ testReByteStorage();
+ testReCharPtrMap();
+ testReConfig();
+ testReContainer();
+ testReException();
+ testReQStringUtil();
+ testReStringUtil();
+ testReWriter();
+ }
+}
+static void testMath(){
+
+}
+static void testExpr(){
+ extern void testReMFParser();
+ extern void testRplBenchmark();
+ extern void testReVM();
+ extern void testReSource();
+ extern void testReLexer();
+ extern void testReMFParser();
+ extern void testReASTree();
+ extern void testReVM();
+
+ //testRplBenchmark();
+ if (s_allTest){
+ testReVM();
+ testReSource();
+ testReLexer();
+ testReMFParser();
+ testReASTree();
+ testReVM();
+ }
+}
+static void testNet(){
+
+}
+static void testOs(){
+
+}
+void allTests(){
+ testBase();
+ if (s_allTest){
+ testBase();
+ testMath();
+ testExpr();
+ testNet();
+ testOs();
+ }
+}
+
+
+
--- /dev/null
+/*
+ * rplastree_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+/** @file
+ * @brief Unit test of the abstract syntax tree.
+ */
+
+
+#include "base/rebase.hpp"
+#include "expr/reexpr.hpp"
+
+class TestReASTree : public ReTest{
+private:
+ ReSource m_source;
+ ReStringReader m_reader;
+ ReStringSourceUnit m_unit;
+ ReASTree m_tree;
+public:
+ TestReASTree() :
+ ReTest("ReASTree"),
+ m_source(),
+ m_reader(m_source),
+ m_unit("<main>", "", &m_reader),
+ m_tree()
+ {}
+public:
+ void testReASException() {
+ try{
+ m_reader.addSource("<main>", "12");
+ m_source.addReader(&m_reader);
+ m_source.addSourceUnit(m_reader.currentSourceUnit());
+ const ReSourcePosition* pos = m_source.newPosition(2);
+ throw ReASException(pos, "simple string: %s", "Hi");
+ checkF(true);
+ } catch (ReASException exc){
+ checkEqu("<main>:0:2: simple string: Hi", exc.getMessage().constData());
+ }
+ }
+ void testReASVariant(){
+ ReASVariant val1;
+ val1.setFloat(2.5E-2);
+ checkEqu(2.5E-2, val1.asFloat());
+ ReASVariant val2(val1);
+ checkEqu(2.5E-2, val2.asFloat());
+
+ val1.setInt(4321);
+ checkEqu(4321, val1.asInt());
+ val2 = val1;
+ checkEqu(4321, val2.asInt());
+
+ val1.setBool(false);
+ checkF(val1.asBool());
+ val2 = val1;
+ checkF(val2.asBool());
+
+ val1.setBool(true);
+ checkT(val1.asBool());
+ val2 = val1;
+ checkT(val2.asBool());
+
+ val1.setString("High noon!");
+ checkEqu("High noon!", *val1.asString());
+ val2 = val1;
+ val1.setString("Bye");
+ checkEqu("High noon!", *val2.asString());
+ ReASVariant val3(val1);
+ checkEqu("Bye", *val3.asString());
+ }
+ void testReASConstant(){
+ ReASConstant constant;
+ //constant.value().setString("Jonny");
+ ReASVariant value;
+ //constant.calc(value);
+ //checkEqu("Jonny", *value.asString());
+ }
+ void testReASNamedValue(){
+ ReASNamedValue value(NULL, m_tree.symbolSpaces()[0], "gugo",
+ ReASNamedValue::A_GLOBAL);
+ checkEqu("gugo", value.name());
+ }
+ virtual void run() {
+ testReASNamedValue();
+ testReASConstant();
+ testReASException();
+ testReASVariant();
+ }
+};
+void testReASTree() {
+ TestReASTree test;
+}
+
+
+
+
+
+
--- /dev/null
+/*
+ * rplbench.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+/** @file
+ * @brief Unit test of the abstract syntax tree.
+ */
+
+
+#include "base/rebase.hpp"
+#include "expr/reexpr.hpp"
+
+class TestRplBenchmark : public ReTest{
+private:
+ const char* m_filename;
+ ReSource m_source;
+ ReFileReader m_reader;
+ ReASTree m_tree;
+public:
+ TestRplBenchmark() :
+ ReTest("RplBenchmark"),
+ m_filename("/home/ws/qt/rplqt/bench/mfbench.mf"),
+ m_source(),
+ m_reader(m_source),
+ m_tree()
+ {
+ m_source.addReader(&m_reader);
+ m_reader.addSource(m_filename);
+ }
+public:
+ void benchmark() {
+ time_t start = time(NULL);
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ time_t end = time(NULL);
+ printf("compilation: %d sec\n", int(end - start));
+ }
+ virtual void run() {
+ try{
+ ReFileSourceUnit* unit = dynamic_cast<ReFileSourceUnit*>
+ (m_reader.currentSourceUnit());
+ if (unit != NULL && ! unit->isOpen())
+ throw ReException("file not found: %s", m_filename);
+ benchmark();
+ } catch(ReException ex){
+ printf("%s\n", ex.getMessage().constData());
+ }
+ }
+};
+void testRplBenchmark() {
+ TestRplBenchmark test;
+ test.run();
+}
+
+
+
--- /dev/null
+/*
+ * rplbytestorage_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+/** @file
+ * @brief Unit test of the byte and C string storage.
+ */
+
+#include "base/rebase.hpp"
+
+class TestReByteStorage : public ReTest{
+public:
+ TestReByteStorage() :
+ ReTest("ReByteStorage")
+ { doIt(); }
+private:
+ void testChars(){
+ ReByteStorage store(100);
+ char* s1 = store.allocateChars(4);
+ memcpy((void*) s1, "123", 4);
+ const char* s2 = store.allocateChars("abc");
+ const char* s3 = store.allocateChars("defghij", 3);
+ checkEqu(s1, "123");
+ checkEqu(s2, "abc");
+ checkEqu(s3, "def");
+ const char* ptr = s1 + 4;
+ checkT(ptr == s2);
+ ptr += 4;
+ checkT(ptr == s3);
+ }
+
+ void testBytes(){
+ ReByteStorage store(100);
+ uint8_t* s1 = store.allocateBytes(4);
+ memcpy((void*) s1, "1234", 4);
+ uint8_t* s2 = store.allocateBytes((void*) "abcd", 4);
+ uint8_t* s3 = store.allocateBytes((void*) "efghij", 4);
+ uint8_t* s4 = store.allocateZeros(4);
+
+ checkEqu("1234abcdefgh", (const char*) s1);
+ uint8_t* ptr = s1 + 4;
+ checkT(ptr == s2);
+ ptr += 4;
+ checkT(ptr == s3);
+ ptr += 4;
+ checkT(ptr == s4);
+ for (int ii = 0; ii < 4; ii++)
+ checkEqu(0, (int) s4[ii]);
+ }
+ void testBufferChange(){
+ ReByteStorage store(10);
+ char buffer[2];
+ buffer[1] = '\0';
+ for (int ii = 0; ii < 10000; ii++){
+ buffer[1] = 'A' + ii % 26;
+ store.allocateBytes(buffer, 1);
+ }
+ int a = 1;
+ }
+
+public:
+ virtual void run() {
+ testBufferChange();
+ testChars();
+ testBytes();
+ }
+};
+void testReByteStorage() {
+ TestReByteStorage test;
+}
+
+
--- /dev/null
+/*
+ * rplcharptrmap_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+#include "base/rebase.hpp"
+
+class TestReCharPtrMap : public ReTest{
+public:
+ TestReCharPtrMap() :
+ ReTest("ReCharPtrMap")
+ {
+ doIt();
+ }
+protected:
+ void testBasic(){
+ ReCharPtrMap<const char*> map;
+ map["x"] = "x1";
+ checkT(map.contains("x"));
+ checkF(map.contains("y"));
+ checkEqu("x1", map["x"]);
+ }
+public:
+ virtual void run(void) {
+ testBasic();
+ }
+};
+void testReCharPtrMap() {
+ TestReCharPtrMap test;
+}
public:
TestReConfig() :
ReTest("ReConfig") {
+ doIt();
}
public:
/*
* cuReContainer.cpp
- *
+ *
* License: Public Domain
* You can use and modify this file without any restriction.
* Do what you want.
/**
* @brief Unit test for <code>ReContainer</code>
*/
-class TestRplContainer : public ReTest {
+class TestReContainer : public ReTest {
public:
- TestRplContainer() : ReTest("RplContainer") {}
+ TestReContainer() : ReTest("RplContainer") { doIt(); }
public:
void testBasic() {
}
};
-void testRplContainer() {
- TestRplContainer test;
+void testReContainer() {
+ TestReContainer test;
}
/*
* cuReEnigma.cpp
- *
+ *
* License: Public Domain
* You can use and modify this file without any restriction.
* Do what you want.
* The latest sources: https://github.com/republib
*/
#include "base/rebase.hpp"
+#include "math/remath.hpp"
/**
* @brief Unit test for <code>ReEnigma</code>.
*/
class TestReEnigma : public ReTest {
public:
- TestReEnigma() : ReTest("ReEnigma") {}
+ TestReEnigma() : ReTest("ReEnigma") { doIt(); }
public:
void testOneCharset(const char* value, const char* charSet,
"850592651836811261879625929");
}
- virtual void doIt() {
+ virtual void run() {
testBytes();
testCharSet();
}
void testReEnigma() {
TestReEnigma test;
- test.run();
}
--- /dev/null
+/*
+ * rplexception_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+#include "base/rebase.hpp"
+
+/** @file
+ * @brief Unit test of the basic exceptions.
+ */
+
+class TestReException : public ReTest{
+public:
+ TestReException() : ReTest("RplException") { doIt(); }
+
+public:
+ void testBasic() {
+ try{
+ throw ReException("simple");
+ checkF(true);
+ } catch (ReException exc){
+ checkEqu("simple", exc.getMessage().constData());
+ }
+ try{
+ throw ReException("String: %s and int %d", "Hi", -333);
+ checkF(true);
+ } catch (ReException exc){
+ checkEqu("String: Hi and int -333", exc.getMessage().constData());
+ }
+ try{
+ throw ReException(LOG_INFO, 1234, &m_memoryLogger,
+ "String: %s and int %d", "Hi", -333);
+ checkF(true);
+ } catch (ReException exc){
+ checkT(logContains("^ .*\\(1234\\): String: Hi and int -333"));
+ }
+ log("ok");
+ }
+ virtual void run() {
+ testBasic();
+ }
+};
+void testReException() {
+ TestReException test;
+}
+
+
+
--- /dev/null
+/*
+ * rpllexer_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+/** @file
+ * @brief Unit test of the syntax symbol extractor.
+ */
+
+#include "base/rebase.hpp"
+#include "expr/reexpr.hpp"
+
+class TestRplLexer : public ReTest, public ReToken{
+public:
+ TestRplLexer() :
+ ReTest("ReLexer"),
+ ReToken(TOKEN_ID)
+ {}
+
+public:
+ void testRplToken(){
+ // test constructor values:
+ checkEqu(TOKEN_ID, tokenType());
+ checkEqu(0, m_value.m_id);
+ checkT(m_string.isEmpty());
+ checkT(m_printableString.isEmpty());
+
+ m_value.m_id = 7422;
+ checkEqu(7422, ReToken::id());
+ m_string = "Wow!";
+ checkEqu("Wow!", ReToken::toString());
+ m_printableString = "GooGoo";
+ checkEqu("GooGoo", rawString());
+ m_tokenType = TOKEN_NUMBER;
+ checkEqu(TOKEN_NUMBER, tokenType());
+
+ clear();
+ checkEqu(TOKEN_UNDEF, tokenType());
+ checkEqu(0, m_value.m_id);
+ checkT(m_string.isEmpty());
+ checkT(m_printableString.isEmpty());
+
+ m_value.m_integer = 773322;
+ checkEqu(773322, asInteger());
+ m_value.m_real = 0.25;
+ checkEqu(0.25, asReal());
+ }
+
+ ReToken* checkToken(ReToken* token, RplTokenType type, int id = 0,
+ const char* string = NULL){
+ checkEqu(type, token->tokenType());
+ if (id != 0)
+ checkEqu(id, token->id());
+ if (string != NULL)
+ checkEqu(string, token->toString());
+ return token;
+ }
+ enum { KEY_UNDEF, KEY_IF, KEY_THEN, KEY_ELSE, KEY_FI
+ };
+# define KEYWORDS "if then else fi"
+ enum { OP_UNDEF, OP_PLUS, OP_TIMES, OP_DIV, OP_GT,
+ OP_LT, OP_GE, OP_LE, OP_EQ, OP_ASSIGN, OP_PLUS_ASSIGN, OP_DIV_ASSIGN,
+ OP_TIMES_ASSIGN
+ };
+# define OPERATORS "+\n* /\n> < >= <= ==\n= += /= *="
+ enum { COMMENT_UNDEF, COMMENT_1, COMMENT_MULTILINE, COMMENT_2
+ };
+# define COMMENTS "/* */ // \n"
+ void testSpace(){
+ ReSource source;
+ ReStringReader reader(source);
+# define BLANKS1 "\t\t \n"
+# define BLANKS2 " \n"
+ reader.addSource("<main>", BLANKS1 BLANKS2);
+ source.addReader(&reader);
+ ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
+ "A-Za-z_",
+ "A-Za-z0-9_",
+ ReLexer::NUMTYPE_DECIMAL,
+ ReLexer::SF_TICK, ReLexer::STORE_ALL);
+ checkToken(lex.nextToken(), TOKEN_SPACE, 0, BLANKS1);
+ checkToken(lex.nextToken(), TOKEN_SPACE, 0, BLANKS2);
+ }
+ void testNumeric(){
+ ReSource source;
+ ReStringReader reader(source);
+ const char* blanks = "321 0x73 7.8e+5";
+ reader.addSource("<main>", blanks);
+ source.addReader(&reader);
+ ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
+ "A-Za-z_",
+ "A-Za-z0-9_",
+ ReLexer::NUMTYPE_ALL,
+ ReLexer::SF_TICK, ReLexer::STORE_ALL);
+ ReToken* token = checkToken(lex.nextToken(), TOKEN_NUMBER);
+ checkEqu(321, token->asInteger());
+ token = checkToken(lex.nextNonSpaceToken(), TOKEN_NUMBER);
+ checkEqu(0x73, token->asInteger());
+ token = checkToken(lex.nextNonSpaceToken(), TOKEN_REAL);
+ checkEqu(7.8e+5, token->asReal());
+ }
+
+ void testOperators(){
+ ReSource source;
+ ReStringReader reader(source);
+ const char* ops = "<< < <<< <= == = ( ) [ ]";
+ reader.addSource("<main>", ops);
+ source.addReader(&reader);
+ enum { UNDEF, SHIFT, LT, SHIFT2, LE, EQ, ASSIGN,
+ LPARENT, RPARENT, LBRACKET, RBRACKET };
+ ReLexer lex(&source, KEYWORDS, ops, "=", COMMENTS,
+ "A-Za-z_",
+ "A-Za-z0-9_",
+ ReLexer::NUMTYPE_ALL,
+ ReLexer::SF_TICK, ReLexer::STORE_ALL);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, SHIFT);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LT);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, SHIFT2);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LE);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, EQ);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, ASSIGN);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LPARENT);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, RPARENT);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LBRACKET);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, RBRACKET);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_END_OF_SOURCE);
+ reader.addSource("<buffer2>", "(([[");
+ lex.startUnit("<buffer2>");
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LPARENT);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LPARENT);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LBRACKET);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LBRACKET);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_END_OF_SOURCE);
+ }
+
+ void testComments(){
+ ReSource source;
+ ReStringReader reader(source);
+
+ reader.addSource("<main>", "/**/9//\n8/***/7// wow\n/*\n*\n*\n**/");
+ source.addReader(&reader);
+
+ enum { COMMENT_UNDEF, COMMENT_MULTILINE, COMMENT_1
+ };
+ ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
+ "A-Za-z_",
+ "A-Za-z0-9_",
+ ReLexer::NUMTYPE_ALL,
+ ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
+ checkToken(lex.nextToken(), TOKEN_COMMENT_START, COMMENT_MULTILINE,
+ "/**/");
+ checkToken(lex.nextToken(), TOKEN_NUMBER);
+ checkToken(lex.nextToken(), TOKEN_COMMENT_START, COMMENT_1,
+ "//\n");
+ checkToken(lex.nextToken(), TOKEN_NUMBER);
+ checkToken(lex.nextToken(), TOKEN_COMMENT_START, COMMENT_MULTILINE,
+ "/***/");
+ checkToken(lex.nextToken(), TOKEN_NUMBER);
+ checkToken(lex.nextToken(), TOKEN_COMMENT_START, COMMENT_1,
+ "// wow\n");
+ checkToken(lex.nextToken(), TOKEN_COMMENT_START, COMMENT_MULTILINE,
+ "/*\n*\n*\n**/");
+ }
+ void testStrings(){
+ ReSource source;
+ ReStringReader reader(source);
+
+ reader.addSource("<main>", "\"abc\\t\\r\\n\\a\\v\"'1\\x9Z\\x21A\\X9'");
+ source.addReader(&reader);
+
+ ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
+ "A-Za-z_",
+ "A-Za-z0-9_",
+ ReLexer::NUMTYPE_ALL,
+ ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
+ checkToken(lex.nextToken(), TOKEN_STRING, '"', "abc\t\r\n\a\v");
+ checkToken(lex.nextToken(), TOKEN_STRING, '\'', "1\tZ!A\t");
+ }
+ void testKeywords(){
+ ReSource source;
+ ReStringReader reader(source);
+
+ reader.addSource("<main>", "if\n\tthen else\nfi");
+ source.addReader(&reader);
+
+ ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
+ "A-Za-z_",
+ "A-Za-z0-9_",
+ ReLexer::NUMTYPE_ALL,
+ ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
+ checkToken(lex.nextToken(), TOKEN_KEYWORD, KEY_IF);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_KEYWORD, KEY_THEN);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_KEYWORD, KEY_ELSE);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_KEYWORD, KEY_FI);
+ checkToken(lex.nextNonSpaceToken(), TOKEN_END_OF_SOURCE);
+ }
+
+ void testIds(){
+ ReSource source;
+ ReStringReader reader(source);
+
+ reader.addSource("<main>", "i\n\tifs\n"
+ "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ source.addReader(&reader);
+
+ ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
+ "A-Za-z_",
+ "A-Za-z0-9_",
+ ReLexer::NUMTYPE_ALL,
+ ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
+ checkToken(lex.nextToken(), TOKEN_ID, 0, "i");
+ checkToken(lex.nextNonSpaceToken(), TOKEN_ID, 0,
+ "ifs");
+ checkToken(lex.nextNonSpaceToken(), TOKEN_ID, 0,
+ "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ }
+
+ void testBasic(){
+ ReSource source;
+ ReStringReader reader(source);
+ source.addReader(&reader);
+ reader.addSource("<main>", "if i>1 then i=1+2*_x9 fi");
+ ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
+ "A-Za-z_",
+ "A-Za-z0-9_",
+ ReLexer::NUMTYPE_ALL,
+ ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
+ ReToken* token;
+ checkToken(lex.nextToken(), TOKEN_KEYWORD, KEY_IF);
+ checkToken(lex.nextToken(), TOKEN_SPACE, 0);
+ checkToken(lex.nextToken(), TOKEN_ID, 0, "i");
+ checkToken(lex.nextToken(), TOKEN_OPERATOR, OP_GT);
+ token = checkToken(lex.nextToken(), TOKEN_NUMBER);
+ checkEqu(1, token->asInteger());
+ checkToken(lex.nextToken(), TOKEN_SPACE, 0);
+ checkToken(lex.nextToken(), TOKEN_KEYWORD, KEY_THEN);
+ checkToken(lex.nextToken(), TOKEN_SPACE, 0);
+
+ }
+ void testPrio(){
+ ReSource source;
+ ReStringReader reader(source);
+ source.addReader(&reader);
+ reader.addSource("x", "");
+ enum { O_UNDEF, O_ASSIGN, O_PLUS, O_MINUS, O_TIMES, O_DIV
+ };
+ ReLexer lex(&source, KEYWORDS,
+ "=\n+ -\n* /", "=",
+ COMMENTS,
+ "A-Za-z_",
+ "A-Za-z0-9_",
+ ReLexer::NUMTYPE_ALL,
+ ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
+ checkT(lex.prioOfOp(O_ASSIGN) < lex.prioOfOp(O_PLUS));
+ checkEqu(lex.prioOfOp(O_PLUS), lex.prioOfOp(O_MINUS));
+ checkT(lex.prioOfOp(O_MINUS) < lex.prioOfOp(O_TIMES));
+ checkEqu(lex.prioOfOp(O_TIMES), lex.prioOfOp(O_DIV));
+ }
+
+ virtual void run(void) {
+ testPrio();
+ testBasic();
+ testIds();
+ testKeywords();
+ testComments();
+ testStrings();
+ testOperators();
+ testNumeric();
+ testSpace();
+ testRplToken();
+ }
+};
+void testReLexer() {
+ TestRplLexer test;
+ test.run();
+}
--- /dev/null
+/*
+ * rplmfparser_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+/** @file
+ * @brief Unit test of the parser for the language "MF".
+ */
+
+#include "base/rebase.hpp"
+#include "expr/reexpr.hpp"
+
+class TestReMFParser : public ReTest{
+private:
+ ReSource m_source;
+ ReASTree m_tree;
+ ReStringReader m_reader;
+ ReFileReader m_fileReader;
+ QByteArray m_currentSource;
+public:
+ TestReMFParser() :
+ ReTest("ReMFParser"),
+ m_source(),
+ m_tree(),
+ m_reader(m_source),
+ m_fileReader(m_source)
+ {
+ m_source.addReader(&m_reader);
+ doIt();
+ }
+protected:
+ void setSource(const char* content){
+ ReASItem::reset();
+ m_currentSource = content;
+ m_tree.clear();
+ m_source.clear();
+ m_reader.clear();
+ m_reader.addSource("<test>", content);
+ m_source.addReader(&m_reader);
+ m_source.addSourceUnit(m_reader.currentSourceUnit());
+ }
+ void setFileSource(const char* filename){
+ ReASItem::reset();
+ m_currentSource = ReStringUtil::read(filename);
+ m_tree.clear();
+ m_source.clear();
+ m_fileReader.clear();
+ m_fileReader.addSource(filename);
+ m_source.addReader(&m_fileReader);
+ m_source.addSourceUnit(m_fileReader.currentSourceUnit());
+ }
+
+private:
+ void checkAST(const char* fileExpected, int lineNo){
+ QByteArray fnExpected = "test";
+ fnExpected += QDir::separator().toLatin1();
+ fnExpected += "mfparser";
+ fnExpected += (char) QDir::separator().toLatin1();
+ fnExpected += fileExpected;
+ QByteArray fnCurrent = getTempFile(fileExpected, "rplmfparser");
+ m_tree.dump(fnCurrent, ReASTree::DMP_NO_GLOBALS, m_currentSource);
+ assertEqualFiles(fnExpected.constData(), fnCurrent.constData(),
+ __FILE__, lineNo);
+ }
+
+public:
+ void fileClassTest(){
+ setFileSource("test/rplmfparser/string1.mf");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("string1.txt", __LINE__);
+ }
+
+ void baseTest(){
+ setSource("2+3*4");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("baseTest.txt", __LINE__);
+ }
+
+ void varDefTest(){
+ setSource("const lazy Str s = 'Hi';\nconst List l;\nInt i = 3;");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("varDefTest.txt", __LINE__);
+ }
+
+ void ifTest(){
+ setSource("Int a;\nInt b;\na = b = 2;\nif 11 < 12\nthen a = 13 * 14\nelse a = 15 / 16\nfi");
+ // setSource("Int a; if 11 < 12 then a = 13 * 14 else a = 15 / 16 fi");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("ifTest1.txt", __LINE__);
+ setSource("Str x;\nif 7 < 6\nthen x = '123';\nfi");
+ parser.parse();
+ checkAST("ifTest2.txt", __LINE__);
+ }
+ void whileTest(){
+ setSource("Int a = 20;\nwhile 3 < 5 do\n a = 7\nod");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("whileTest.txt", __LINE__);
+ }
+
+ void repeatTest(){
+ setSource("Int a;\nrepeat\na++;\nuntil a != 2 * 3;");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("repeatTest.txt", __LINE__);
+ }
+ void forCTest(){
+ setSource("Int a;\nfor b from 10 to 1 step -2 do\na += 1;\nod");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("forC1.txt", __LINE__);
+ setSource("Int a; for to 10 do a += 1 od");
+ parser.parse();
+ checkAST("forC2.txt", __LINE__);
+ }
+ void opTest(){
+ checkEqu(25, ReMFParser::O_QUESTION);
+ checkEqu(37, ReMFParser::O_RSHIFT2);
+ checkEqu(41, ReMFParser::O_DEC);
+ checkEqu(48, ReMFParser::O_RBRACE);
+ setSource("Int a = 1;\nInt b = 100;\n--a;\nb++;\na--*++b**(8-3);\na=b=(a+(b-2)*3)");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("opTest1.txt", __LINE__);
+ }
+ void forItTest(){
+ setSource("Map a;\nfor x in a do\na += 1;\nod");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("forIt1.txt", __LINE__);
+ }
+ void listTest(){
+ ReMFParser parser(m_source, m_tree);
+ setSource("List b = [];");
+ parser.parse();
+ checkAST("list1.txt", __LINE__);
+ setSource("List a = [2+3, 3.14, 7, 'hi', a]; List b = [];");
+ parser.parse();
+ checkAST("list2.txt", __LINE__);
+ }
+ void mapTest(){
+ setSource("Map a = {};");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("map1.txt", __LINE__);
+ setSource("Map a = {'a': 2+3,'bcd':3.14,'ccc':7, 'hi':'world'};\nMap b = {};");
+ parser.parse();
+ checkAST("map2.txt", __LINE__);
+ }
+ void methodCallTest(){
+ //setSource("max(4,3.14);");
+ setSource("rand();\nsin(a);\nmax(1+2*3,4**(5-4));");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("methc1.txt", __LINE__);
+ }
+ void fieldTest(){
+ setSource("file.find('*.c')[0].name;\n[1,2,3].join(' ');\n3.14.trunc;");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("field1.txt", __LINE__);
+ }
+
+ void methodTest(){
+ setSource("func Float pi: 3.1415; endf func Str delim(): '/' endf;");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("meth1.txt", __LINE__);
+ setSource("func Int fac(const Int n):\n"
+ "Int rc; if rc <= 1 then rc = 1 else rc = n*fac(n-1) fi\n"
+ "rc endf");
+ parser.parse();
+ checkAST("meth2.txt", __LINE__);
+ setSource("func Int max(Int a, Int b):\n Int rc = a;\n"
+ "if a < b then rc = b; fi\nrc\n"
+ "endf\n"
+ "func Int max(const Int a, Int b, Int c):\n"
+ "max(a, max(b, c))\n"
+ "endf");
+ parser.parse();
+ checkAST("meth3.txt", __LINE__);
+ setSource("func Int max(const Int a, Int b, Int c):\n"
+ "func Int max(Int a, Int b):\n Int rc = a;\n"
+ "if a < b then rc = b; fi\nrc\n"
+ "endf\n"
+ "max(a, max(b, c))\n"
+ "endf");
+ parser.parse();
+ checkAST("meth4.txt", __LINE__);
+ }
+ void mainTest(){
+ setSource("Int a=2+3*4;\nfunc Void main():\na;\nendf");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ checkAST("main1.txt", __LINE__);
+ }
+
+ virtual void run(void) {
+ mainTest();
+ varDefTest();
+ repeatTest();
+ baseTest();
+ whileTest();
+ methodTest();
+ fieldTest();
+ methodCallTest();
+ mapTest();
+ forItTest();
+ forCTest();
+ listTest();
+ opTest();
+ fileClassTest();
+ }
+};
+void testReMFParser() {
+ TestReMFParser test;
+}
+
+
--- /dev/null
+/*
+ * rplmatrix_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+/** @file
+ * @brief Unit test of the matrices.
+ */
+
+#include "base/rebase.hpp"
+#include "math/remath.hpp"
+
+class TestRplMatrix : public ReTest{
+public:
+ TestRplMatrix() : ReTest("RplMatrix") { doIt(); }
+
+public:
+ void fillMatrix(RplMatrix& mx, MatVal offset = 0){
+ for(int row = 0; row < mx.getRows(); row++){
+ for (int col = 0; col < mx.getCols(); col++){
+ mx.set(row, col, 100.0*row + col + offset);
+ }
+ }
+ }
+ void checkMatrix(const RplMatrix& mx, MatVal offset = 0){
+ int count = 0;
+ for(int row = 0; row < mx.getRows(); row++){
+ for (int col = 0; col < mx.getCols(); col++){
+ checkEqu(100.0*row + col + offset, mx.get(row, col));
+ count++;
+ }
+ }
+ checkEqu(mx.getCols()*mx.getRows(), count);
+ }
+ void fillConst(RplMatrix& mx, MatVal value){
+ for(int row = 0; row < mx.getRows(); row++){
+ for (int col = 0; col < mx.getCols(); col++){
+ mx.set(row, col, value);
+ }
+ }
+ }
+ void checkConst(const RplMatrix& mx, MatVal value){
+ int count = 0;
+ for(int row = 0; row < mx.getRows(); row++){
+ for (int col = 0; col < mx.getCols(); col++){
+ checkEqu(value, mx.get(row, col));
+ count++;
+ }
+ }
+ checkEqu(mx.getCols()*mx.getRows(), count);
+ }
+
+ void testBasic() {
+ Tuple2 tuple(-2.0, 0.5);
+ checkEqu(-2.0, tuple.m_value1);
+ checkEqu(0.5, tuple.m_value2);
+ RplMatrix mat("mx");
+ try{
+ throw RplMatrixException(mat, "String: %s and int %d", "Hi", -333);
+ checkF(true);
+ } catch (RplMatrixException exc){
+ checkEqu("mx: String: Hi and int -333", exc.getMessage());
+ }
+ RplMatrix mat2;
+ try{
+ throw RplMatrixException(mat2, "String: %s and int %d", "Hi", -333);
+ checkF(true);
+ } catch (RplMatrixException exc){
+ checkEqu("String: Hi and int -333", exc.getMessage());
+ }
+ checkEqu("mx", mat.getName());
+ checkEqu("", mat2.getName());
+
+ RplMatrix m2x3(2, 3, "m2x3");
+ checkEqu("m2x3", m2x3.getName());
+ checkEqu(2, m2x3.getRows());
+ checkEqu(3, m2x3.getCols());
+ fillMatrix(m2x3);
+ checkMatrix(m2x3);
+
+ RplMatrix mxCopy(m2x3);
+ checkEqu("m2x3-copy", mxCopy.getName());
+ checkEqu(2, mxCopy.getRows());
+ checkEqu(3, mxCopy.getCols());
+ checkMatrix(mxCopy);
+
+ RplMatrix mxCopy2("mxCopy2");
+ mxCopy2 = m2x3;
+ checkEqu("mxCopy2", mxCopy2.getName());
+ checkEqu(2, mxCopy2.getRows());
+ checkEqu(3, mxCopy2.getCols());
+ checkMatrix(mxCopy2);
+ }
+ void testAddOperators(){
+ RplMatrix m1(3, 2, "m1");
+ fillMatrix(m1);
+ checkMatrix(m1);
+ RplMatrix m2(3, 2, "m2");
+ fillMatrix(m2, 42);
+ checkMatrix(m2, 42);
+ RplMatrix m3(3, 2, "m3");
+ fillMatrix(m3, -42);
+ checkMatrix(m3, -42);
+
+ m1 += 42;
+ checkMatrix(m1, 42);
+
+ checkT(m1 == m2);
+ checkF(m1 == m3);
+
+ m1 -= 42;
+ checkMatrix(m1);
+ m1 -= m1;
+ checkConst(m1, 0);
+
+ fillMatrix(m1);
+ m1 -= m3;
+ checkConst(m1, 42);
+ m1 += m2;
+ checkMatrix(m1, 42*2);
+ }
+ void testCompareOperators(){
+ RplMatrix m1(3, 2, "m1");
+ fillMatrix(m1);
+ checkMatrix(m1);
+ RplMatrix m2(3, 2, "m2");
+ fillMatrix(m2);
+
+ checkT(m1 == m2);
+ checkF(m1 != m2);
+ // modify each element, comparism must return false:
+ int row, col;
+ for (row = 0; row < m2.getRows(); row++)
+ for (col = 0; col < m2.getCols(); col++){
+ fillMatrix(m2);
+ m2.set(row, col, -1);
+ checkF(m1 == m2);
+ checkT(m1 != m2);
+ }
+
+ fillConst(m1, 42);
+ checkT(m1 == 42);
+ checkF(m1 == 43);
+ checkT(m1 != 43);
+ for (row = 0; row < m1.getRows(); row++)
+ for (col = 0; col < m1.getCols(); col++){
+ fillMatrix(m1, 42);
+ m1.set(row, col, -1);
+ checkF(m1 == 42);
+ checkT(m1 != 42);
+ }
+ }
+
+ void testCheckDefinition(){
+ RplMatrix m1(3, 2, "m1");
+ fillMatrix(m1);
+ checkMatrix(m1);
+ RplMatrix m2(3, 2, "m2");
+ fillMatrix(m2);
+
+ m1.checkDefinition(1, 1);
+ m1.checkDefinition(1000, 1000);
+ m1.checkDefinition(0, 0);
+ try {
+ m1.checkDefinition(-1, 1);
+ checkT(false);
+ } catch(RplMatrixException exc){
+ checkEqu("m1: row number negative: -1", exc.getMessage());
+ }
+ try {
+ m1.checkDefinition(1, -1);
+ checkT(false);
+ } catch(RplMatrixException exc){
+ checkEqu("m1: column number negative: -1", exc.getMessage());
+ }
+
+ }
+ void testCheck(){
+ RplMatrix m1(3, 2, "m1");
+ fillMatrix(m1);
+ checkMatrix(m1);
+
+ m1.check(0, 0);
+ m1.check(3-1, 2-1);
+ try {
+ m1.check(-1, 1);
+ checkT(false);
+ } catch(RplMatrixException exc){
+ checkEqu("m1: invalid row: -1 not in [0,3[", exc.getMessage());
+ }
+ try {
+ m1.check(3, 1);
+ checkT(false);
+ } catch(RplMatrixException exc){
+ checkEqu("m1: invalid row: 3 not in [0,3[", exc.getMessage());
+ }
+ try {
+ m1.check(1, -1);
+ checkT(false);
+ } catch(RplMatrixException exc){
+ checkEqu("m1: invalid column: -1 not in [0,2[", exc.getMessage());
+ }
+ try {
+ m1.check(1, 2);
+ checkT(false);
+ } catch(RplMatrixException exc){
+ checkEqu("m1: invalid column: 2 not in [0,2[", exc.getMessage());
+ }
+ }
+ void testCheckSameDimension(){
+ RplMatrix m1(3, 2, "m1");
+ RplMatrix m2(3, 2, "m2");
+
+ m1.checkSameDimension(m2);
+
+ m2.resize(2, 2);
+ try {
+ m1.checkSameDimension(m2);
+ checkT(false);
+ } catch(RplMatrixException exc){
+ checkEqu("m1: m2 has a different row count: 3 / 2", exc.getMessage());
+ }
+ m2.resize(3, 3);
+ try {
+ m1.checkSameDimension(m2);
+ checkT(false);
+ } catch(RplMatrixException exc){
+ checkEqu("m1: m2 has a different column count: 2 / 3", exc.getMessage());
+ }
+ }
+ void testResize(){
+ RplMatrix m1(3, 2, "m1");
+ fillMatrix(m1);
+ checkMatrix(m1);
+ RplMatrix m2(2, 4, "m2");
+ fillConst(m2, 0);
+ checkConst(m2, 0);
+
+ m1.resize(2, 4);
+ checkEqu(2, m1.getRows());
+ checkEqu(4, m1.getCols());
+ checkT(m1 == m2);
+ }
+
+ void testMinMax(){
+ RplMatrix m1(4, 5, "m1");
+ fillMatrix(m1);
+ checkMatrix(m1);
+ m1.set(0, 0, -98);
+ m1.set(3, 4, 9999);
+ Tuple2 miniMax = m1.minMax();
+ checkEqu(-98.0, miniMax.m_value1);
+ checkEqu(9999.0, miniMax.m_value2);
+
+ fillMatrix(m1);
+ checkMatrix(m1);
+ m1.set(1, 1, 7777);
+ m1.set(3, 4, -987);
+ miniMax = m1.minMax();
+ checkEqu(-987.0, miniMax.m_value1);
+ checkEqu(7777.0, miniMax.m_value2);
+ }
+
+ void testTranspose()
+ {
+ RplMatrix m1(1, 5, "m1");
+ fillMatrix(m1);
+ RplMatrix m2(m1.transpose());
+
+ checkEqu(5, m2.getRows());
+ checkEqu(1, m2.getCols());
+
+ int row, col;
+ col = 0;
+ for (row = 0; row < 5; row++){
+ checkEqu(qreal(col*100+row), m2.get(row, 0));
+ }
+
+ m1.resize(35, 73);
+ fillMatrix(m1);
+ m2 = m1.transpose();
+
+ checkEqu(73, m2.getRows());
+ checkEqu(35, m2.getCols());
+
+ int count = 0;
+ for (row = 0; row < m2.getRows(); row++){
+ for (col = 0; col < m2.getCols(); col++){
+ checkEqu(qreal(col*100+row), m2.get(row, col));
+ count++;
+ }
+ }
+ checkEqu(73*35, count);
+ }
+ void testToString(){
+ RplMatrix m1(1, 1, "m1");
+ m1.set(0, 0, 2.34);
+ checkEqu("[2.340000,\n]", m1.toString().constData());
+ checkEqu("jonny[2.34000 |]", m1.toString("jonny", "%.5f", "|", " ").constData());
+
+ m1.resize(2, 1);
+ m1.set(0, 0, 2.34);
+ m1.set(1, 0, 55.5);
+
+ checkEqu("[2.340000,\n55.500000,\n]", m1.toString().constData());
+ checkEqu("jonny[2.34000 |55.50000 |]", m1.toString("jonny", "%.5f", "|", " ").constData());
+ log("");
+ }
+ void testReadCsv(){
+ QByteArray fn = getTempFile("rplmatrixtest.csv");
+ const char* content;
+ RplMatrix m1(1,1,"m1");
+
+ fillMatrix(m1);
+ content = ",Port0,Port1,Port2\n"
+ "element1,5, -3E-99 , 0.5\n"
+ "element2,7,-22.3,44\n"
+ "\n"
+ "2 Elements, 3, Ports";
+ ReStringUtil::write(fn, content);
+ m1.readFromCvs(fn, 256);
+ checkEqu(2, m1.getRows());
+ checkEqu(3, m1.getCols());
+
+ checkEqu(5.0, m1.get(0, 0));
+ checkEqu(-3.0E-99, m1.get(0, 1));
+ checkEqu(0.5, m1.get(0, 2));
+
+ checkEqu(7.0, m1.get(1, 0));
+ checkEqu(-22.3, m1.get(1, 1));
+ checkEqu(44.0, m1.get(1, 2));
+
+ fillMatrix(m1);
+ content = "Port0,Port1,Port2\n"
+ "5, -3E-99 , 0.5\n";
+ ReStringUtil::write(fn, content);
+ m1.readFromCvs(fn, 256);
+ checkEqu(1, m1.getRows());
+ checkEqu(3, m1.getCols());
+ checkEqu(5.0, m1.get(0, 0));
+ checkEqu(-3.0E-99, m1.get(0, 1));
+ checkEqu(0.5, m1.get(0, 2));
+
+
+/*
+ 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);
+*/
+ }
+ virtual void run(void) {
+ testBasic();
+ testAddOperators();
+ testCompareOperators();
+ testCheckDefinition();
+ testCheck();
+ testCheckSameDimension();
+ testResize();
+ testMinMax();
+ testTranspose();
+ testToString();
+ testReadCsv();
+ }
+};
+void testRplMatrix() {
+ TestRplMatrix test;
+}
--- /dev/null
+/*
+ * rplqstring_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+/** @file
+ * @brief Unit test of the ReString tools.
+ */
+
+#include "base/rebase.hpp"
+
+class TestReQStringUtil : public ReTest {
+public:
+ TestReQStringUtil() :
+ ReTest("ReQStringUtil")
+ { doIt(); }
+
+public:
+ void testLengthOfUInt64(){
+ quint64 value = -3;
+ checkEqu(1, ReQStringUtil::lengthOfUInt64(ReString("0"), 0, 10, &value));
+ checkEqu(int64_t(0), value);
+ checkEqu(3, ReQStringUtil::lengthOfUInt64("x432", 1, 10, &value));
+ checkEqu(int64_t(432LL), value);
+ checkEqu(3, ReQStringUtil::lengthOfUInt64("x432 x", 1, 10, &value));
+ checkEqu(int64_t(432LL), value);
+ checkEqu(3, ReQStringUtil::lengthOfUInt64("x432fabc x", 1, 10, &value));
+ checkEqu(int64_t(432LL), value);
+ checkEqu(16, ReQStringUtil::lengthOfUInt64("a1234567890123567", 1, 10, &value));
+ checkEqu(int64_t(1234567890123567LL), value);
+ checkEqu(10, ReQStringUtil::lengthOfUInt64("x1234abcdef", 1, 16, &value));
+ checkEqu(int64_t(0x1234abcdefLL), value);
+ checkEqu(3, ReQStringUtil::lengthOfUInt64("432", 0, 8, &value));
+ checkEqu(int64_t(0432LL), value);
+ checkEqu(6, ReQStringUtil::lengthOfUInt64(" 765432 ", 1, 8, &value));
+ checkEqu(int64_t(0765432LL), value);
+
+ checkEqu(0, ReQStringUtil::lengthOfUInt64("1 ", 1, 8, &value));
+ checkEqu(0, ReQStringUtil::lengthOfUInt64("", 1, 8, &value));
+ }
+ void testLengthOfUInt(){
+ uint value = 3;
+ checkEqu(1, ReQStringUtil::lengthOfUInt(ReString("0"), 0, 10, &value));
+ checkEqu(0, value);
+ checkEqu(3, ReQStringUtil::lengthOfUInt("x432", 1, 10, &value));
+ checkEqu(432, value);
+ checkEqu(3, ReQStringUtil::lengthOfUInt("x432 x", 1, 10, &value));
+ checkEqu(432, value);
+ checkEqu(3, ReQStringUtil::lengthOfUInt("x432fabc x", 1, 10, &value));
+ checkEqu(432, value);
+ checkEqu(3, ReQStringUtil::lengthOfUInt("432", 0, 8, &value));
+ checkEqu(0432, value);
+ checkEqu(6, ReQStringUtil::lengthOfUInt(" 765432 ", 1, 8, &value));
+ checkEqu(0765432, value);
+
+ checkEqu(0, ReQStringUtil::lengthOfUInt("1 ", 1, 8, &value));
+ checkEqu(0, ReQStringUtil::lengthOfUInt("", 1, 8, &value));
+ }
+ void testLengthOfReal(){
+ qreal value;
+ checkEqu(4, ReQStringUtil::lengthOfReal(ReString("0.25"), 0, &value));
+ checkEqu(0.25, value);
+ checkEqu(3, ReQStringUtil::lengthOfReal(ReString("X.25"), 1, &value));
+ checkEqu(0.25, value);
+ checkEqu(1, ReQStringUtil::lengthOfReal(ReString(" 0"), 1, &value));
+ checkEqu(0.0, value);
+ checkEqu(17, ReQStringUtil::lengthOfReal(ReString("X12345678901234567"), 1, &value));
+ checkEqu(12345678901234567.0, value);
+ checkEqu(2, ReQStringUtil::lengthOfReal(ReString(".5"), 0, &value));
+ checkEqu(0.5, value);
+ checkEqu(5, ReQStringUtil::lengthOfReal(ReString("2.5e2x"), 0, &value));
+ checkEqu(250.0, value);
+ checkEqu(6, ReQStringUtil::lengthOfReal(ReString("2.5e+2"), 0, &value));
+ checkEqu(250.0, value);
+ checkEqu(7, ReQStringUtil::lengthOfReal(ReString("2.5E-33"), 0, &value));
+ checkEqu(2.5e-33, value);
+
+ checkEqu(3, ReQStringUtil::lengthOfReal(ReString("2.5E"), 0, &value));
+ checkEqu(2.5, value);
+ checkEqu(3, ReQStringUtil::lengthOfReal(ReString("2.5E+"), 0, &value));
+ checkEqu(2.5, value);
+ checkEqu(3, ReQStringUtil::lengthOfReal(ReString("2.5E-a"), 0, &value));
+ checkEqu(2.5, value);
+ }
+
+ void testValueOfHexDigit(){
+ checkEqu(0, ReQStringUtil::valueOfHexDigit('0'));
+ checkEqu(9, ReQStringUtil::valueOfHexDigit('9'));
+ checkEqu(10, ReQStringUtil::valueOfHexDigit('a'));
+ checkEqu(15, ReQStringUtil::valueOfHexDigit('f'));
+ checkEqu(10, ReQStringUtil::valueOfHexDigit('A'));
+ checkEqu(15, ReQStringUtil::valueOfHexDigit('F'));
+
+ checkEqu(-1, ReQStringUtil::valueOfHexDigit('0' - 1));
+ checkEqu(-1, ReQStringUtil::valueOfHexDigit('9' + 1));
+ checkEqu(-1, ReQStringUtil::valueOfHexDigit('A' - 1));
+ checkEqu(-1, ReQStringUtil::valueOfHexDigit('F' + 1));
+ checkEqu(-1, ReQStringUtil::valueOfHexDigit('a' - 1));
+ checkEqu(-1, ReQStringUtil::valueOfHexDigit('f' + 1));
+ }
+ void testUtf8(){
+ ReString name = "Heinz Müller";
+ char buffer[32];
+ checkEqu("Heinz Müller", ReQStringUtil::utf8(name, buffer, sizeof buffer));
+ memset(buffer, 'x', sizeof buffer);
+ checkEqu("Heinz", ReQStringUtil::utf8(name, buffer, (size_t) (5+1)));
+ checkEqu(buffer[6], 'x');
+ }
+
+ void testUnitParser(){
+ ReUnitParser parser("-1-2*3*4+2^3*4", NULL);
+ checkT(parser.isValid());
+ checkEqu(7, parser.asInt());
+ checkEqu(7LL, parser.asInt64());
+ checkEqu(7.0, parser.asReal());
+ }
+ void testSizeParser(){
+ ReSizeParser parser("2^3byte+2*1k+1m+1g+1t");
+ checkT(parser.isValid());
+ checkEqu(1001001002008LL, parser.asInt64());
+
+ ReSizeParser parser2("1ki+1mi+1gi+1ti");
+ checkT(parser2.isValid());
+ checkEqu(1100586419200ll, parser2.asInt64());
+ }
+ void testDateTimeParser(){
+ ReDateTimeParser parser("1+1min+1h+1day+1week");
+ checkT(parser.isValid());
+ checkEqu(694861, parser.asInt());
+ }
+
+ virtual void run(void) {
+ testUnitParser();
+ testSizeParser();
+ testDateTimeParser();
+ testUtf8();
+ testLengthOfUInt64();
+ testLengthOfUInt();
+ testLengthOfReal();
+ testValueOfHexDigit();
+ }
+};
+void testReQStringUtil() {
+ TestReQStringUtil test;
+}
+
--- /dev/null
+/*
+ * rplsource_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+/** @file
+ * @brief Unit test of the input media reader.
+ */
+
+#include "base/rebase.hpp"
+#include "expr/reexpr.hpp"
+
+class TestReSource : public ReTest{
+public:
+ TestReSource() : ReTest("TestReSource") { doIt(); }
+
+private:
+ QByteArray m_content1_1;
+ QByteArray m_content1_2;
+ QByteArray m_content2;
+ ReSource m_source;
+
+protected:
+ void init(){
+ m_content1_1 = "# test\nimport source2\n";
+ m_content1_2 = "a=1;\nveeeeeeeeery looooooooooooooong\n";
+ m_content2 = "x=2";
+ }
+
+ void testReStringSourceUnit(){
+ ReStringReader reader(m_source);
+ QByteArray content("a=1;\nveeeeeeeeery looooooooooooooong\n");
+ ReStringSourceUnit unit("test", content, &reader);
+ unit.setLineNo(144);
+ checkEqu(144, unit.lineNo());
+ checkEqu("test", unit.name());
+ }
+ void checkOne(int maxSize, ReReader& reader){
+ QByteArray total;
+ QByteArray buffer;
+ int lineNo = 0;
+ bool hasMore;
+ checkF(reader.openSourceUnit("unknownSource"));
+ checkT(reader.openSourceUnit("source1"));
+ while(reader.nextLine(maxSize, buffer, hasMore)){
+ lineNo++;
+ total += buffer;
+ buffer.clear();
+ while(hasMore && reader.fillBuffer(maxSize, buffer, hasMore)){
+ total += buffer;
+ buffer.clear();
+ }
+ bool isImport = total.endsWith("source2\n");
+ if (isImport){
+ reader.openSourceUnit("source2");
+ checkEqu("source2", reader.currentSourceUnit()->name());
+ while(reader.nextLine(maxSize, buffer, hasMore)){
+ lineNo++;
+ while(hasMore && reader.fillBuffer(maxSize, buffer, hasMore)){
+ total += buffer;
+ buffer.clear();
+ }
+ }
+ checkEqu("source1", reader.currentSourceUnit()->name());
+ }
+ }
+ checkEqu(5, lineNo);
+ checkEqu(m_content1_1 + m_content2 + m_content1_2, total);
+
+ }
+
+ void testReStringReader(){
+ ReStringReader reader(m_source);
+ reader.addSource("source1", m_content1_1 + m_content1_2);
+ reader.addSource("source2", m_content2);
+ ReSourceUnit* unit = reader.openSourceUnit("source1");
+ checkNN(unit);
+ checkEqu("source1", unit->name());
+ checkEqu(0, unit->lineNo());
+ checkOne(6, reader);
+ checkOne(100, reader);
+ reader.replaceSource("source2", "content2");
+
+ unit = reader.openSourceUnit("source2");
+ QByteArray buffer;
+ bool hasMore;
+ checkT(reader.nextLine(50, buffer, hasMore));
+ checkEqu("content2", buffer);
+ checkF(hasMore);
+ }
+
+public:
+ void run(void) {
+ init();
+ testReStringSourceUnit();
+ testReStringReader();
+ }
+};
+void testReSource() {
+ TestReSource test;
+}
+
+
+
--- /dev/null
+/*
+ * rplstring_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+/** @file
+ * @brief Unit test of the QByteArray tools.
+ */
+#include "base/rebase.hpp"
+/**
+ * @brief Unit test for <code>ReStringUtil</code>.
+ */
+class TestReStringUtil : public ReTest {
+public:
+ TestReStringUtil() : ReTest("ReStringUtil") { doIt(); }
+
+public:
+ void testCountChar(){
+ checkEqu(1, ReStringUtil::countChar("x", 'x'));
+ checkEqu(0, ReStringUtil::countChar("X", 'x'));
+ checkEqu(2, ReStringUtil::countChar("xbxxbxx", 'b'));
+ }
+
+ void testCount() {
+ checkEqu(0, ReStringUtil::count("abc", " "));
+ checkEqu(1, ReStringUtil::count("abc", "b"));
+ checkEqu(2, ReStringUtil::count("axx", "x"));
+
+ checkEqu(0, ReStringUtil::count("abbc", "bbb"));
+ checkEqu(1, ReStringUtil::count("\n\n", "\n\n"));
+ checkEqu(2, ReStringUtil::count(" a ", " "));
+ }
+
+ void testCutString() {
+ QByteArray source("123");
+ QByteArray buffer;
+ checkEqu(QByteArray("123"), ReStringUtil::cutString(source, 4, buffer));
+ checkEqu(QByteArray("123"), ReStringUtil::cutString(source, 3, buffer));
+ checkEqu(QByteArray("12..."), ReStringUtil::cutString(source, 2, buffer));
+ checkEqu(QByteArray("12"), ReStringUtil::cutString(source, 2, buffer, ""));
+ }
+
+ void testHexDump() {
+ QByteArray data("abc123\nxyz");
+ checkEqu(QByteArray("61 62 63 31 abc1\n"
+ "32 33 0a 78 23.x\n"
+ "79 7a yz\n"),
+ ReStringUtil::hexDump((uint8_t*) data.constData(), data.length(), 4));
+ checkEqu(QByteArray("61 62 63 31 32 33 0a 78 79 7a abc123.xyz"),
+ ReStringUtil::hexDump((uint8_t*) data.constData(), data.length(), 10));
+ checkEqu(QByteArray("61 62 63 31 32 33 0a 78 79 7a abc123.xyz"),
+ ReStringUtil::hexDump((uint8_t*) data.constData(), data.length(), 12));
+ }
+
+ void testReadWrite() {
+ QByteArray fn = getTempFile("test.dat");
+ const char* content = "Hello world\nLine2\n";
+ checkT(ReStringUtil::write(fn, content));
+ checkEqu(content, ReStringUtil::read(fn, false));
+ checkEqu(content, ReStringUtil::read(fn, true) + "\n");
+ }
+
+ void testToArray() {
+ QList<QByteArray> array = ReStringUtil::toArray("1 abc 3", " ");
+ checkEqu(3, array.size());
+ checkEqu("1", array.at(0));
+ checkEqu("abc", array.at(1));
+ checkEqu("3", array.at(2));
+ }
+
+ void testToNumber() {
+ checkEqu("3", ReStringUtil::toNumber(3));
+ checkEqu("-33", ReStringUtil::toNumber(-33));
+ checkEqu("003", ReStringUtil::toNumber(3, "%03d"));
+ }
+
+ void testLengthOfNumber(){
+ checkEqu(3, ReStringUtil::lengthOfNumber("0.3xxx"));
+ checkEqu(5, ReStringUtil::lengthOfNumber(" \t0.3xxx"));
+ checkEqu(3, ReStringUtil::lengthOfNumber("-.3xxx"));
+ checkEqu(2, ReStringUtil::lengthOfNumber(".3exxx"));
+ checkEqu(2, ReStringUtil::lengthOfNumber(".3e+xxx"));
+ checkEqu(16, ReStringUtil::lengthOfNumber("1234567.9012E+77"));
+ checkEqu(17, ReStringUtil::lengthOfNumber("-1234567.9012E+77 "));
+ checkEqu(18, ReStringUtil::lengthOfNumber("-1234567.9012E+77 ", true));
+ checkEqu(18, ReStringUtil::lengthOfNumber("-1234567.9012E+77 x", true));
+ checkEqu(20, ReStringUtil::lengthOfNumber(" -1234567.9012E+77 x", true));
+ }
+
+ void checkCsv(const char* content, char expected){
+ QByteArray fn = getTempFile("testrplstring.csv");
+ ReStringUtil::write(fn, content);
+ FILE* fp = fopen(fn, "r");
+ checkNN(fp);
+ char buffer[256];
+ checkEqu(expected, ReStringUtil::findCsvSeparator(fp, buffer, sizeof buffer));
+ fclose(fp);
+ }
+
+ void testFindCsvSeparator(){
+ const char* content = ",,,\t;;;||||";
+ checkCsv(content, '\t');
+
+ content = "col1,col2\n1.5,3,5\n";
+ checkCsv(content, ',');
+
+ content = "col1;col2\n1,50;3.5\n"
+ "7;8\n10;12\n13;14";
+ checkCsv(content, ';');
+
+ content = "0.3 7.8 8.9\n7.8 9.4 8.3";
+ checkCsv(content, ' ');
+
+ content = "0.3|7.8|8.9\n7.8| 9.4|8.3";
+ checkCsv(content, '|');
+
+ content = "0,3;7.8;8.9";
+ checkCsv(content, ';');
+ }
+ void testLengthOfUInt64(){
+ quint64 value = -3;
+ checkEqu(1, ReStringUtil::lengthOfUInt64("0", 10, &value));
+ checkEqu((int64_t) 0LL, value);
+ checkEqu(3, ReStringUtil::lengthOfUInt64("432", 10, &value));
+ checkEqu((int64_t) 432LL, value);
+ checkEqu(3, ReStringUtil::lengthOfUInt64("432 x", 10, &value));
+ checkEqu((int64_t) 432LL, value);
+ checkEqu(3, ReStringUtil::lengthOfUInt64("432fabc x", 10, &value));
+ checkEqu((int64_t) 432LL, value);
+ checkEqu(16, ReStringUtil::lengthOfUInt64("1234567890123567", 10, &value));
+ checkEqu((int64_t) 1234567890123567LL, value);
+ checkEqu(10, ReStringUtil::lengthOfUInt64("1234abcdef", 16, &value));
+ checkEqu((int64_t) 0x1234abcdefLL, value);
+ checkEqu(3, ReStringUtil::lengthOfUInt64("432", 8, &value));
+ checkEqu((int64_t) 0432LL, value);
+ checkEqu(6, ReStringUtil::lengthOfUInt64("765432 ", 8, &value));
+ checkEqu((int64_t) 0765432LL, value);
+
+ checkEqu(0, ReStringUtil::lengthOfUInt64(" ", 8, &value));
+ checkEqu(0, ReStringUtil::lengthOfUInt64("", 8, &value));
+ }
+ void testLengthOfReal(){
+ qreal value;
+ checkEqu(1, ReStringUtil::lengthOfReal("0", &value));
+ checkEqu(0.0, value);
+ checkEqu(1, ReStringUtil::lengthOfReal("0%", &value));
+ checkEqu(0.0, value);
+ checkEqu(4, ReStringUtil::lengthOfReal("0.25", &value));
+ checkEqu(0.25, value);
+ checkEqu(3, ReStringUtil::lengthOfReal(".25", &value));
+ checkEqu(0.25, value);
+ checkEqu(17, ReStringUtil::lengthOfReal("12345678901234567", &value));
+ checkEqu(12345678901234567.0, value);
+ checkEqu(2, ReStringUtil::lengthOfReal(".5", &value));
+ checkEqu(0.5, value);
+ checkEqu(5, ReStringUtil::lengthOfReal("2.5e2x", &value));
+ checkEqu(250.0, value);
+ checkEqu(6, ReStringUtil::lengthOfReal("2.5e+2", &value));
+ checkEqu(250.0, value);
+ checkEqu(7, ReStringUtil::lengthOfReal("2.5E-33", &value));
+ checkEqu(2.5e-33, value);
+
+ checkEqu(3, ReStringUtil::lengthOfReal("2.5E", &value));
+ checkEqu(2.5, value);
+ checkEqu(3, ReStringUtil::lengthOfReal("2.5E+", &value));
+ checkEqu(2.5, value);
+ checkEqu(3, ReStringUtil::lengthOfReal("2.5E-a", &value));
+ checkEqu(2.5, value);
+ }
+
+ virtual void run() {
+ testLengthOfReal();
+ testLengthOfUInt64();
+ testCountChar();
+ testCount();
+ testCutString();
+ testToNumber();
+ testToArray();
+ testHexDump();
+ testReadWrite();
+ testLengthOfNumber();
+ testFindCsvSeparator();
+ }
+};
+
+void testReStringUtil() {
+ TestReStringUtil test;
+}
+
+
+
--- /dev/null
+/*
+ * cuReTraverser.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+#include "base/rebase.hpp"
+#include "os/reos.hpp"
+
+class TestReTraverser: public ReTestUnit {
+public:
+ TestReTraverser() :
+ ReTestUnit("ReTraverser", __FILE__),
+ m_base(),
+ m_buffer(),
+ m_logger(ReLogger::globalLogger()) {
+ m_base = testDir();
+ m_base.append("traverser");
+ _mkdir(m_base.str(), ALLPERMS);
+ m_base.append(OS_SEPARATOR, -1);
+ run();
+ ReDirectory::deleteTree(m_base.str(), true);
+ }
+private:
+ ReByteBuffer m_base;
+ ReByteBuffer m_buffer;
+ ReLogger* m_logger;
+private:
+ const char* makeDir(const char* relPath) {
+ m_buffer = m_base;
+ m_buffer.append(relPath);
+ m_buffer.replaceAll("/", 1, OS_SEPARATOR, -1);
+ _mkdir(m_buffer.str(), ALLPERMS);
+ struct stat info;
+ if (stat(m_buffer.str(), &info) != 0) {
+ logF(true, "cannot create dir %1$s", m_buffer.str());
+ }
+ return m_buffer.str();
+ }
+ void makeFile(const char* relPath) {
+ ReByteBuffer path(m_base);
+ path.append("/").append(relPath);
+ path.replaceAll("/", 1, OS_SEPARATOR, -1);
+ createFile(path.str(), relPath);
+ struct stat info;
+ if (stat(path.str(), &info) != 0) {
+ logF(true, "cannot create file %1$s", path.str());
+ }
+ }
+ void initTree() {
+ makeFile("1.txt");
+ makeDir("dir1");
+ makeDir("dir2");
+ makeDir("dir1/dir1_1");
+ makeDir("dir1/dir1_2");
+ makeDir("dir1/dir1_2/dir1_2_1");
+ makeDir("dir1/cache");
+ makeFile("dir1/dir1_2/dir1_2_1/x1.txt");
+ makeFile("dir1/dir1_2/dir1_2_1/x2.txt");
+ makeFile("dir2/2.x");
+ makeFile("dir1/cache/cache.txt");
+ }
+ void run() {
+ testFilter();
+ initTree();
+
+ testBasic();
+ testList();
+ }
+ void testFilter() {
+ ReDirEntryFilter filter;
+
+ }
+ void testList() {
+ const char* argv[] = { "list", m_base.str(), NULL };
+ ReDirList(m_logger).run(2, argv);
+ }
+ void testCopyFile() {
+#if defined __linux__
+ ReByteBuffer src(m_base);
+ src.append("dir1/dir1_2/dir1_2_1/x1.txt");
+ ReByteBuffer trg(testDir());
+ trg.append("copy_x1.txt");
+ ReByteBuffer buffer;
+ buffer.ensureSize(5);
+ ReDirSync::copyFile(src.str(), NULL, trg.str(), buffer,
+ ReLogger::globalLogger());
+ checkFileEqu(src.str(), trg.str());
+#else
+ log(false, "testCopyFile not implemented");
+#endif
+ }
+
+ void checkRelDate(time_t absTime, int relTime) {
+ int diff = int(time(NULL) - relTime - absTime);
+ if (diff < 0)
+ diff = -diff;
+ checkT(diff < 2);
+ }
+
+ void checkOneFile(const char* node, const char* parent,
+ const ReHashList& hash) {
+ ReByteBuffer path, expected;
+ checkT(hash.get(ReByteBuffer(node), path));
+ expected.set(parent, -1);
+ if (!expected.endsWith(OS_SEPARATOR))
+ expected.append(OS_SEPARATOR);
+ if (!path.endsWith(expected.str(), -1))
+ checkT(false);
+ }
+ void testBasic() {
+ ReTraverser traverser(m_base.str());
+ RePatternList patterns;
+ // exclude */cache/*
+ ReByteBuffer buffer(";*;-cache");
+ patterns.set(buffer.str());
+ traverser.setDirPattern(&patterns);
+ int level = 0;
+ ReDirStatus_t* entry;
+ ReHashList hashPath;
+ ReSeqArray listChanged;
+ int state = 0;
+ while ((entry = traverser.rawNextFile(level)) != NULL) {
+ const char* node = entry->node();
+ hashPath.put(ReByteBuffer(node, -1), entry->m_path);
+ if (traverser.hasChangedPath(state))
+ listChanged.add(-1, node);
+ logF(false, "%d: %-12s %2d %s", level, node, int(entry->fileSize()),
+ entry->m_path.str());
+ }
+ checkOneFile("x1.txt", "dir1_2_1", hashPath);
+ checkOneFile("x2.txt", "dir1_2_1", hashPath);
+ bool changed1 = listChanged.find("x1.txt") != (ReSeqArray::Index) -1;
+ bool changed2 = listChanged.find("x2.txt") != (ReSeqArray::Index) -1;
+ checkT(changed1 != changed2);
+ checkOneFile("dir1_2_1", "dir1_2", hashPath);
+ checkT(listChanged.find("dir1_2_1") >= 0);
+ checkOneFile("dir1_1", "dir1", hashPath);
+ checkOneFile("dir1_2", "dir1", hashPath);
+ changed1 = listChanged.find("dir1_1") != (ReSeqArray::Index) -1;
+ changed2 = listChanged.find("dir1_2") != (ReSeqArray::Index) -1;
+ checkT(changed1 != changed2);
+ checkF(hashPath.get("cache.txt", buffer));
+ }
+};
+extern void testReTraverser(void);
+
+void testReTraverser(void) {
+ TestReTraverser unit;
+}
--- /dev/null
+/*
+ * rplvm_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+#include "base/rebase.hpp"
+#include "expr/reexpr.hpp"
+
+class TestReVM : public ReTest{
+private:
+ ReSource m_source;
+ ReASTree m_tree;
+ ReStringReader m_reader;
+ const char* m_currentSource;
+public:
+ TestReVM() :
+ ReTest("ReVM"),
+ m_source(),
+ m_tree(),
+ m_reader(m_source)
+ {
+ m_source.addReader(&m_reader);
+ doIt();
+ }
+protected:
+ void setSource(const char* content){
+ ReASItem::reset();
+ m_currentSource = content;
+ m_tree.clear();
+ m_source.clear();
+ m_reader.clear();
+ m_reader.addSource("<test>", content);
+ m_source.addReader(&m_reader);
+ m_source.addSourceUnit(m_reader.currentSourceUnit());
+ }
+
+private:
+ void checkAST(const char* fileExpected, int lineNo){
+ QByteArray fnExpected = "test";
+ fnExpected += QDir::separator().toLatin1();
+ fnExpected += "ReVM";
+ fnExpected += (char) QDir::separator().toLatin1();
+ fnExpected += fileExpected;
+ QByteArray fnCurrent = getTempFile(fileExpected, "ReVM");
+ ReMFParser parser(m_source, m_tree);
+ parser.parse();
+ ReVirtualMachine vm(m_tree, m_source);
+ vm.setFlag(ReVirtualMachine::VF_TRACE_STATEMENTS);
+ ReFileWriter writer(fnCurrent);
+ vm.setTraceWriter(&writer);
+ writer.write(m_currentSource);
+ vm.executeModule("<test>");
+ assertEqualFiles(fnExpected.constData(), fnCurrent.constData(),
+ __FILE__, lineNo);
+ }
+public:
+ void baseTest(){
+ setSource("Int a=2+3*4;\nfunc Void main():\na;\nendf");
+ checkAST("baseTest.txt", __LINE__);
+ }
+ virtual void run(void) {
+ baseTest();
+ }
+};
+void testReVM() {
+ TestReVM test;
+}
+
--- /dev/null
+/*
+ * rplwriter_test.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+/** @file
+ * @brief Unit test of the output media writers.
+ */
+
+#include "base/rebase.hpp"
+/**
+ * @brief Unit test for <code>ReStringUtil</code>.
+ */
+class TestReWriter : public ReTest {
+public:
+ TestReWriter() : ReTest("ReWriter") { doIt(); }
+
+private:
+ void testFileWriter(){
+ QByteArray fn = getTempFile("rplwriter.txt");
+ ReFileWriter writer(fn);
+ writer.writeLine("abc");
+ writer.formatLine("%04d", 42);
+ writer.writeIndented(3, "123");
+ writer.indent(2);
+ writer.write("pi");
+ writer.format("%3c%.2f", ':', 3.1415);
+ writer.writeLine();
+ writer.close();
+ QByteArray current = ReStringUtil::read(fn, false);
+ checkEqu("abc\n0042\n\t\t\t123\n\t\tpi :3.14\n", current);
+ }
+
+public:
+ virtual void run(void) {
+ testFileWriter();
+ }
+};
+void testReWriter() {
+ TestReWriter test;
+}
+
+
+
+++ /dev/null
-/*
- * main.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-#include "../rplcore/rplcore.hpp"
-#include "../rplmath/rplmath.hpp"
-
-#include <QCoreApplication>
-
-void testCore(){
- extern void testReString();
- testReString();
-
- extern void testReCharPtrMap();
- testReCharPtrMap();
-
- extern void testRplWriter();
- testRplWriter();
-
- extern void testRplByteStorage();
- testRplByteStorage();
-
- extern void testRplQString();
- testRplQString();
-
- extern void testReString();
- testReString();
-
- extern void testRplException();
- testRplException();
-}
-
-void testExpr(){
- extern void testRplMFParser();
- testRplMFParser();
-
- extern void testRplBenchmark();
- //testRplBenchmark();
-
- extern void testReVM();
- testReVM();
-
- extern void testReSource();
- testReSource();
-
- extern void testRplLexer();
- testRplLexer();
-
- extern void testRplMFParser();
- testRplMFParser();
-
- extern void testReASTree();
- testReASTree();
-
- extern void testReVM();
- testReVM();
-
-}
-
-void testStandard(){
- testExpr();
- testCore();
- extern void testRplMatrix();
- testRplMatrix();
-
-}
-
-void labor(){
-}
-
-int main(int argc, char *argv[])
-{
- //labor();
- if (argc > 1)
- printf("not used: %s\n", argv[1]);
-
- testStandard();
-
-}
+++ /dev/null
-/*
- * rplastree_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-/** @file
- * @brief Unit test of the abstract syntax tree.
- */
-
-
-#include "base/rebase.hpp"
-#include "expr/reexpr.hpp"
-#include "rplcore/rpltest.hpp"
-
-class TestReASTree : public ReTest{
-private:
- ReSource m_source;
- ReStringReader m_reader;
- ReStringSourceUnit m_unit;
- ReASTree m_tree;
-public:
- TestReASTree() :
- ReTest("ReASTree"),
- m_source(),
- m_reader(m_source),
- m_unit("<main>", "", &m_reader),
- m_tree()
- {}
-public:
- void testReASException() {
- try{
- m_reader.addSource("<main>", "12");
- m_source.addReader(&m_reader);
- m_source.addSourceUnit(m_reader.currentSourceUnit());
- const ReSourcePosition* pos = m_source.newPosition(2);
- throw ReASException(pos, "simple string: %s", "Hi");
- checkF(true);
- } catch (ReASException exc){
- checkEqu("<main>:0:2: simple string: Hi", exc.getMessage().constData());
- }
- }
- void testReASVariant(){
- ReASVariant val1;
- val1.setFloat(2.5E-2);
- checkEqu(2.5E-2, val1.asFloat());
- ReASVariant val2(val1);
- checkEqu(2.5E-2, val2.asFloat());
-
- val1.setInt(4321);
- checkEqu(4321, val1.asInt());
- val2 = val1;
- checkEqu(4321, val2.asInt());
-
- val1.setBool(false);
- checkF(val1.asBool());
- val2 = val1;
- checkF(val2.asBool());
-
- val1.setBool(true);
- checkT(val1.asBool());
- val2 = val1;
- checkT(val2.asBool());
-
- val1.setString("High noon!");
- checkEqu("High noon!", *val1.asString());
- val2 = val1;
- val1.setString("Bye");
- checkEqu("High noon!", *val2.asString());
- ReASVariant val3(val1);
- checkEqu("Bye", *val3.asString());
- }
- void testReASConstant(){
- ReASConstant constant;
- //constant.value().setString("Jonny");
- ReASVariant value;
- //constant.calc(value);
- //checkEqu("Jonny", *value.asString());
- }
- void testReASNamedValue(){
- ReASNamedValue value(NULL, m_tree.symbolSpaces()[0], "gugo",
- ReASNamedValue::A_GLOBAL);
- checkEqu("gugo", value.name());
- }
- virtual void doIt() {
- testReASNamedValue();
- testReASConstant();
- testReASException();
- testReASVariant();
- }
-};
-void testReASTree() {
- TestReASTree test;
- test.run();
-}
-
-
-
-
-
-
+++ /dev/null
-/*
- * rplbench.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-/** @file
- * @brief Unit test of the abstract syntax tree.
- */
-
-
-#include "base/rebase.hpp"
-#include "expr/reexpr.hpp"
-#include "rplcore/rpltest.hpp"
-
-class TestRplBenchmark : public ReTest{
-private:
- const char* m_filename;
- ReSource m_source;
- ReFileReader m_reader;
- ReASTree m_tree;
-public:
- TestRplBenchmark() :
- ReTest("RplBenchmark"),
- m_filename("/home/ws/qt/rplqt/bench/mfbench.mf"),
- m_source(),
- m_reader(m_source),
- m_tree()
- {
- m_source.addReader(&m_reader);
- m_reader.addSource(m_filename);
- }
-public:
- void benchmark() {
- time_t start = time(NULL);
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- time_t end = time(NULL);
- printf("compilation: %d sec\n", int(end - start));
- }
- virtual void doIt() {
- try{
- ReFileSourceUnit* unit = dynamic_cast<ReFileSourceUnit*>
- (m_reader.currentSourceUnit());
- if (unit != NULL && ! unit->isOpen())
- throw ReException("file not found: %s", m_filename);
- benchmark();
- } catch(ReException ex){
- printf("%s\n", ex.getMessage().constData());
- }
- }
-};
-void testRplBenchmark() {
- TestRplBenchmark test;
- test.run();
-}
-
-
-
+++ /dev/null
-/*
- * rplbytestorage_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-/** @file
- * @brief Unit test of the byte and C string storage.
- */
-
-#include "../base/rebase.hpp"
-#include "../base/ReTest.hpp"
-
-class TestRplByteStorage : public ReTest{
-public:
- TestRplByteStorage() :
- ReTest("RplByteStorage")
- {}
-private:
- void testChars(){
- ReByteStorage store(100);
- char* s1 = store.allocateChars(4);
- memcpy((void*) s1, "123", 4);
- const char* s2 = store.allocateChars("abc");
- const char* s3 = store.allocateChars("defghij", 3);
- checkEqu(s1, "123");
- checkEqu(s2, "abc");
- checkEqu(s3, "def");
- const char* ptr = s1 + 4;
- checkT(ptr == s2);
- ptr += 4;
- checkT(ptr == s3);
- }
-
- void testBytes(){
- ReByteStorage store(100);
- uint8_t* s1 = store.allocateBytes(4);
- memcpy((void*) s1, "1234", 4);
- uint8_t* s2 = store.allocateBytes((void*) "abcd", 4);
- uint8_t* s3 = store.allocateBytes((void*) "efghij", 4);
- uint8_t* s4 = store.allocateZeros(4);
-
- checkEqu("1234abcdefgh", (const char*) s1);
- uint8_t* ptr = s1 + 4;
- checkT(ptr == s2);
- ptr += 4;
- checkT(ptr == s3);
- ptr += 4;
- checkT(ptr == s4);
- for (int ii = 0; ii < 4; ii++)
- checkEqu(0, (int) s4[ii]);
- }
- void testBufferChange(){
- ReByteStorage store(10);
- char buffer[2];
- buffer[1] = '\0';
- for (int ii = 0; ii < 10000; ii++){
- buffer[1] = 'A' + ii % 26;
- store.allocateBytes(buffer, 1);
- }
- int a = 1;
- }
-
-public:
- virtual void doIt() {
- testBufferChange();
- testChars();
- testBytes();
- }
-};
-void testRplByteStorage() {
- TestRplByteStorage test;
- test.run();
-}
-
-
+++ /dev/null
-/*
- * rplcharptrmap_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-#include "base/rebase.hpp"
-#include "rplcore/rpltest.hpp"
-
-class TestReCharPtrMap : public ReTest{
-public:
- TestReCharPtrMap() :
- ReTest("ReCharPtrMap")
- {
- }
-protected:
- void testBasic(){
- ReCharPtrMap<const char*> map;
- map["x"] = "x1";
- checkT(map.contains("x"));
- checkF(map.contains("y"));
- checkEqu("x1", map["x"]);
- }
-
- virtual void doIt(void) {
- testBasic();
- }
-};
-void testReCharPtrMap() {
- TestReCharPtrMap test;
- test.run();
-}
+++ /dev/null
-/*
- * rplexception_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-#include "base/rebase.hpp"
-#include "rplcore/rpltest.hpp"
-/** @file
- * @brief Unit test of the basic exceptions.
- */
-
-class TestRplException : public ReTest{
-public:
- TestRplException() : ReTest("RplException") {}
-
-public:
- void testBasic() {
- try{
- throw ReException("simple");
- checkF(true);
- } catch (ReException exc){
- checkEqu("simple", exc.getMessage().constData());
- }
- try{
- throw ReException("String: %s and int %d", "Hi", -333);
- checkF(true);
- } catch (ReException exc){
- checkEqu("String: Hi and int -333", exc.getMessage().constData());
- }
- try{
- throw ReException(LOG_INFO, 1234, &m_memoryLogger,
- "String: %s and int %d", "Hi", -333);
- checkF(true);
- } catch (ReException exc){
- checkT(logContains("^ .*\\(1234\\): String: Hi and int -333"));
- }
- log("ok");
- }
- virtual void doIt() {
- testBasic();
- }
-};
-void testRplException() {
- TestRplException test;
- test.run();
-}
-
-
-
+++ /dev/null
-/*
- * rpllexer_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-/** @file
- * @brief Unit test of the syntax symbol extractor.
- */
-
-#include "base/rebase.hpp"
-#include "expr/reexpr.hpp"
-#include "rplcore/rpltest.hpp"
-
-class TestRplLexer : public ReTest, public ReToken{
-public:
- TestRplLexer() :
- ReTest("ReLexer"),
- ReToken(TOKEN_ID)
- {}
-
-public:
- void testRplToken(){
- // test constructor values:
- checkEqu(TOKEN_ID, tokenType());
- checkEqu(0, m_value.m_id);
- checkT(m_string.isEmpty());
- checkT(m_printableString.isEmpty());
-
- m_value.m_id = 7422;
- checkEqu(7422, ReToken::id());
- m_string = "Wow!";
- checkEqu("Wow!", ReToken::toString());
- m_printableString = "GooGoo";
- checkEqu("GooGoo", rawString());
- m_tokenType = TOKEN_NUMBER;
- checkEqu(TOKEN_NUMBER, tokenType());
-
- clear();
- checkEqu(TOKEN_UNDEF, tokenType());
- checkEqu(0, m_value.m_id);
- checkT(m_string.isEmpty());
- checkT(m_printableString.isEmpty());
-
- m_value.m_integer = 773322;
- checkEqu(773322, asInteger());
- m_value.m_real = 0.25;
- checkEqu(0.25, asReal());
- }
-
- ReToken* checkToken(ReToken* token, RplTokenType type, int id = 0,
- const char* string = NULL){
- checkEqu(type, token->tokenType());
- if (id != 0)
- checkEqu(id, token->id());
- if (string != NULL)
- checkEqu(string, token->toString());
- return token;
- }
- enum { KEY_UNDEF, KEY_IF, KEY_THEN, KEY_ELSE, KEY_FI
- };
-# define KEYWORDS "if then else fi"
- enum { OP_UNDEF, OP_PLUS, OP_TIMES, OP_DIV, OP_GT,
- OP_LT, OP_GE, OP_LE, OP_EQ, OP_ASSIGN, OP_PLUS_ASSIGN, OP_DIV_ASSIGN,
- OP_TIMES_ASSIGN
- };
-# define OPERATORS "+\n* /\n> < >= <= ==\n= += /= *="
- enum { COMMENT_UNDEF, COMMENT_1, COMMENT_MULTILINE, COMMENT_2
- };
-# define COMMENTS "/* */ // \n"
- void testSpace(){
- ReSource source;
- ReStringReader reader(source);
-# define BLANKS1 "\t\t \n"
-# define BLANKS2 " \n"
- reader.addSource("<main>", BLANKS1 BLANKS2);
- source.addReader(&reader);
- ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
- "A-Za-z_",
- "A-Za-z0-9_",
- ReLexer::NUMTYPE_DECIMAL,
- ReLexer::SF_TICK, ReLexer::STORE_ALL);
- checkToken(lex.nextToken(), TOKEN_SPACE, 0, BLANKS1);
- checkToken(lex.nextToken(), TOKEN_SPACE, 0, BLANKS2);
- }
- void testNumeric(){
- ReSource source;
- ReStringReader reader(source);
- const char* blanks = "321 0x73 7.8e+5";
- reader.addSource("<main>", blanks);
- source.addReader(&reader);
- ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
- "A-Za-z_",
- "A-Za-z0-9_",
- ReLexer::NUMTYPE_ALL,
- ReLexer::SF_TICK, ReLexer::STORE_ALL);
- ReToken* token = checkToken(lex.nextToken(), TOKEN_NUMBER);
- checkEqu(321, token->asInteger());
- token = checkToken(lex.nextNonSpaceToken(), TOKEN_NUMBER);
- checkEqu(0x73, token->asInteger());
- token = checkToken(lex.nextNonSpaceToken(), TOKEN_REAL);
- checkEqu(7.8e+5, token->asReal());
- }
-
- void testOperators(){
- ReSource source;
- ReStringReader reader(source);
- const char* ops = "<< < <<< <= == = ( ) [ ]";
- reader.addSource("<main>", ops);
- source.addReader(&reader);
- enum { UNDEF, SHIFT, LT, SHIFT2, LE, EQ, ASSIGN,
- LPARENT, RPARENT, LBRACKET, RBRACKET };
- ReLexer lex(&source, KEYWORDS, ops, "=", COMMENTS,
- "A-Za-z_",
- "A-Za-z0-9_",
- ReLexer::NUMTYPE_ALL,
- ReLexer::SF_TICK, ReLexer::STORE_ALL);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, SHIFT);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LT);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, SHIFT2);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LE);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, EQ);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, ASSIGN);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LPARENT);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, RPARENT);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LBRACKET);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, RBRACKET);
- checkToken(lex.nextNonSpaceToken(), TOKEN_END_OF_SOURCE);
- reader.addSource("<buffer2>", "(([[");
- lex.startUnit("<buffer2>");
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LPARENT);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LPARENT);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LBRACKET);
- checkToken(lex.nextNonSpaceToken(), TOKEN_OPERATOR, LBRACKET);
- checkToken(lex.nextNonSpaceToken(), TOKEN_END_OF_SOURCE);
- }
-
- void testComments(){
- ReSource source;
- ReStringReader reader(source);
-
- reader.addSource("<main>", "/**/9//\n8/***/7// wow\n/*\n*\n*\n**/");
- source.addReader(&reader);
-
- enum { COMMENT_UNDEF, COMMENT_MULTILINE, COMMENT_1
- };
- ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
- "A-Za-z_",
- "A-Za-z0-9_",
- ReLexer::NUMTYPE_ALL,
- ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
- checkToken(lex.nextToken(), TOKEN_COMMENT_START, COMMENT_MULTILINE,
- "/**/");
- checkToken(lex.nextToken(), TOKEN_NUMBER);
- checkToken(lex.nextToken(), TOKEN_COMMENT_START, COMMENT_1,
- "//\n");
- checkToken(lex.nextToken(), TOKEN_NUMBER);
- checkToken(lex.nextToken(), TOKEN_COMMENT_START, COMMENT_MULTILINE,
- "/***/");
- checkToken(lex.nextToken(), TOKEN_NUMBER);
- checkToken(lex.nextToken(), TOKEN_COMMENT_START, COMMENT_1,
- "// wow\n");
- checkToken(lex.nextToken(), TOKEN_COMMENT_START, COMMENT_MULTILINE,
- "/*\n*\n*\n**/");
- }
- void testStrings(){
- ReSource source;
- ReStringReader reader(source);
-
- reader.addSource("<main>", "\"abc\\t\\r\\n\\a\\v\"'1\\x9Z\\x21A\\X9'");
- source.addReader(&reader);
-
- ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
- "A-Za-z_",
- "A-Za-z0-9_",
- ReLexer::NUMTYPE_ALL,
- ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
- checkToken(lex.nextToken(), TOKEN_STRING, '"', "abc\t\r\n\a\v");
- checkToken(lex.nextToken(), TOKEN_STRING, '\'', "1\tZ!A\t");
- }
- void testKeywords(){
- ReSource source;
- ReStringReader reader(source);
-
- reader.addSource("<main>", "if\n\tthen else\nfi");
- source.addReader(&reader);
-
- ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
- "A-Za-z_",
- "A-Za-z0-9_",
- ReLexer::NUMTYPE_ALL,
- ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
- checkToken(lex.nextToken(), TOKEN_KEYWORD, KEY_IF);
- checkToken(lex.nextNonSpaceToken(), TOKEN_KEYWORD, KEY_THEN);
- checkToken(lex.nextNonSpaceToken(), TOKEN_KEYWORD, KEY_ELSE);
- checkToken(lex.nextNonSpaceToken(), TOKEN_KEYWORD, KEY_FI);
- checkToken(lex.nextNonSpaceToken(), TOKEN_END_OF_SOURCE);
- }
-
- void testIds(){
- ReSource source;
- ReStringReader reader(source);
-
- reader.addSource("<main>", "i\n\tifs\n"
- "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
- source.addReader(&reader);
-
- ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
- "A-Za-z_",
- "A-Za-z0-9_",
- ReLexer::NUMTYPE_ALL,
- ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
- checkToken(lex.nextToken(), TOKEN_ID, 0, "i");
- checkToken(lex.nextNonSpaceToken(), TOKEN_ID, 0,
- "ifs");
- checkToken(lex.nextNonSpaceToken(), TOKEN_ID, 0,
- "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
- }
-
- void testBasic(){
- ReSource source;
- ReStringReader reader(source);
- source.addReader(&reader);
- reader.addSource("<main>", "if i>1 then i=1+2*_x9 fi");
- ReLexer lex(&source, KEYWORDS, OPERATORS, "=", COMMENTS,
- "A-Za-z_",
- "A-Za-z0-9_",
- ReLexer::NUMTYPE_ALL,
- ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
- ReToken* token;
- checkToken(lex.nextToken(), TOKEN_KEYWORD, KEY_IF);
- checkToken(lex.nextToken(), TOKEN_SPACE, 0);
- checkToken(lex.nextToken(), TOKEN_ID, 0, "i");
- checkToken(lex.nextToken(), TOKEN_OPERATOR, OP_GT);
- token = checkToken(lex.nextToken(), TOKEN_NUMBER);
- checkEqu(1, token->asInteger());
- checkToken(lex.nextToken(), TOKEN_SPACE, 0);
- checkToken(lex.nextToken(), TOKEN_KEYWORD, KEY_THEN);
- checkToken(lex.nextToken(), TOKEN_SPACE, 0);
-
- }
- void testPrio(){
- ReSource source;
- ReStringReader reader(source);
- source.addReader(&reader);
- reader.addSource("x", "");
- enum { O_UNDEF, O_ASSIGN, O_PLUS, O_MINUS, O_TIMES, O_DIV
- };
- ReLexer lex(&source, KEYWORDS,
- "=\n+ -\n* /", "=",
- COMMENTS,
- "A-Za-z_",
- "A-Za-z0-9_",
- ReLexer::NUMTYPE_ALL,
- ReLexer::SF_LIKE_C, ReLexer::STORE_ALL);
- checkT(lex.prioOfOp(O_ASSIGN) < lex.prioOfOp(O_PLUS));
- checkEqu(lex.prioOfOp(O_PLUS), lex.prioOfOp(O_MINUS));
- checkT(lex.prioOfOp(O_MINUS) < lex.prioOfOp(O_TIMES));
- checkEqu(lex.prioOfOp(O_TIMES), lex.prioOfOp(O_DIV));
- }
-
- virtual void doIt(void) {
- testPrio();
- testBasic();
- testIds();
- testKeywords();
- testComments();
- testStrings();
- testOperators();
- testNumeric();
- testSpace();
- testRplToken();
- }
-};
-void testRplLexer() {
- TestRplLexer test;
- test.run();
-}
+++ /dev/null
-/*
- * rplmatrix_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-/** @file
- * @brief Unit test of the matrices.
- */
-
-#include "base/rebase.hpp"
-#include "rplmath/rplmath.hpp"
-#include "rplcore/rpltest.hpp"
-
-class TestRplMatrix : public ReTest{
-public:
- TestRplMatrix() : ReTest("RplMatrix") {}
-
-public:
- void fillMatrix(RplMatrix& mx, MatVal offset = 0){
- for(int row = 0; row < mx.getRows(); row++){
- for (int col = 0; col < mx.getCols(); col++){
- mx.set(row, col, 100.0*row + col + offset);
- }
- }
- }
- void checkMatrix(const RplMatrix& mx, MatVal offset = 0){
- int count = 0;
- for(int row = 0; row < mx.getRows(); row++){
- for (int col = 0; col < mx.getCols(); col++){
- checkEqu(100.0*row + col + offset, mx.get(row, col));
- count++;
- }
- }
- checkEqu(mx.getCols()*mx.getRows(), count);
- }
- void fillConst(RplMatrix& mx, MatVal value){
- for(int row = 0; row < mx.getRows(); row++){
- for (int col = 0; col < mx.getCols(); col++){
- mx.set(row, col, value);
- }
- }
- }
- void checkConst(const RplMatrix& mx, MatVal value){
- int count = 0;
- for(int row = 0; row < mx.getRows(); row++){
- for (int col = 0; col < mx.getCols(); col++){
- checkEqu(value, mx.get(row, col));
- count++;
- }
- }
- checkEqu(mx.getCols()*mx.getRows(), count);
- }
-
- void testBasic() {
- Tuple2 tuple(-2.0, 0.5);
- checkEqu(-2.0, tuple.m_value1);
- checkEqu(0.5, tuple.m_value2);
- RplMatrix mat("mx");
- try{
- throw RplMatrixException(mat, "String: %s and int %d", "Hi", -333);
- checkF(true);
- } catch (RplMatrixException exc){
- checkEqu("mx: String: Hi and int -333", exc.getMessage());
- }
- RplMatrix mat2;
- try{
- throw RplMatrixException(mat2, "String: %s and int %d", "Hi", -333);
- checkF(true);
- } catch (RplMatrixException exc){
- checkEqu("String: Hi and int -333", exc.getMessage());
- }
- checkEqu("mx", mat.getName());
- checkEqu("", mat2.getName());
-
- RplMatrix m2x3(2, 3, "m2x3");
- checkEqu("m2x3", m2x3.getName());
- checkEqu(2, m2x3.getRows());
- checkEqu(3, m2x3.getCols());
- fillMatrix(m2x3);
- checkMatrix(m2x3);
-
- RplMatrix mxCopy(m2x3);
- checkEqu("m2x3-copy", mxCopy.getName());
- checkEqu(2, mxCopy.getRows());
- checkEqu(3, mxCopy.getCols());
- checkMatrix(mxCopy);
-
- RplMatrix mxCopy2("mxCopy2");
- mxCopy2 = m2x3;
- checkEqu("mxCopy2", mxCopy2.getName());
- checkEqu(2, mxCopy2.getRows());
- checkEqu(3, mxCopy2.getCols());
- checkMatrix(mxCopy2);
- }
- void testAddOperators(){
- RplMatrix m1(3, 2, "m1");
- fillMatrix(m1);
- checkMatrix(m1);
- RplMatrix m2(3, 2, "m2");
- fillMatrix(m2, 42);
- checkMatrix(m2, 42);
- RplMatrix m3(3, 2, "m3");
- fillMatrix(m3, -42);
- checkMatrix(m3, -42);
-
- m1 += 42;
- checkMatrix(m1, 42);
-
- checkT(m1 == m2);
- checkF(m1 == m3);
-
- m1 -= 42;
- checkMatrix(m1);
- m1 -= m1;
- checkConst(m1, 0);
-
- fillMatrix(m1);
- m1 -= m3;
- checkConst(m1, 42);
- m1 += m2;
- checkMatrix(m1, 42*2);
- }
- void testCompareOperators(){
- RplMatrix m1(3, 2, "m1");
- fillMatrix(m1);
- checkMatrix(m1);
- RplMatrix m2(3, 2, "m2");
- fillMatrix(m2);
-
- checkT(m1 == m2);
- checkF(m1 != m2);
- // modify each element, comparism must return false:
- int row, col;
- for (row = 0; row < m2.getRows(); row++)
- for (col = 0; col < m2.getCols(); col++){
- fillMatrix(m2);
- m2.set(row, col, -1);
- checkF(m1 == m2);
- checkT(m1 != m2);
- }
-
- fillConst(m1, 42);
- checkT(m1 == 42);
- checkF(m1 == 43);
- checkT(m1 != 43);
- for (row = 0; row < m1.getRows(); row++)
- for (col = 0; col < m1.getCols(); col++){
- fillMatrix(m1, 42);
- m1.set(row, col, -1);
- checkF(m1 == 42);
- checkT(m1 != 42);
- }
- }
-
- void testCheckDefinition(){
- RplMatrix m1(3, 2, "m1");
- fillMatrix(m1);
- checkMatrix(m1);
- RplMatrix m2(3, 2, "m2");
- fillMatrix(m2);
-
- m1.checkDefinition(1, 1);
- m1.checkDefinition(1000, 1000);
- m1.checkDefinition(0, 0);
- try {
- m1.checkDefinition(-1, 1);
- checkT(false);
- } catch(RplMatrixException exc){
- checkEqu("m1: row number negative: -1", exc.getMessage());
- }
- try {
- m1.checkDefinition(1, -1);
- checkT(false);
- } catch(RplMatrixException exc){
- checkEqu("m1: column number negative: -1", exc.getMessage());
- }
-
- }
- void testCheck(){
- RplMatrix m1(3, 2, "m1");
- fillMatrix(m1);
- checkMatrix(m1);
-
- m1.check(0, 0);
- m1.check(3-1, 2-1);
- try {
- m1.check(-1, 1);
- checkT(false);
- } catch(RplMatrixException exc){
- checkEqu("m1: invalid row: -1 not in [0,3[", exc.getMessage());
- }
- try {
- m1.check(3, 1);
- checkT(false);
- } catch(RplMatrixException exc){
- checkEqu("m1: invalid row: 3 not in [0,3[", exc.getMessage());
- }
- try {
- m1.check(1, -1);
- checkT(false);
- } catch(RplMatrixException exc){
- checkEqu("m1: invalid column: -1 not in [0,2[", exc.getMessage());
- }
- try {
- m1.check(1, 2);
- checkT(false);
- } catch(RplMatrixException exc){
- checkEqu("m1: invalid column: 2 not in [0,2[", exc.getMessage());
- }
- }
- void testCheckSameDimension(){
- RplMatrix m1(3, 2, "m1");
- RplMatrix m2(3, 2, "m2");
-
- m1.checkSameDimension(m2);
-
- m2.resize(2, 2);
- try {
- m1.checkSameDimension(m2);
- checkT(false);
- } catch(RplMatrixException exc){
- checkEqu("m1: m2 has a different row count: 3 / 2", exc.getMessage());
- }
- m2.resize(3, 3);
- try {
- m1.checkSameDimension(m2);
- checkT(false);
- } catch(RplMatrixException exc){
- checkEqu("m1: m2 has a different column count: 2 / 3", exc.getMessage());
- }
- }
- void testResize(){
- RplMatrix m1(3, 2, "m1");
- fillMatrix(m1);
- checkMatrix(m1);
- RplMatrix m2(2, 4, "m2");
- fillConst(m2, 0);
- checkConst(m2, 0);
-
- m1.resize(2, 4);
- checkEqu(2, m1.getRows());
- checkEqu(4, m1.getCols());
- checkT(m1 == m2);
- }
-
- void testMinMax(){
- RplMatrix m1(4, 5, "m1");
- fillMatrix(m1);
- checkMatrix(m1);
- m1.set(0, 0, -98);
- m1.set(3, 4, 9999);
- Tuple2 miniMax = m1.minMax();
- checkEqu(-98.0, miniMax.m_value1);
- checkEqu(9999.0, miniMax.m_value2);
-
- fillMatrix(m1);
- checkMatrix(m1);
- m1.set(1, 1, 7777);
- m1.set(3, 4, -987);
- miniMax = m1.minMax();
- checkEqu(-987.0, miniMax.m_value1);
- checkEqu(7777.0, miniMax.m_value2);
- }
-
- void testTranspose()
- {
- RplMatrix m1(1, 5, "m1");
- fillMatrix(m1);
- RplMatrix m2(m1.transpose());
-
- checkEqu(5, m2.getRows());
- checkEqu(1, m2.getCols());
-
- int row, col;
- col = 0;
- for (row = 0; row < 5; row++){
- checkEqu(qreal(col*100+row), m2.get(row, 0));
- }
-
- m1.resize(35, 73);
- fillMatrix(m1);
- m2 = m1.transpose();
-
- checkEqu(73, m2.getRows());
- checkEqu(35, m2.getCols());
-
- int count = 0;
- for (row = 0; row < m2.getRows(); row++){
- for (col = 0; col < m2.getCols(); col++){
- checkEqu(qreal(col*100+row), m2.get(row, col));
- count++;
- }
- }
- checkEqu(73*35, count);
- }
- void testToString(){
- RplMatrix m1(1, 1, "m1");
- m1.set(0, 0, 2.34);
- checkEqu("[2.340000,\n]", m1.toString().constData());
- checkEqu("jonny[2.34000 |]", m1.toString("jonny", "%.5f", "|", " ").constData());
-
- m1.resize(2, 1);
- m1.set(0, 0, 2.34);
- m1.set(1, 0, 55.5);
-
- checkEqu("[2.340000,\n55.500000,\n]", m1.toString().constData());
- checkEqu("jonny[2.34000 |55.50000 |]", m1.toString("jonny", "%.5f", "|", " ").constData());
- log("");
- }
- void testReadCsv(){
- QByteArray fn = getTempFile("rplmatrixtest.csv");
- const char* content;
- RplMatrix m1(1,1,"m1");
-
- fillMatrix(m1);
- content = ",Port0,Port1,Port2\n"
- "element1,5, -3E-99 , 0.5\n"
- "element2,7,-22.3,44\n"
- "\n"
- "2 Elements, 3, Ports";
- ReStringUtil::write(fn, content);
- m1.readFromCvs(fn, 256);
- checkEqu(2, m1.getRows());
- checkEqu(3, m1.getCols());
-
- checkEqu(5.0, m1.get(0, 0));
- checkEqu(-3.0E-99, m1.get(0, 1));
- checkEqu(0.5, m1.get(0, 2));
-
- checkEqu(7.0, m1.get(1, 0));
- checkEqu(-22.3, m1.get(1, 1));
- checkEqu(44.0, m1.get(1, 2));
-
- fillMatrix(m1);
- content = "Port0,Port1,Port2\n"
- "5, -3E-99 , 0.5\n";
- ReStringUtil::write(fn, content);
- m1.readFromCvs(fn, 256);
- checkEqu(1, m1.getRows());
- checkEqu(3, m1.getCols());
- checkEqu(5.0, m1.get(0, 0));
- checkEqu(-3.0E-99, m1.get(0, 1));
- checkEqu(0.5, m1.get(0, 2));
-
-
-/*
- 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);
-*/
- }
- virtual void doIt(void) {
- testBasic();
- testAddOperators();
- testCompareOperators();
- testCheckDefinition();
- testCheck();
- testCheckSameDimension();
- testResize();
- testMinMax();
- testTranspose();
- testToString();
- testReadCsv();
- }
-};
-void testRplMatrix() {
- TestRplMatrix test;
- test.run();
-}
+++ /dev/null
-/*
- * rplmfparser_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-/** @file
- * @brief Unit test of the parser for the language "MF".
- */
-
-#include "base/rebase.hpp"
-#include "expr/reexpr.hpp"
-#include "rplcore/rpltest.hpp"
-
-class TestRplMFParser : public ReTest{
-private:
- ReSource m_source;
- ReASTree m_tree;
- ReStringReader m_reader;
- ReFileReader m_fileReader;
- QByteArray m_currentSource;
-public:
- TestRplMFParser() :
- ReTest("ReMFParser"),
- m_source(),
- m_tree(),
- m_reader(m_source),
- m_fileReader(m_source)
- {
- m_source.addReader(&m_reader);
- }
-protected:
- void setSource(const char* content){
- ReASItem::reset();
- m_currentSource = content;
- m_tree.clear();
- m_source.clear();
- m_reader.clear();
- m_reader.addSource("<test>", content);
- m_source.addReader(&m_reader);
- m_source.addSourceUnit(m_reader.currentSourceUnit());
- }
- void setFileSource(const char* filename){
- ReASItem::reset();
- m_currentSource = ReStringUtil::read(filename);
- m_tree.clear();
- m_source.clear();
- m_fileReader.clear();
- m_fileReader.addSource(filename);
- m_source.addReader(&m_fileReader);
- m_source.addSourceUnit(m_fileReader.currentSourceUnit());
- }
-
-private:
- void checkAST(const char* fileExpected, int lineNo){
- QByteArray fnExpected = "test";
- fnExpected += QDir::separator().toLatin1();
- fnExpected += "mfparser";
- fnExpected += (char) QDir::separator().toLatin1();
- fnExpected += fileExpected;
- QByteArray fnCurrent = getTempFile(fileExpected, "rplmfparser");
- m_tree.dump(fnCurrent, ReASTree::DMP_NO_GLOBALS, m_currentSource);
- assertEqualFiles(fnExpected.constData(), fnCurrent.constData(),
- __FILE__, lineNo);
- }
-
-public:
- void fileClassTest(){
- setFileSource("test/rplmfparser/string1.mf");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("string1.txt", __LINE__);
- }
-
- void baseTest(){
- setSource("2+3*4");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("baseTest.txt", __LINE__);
- }
-
- void varDefTest(){
- setSource("const lazy Str s = 'Hi';\nconst List l;\nInt i = 3;");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("varDefTest.txt", __LINE__);
- }
-
- void ifTest(){
- setSource("Int a;\nInt b;\na = b = 2;\nif 11 < 12\nthen a = 13 * 14\nelse a = 15 / 16\nfi");
- // setSource("Int a; if 11 < 12 then a = 13 * 14 else a = 15 / 16 fi");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("ifTest1.txt", __LINE__);
- setSource("Str x;\nif 7 < 6\nthen x = '123';\nfi");
- parser.parse();
- checkAST("ifTest2.txt", __LINE__);
- }
- void whileTest(){
- setSource("Int a = 20;\nwhile 3 < 5 do\n a = 7\nod");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("whileTest.txt", __LINE__);
- }
-
- void repeatTest(){
- setSource("Int a;\nrepeat\na++;\nuntil a != 2 * 3;");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("repeatTest.txt", __LINE__);
- }
- void forCTest(){
- setSource("Int a;\nfor b from 10 to 1 step -2 do\na += 1;\nod");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("forC1.txt", __LINE__);
- setSource("Int a; for to 10 do a += 1 od");
- parser.parse();
- checkAST("forC2.txt", __LINE__);
- }
- void opTest(){
- checkEqu(25, ReMFParser::O_QUESTION);
- checkEqu(37, ReMFParser::O_RSHIFT2);
- checkEqu(41, ReMFParser::O_DEC);
- checkEqu(48, ReMFParser::O_RBRACE);
- setSource("Int a = 1;\nInt b = 100;\n--a;\nb++;\na--*++b**(8-3);\na=b=(a+(b-2)*3)");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("opTest1.txt", __LINE__);
- }
- void forItTest(){
- setSource("Map a;\nfor x in a do\na += 1;\nod");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("forIt1.txt", __LINE__);
- }
- void listTest(){
- ReMFParser parser(m_source, m_tree);
- setSource("List b = [];");
- parser.parse();
- checkAST("list1.txt", __LINE__);
- setSource("List a = [2+3, 3.14, 7, 'hi', a]; List b = [];");
- parser.parse();
- checkAST("list2.txt", __LINE__);
- }
- void mapTest(){
- setSource("Map a = {};");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("map1.txt", __LINE__);
- setSource("Map a = {'a': 2+3,'bcd':3.14,'ccc':7, 'hi':'world'};\nMap b = {};");
- parser.parse();
- checkAST("map2.txt", __LINE__);
- }
- void methodCallTest(){
- //setSource("max(4,3.14);");
- setSource("rand();\nsin(a);\nmax(1+2*3,4**(5-4));");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("methc1.txt", __LINE__);
- }
- void fieldTest(){
- setSource("file.find('*.c')[0].name;\n[1,2,3].join(' ');\n3.14.trunc;");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("field1.txt", __LINE__);
- }
-
- void methodTest(){
- setSource("func Float pi: 3.1415; endf func Str delim(): '/' endf;");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("meth1.txt", __LINE__);
- setSource("func Int fac(const Int n):\n"
- "Int rc; if rc <= 1 then rc = 1 else rc = n*fac(n-1) fi\n"
- "rc endf");
- parser.parse();
- checkAST("meth2.txt", __LINE__);
- setSource("func Int max(Int a, Int b):\n Int rc = a;\n"
- "if a < b then rc = b; fi\nrc\n"
- "endf\n"
- "func Int max(const Int a, Int b, Int c):\n"
- "max(a, max(b, c))\n"
- "endf");
- parser.parse();
- checkAST("meth3.txt", __LINE__);
- setSource("func Int max(const Int a, Int b, Int c):\n"
- "func Int max(Int a, Int b):\n Int rc = a;\n"
- "if a < b then rc = b; fi\nrc\n"
- "endf\n"
- "max(a, max(b, c))\n"
- "endf");
- parser.parse();
- checkAST("meth4.txt", __LINE__);
- }
- void mainTest(){
- setSource("Int a=2+3*4;\nfunc Void main():\na;\nendf");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- checkAST("main1.txt", __LINE__);
- }
-
- virtual void doIt(void) {
- mainTest();
- varDefTest();
- repeatTest();
- baseTest();
- whileTest();
- methodTest();
- fieldTest();
- methodCallTest();
- mapTest();
- forItTest();
- forCTest();
- listTest();
- opTest();
- fileClassTest();
- }
-};
-void testRplMFParser() {
- TestRplMFParser test;
- test.run();
-}
-
-
+++ /dev/null
-/*
- * rplqstring_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-/** @file
- * @brief Unit test of the ReString tools.
- */
-
-#include "base/rebase.hpp"
-#include "rplcore/rpltest.hpp"
-
-class TestRplQString : public ReTest {
-public:
- TestRplQString() :
- ReTest("ReQString")
- {}
-
-public:
- void testLengthOfUInt64(){
- quint64 value = -3;
- checkEqu(1, ReQString::lengthOfUInt64(ReString("0"), 0, 10, &value));
- checkEqu(0LL, value);
- checkEqu(3, ReQString::lengthOfUInt64("x432", 1, 10, &value));
- checkEqu(432LL, value);
- checkEqu(3, ReQString::lengthOfUInt64("x432 x", 1, 10, &value));
- checkEqu(432LL, value);
- checkEqu(3, ReQString::lengthOfUInt64("x432fabc x", 1, 10, &value));
- checkEqu(432LL, value);
- checkEqu(16, ReQString::lengthOfUInt64("a1234567890123567", 1, 10, &value));
- checkEqu(1234567890123567LL, value);
- checkEqu(10, ReQString::lengthOfUInt64("x1234abcdef", 1, 16, &value));
- checkEqu(0x1234abcdefLL, value);
- checkEqu(3, ReQString::lengthOfUInt64("432", 0, 8, &value));
- checkEqu(0432LL, value);
- checkEqu(6, ReQString::lengthOfUInt64(" 765432 ", 1, 8, &value));
- checkEqu(0765432LL, value);
-
- checkEqu(0, ReQString::lengthOfUInt64("1 ", 1, 8, &value));
- checkEqu(0, ReQString::lengthOfUInt64("", 1, 8, &value));
- }
- void testLengthOfUInt(){
- uint value = 3;
- checkEqu(1, ReQString::lengthOfUInt(ReString("0"), 0, 10, &value));
- checkEqu(0, value);
- checkEqu(3, ReQString::lengthOfUInt("x432", 1, 10, &value));
- checkEqu(432, value);
- checkEqu(3, ReQString::lengthOfUInt("x432 x", 1, 10, &value));
- checkEqu(432, value);
- checkEqu(3, ReQString::lengthOfUInt("x432fabc x", 1, 10, &value));
- checkEqu(432, value);
- checkEqu(3, ReQString::lengthOfUInt("432", 0, 8, &value));
- checkEqu(0432, value);
- checkEqu(6, ReQString::lengthOfUInt(" 765432 ", 1, 8, &value));
- checkEqu(0765432, value);
-
- checkEqu(0, ReQString::lengthOfUInt("1 ", 1, 8, &value));
- checkEqu(0, ReQString::lengthOfUInt("", 1, 8, &value));
- }
- void testLengthOfReal(){
- qreal value;
- checkEqu(4, ReQString::lengthOfReal(ReString("0.25"), 0, &value));
- checkEqu(0.25, value);
- checkEqu(3, ReQString::lengthOfReal(ReString("X.25"), 1, &value));
- checkEqu(0.25, value);
- checkEqu(1, ReQString::lengthOfReal(ReString(" 0"), 1, &value));
- checkEqu(0.0, value);
- checkEqu(17, ReQString::lengthOfReal(ReString("X12345678901234567"), 1, &value));
- checkEqu(12345678901234567.0, value);
- checkEqu(2, ReQString::lengthOfReal(ReString(".5"), 0, &value));
- checkEqu(0.5, value);
- checkEqu(5, ReQString::lengthOfReal(ReString("2.5e2x"), 0, &value));
- checkEqu(250.0, value);
- checkEqu(6, ReQString::lengthOfReal(ReString("2.5e+2"), 0, &value));
- checkEqu(250.0, value);
- checkEqu(7, ReQString::lengthOfReal(ReString("2.5E-33"), 0, &value));
- checkEqu(2.5e-33, value);
-
- checkEqu(3, ReQString::lengthOfReal(ReString("2.5E"), 0, &value));
- checkEqu(2.5, value);
- checkEqu(3, ReQString::lengthOfReal(ReString("2.5E+"), 0, &value));
- checkEqu(2.5, value);
- checkEqu(3, ReQString::lengthOfReal(ReString("2.5E-a"), 0, &value));
- checkEqu(2.5, value);
- }
-
- void testValueOfHexDigit(){
- checkEqu(0, ReQString::valueOfHexDigit('0'));
- checkEqu(9, ReQString::valueOfHexDigit('9'));
- checkEqu(10, ReQString::valueOfHexDigit('a'));
- checkEqu(15, ReQString::valueOfHexDigit('f'));
- checkEqu(10, ReQString::valueOfHexDigit('A'));
- checkEqu(15, ReQString::valueOfHexDigit('F'));
-
- checkEqu(-1, ReQString::valueOfHexDigit('0' - 1));
- checkEqu(-1, ReQString::valueOfHexDigit('9' + 1));
- checkEqu(-1, ReQString::valueOfHexDigit('A' - 1));
- checkEqu(-1, ReQString::valueOfHexDigit('F' + 1));
- checkEqu(-1, ReQString::valueOfHexDigit('a' - 1));
- checkEqu(-1, ReQString::valueOfHexDigit('f' + 1));
- }
- void testUtf8(){
- ReString name = "Heinz Müller";
- char buffer[32];
- checkEqu("Heinz Müller", ReQString::utf8(name, buffer, sizeof buffer));
- memset(buffer, 'x', sizeof buffer);
- checkEqu("Heinz", ReQString::utf8(name, buffer, (size_t) (5+1)));
- checkEqu(buffer[6], 'x');
- }
-
- virtual void doIt(void) {
- testUtf8();
- testLengthOfUInt64();
- testLengthOfUInt();
- testLengthOfReal();
- testValueOfHexDigit();
- }
-};
-void testRplQString() {
- TestRplQString test;
- test.run();
-}
-
+++ /dev/null
-/*
- * rplsource_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-/** @file
- * @brief Unit test of the input media reader.
- */
-
-#include "base/rebase.hpp"
-#include "expr/reexpr.hpp"
-#include "rplcore/rpltest.hpp"
-
-class TestReSource : public ReTest{
-public:
- TestReSource() : ReTest("TestReSource") {}
-
-private:
- QByteArray m_content1_1;
- QByteArray m_content1_2;
- QByteArray m_content2;
- ReSource m_source;
-
-protected:
- void init(){
- m_content1_1 = "# test\nimport source2\n";
- m_content1_2 = "a=1;\nveeeeeeeeery looooooooooooooong\n";
- m_content2 = "x=2";
- }
-
- void testReStringSourceUnit(){
- ReStringReader reader(m_source);
- QByteArray content("a=1;\nveeeeeeeeery looooooooooooooong\n");
- ReStringSourceUnit unit("test", content, &reader);
- unit.setLineNo(144);
- checkEqu(144, unit.lineNo());
- checkEqu("test", unit.name());
- }
- void checkOne(int maxSize, ReReader& reader){
- QByteArray total;
- QByteArray buffer;
- int lineNo = 0;
- bool hasMore;
- checkF(reader.openSourceUnit("unknownSource"));
- checkT(reader.openSourceUnit("source1"));
- while(reader.nextLine(maxSize, buffer, hasMore)){
- lineNo++;
- total += buffer;
- buffer.clear();
- while(hasMore && reader.fillBuffer(maxSize, buffer, hasMore)){
- total += buffer;
- buffer.clear();
- }
- bool isImport = total.endsWith("source2\n");
- if (isImport){
- reader.openSourceUnit("source2");
- checkEqu("source2", reader.currentSourceUnit()->name());
- while(reader.nextLine(maxSize, buffer, hasMore)){
- lineNo++;
- while(hasMore && reader.fillBuffer(maxSize, buffer, hasMore)){
- total += buffer;
- buffer.clear();
- }
- }
- checkEqu("source1", reader.currentSourceUnit()->name());
- }
- }
- checkEqu(5, lineNo);
- checkEqu(m_content1_1 + m_content2 + m_content1_2, total);
-
- }
-
- void testReStringReader(){
- ReStringReader reader(m_source);
- reader.addSource("source1", m_content1_1 + m_content1_2);
- reader.addSource("source2", m_content2);
- ReSourceUnit* unit = reader.openSourceUnit("source1");
- checkNN(unit);
- checkEqu("source1", unit->name());
- checkEqu(0, unit->lineNo());
- checkOne(6, reader);
- checkOne(100, reader);
- reader.replaceSource("source2", "content2");
-
- unit = reader.openSourceUnit("source2");
- QByteArray buffer;
- bool hasMore;
- checkT(reader.nextLine(50, buffer, hasMore));
- checkEqu("content2", buffer);
- checkF(hasMore);
- }
-
-public:
- virtual void doIt(void) {
- init();
- testReStringSourceUnit();
- testReStringReader();
- }
-};
-void testReSource() {
- TestReSource test;
- test.run();
-}
-
-
-
+++ /dev/null
-/*
- * rplstring_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-/** @file
- * @brief Unit test of the QByteArray tools.
- */
-#include "base/rebase.hpp"
-#include "rplcore/rpltest.hpp"
-/**
- * @brief Unit test for <code>ReStringUtil</code>.
- */
-class TestReString : public ReTest {
-public:
- TestReString() : ReTest("ReStringUtil") {}
-
-public:
- void testCountChar(){
- checkEqu(1, ReStringUtil::countChar("x", 'x'));
- checkEqu(0, ReStringUtil::countChar("X", 'x'));
- checkEqu(2, ReStringUtil::countChar("xbxxbxx", 'b'));
- }
-
- void testCount() {
- checkEqu(0, ReStringUtil::count("abc", " "));
- checkEqu(1, ReStringUtil::count("abc", "b"));
- checkEqu(2, ReStringUtil::count("axx", "x"));
-
- checkEqu(0, ReStringUtil::count("abbc", "bbb"));
- checkEqu(1, ReStringUtil::count("\n\n", "\n\n"));
- checkEqu(2, ReStringUtil::count(" a ", " "));
- }
-
- void testCutString() {
- QByteArray source("123");
- QByteArray buffer;
- checkEqu(QByteArray("123"), ReStringUtil::cutString(source, 4, buffer));
- checkEqu(QByteArray("123"), ReStringUtil::cutString(source, 3, buffer));
- checkEqu(QByteArray("12..."), ReStringUtil::cutString(source, 2, buffer));
- checkEqu(QByteArray("12"), ReStringUtil::cutString(source, 2, buffer, ""));
- }
-
- void testHexDump() {
- QByteArray data("abc123\nxyz");
- checkEqu(QByteArray("61 62 63 31 abc1\n"
- "32 33 0a 78 23.x\n"
- "79 7a yz\n"),
- ReStringUtil::hexDump((uint8_t*) data.constData(), data.length(), 4));
- checkEqu(QByteArray("61 62 63 31 32 33 0a 78 79 7a abc123.xyz"),
- ReStringUtil::hexDump((uint8_t*) data.constData(), data.length(), 10));
- checkEqu(QByteArray("61 62 63 31 32 33 0a 78 79 7a abc123.xyz"),
- ReStringUtil::hexDump((uint8_t*) data.constData(), data.length(), 12));
- }
-
- void testReadWrite() {
- QByteArray fn = getTempFile("test.dat");
- const char* content = "Hello world\nLine2\n";
- checkT(ReStringUtil::write(fn, content));
- checkEqu(content, ReStringUtil::read(fn, false));
- checkEqu(content, ReStringUtil::read(fn, true) + "\n");
- }
-
- void testToArray() {
- QList<QByteArray> array = ReStringUtil::toArray("1 abc 3", " ");
- checkEqu(3, array.size());
- checkEqu("1", array.at(0));
- checkEqu("abc", array.at(1));
- checkEqu("3", array.at(2));
- }
-
- void testToNumber() {
- checkEqu("3", ReStringUtil::toNumber(3));
- checkEqu("-33", ReStringUtil::toNumber(-33));
- checkEqu("003", ReStringUtil::toNumber(3, "%03d"));
- }
-
- void testLengthOfNumber(){
- checkEqu(3, ReStringUtil::lengthOfNumber("0.3xxx"));
- checkEqu(5, ReStringUtil::lengthOfNumber(" \t0.3xxx"));
- checkEqu(3, ReStringUtil::lengthOfNumber("-.3xxx"));
- checkEqu(2, ReStringUtil::lengthOfNumber(".3exxx"));
- checkEqu(2, ReStringUtil::lengthOfNumber(".3e+xxx"));
- checkEqu(16, ReStringUtil::lengthOfNumber("1234567.9012E+77"));
- checkEqu(17, ReStringUtil::lengthOfNumber("-1234567.9012E+77 "));
- checkEqu(18, ReStringUtil::lengthOfNumber("-1234567.9012E+77 ", true));
- checkEqu(18, ReStringUtil::lengthOfNumber("-1234567.9012E+77 x", true));
- checkEqu(20, ReStringUtil::lengthOfNumber(" -1234567.9012E+77 x", true));
- }
-
- void checkCsv(const char* content, char expected){
- QByteArray fn = getTempFile("testrplstring.csv");
- ReStringUtil::write(fn, content);
- FILE* fp = fopen(fn, "r");
- checkNN(fp);
- char buffer[256];
- checkEqu(expected, ReStringUtil::findCsvSeparator(fp, buffer, sizeof buffer));
- fclose(fp);
- }
-
- void testFindCsvSeparator(){
- const char* content = ",,,\t;;;||||";
- checkCsv(content, '\t');
-
- content = "col1,col2\n1.5,3,5\n";
- checkCsv(content, ',');
-
- content = "col1;col2\n1,50;3.5\n"
- "7;8\n10;12\n13;14";
- checkCsv(content, ';');
-
- content = "0.3 7.8 8.9\n7.8 9.4 8.3";
- checkCsv(content, ' ');
-
- content = "0.3|7.8|8.9\n7.8| 9.4|8.3";
- checkCsv(content, '|');
-
- content = "0,3;7.8;8.9";
- checkCsv(content, ';');
- }
- void testLengthOfUInt64(){
- quint64 value = -3;
- checkEqu(1, ReStringUtil::lengthOfUInt64("0", 10, &value));
- checkEqu(0LL, value);
- checkEqu(3, ReStringUtil::lengthOfUInt64("432", 10, &value));
- checkEqu(432LL, value);
- checkEqu(3, ReStringUtil::lengthOfUInt64("432 x", 10, &value));
- checkEqu(432LL, value);
- checkEqu(3, ReStringUtil::lengthOfUInt64("432fabc x", 10, &value));
- checkEqu(432LL, value);
- checkEqu(16, ReStringUtil::lengthOfUInt64("1234567890123567", 10, &value));
- checkEqu(1234567890123567LL, value);
- checkEqu(10, ReStringUtil::lengthOfUInt64("1234abcdef", 16, &value));
- checkEqu(0x1234abcdefLL, value);
- checkEqu(3, ReStringUtil::lengthOfUInt64("432", 8, &value));
- checkEqu(0432LL, value);
- checkEqu(6, ReStringUtil::lengthOfUInt64("765432 ", 8, &value));
- checkEqu(0765432LL, value);
-
- checkEqu(0, ReStringUtil::lengthOfUInt64(" ", 8, &value));
- checkEqu(0, ReStringUtil::lengthOfUInt64("", 8, &value));
- }
- void testLengthOfReal(){
- qreal value;
- checkEqu(1, ReStringUtil::lengthOfReal("0", &value));
- checkEqu(0.0, value);
- checkEqu(1, ReStringUtil::lengthOfReal("0%", &value));
- checkEqu(0.0, value);
- checkEqu(4, ReStringUtil::lengthOfReal("0.25", &value));
- checkEqu(0.25, value);
- checkEqu(3, ReStringUtil::lengthOfReal(".25", &value));
- checkEqu(0.25, value);
- checkEqu(17, ReStringUtil::lengthOfReal("12345678901234567", &value));
- checkEqu(12345678901234567.0, value);
- checkEqu(2, ReStringUtil::lengthOfReal(".5", &value));
- checkEqu(0.5, value);
- checkEqu(5, ReStringUtil::lengthOfReal("2.5e2x", &value));
- checkEqu(250.0, value);
- checkEqu(6, ReStringUtil::lengthOfReal("2.5e+2", &value));
- checkEqu(250.0, value);
- checkEqu(7, ReStringUtil::lengthOfReal("2.5E-33", &value));
- checkEqu(2.5e-33, value);
-
- checkEqu(3, ReStringUtil::lengthOfReal("2.5E", &value));
- checkEqu(2.5, value);
- checkEqu(3, ReStringUtil::lengthOfReal("2.5E+", &value));
- checkEqu(2.5, value);
- checkEqu(3, ReStringUtil::lengthOfReal("2.5E-a", &value));
- checkEqu(2.5, value);
- }
-
- virtual void doIt() {
- testLengthOfReal();
- testLengthOfUInt64();
- testCountChar();
- testCount();
- testCutString();
- testToNumber();
- testToArray();
- testHexDump();
- testReadWrite();
- testLengthOfNumber();
- testFindCsvSeparator();
- }
-};
-
-void testReString() {
- TestReString test;
- test.run();
-}
-
-
-
+++ /dev/null
-/*
- * rplvm_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-#include "base/rebase.hpp"
-#include "expr/reexpr.hpp"
-#include "rplcore/rpltest.hpp"
-
-class TestReVM : public ReTest{
-private:
- ReSource m_source;
- ReASTree m_tree;
- ReStringReader m_reader;
- const char* m_currentSource;
-public:
- TestReVM() :
- ReTest("ReVM"),
- m_source(),
- m_tree(),
- m_reader(m_source)
- {
- m_source.addReader(&m_reader);
- }
-protected:
- void setSource(const char* content){
- ReASItem::reset();
- m_currentSource = content;
- m_tree.clear();
- m_source.clear();
- m_reader.clear();
- m_reader.addSource("<test>", content);
- m_source.addReader(&m_reader);
- m_source.addSourceUnit(m_reader.currentSourceUnit());
- }
-
-private:
- void checkAST(const char* fileExpected, int lineNo){
- QByteArray fnExpected = "test";
- fnExpected += QDir::separator().toLatin1();
- fnExpected += "ReVM";
- fnExpected += (char) QDir::separator().toLatin1();
- fnExpected += fileExpected;
- QByteArray fnCurrent = getTempFile(fileExpected, "ReVM");
- ReMFParser parser(m_source, m_tree);
- parser.parse();
- ReVirtualMachine vm(m_tree, m_source);
- vm.setFlag(ReVirtualMachine::VF_TRACE_STATEMENTS);
- ReFileWriter writer(fnCurrent);
- vm.setTraceWriter(&writer);
- writer.write(m_currentSource);
- vm.executeModule("<test>");
- assertEqualFiles(fnExpected.constData(), fnCurrent.constData(),
- __FILE__, lineNo);
- }
-public:
- void baseTest(){
- setSource("Int a=2+3*4;\nfunc Void main():\na;\nendf");
- checkAST("baseTest.txt", __LINE__);
- }
- virtual void doIt(void) {
- baseTest();
- }
-};
-void testReVM() {
- TestReVM test;
- test.run();
-}
-
+++ /dev/null
-/*
- * rplwriter_test.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-/** @file
- * @brief Unit test of the output media writers.
- */
-
-#include "base/rebase.hpp"
-#include "rplcore/rpltest.hpp"
-/**
- * @brief Unit test for <code>ReStringUtil</code>.
- */
-class TestRplWriter : public ReTest {
-public:
- TestRplWriter() : ReTest("ReWriter") {}
-
-private:
- void testFileWriter(){
- QByteArray fn = getTempFile("rplwriter.txt");
- ReFileWriter writer(fn);
- writer.writeLine("abc");
- writer.formatLine("%04d", 42);
- writer.writeIndented(3, "123");
- writer.indent(2);
- writer.write("pi");
- writer.format("%3c%.2f", ':', 3.1415);
- writer.writeLine();
- writer.close();
- QByteArray current = ReStringUtil::read(fn, false);
- checkEqu("abc\n0042\n\t\t\t123\n\t\tpi :3.14\n", current);
- }
-
-public:
- virtual void doIt(void) {
- testFileWriter();
- }
-};
-void testRplWriter() {
- TestRplWriter test;
- test.run();
-}
-
-
-
throw ReLexException(*m_currentPosition,
"missing hexadecimal digit behind \\x");
cc = m_input[length++];
- int hexVal = ReQString::valueOfHexDigit(cc);
+ int hexVal = ReQStringUtil::valueOfHexDigit(cc);
if (hexVal < 0)
throw ReLexException(*m_currentPosition,
"not a hexadecimal digit behind \\x: %lc", QChar(cc));
if (length < inputLength){
cc = m_input[length];
- int nibble = ReQString::valueOfHexDigit(cc);
+ int nibble = ReQStringUtil::valueOfHexDigit(cc);
if (nibble >= 0){
length++;
hexVal = hexVal * 16 + nibble;
#ifndef RETCPCLIENT_HPP
#define RETCPCLIENT_HPP
+#ifndef REBASE_HPP
+#include "base/rebase.hpp"
+#include "math/remath.hpp"
+#include "net/renet.hpp"
+#endif
+
+
class ReTCPPeer;
class RplTcpClient: public QObject {
#ifndef RPLTCPPEER_HPP
#define RPLTCPPEER_HPP
+#ifndef REBASE_HPP
+#include "base/rebase.hpp"
+#include "math/remath.hpp"
+#include "net/renet.hpp"
+#endif
+
class ReTCPPeer: public QObject {
Q_OBJECT
public:
/*
* ReTCPServer.hpp
- *
+ *
* License: Public Domain
* You can use and modify this file without any restriction.
* Do what you want.
#ifndef RPLTCPSERVER_HPP
#define RPLTCPSERVER_HPP
+#ifndef REBASE_HPP
+#include "base/rebase.hpp"
+#include "math/remath.hpp"
+#include "net/renet.hpp"
+#endif
+
// the sources generated from QT include this file directly:
#ifndef RPLNET_HPP
#include "renet.hpp"
--- /dev/null
+/*
+ * ReTraverser.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+#include "base/rebase.hpp"
+#include "os/reos.hpp"
+#if defined __WIN32__
+#include "accctrl.h"
+#include "aclapi.h"
+#pragma comment(lib, "advapi32.lib")
+#endif
+
+enum {
+ LC_RIGHTS_AS_STRING_1 = LOC_FIRST_OF(LOC_TRAVERSER), // 50401
+ LC_RIGHTS_AS_STRING_2, // 50402
+ LC_RIGHTS_AS_STRING_3, // 50403
+ LC_GET_PRIVILEGE_1, // 50404
+ LC_GET_PRIVILEGE_2, // 50405
+ LC_GET_PRIVILEGE_3, // 50406
+ LC_GET_FILE_OWNER_1, // 50407
+ LC_GET_FILE_OWNER_2, // 50408
+};
+
+int ReDirEntryFilter::m_serialId = buildSerialId(CLASSID_DIR_ENTRY_FILTER, 1);
+
+/**
+ * Constructor.
+ */
+ReDirStatus_t::ReDirStatus_t(ReLogger* logger) :
+ m_path(),
+ m_fullName(),
+ m_passNo(0),
+ m_logger(logger),
+#ifdef __linux__
+ m_handle(NULL),
+ m_data(NULL)
+//m_status;
+#elif defined WIN32
+m_handle(INVALID_HANDLE_VALUE),
+//m_data;
+m_getPrivilege(true)
+#endif
+{
+#ifdef __linux__
+ memset(&m_status, 0, sizeof m_status);
+#elif defined WIN32
+ memset(&m_data, 0, sizeof m_data);
+#endif
+}
+
+/**
+ * Returns the last access time.
+ *
+ * @return the last access time
+ */
+const ReFileTime_t* ReDirStatus_t::accessed() {
+#ifdef __linux__
+ return &(getStatus()->st_atim);
+#elif defined __WIN32__
+ return &m_data.ftLastAccessTime;
+#endif
+}
+
+/**
+ * Returns the filesize.
+ *
+ * @return the filesize
+ */
+ReFileSize_t ReDirStatus_t::fileSize() {
+#ifdef __linux__
+ return getStatus()->st_size;
+#elif defined __WIN32__
+ return ((int64_t) m_data.nFileSizeHigh << 32) + m_data.nFileSizeLow;
+#endif
+}
+
+/**
+ * Returns the file time as a string.
+ *
+ * @param buffer OUT: the file time
+ * @return <code>buffer.str()</code> (for chaining)
+ */
+const char* ReDirStatus_t::filetimeAsString(ReByteBuffer& buffer) {
+ return filetimeToString(modified(), buffer);
+}
+
+/**
+ * Converts a filetime to a string.
+ *
+ * @param time the filetime to convert
+ * @param buffer OUT: the buffer for the string
+ * @return <code>buffer.str()</code>, e.g. "2014.01.07 02:59:43"
+ */
+const char* ReDirStatus_t::filetimeToString(const ReFileTime_t* time,
+ ReByteBuffer& buffer) {
+ time_t time1 = filetimeToTime(time);
+ struct tm* time2 = localtime(&time1);
+ buffer.setLength(4 + 2 * 2 + 2 * 2 + 1 + 3 * 2 + 2 * 1);
+ strftime(buffer.buffer(), buffer.length(), "%Y.%m.%d %H:%M:%S", time2);
+ return buffer.str();
+}
+
+/**
+ * Converts a filetime to a unix time (seconds since the Epoche).
+ *
+ * @param filetime the filetime to convert
+ * @return the count of seconds since 1.1.1970
+ */
+time_t ReDirStatus_t::filetimeToTime(const ReFileTime_t* filetime) {
+#ifdef __linux__
+ return filetime->tv_sec;
+#elif defined __WIN32__
+ // 64-bit arithmetic:
+ LARGE_INTEGER date, adjust;
+ date.HighPart = filetime->dwHighDateTime;
+ date.LowPart = filetime->dwLowDateTime;
+ // 100-nanoseconds = milliseconds * 10000
+ adjust.QuadPart = 11644473600000 * 10000;
+ // removes the diff between 1970 and 1601
+ date.QuadPart -= adjust.QuadPart;
+ // converts back from 100-nanoseconds to seconds
+ time_t rc = (time_t) (date.QuadPart / 10000000);
+ return rc;
+#endif
+}
+
+/**
+ * Loads the info about the first file into the instance.
+ *
+ * @return <code>true</code>: success
+ */
+bool ReDirStatus_t::findFirst() {
+ bool rc = false;
+#if defined __linux__
+ if (m_handle != NULL)
+ closedir(m_handle);
+ m_handle = opendir(m_path.str());
+ rc = m_handle != NULL && (m_data = readdir(m_handle)) != NULL;
+ m_status.st_ino = 0;
+#elif defined __WIN32__
+ if (m_handle != INVALID_HANDLE_VALUE)
+ FindClose(m_handle);
+ ReByteBuffer thePath(m_path);
+ thePath.append(m_path.lastChar() == '\\' ? "*" : "\\*");
+ m_handle = FindFirstFileA(thePath.str(), &m_data);
+ rc = m_handle != INVALID_HANDLE_VALUE;
+#endif
+ m_fullName.setLength(0);
+ return rc;
+}
+
+/**
+ * Loads the info about the next file into the instance.
+ *
+ * @return <code>true</code>: success
+ */
+bool ReDirStatus_t::findNext() {
+#if defined __linux__
+ bool rc = m_handle != NULL && (m_data = readdir(m_handle)) != NULL;
+ m_status.st_ino = 0;
+#elif defined __WIN32__
+ bool rc = m_handle != INVALID_HANDLE_VALUE && FindNextFileA(m_handle, &m_data);
+#endif
+ m_fullName.setLength(0);
+ return rc;
+}
+
+/**
+ * Frees the resources of an instance.
+ */
+void ReDirStatus_t::freeEntry() {
+#if defined __linux__
+ if (m_handle != NULL) {
+ closedir(m_handle);
+ m_handle = NULL;
+ }
+#elif defined __WIN32__
+ if (m_handle != INVALID_HANDLE_VALUE) {
+ FindClose(m_handle);
+ m_handle = INVALID_HANDLE_VALUE;
+ }
+#endif
+ m_path.setLength(0);
+ m_fullName.setLength(0);
+}
+
+/**
+ * Returns the full filename (with path).
+ *
+ * @return the filename with path
+ */
+const char* ReDirStatus_t::fullName() {
+ if (m_fullName.length() == 0)
+ m_fullName.set(m_path).append(node(), -1);
+ return m_fullName.str();
+}
+
+#if defined __WIN32__
+/** Gets the name of the file owner.
+ *
+ * @param handle file handle (see <code>CreateFile()</code>)
+ * @param name OUT: the owner: [domain\\]name
+ * @return <code>true</code>: success
+ */
+bool ReDirStatus_t::getFileOwner(HANDLE handle, const char* file,
+ ReByteBuffer& name, ReLogger* logger) {
+ bool rc = false;
+ PSID pSidOwner = NULL;
+ PSECURITY_DESCRIPTOR pSD = NULL;
+ if (GetSecurityInfo(handle, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION, &pSidOwner, NULL, NULL, NULL, &pSD) != ERROR_SUCCESS) {
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_GET_FILE_OWNER_1,
+ "GetSecurityInfo($1): $2").arg(file).arg((int) GetLastError()).end();
+ } else {
+ char accountName[128];
+ char domainName[128];
+ DWORD dwAcctName = sizeof accountName;
+ DWORD dwDomainName = sizeof domainName;
+ SID_NAME_USE eUse = SidTypeUnknown;
+ if (! LookupAccountSid(NULL, pSidOwner, accountName, &dwAcctName, domainName,
+ &dwDomainName, &eUse)) {
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_SECURITY, LC_GET_FILE_OWNER_2,
+ "LookupAccountSid(): $1").arg((int) GetLastError()).end();
+ } else {
+ if (dwDomainName > 0)
+ name.append(domainName).appendChar('\\');
+ name.append(accountName);
+ rc = true;
+ }
+ }
+ return rc;
+}
+#endif /* __WIN32__ */
+
+#if defined __WIN32__
+/** Tries to get a privilege.
+ *
+ * @param privilege the name of the privilege, e.g. "SeBackup"
+ * @param logger logger for error logging
+ */
+bool ReDirStatus_t::getPrivilege(const char* privilege, ReLogger* logger) {
+ bool rc = false;
+ LUID luidPrivilege;
+ HANDLE hAccessToken;
+ if (! OpenProcessToken (GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hAccessToken)) {
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_GET_PRIVILEGE_1,
+ "OpenProcessToken(): $1").arg((int) GetLastError()).end();
+ } else if (! LookupPrivilegeValue (NULL, SE_BACKUP_NAME, &luidPrivilege)) {
+ if (logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_GET_PRIVILEGE_2,
+ "LookupPrivilegeValue(): $1").arg((int) GetLastError()).end();
+ } else {
+ TOKEN_PRIVILEGES tpPrivileges;
+ tpPrivileges.PrivilegeCount = 1;
+ tpPrivileges.Privileges[0].Luid = luidPrivilege;
+ tpPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+ if (AdjustTokenPrivileges (hAccessToken, FALSE, &tpPrivileges,
+ 0, NULL, NULL) == 0)
+ rc = true;
+ else {
+ int error = GetLastError();
+ if (error != 1300 && logger != NULL)
+ logger->sayF(LOG_ERROR | CAT_FILE, LC_GET_PRIVILEGE_3,
+ "AdjustTokenPrivileges(): $1").arg((int) GetLastError()).end();
+ }
+ }
+ return rc;
+}
+#endif /* __WIN32__ */
+
+/**
+ * Tests whether the instance is a directory.
+ *
+ * @return <code>true</code>: instance contains the data of a directory
+ */
+bool ReDirStatus_t::isDirectory() {
+#ifdef __linux__
+ return m_data->d_type == DT_DIR
+ || (m_data->d_type == DT_UNKNOWN && S_ISDIR(getStatus()->st_mode));
+#elif defined __WIN32__
+ return 0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+#endif
+}
+
+/**
+ * Tests whether the instance contains data about "." or "..".
+ *
+ * @return <code>true</code>: an ignorable entry has been found
+ */
+bool ReDirStatus_t::isDotDir() const {
+#ifdef __linux__
+ bool rc = m_data == NULL
+ || (m_data->d_name[0] == '.'
+ && (m_data->d_name[1] == '\0'
+ || (m_data->d_name[1] == '.' && m_data->d_name[2] == '\0')));
+#elif defined __WIN32__
+ bool rc = m_data.cFileName[0] == '.' && (m_data.cFileName[1] == '\0'
+ || (m_data.cFileName[1] == '.' && m_data.cFileName[2] == '\0'));
+#endif
+ return rc;
+}
+
+/**
+ * Tests whether the instance is a symbolic link.
+ *
+ * Unter windows it tests whether the the instance is a reparse point.
+ *
+ * @return <code>true</code>: instance contains the data of a link
+ */
+bool ReDirStatus_t::isLink() {
+ bool rc;
+#ifdef __linux__
+ rc = m_data->d_type == DT_LNK
+ || (m_data->d_type == DT_UNKNOWN && S_ISLNK(getStatus()->st_mode));
+#elif defined __WIN32__
+ rc = 0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT);
+#endif
+ return rc;
+}
+/**
+ * Tests whether the instance is a "normal" file.
+ *
+ * @return <code>true</code>: instance contains the data of a not special file
+ */
+bool ReDirStatus_t::isRegular() {
+#ifdef __linux__
+ return m_data->d_type == DT_REG
+ || (m_data->d_type == DT_UNKNOWN && S_ISREG(getStatus()->st_mode));
+#elif defined __WIN32__
+ return 0 == (m_data.dwFileAttributes & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE));
+#endif
+}
+/**
+ * Returns the modification time.
+ *
+ * @return the modification time
+ */
+const ReFileTime_t* ReDirStatus_t::modified() {
+#ifdef __linux__
+ return &(getStatus()->st_mtim);
+#elif defined __WIN32__
+ return &m_data.ftLastWriteTime;
+#endif
+}
+
+/**
+ * Returns the name of the current file (without path).
+ *
+ * @return the name of the current file.
+ */
+const char* ReDirStatus_t::node() const {
+#ifdef __linux__
+ return m_data->d_name;
+#elif defined __WIN32__
+ return m_data.cFileName;
+#endif
+}
+
+inline void addRight(int mode, ReByteBuffer& buffer) {
+ char right;
+ switch (mode & 7) {
+ case 1:
+ right = 'x';
+ break;
+ case 2:
+ right = 'w';
+ break;
+ case 3:
+ right = 'X';
+ break;
+ case 4:
+ right = 'r';
+ break;
+ case 5:
+ right = 'R';
+ break;
+ case 6:
+ right = 'W';
+ break;
+ case 7:
+ right = 'A';
+ break;
+ default:
+ right = '-';
+ break;
+ }
+ buffer.appendChar(right);
+}
+inline void addId(const char* id, int maxLength, ReByteBuffer& buffer) {
+ int length = strlen(id);
+ if (length == maxLength)
+ buffer.append(id, length);
+ else if (length < maxLength)
+ buffer.append(id, length).appendChar(' ', maxLength - length);
+ else {
+ buffer.append(id, 2);
+ buffer.append(id + length - maxLength - 2, maxLength - 2);
+ }
+}
+/**
+ * Returns the file rights as a string.
+ *
+ * @param buffer OUT: the file rights
+ * @param numerical <code>true</code>: the owner/group should be numerical (UID/GID)
+ * @param ownerWidth the width for group/owner
+ * @return <code>buffer.str()</code> (for chaining)
+ */
+const char* ReDirStatus_t::rightsAsString(ReByteBuffer& buffer, bool numerical,
+ int ownerWidth) {
+ buffer.setLength(0);
+#if defined __linux__
+ if (numerical) {
+ buffer.appendInt(getStatus()->st_mode & ALLPERMS, "%04o");
+ buffer.appendInt(getStatus()->st_uid, " %4d");
+ buffer.appendInt(getStatus()->st_gid, " %4d");
+ } else {
+ int mode = getStatus()->st_mode & ALLPERMS;
+ addRight(mode >> 6, buffer);
+ addRight(mode >> 3, buffer);
+ addRight(mode, buffer);
+ buffer.appendChar(' ');
+ struct passwd* passwd = getpwuid(getStatus()->st_uid);
+ if (passwd == NULL)
+ buffer.appendInt(getStatus()->st_uid, "%4d");
+ else
+ addId(passwd->pw_name, 5, buffer);
+ buffer.appendChar(' ');
+ struct group* group = getgrgid(getStatus()->st_gid);
+ if (group == NULL)
+ buffer.appendInt(getStatus()->st_gid, "%4d");
+ else
+ addId(group->gr_name, 5, buffer);
+ buffer.appendChar(' ');
+ }
+#elif defined __WIN32__
+ const char* name = fullName();
+ HANDLE handle = INVALID_HANDLE_VALUE;
+ if (! isDirectory()) {
+ if ( (handle = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
+ m_logger->sayF(LOG_ERROR | CAT_FILE, LC_RIGHTS_AS_STRING_1,
+ "CreateFile($1): $2").arg(name).arg((int) GetLastError()).end();
+ } else if (m_getPrivilege) {
+ // we try only one time:
+ m_getPrivilege = false;
+ if (getPrivilege(SE_BACKUP_NAME, m_logger)) {
+ if ( (handle = CreateFile(name, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ NULL)) != INVALID_HANDLE_VALUE)
+ m_logger->sayF(LOG_ERROR | CAT_FILE, LC_RIGHTS_AS_STRING_2,
+ "CreateFile($1): $2").arg(name).arg((int) GetLastError()).end();
+ }
+
+ }
+ ReByteBuffer owner;
+ if (handle != INVALID_HANDLE_VALUE)
+ getFileOwner(handle, name, owner, m_logger);
+ CloseHandle(handle);
+ buffer.appendFix(owner.str(), owner.length(), ownerWidth, ownerWidth);
+#endif
+ return buffer.str();
+}
+
+/**
+ * Converts the unix time (time_t) to the file time.
+ *
+ * @param time the unix time (secondes since 1.1.1970)
+ * @param filetime OUT: the OS specific filetime
+ */
+void ReDirStatus_t::timeToFiletime(time_t time, ReFileTime_t& filetime) {
+#ifdef __linux__
+ filetime.tv_sec = time;
+ filetime.tv_nsec = 0;
+#elif defined __WIN32__
+ LONGLONG ll = Int32x32To64(time, 10000000) + 116444736000000000;
+ filetime.dwLowDateTime = (DWORD)ll;
+ filetime.dwHighDateTime = ll >> 32;
+#endif
+}
+/**
+ * Returns the type of the entry.
+ * return the file type, e.g. TF_REGULAR
+ */
+ReDirStatus_t::Type_t ReDirStatus_t::type() {
+ Type_t rc = TF_UNDEF;
+#if defined __linux__
+ int flags = getStatus()->st_mode;
+ if (S_ISDIR(flags))
+ rc = TF_SUBDIR;
+ else if (flags == 0 || S_ISREG(flags))
+ rc = TF_REGULAR;
+ else if (S_ISLNK(flags))
+ rc = TF_LINK;
+ else if (S_ISCHR(flags))
+ rc = TF_CHAR;
+ else if (S_ISBLK(flags))
+ rc = TF_BLOCK;
+ else if (S_ISFIFO(flags))
+ rc = TF_PIPE;
+ else if (S_ISSOCK(flags))
+ rc = TF_SOCKET;
+ else
+ rc = TF_OTHER;
+#elif defined __WIN32__
+ int flags = (m_data.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY
+ | FILE_ATTRIBUTE_HIDDEN
+ | FILE_ATTRIBUTE_SYSTEM
+ | FILE_ATTRIBUTE_ARCHIVE
+ | FILE_ATTRIBUTE_NORMAL
+ | FILE_ATTRIBUTE_TEMPORARY
+ | FILE_ATTRIBUTE_SPARSE_FILE
+ | FILE_ATTRIBUTE_COMPRESSED
+ | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
+ | FILE_ATTRIBUTE_ENCRYPTED
+ | FILE_ATTRIBUTE_HIDDEN));
+
+ if (0 == flags)
+ rc = TF_REGULAR;
+ else if (0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ rc = (0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
+ ? TF_LINK_DIR : TF_SUBDIR;
+ } else if (0 != (m_data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
+ rc = TF_LINK;
+ else
+ rc = TF_OTHER;
+#endif
+ return rc;
+}
+
+/**
+ * Returns the filetype as a single character.
+ *
+ * @return the filetype, e.g. 'd' for a directory
+ */
+char ReDirStatus_t::typeAsChar() {
+ char rc = ' ';
+ switch (type()) {
+ case TF_REGULAR:
+ rc = ' ';
+ break;
+ case TF_LINK:
+ rc = 'l';
+ break;
+ case TF_SUBDIR:
+ rc = 'd';
+ break;
+ case TF_CHAR:
+ rc = 'c';
+ break;
+ case TF_BLOCK:
+ rc = 'b';
+ break;
+ case TF_PIPE:
+ rc = 'p';
+ break;
+ case TF_SOCKET:
+ rc = 's';
+ break;
+ default:
+ rc = 'o';
+ break;
+ }
+ return rc;
+}
+/**
+ * Constructor.
+ */
+ReDirEntryFilter::ReDirEntryFilter() :
+ ReSerializable(m_serialId),
+ m_types(ReDirStatus_t::TC_ALL),
+ m_nodePatterns(NULL),
+ m_pathPatterns(NULL),
+ m_minSize(0),
+ m_maxSize(-1),
+ //m_minAge(0),
+ //m_maxAge(0),
+ m_minDepth(0),
+ m_maxDepth(512),
+ m_allDirectories(false) {
+ setFiletimeUndef(m_minAge);
+ setFiletimeUndef(m_maxAge);
+}
+
+/**
+ * Destructor.
+ */
+ReDirEntryFilter::~ReDirEntryFilter() {
+}
+
+/**
+ * Sets the members of the instance from a byte sequence.
+ *
+ * @param sequence IN/OUT: the serialized byte sequence
+ * @param length INT/OUT the length of <code>sequence</code>
+ */
+void ReDirEntryFilter::deserialize(const uint8_t*& sequence, size_t& length) {
+ int id;
+ unpackInt24(sequence, length, id);
+ if (id != m_serialId)
+ throw ReSerializeFormatException("wrong serialId", this);
+ ReByteBuffer buffer;
+ unpackString64k(sequence, length, buffer);
+ bool ignoreCase;
+ unpackBool(sequence, length, ignoreCase);
+ m_nodePatterns->set(buffer.str(), ignoreCase);
+ unpackString64k(sequence, length, buffer);
+ unpackBool(sequence, length, ignoreCase);
+ unpackString64k(sequence, length, buffer);
+ m_pathPatterns->set(buffer.str(), ignoreCase);
+ unpackInt64(sequence, length, m_minSize);
+ unpackInt64(sequence, length, m_maxSize);
+ int64_t value;
+ unpackInt64(sequence, length, value);
+ unpackBool(sequence, length, m_allDirectories);
+}
+/**
+ * Packs the members into a byte sequence.
+ *
+ * @param sequence IN/OUT: the place for the byte sequence
+ */
+ReByteBuffer& ReDirEntryFilter::serialize(ReByteBuffer& sequence) {
+ sequence.appendBits24(m_serialId);
+ packString64k(sequence, m_nodePatterns->patternString());
+ packBool(sequence, m_nodePatterns->ignoreCase());
+ packString64k(sequence, m_pathPatterns->patternString());
+ packBool(sequence, m_pathPatterns->ignoreCase());
+ sequence.appendBits64(m_minSize);
+ sequence.appendBits64(m_maxSize);
+ uint64_t value;
+#if defined __linux__
+ value = (m_minAge.tv_sec << 32) + m_minAge.tv_nsec;
+ sequence.appendBits64(int64_t(value));
+ value = (m_minAge.tv_sec << 32) + m_minAge.tv_nsec;
+#elif defined __WIN32__
+#error "missing impl"
+#endif
+ sequence.appendBits64(int64_t(value));
+ packBool(sequence, m_allDirectories);
+}
+
+/**
+ * Tests whether an entry matches the conditions of the filter.
+ *
+ * @param entry entry to test
+ * @return <true>: the entry matches the conditions of the filter<br>
+ * <false>: otherwise
+ */
+bool ReDirEntryFilter::match(ReDirStatus_t& entry) {
+ bool rc = false;
+ do {
+ if (m_allDirectories && entry.isDirectory()) {
+ rc = true;
+ break;
+ }
+ if (0 == (entry.type() & m_types))
+ break;
+ int64_t size = entry.fileSize();
+ if (m_minSize > 0 && size < m_minSize)
+ break;
+ if (m_maxSize >= 0 && size > m_maxSize)
+ break;
+ if (!filetimeIsUndefined(m_minAge) && *entry.modified() > m_minAge)
+ break;
+ if (!filetimeIsUndefined(m_maxAge) && m_maxAge > *entry.modified())
+ break;
+ const char* node = entry.node();
+ if (m_nodePatterns != NULL && !m_nodePatterns->match(node))
+ break;
+ rc = true;
+ } while (false);
+ return rc;
+}
+;
+
+#ifdef __linux__
+/**
+ * Returns the status of the current file (lazy loading).
+ *
+ * @return the status of the current file
+ */
+struct stat* ReDirStatus_t::getStatus() {
+ if (m_status.st_ino == 0) {
+ if (stat(fullName(), &m_status) != 0)
+ m_status.st_ino = 0;
+ }
+ return &m_status;
+}
+#endif
+
+/**
+ * Constructor.
+ */
+ReDirTreeStatistic::ReDirTreeStatistic() :
+ m_directories(0),
+ m_files(0),
+ m_sizes(0ll) {
+}
+/**
+ * Builds a string describing the data.
+ *
+ * @param buffer IN/OUT: a buffer for the result
+ * @param append <code>true</code>: the string will be appended to the buffer<br>
+ * <code>false</code>: the buffer will be cleared at the beginning
+ * @param formatFiles the <code>sprintf</code> format for the file count, e.g. "%8d"
+ * @param formatSized the <code>sprintf</code> format for the MByte format, e.g. "%12.6f"
+ * @param formatFiles the <code>sprintf</code> format for the directory count, e.g. "%6d"
+ * @return a human readable string
+ */
+const char* ReDirTreeStatistic::statisticAsString(ReByteBuffer& buffer,
+ bool append, const char* formatFiles, const char* formatSizes,
+ const char* formatDirs) {
+ if (!append)
+ buffer.setLength(0);
+ buffer.appendInt(m_files, formatFiles);
+ buffer.append(i18n("file(s)")).appendChar(' ');
+ buffer.append(m_sizes / 1000.0 / 1000, formatSizes);
+ buffer.append(" ", 1).append(i18n("MByte")).appendChar(' ');
+ buffer.appendInt(m_directories, formatDirs);
+ buffer.append(i18n("dirs(s)"));
+ return buffer.str();
+}
+
+/**
+ * Constructor.
+ *
+ * @param triggerCount efficiency: only every N calls a time check takes place
+ * @param interval the minimum number of seconds between two traces
+ */
+ReTraceUnit::ReTraceUnit(int triggerCount, int interval) :
+ m_count(0),
+ m_triggerCount(triggerCount),
+ m_lastTrace(0),
+ m_interval(interval),
+ m_startTime(time(NULL)) {
+ m_lastTrace = m_startTime;
+}
+/**
+ * Destructor.
+ */
+ReTraceUnit::~ReTraceUnit() {
+}
+
+/**
+ * Prints a message.
+ *
+ * Often overwritten by a subclass.
+ *
+ * @param message message for the trace
+ * @return <code>true</code> (for chaining)
+ */
+bool ReTraceUnit::trace(const char* message) {
+ printf("%s\n", message);
+ return true;
+}
+
+/**
+ * Constructor.
+ *
+ * @param base the base directory. The traversal starts at this point
+ */
+ReTraverser::ReTraverser(const char* base, ReTraceUnit* tracer,
+ ReLogger* logger) :
+ ReDirTreeStatistic(),
+ m_minLevel(0),
+ m_maxLevel(512),
+ m_level(-1),
+ m_base(base),
+ // m_dirs
+ m_passNoForDirSearch(2),
+ m_dirPatterns(NULL),
+ m_tracer(tracer),
+ m_logger(logger) {
+ memset(m_dirs, 0, sizeof m_dirs);
+ m_dirs[0] = new ReDirStatus_t(m_logger);
+ // remove a preceeding "./". This simplifies the pattern expressions:
+ if (m_base.startsWith(
+ ReByteBuffer(".").appendChar(OS_SEPARATOR_CHAR).str())) {
+ m_base.remove(0, 2);
+ }
+}
+
+/**
+ * Destructor.
+ */
+ReTraverser::~ReTraverser() {
+ destroy();
+}
+
+/**
+ * Initializes the instance to process a new base.
+ *
+ * @param base the base directory to search
+ */
+void ReTraverser::changeBase(const char* base) {
+ destroy();
+ m_base.setLength(0).append(base);
+ memset(m_dirs, 0, sizeof m_dirs);
+ m_dirs[0] = new ReDirStatus_t(m_logger);
+ // remove a preceeding "./". This simplifies the pattern expressions:
+ if (m_base.startsWith(
+ ReByteBuffer(".").appendChar(OS_SEPARATOR_CHAR).str())) {
+ m_base.remove(0, 2);
+ }
+}
+
+/**
+ * Releases the resources.
+ */
+void ReTraverser::destroy() {
+ for (size_t ix = 0; ix < sizeof m_dirs / sizeof m_dirs[0]; ix++) {
+ if (m_dirs[ix] != NULL) {
+ m_dirs[ix]->freeEntry();
+ delete m_dirs[ix];
+ m_dirs[ix] = NULL;
+ }
+ }
+}
+/**
+ * Returns the info about the next file in the directory tree traversal.
+ *
+ * @param level OUT: the level relative to the base.<br>
+ * 0 means the file is inside the base.<br>
+ * Not defined if the result is NULL
+ * @return NULL no more files<br>
+ * otherwise: the stack entry with the next file in the
+ * directory tree. May be a directory too
+ */
+ReDirStatus_t* ReTraverser::rawNextFile(int& level) {
+ ReDirStatus_t* rc = NULL;
+ bool alreadyRead = false;
+ bool again;
+ do {
+ again = false;
+ if (m_level < 0) {
+ // Not yet initialized?
+ if (m_dirs[0]->m_passNo == 2)
+ rc = NULL;
+ else {
+ // first call:
+ if (initEntry(m_base.str(), NULL, 0)) {
+ m_directories++;
+ if (1 != m_passNoForDirSearch)
+ rc = m_dirs[0];
+ else
+ again = alreadyRead = true;
+ }
+ }
+ } else {
+ ReDirStatus_t* current = m_dirs[m_level];
+ if (alreadyRead || current->findNext()) {
+ alreadyRead = false;
+ // a file or directory found:
+ if (m_tracer != NULL && m_tracer->isCountTriggered()
+ && m_tracer->isTimeTriggered())
+ m_tracer->trace(current->fullName());
+ if (current->m_passNo != m_passNoForDirSearch) {
+ // we search for any file:
+ rc = m_dirs[m_level];
+ } else {
+ // we are interested only in true subdirectories:
+ again = true;
+ if (m_level < m_maxLevel && current->isDirectory()
+ && !current->isDotDir() && !current->isLink()
+ && (m_dirPatterns == NULL
+ || isAllowedDir(current->node()))) {
+ // open a new level
+ alreadyRead = initEntry(current->m_path,
+ current->node(), m_level + 1);
+ m_directories++;
+ }
+ }
+ } else {
+ // the current subdir does not have more files:
+ if (current->m_passNo == 1) {
+ // we start the second pass:
+ alreadyRead = initEntry(current->m_path, NULL, -1);
+ current->m_passNo = 2;
+ again = true;
+ } else {
+ // this subdirectory is complete. We continue in the parent directory:
+ current->freeEntry();
+ if (--m_level >= 0) {
+ again = true;
+ }
+ }
+ }
+ }
+ if (rc != NULL && rc->isDotDir())
+ again = true;
+ } while (again);
+ if (rc != NULL && !rc->isDirectory()) {
+ m_files++;
+ if (m_sizes >= 0)
+ m_sizes += rc->fileSize();
+ }
+ level = m_level;
+ return rc;
+}
+/**
+ * Returns the info about the next file matching the filter options.
+ *
+ * @param level OUT: the level relative to the base.<br>
+ * 0 means the file is inside the base.<br>
+ * Not defined if the result is NULL
+ * @param filter NULL: every file matches<br>
+ * otherwise: each found file must match this filter conditions
+ * @return NULL no more files<br>
+ * otherwise: the info about the next file in the
+ * directory tree
+ */
+ReDirStatus_t* ReTraverser::nextFile(int& level, ReDirEntryFilter* filter) {
+ ReDirStatus_t* rc = rawNextFile(level);
+ while (rc != NULL) {
+ if (filter == NULL || filter->match(*rc)) {
+ break;
+ }
+ rc = rawNextFile(level);
+ }
+ return rc;
+}
+
+/**
+ * Initializes an entry in the directory entry stack.
+ *
+ * @param parent the parent directory of the entry
+ * @param node the name of the directory belonging to the entry (without path)
+ * @param level the index of the entry in the stack.<br>
+ * If < 0: m_levels and m_path will not be changed
+ * @return <code>true</code>: a new file is available<br>
+ * <cude>false/code>: findFirstEntry() signals: no entry.
+ */
+bool ReTraverser::initEntry(const ReByteBuffer& parent, const char* node,
+ int level) {
+ bool rc = false;
+ if (level < MAX_ENTRY_STACK_DEPTH) {
+ if (level >= 0)
+ m_level = level;
+ if (m_dirs[m_level] == NULL)
+ m_dirs[m_level] = new ReDirStatus_t(m_logger);
+ ReDirStatus_t* current = m_dirs[m_level];
+ current->m_passNo = 1;
+ if (level >= 0) {
+ current->m_path.set(parent.str(), parent.length());
+ if (!parent.endsWith(OS_SEPARATOR))
+ current->m_path.append(OS_SEPARATOR);
+ if (node != NULL)
+ current->m_path.append(node).append(OS_SEPARATOR);
+ }
+ rc = current->findFirst();
+ }
+ return rc;
+}
+
+/**
+ * Sets some properties from a filter.
+ *
+ * @param filter the filter with the properties to set
+ */
+void ReTraverser::setPropertiesFromFilter(ReDirEntryFilter* filter) {
+ m_minLevel = filter->m_minDepth;
+ m_maxLevel = filter->m_maxDepth;
+ setDirPattern(filter->m_pathPatterns);
+}
+
+/**
+ * Returns the info of an entry the directory stack.
+ *
+ * @param offsetFromTop 0: return the top of stack<br>
+ * 1: returns the entry one below the top<br>
+ * 2: ...
+ * @return NULL: not available<br>
+ * otherwise: the wanted entry
+ */
+ReDirStatus_t* ReTraverser::topOfStack(int offsetFromTop) {
+ ReDirStatus_t* rc = NULL;
+ if (offsetFromTop >= 0 && m_level - 1 - offsetFromTop >= 0)
+ rc = m_dirs[m_level - 1 - offsetFromTop];
+ return rc;
+}
--- /dev/null
+/*
+ * ReTraverser.hpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+#ifndef OS_RETRAVERSER_HPP_
+#define OS_RETRAVERSER_HPP_
+
+#include "string/ReMatcher.hpp"
+#ifdef __linux__
+#include <sys/types.h>
+#include <sys/stat.h>
+
+typedef DIR* FindFileHandle_t;
+#endif
+/** Returns whether a filetime is undefined.
+ * @param time the filetime to test
+ * @return <code>true</code>: the given filetime is undefined
+ */
+inline bool filetimeIsUndefined(ReFileTime_t& time) {
+#if defined __linux__
+ return time.tv_sec == 0 && time.tv_nsec == 0;
+#elif defined __WIN32__
+ return time.dwHighDateTime == 0 && time.dwLowDateTime == 0;
+#endif
+}
+/** Sets the filetime to undefined.
+ * @param time the filetime to clear
+ */
+inline void setFiletimeUndef(ReFileTime_t& time) {
+#if defined __linux__
+ time.tv_sec = time.tv_nsec = 0;
+#elif defined __WIN32__
+ time.dwHighDateTime = time.dwLowDateTime = 0;
+#endif
+}
+
+class ReDirStatus_t {
+public:
+ enum Type_t {
+ TF_UNDEF = 0,
+ // single property flags:
+ TF_SUBDIR = 1 << 0,
+ TF_REGULAR = 1 << 1,
+ TF_LINK = 1 << 2,
+ TF_LINK_DIR = 1 << 3,
+ TF_BLOCK = 1 << 4,
+ TF_PIPE = 1 << 5,
+ TF_CHAR = 1 << 6,
+ TF_SOCKET = 1 << 7,
+ TF_OTHER = 1 << 8,
+ // collections:
+ TC_SPECIAL = (TF_BLOCK | TF_CHAR | TF_SOCKET | TF_PIPE | TF_OTHER),
+ TC_NON_DIR = (TC_SPECIAL | TF_LINK | TF_REGULAR),
+ TC_ALL = (TF_SUBDIR | TC_NON_DIR | TF_LINK_DIR)
+ };
+
+public:
+ ReDirStatus_t(ReLogger* logger);
+public:
+ const ReFileTime_t* accessed();
+ ReFileSize_t fileSize();
+ const char* filetimeAsString(ReByteBuffer& buffer);
+ bool findFirst();
+ bool findNext();
+ void freeEntry();
+ const char* fullName();
+ bool isDirectory();
+ bool isDotDir() const;
+ bool isLink();
+ bool isRegular();
+ const ReFileTime_t* modified();
+ const char* node() const;
+ const char* rightsAsString(ReByteBuffer& buffer, bool numerical,
+ int ownerWidth);
+ Type_t type();
+ char typeAsChar();
+public:
+ static const char* filetimeToString(const ReFileTime_t* time,
+ ReByteBuffer& buffer);
+ static time_t filetimeToTime(const ReFileTime_t* time);
+#if defined __WIN32__
+ static bool getFileOwner(HANDLE handle, const char* file, ReByteBuffer& name,
+ ReLogger* logger = NULL);
+ static bool getPrivilege(const char* privilege, ReLogger* logger);
+#endif
+ static void timeToFiletime(time_t time, ReFileTime_t& filetime);
+public:
+ ReByteBuffer m_path;
+ ReByteBuffer m_fullName;
+ int m_passNo;
+ ReLogger* m_logger;
+#ifdef __linux__
+ DIR* m_handle;
+ struct dirent* m_data;
+ struct stat m_status;
+public:
+ struct stat* getStatus();
+#elif defined WIN32
+ HANDLE m_handle;
+ WIN32_FIND_DATAA m_data;
+ bool m_getPrivilege;
+#endif
+};
+class ReDirEntryFilter: public ReSerializable {
+public:
+ ReDirEntryFilter();
+ ~ReDirEntryFilter();
+public:
+ virtual void deserialize(const uint8_t*& sequence, size_t& length);
+ bool match(ReDirStatus_t& entry);
+ virtual ReByteBuffer& serialize(ReByteBuffer& sequence);
+public:
+ ReDirStatus_t::Type_t m_types;
+ RePatternList* m_nodePatterns;
+ RePatternList* m_pathPatterns;
+ ReFileSize_t m_minSize;
+ ReFileSize_t m_maxSize;
+ ReFileTime_t m_minAge;
+ ReFileTime_t m_maxAge;
+ int m_minDepth;
+ int m_maxDepth;
+ bool m_allDirectories;
+private:
+ static int m_serialId;
+};
+
+class ReTraceUnit {
+public:
+ ReTraceUnit(int m_triggerCount = 10, int interval = 60);
+ virtual ~ReTraceUnit();
+public:
+ /** Returns whether the the instance is triggered.
+ * To avoid too the not cheap call of time() the trace unit uses a counter.
+ * If the counter reaches a given level the time check should be done.
+ * @return <code>true</code>: the counter has reached <code>m_triggerCount</code>
+ */
+ inline bool isCountTriggered() {
+ bool rc = ++m_count % m_triggerCount == 0;
+ return rc;
+ }
+ /** Tests whether a given waiting time has been gone since the last trace.
+ * @return <code>true</code>: the last trace has been done after
+ * at least <code>m_interval</code> seconds
+ */
+ inline bool isTimeTriggered() {
+ time_t now = time(NULL);
+ bool rc = now - m_lastTrace > m_interval;
+ if (rc) {
+ m_lastTrace = now;
+ }
+ return rc;
+ }
+ virtual bool trace(const char* message);
+protected:
+ int m_count;
+ int m_triggerCount;
+ time_t m_lastTrace;
+ int m_interval;
+ time_t m_startTime;
+};
+
+class ReDirTreeStatistic {
+public:
+ ReDirTreeStatistic();
+public:
+ const char* statisticAsString(ReByteBuffer& buffer, bool append = false,
+ const char* formatFiles = "%8d ", const char* formatSizes = "%12.6f",
+ const char* formatDirs = "%7d ");
+ /**
+ * Resets the counters.
+ */
+ inline void clear() {
+ m_files = m_directories = 0;
+ m_sizes = 0ll;
+ }
+public:
+ int m_directories;
+ int m_files;
+ int64_t m_sizes;
+};
+
+#define MAX_ENTRY_STACK_DEPTH 256
+class ReTraverser: public ReDirTreeStatistic {
+public:
+ ReTraverser(const char* base, ReTraceUnit* tracer = NULL, ReLogger* logger =
+ NULL);
+ virtual ~ReTraverser();
+public:
+ void changeBase(const char* base);
+ /**
+ * Return the number of entered directories .
+ * @return the number of directories entered until now
+ */
+ inline int directories() const {
+ return m_directories;
+ }
+ /**
+ * Return the number of found files.
+ * @return the number of files found until now
+ */
+ inline int files() const {
+ return m_files;
+ }
+ /** Returns whether the current directory has changed since the last call.
+ * @param state IN/OUT: stored info about the current directory.
+ * The value has no interest for the caller
+ * @return <code>true</code>: the path has been changed
+ */
+ inline bool hasChangedPath(int& state) {
+ bool rc = m_directories > state;
+ state = m_directories;
+ return rc;
+ }
+ ReDirStatus_t* rawNextFile(int& level);
+ ReDirStatus_t* nextFile(int& level, ReDirEntryFilter* filter = NULL);
+ /** Sets the tree traversal algorithm.
+ * @param depthFirst <code>true</code>: files of the subdirectories will
+ * be returned earlier
+ */
+ void setDepthFirst(bool depthFirst) {
+ m_passNoForDirSearch = depthFirst ? 1 : 2;
+ }
+ /** Sets directory filter (pattern list).
+ * @param pattern pattern list for the subdirs to be entered
+ */
+ inline void setDirPattern(RePatternList* pattern) {
+ m_dirPatterns = pattern;
+ if (pattern != NULL)
+ m_dirPatterns->setIgnoreCase(true);
+ }
+ /** Sets the maximal depth.
+ * @param value the value to set
+ */
+ inline void setMaxLevel(int value) {
+ m_maxLevel = value;
+ }
+ /** Sets the minimal depth.
+ * @param value the value to set
+ */
+ inline void setMinLevel(int value) {
+ m_minLevel = value;
+ }
+ void setPropertiesFromFilter(ReDirEntryFilter* filter);
+ /**
+ * Return the sum of file lengths of the found files.
+ * @return the sum of file lengths of the files found until now
+ */
+ inline int64_t sizes() const {
+ return m_sizes;
+ }
+ ReDirStatus_t* topOfStack(int offset = 0);
+protected:
+ void destroy();
+ void freeEntry(int level);
+ bool initEntry(const ReByteBuffer& parent, const char* node, int level);
+ /**
+ * Tests whether a directory should be processed.
+ * @param node the base name of the subdir
+ * @return <code>true</code>: the subdir will be processed<br>
+ * <code>false</code>: do not enter this subdir
+ */
+ inline bool isAllowedDir(const char* node) {
+ bool rc = m_dirPatterns->match(node);
+ return rc;
+ }
+protected:
+ int m_minLevel;
+ int m_maxLevel;
+ int m_level;
+ ReByteBuffer m_base;
+ ReDirStatus_t* m_dirs[MAX_ENTRY_STACK_DEPTH];
+ /// each directory will be passed twice: for all files + for directories only
+ /// 1: depth first 2: breadth first
+ int m_passNoForDirSearch;
+ /// a subdirectory will be entered only if this pattern list matches
+ /// if NULL any directory will be entered
+ RePatternList* m_dirPatterns;
+ ReDirTreeStatistic m_statistic;
+ ReTraceUnit* m_tracer;
+ ReLogger* m_logger;
+};
+
+#endif /* OS_RETRAVERSER_HPP_ */
--- /dev/null
+/*
+ * reos.hpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+#ifndef OS_REOS_HPP_
+#define OS_REOS_HPP_
+
+#if defined __linux__
+#include "unistd.h"
+#include <dirent.h>
+#include <grp.h>
+#include <pwd.h>
+#elif defined __WIN32__
+#include <tchar.h>
+#include "windows.h"
+#include <winnt.h>
+#else
+#error "unknown os"
+#endif
+
+/** Returns whether a time is greater (younger) than another.
+ * @param time1 first operand
+ * @param time2 second operand
+ * @return <code>true</code>: time1 > time2
+ */
+inline bool operator >(const ReFileTime_t& time1, const ReFileTime_t& time2) {
+#if defined __linux__
+ return time1.tv_sec > time2.tv_sec
+ || (time1.tv_sec == time2.tv_sec && time1.tv_nsec > time2.tv_nsec);
+#else
+ return time1.dwHighDateTime > time2.dwHighDateTime
+ || (time1.dwHighDateTime == time2.dwHighDateTime
+ && time1.dwLowDateTime > time2.dwLowDateTime);
+#endif
+}
+#include "os/ReTraverser.hpp"
+#include "os/ReDirTools.hpp"
+#include "net/renet.hpp"
+#include "os/ReRemoteDir.hpp"
+
+#endif /* OS_REOS_HPP_ */
/*
* remodules.hpp
- *
+ *
* License: Public Domain
* You can use and modify this file without any restriction.
* Do what you want.
LOC_SOURCE,
LOC_VM,
LOC_MFPARSER, // 115
+ LOC_TRAVERSER,
};
#define LOC_FIRST_OF(moduleNo) (moduleNo*100+1)
class RplModules {
--- /dev/null
+/*
+ * rplstaticlib.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+
+
+int main(int argc, char** argv){
+ void allTests();
+ allTests();
+}
QT -= gui
-TARGET = rplstatic
-TEMPLATE = lib
-CONFIG += staticlib
+TARGET = ReStaticLib
+#TEMPLATE = lib
+#CONFIG += staticlib
INCLUDEPATH = .. /usr/include/c++/4.9
../base/ReStringUtil.cpp \
../base/ReTerminator.cpp \
../base/ReTest.cpp \
+ ../base/ReByteStorage.cpp \
+ ../base/ReWriter.cpp \
+ ../base/ReCharPtrMap.cpp \
../math/ReEnigma.cpp \
../math/ReMatrix.cpp \
../math/ReRandom.cpp \
../net/ReTCPServer.cpp \
../expr/ReLexer.cpp \
../expr/ReSource.cpp \
- ../base/ReQString.cpp \
+ ../base/ReQStringUtil.cpp \
../expr/ReASTree.cpp \
../expr/ReASClasses.cpp \
../expr/ReMFParser.cpp \
../expr/ReVM.cpp \
../expr/ReParser.cpp \
- ../base/ReByteStorage.cpp \
- ../base/ReWriter.cpp \
- ../base/ReCharPtrMap.cpp
+ ../bench/cppbench.cpp \
+ ../cunit/cuReConfig.cpp \
+ ../cunit/cuReContainer.cpp \
+ ../cunit/cuReEnigma.cpp \
+ ../cunit/cuReASTree.cpp \
+ ../cunit/cuReBench.cpp \
+ ../cunit/cuReByteStorage.cpp \
+ ../cunit/cuReCharPtrMap.cpp \
+ ../cunit/cuReException.cpp \
+ ../cunit/cuReLexer.cpp \
+ ../cunit/cuReMatrix.cpp \
+ ../cunit/cuReQStringUtil.cpp \
+ ../cunit/cuReSource.cpp \
+ ../cunit/cuReStringUtil.cpp \
+ ../cunit/cuReVM.cpp \
+ ../cunit/cuReWriter.cpp \
+ ../cunit/allTests.cpp \
+ ReStaticLib.cpp \
+ ../cunit/cuReMFParser.cpp
HEADERS += ../remodules.hpp \
../base/ReConfig.hpp \
../expr/ReLexer.hpp \
../expr/reexpr.hpp \
../expr/ReSource.hpp \
- ../base/ReQString.hpp \
+ ../base/ReQStringUtil.hpp \
../expr/ReASTree.hpp \
../expr/ReASClasses.hpp \
../expr/ReMFParser.hpp \
../expr/ReParser.hpp \
../base/ReByteStorage.hpp \
../base/ReWriter.hpp \
- ../base/ReCharPtrMap.hpp
+ ../base/ReCharPtrMap.hpp \
+ ../base/ReQStringUtil.hpp
unix:!symbian {
maemo5 {
+++ /dev/null
-/*
- * rplstaticlib.cpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-
-#include "../static/rplstaticlib.hpp"
-
-
-RplStaticLib::RplStaticLib()
-{
-}
+++ /dev/null
-/*
- * rplstaticlib.hpp
- *
- * License: Public Domain
- * You can use and modify this file without any restriction.
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * You also can use this license: http://www.wtfpl.net
- * The latest sources: https://github.com/republib
- */
-
-
-#ifndef RPLSTATICLIB_HPP
-#define RPLSTATICLIB_HPP
-
-
-class RplStaticLib
-{
-
-public:
- RplStaticLib();
-};
-
-#endif // RPLSTATICLIB_HPP