]> gitweb.hamatoma.de Git - reqt/commitdiff
+rplstring_test.cpp, rplmatrix_test full tested
authorhama <hama@siduction.net>
Sun, 1 Jun 2014 00:56:04 +0000 (02:56 +0200)
committerhama <hama@siduction.net>
Sun, 1 Jun 2014 00:56:04 +0000 (02:56 +0200)
rplcore/rplstring.cpp
rplcore/rplstring.hpp
rplmath/rplmatrix.cpp
unittests/main.cpp
unittests/rplmatrix_test.cpp
unittests/rplstring_test.cpp [new file with mode: 0644]
unittests/unittests.pro

index f174564b504b5339c466b14ae8ae47033af6e422..6a2b3e7b4e59cecd7e79a414eed7ae5b3963ea86 100644 (file)
  * This is a class with static members only.
  */
 
+/**
+ * @brief Counts the occurrences of a given char in a string.
+ *
+ * @param line the text to inspect
+ * @param cc   the char to count
+ * @return             the number of <code>cc</code> in the text
+ */
+int RplString::countChar(const char* line, char cc)
+{
+    const char* ptr = line;
+    int rc = 0;
+    while( (ptr = strchr(ptr, cc)) != NULL){
+        rc++;
+        ptr++;
+    }
+    return rc;
+}
 /**
  * Counts the occurrences of a string in a string.
  *
@@ -283,87 +300,118 @@ bool RplString::write(const char* file, const char* content, const char* mode) {
     }
     return fp != NULL;
 }
-
-// ------------------
-#if ! defined RPL_TEST
-#define RPL_TEST
-#endif
-#ifdef RPL_TEST
-#include "rplcore/rpltest.hpp"
 /**
- * @brief Unit test for <code>RplString</code>.
+ * @brief Returns the length of the number string.
+ *
+ * @param text                  a text to inspect
+ * @param skipTrailingSpaces    true: if spaces are behind the number
+ *                              the result contains the length of these
+ * @return             0: not a number<br>
+ *                             otherwise: the length of the number string
  */
-class TestRplString : public RplTest {
-public:
-    TestRplString() : RplTest("RplString") {}
-
-public:
-    void testCount() {
-        checkE(0, RplString::count("abc", " "));
-        checkE(1, RplString::count("abc", "b"));
-        checkE(2, RplString::count("axx", "x"));
-
-        checkE(0, RplString::count("abbc", "bbb"));
-        checkE(1, RplString::count("\n\n", "\n\n"));
-        checkE(2, RplString::count("  a  ", "  "));
+int RplString::lengthOfNumber(const char* text, bool skipTrailingSpaces){
+    int rc = 0;
+    bool found = false;
+    const char* ptr = text;
+    while(isspace(*ptr))
+        ptr++;
+    if ( (*ptr == '+' || *ptr == '-'))
+        ptr++;
+    found = isdigit(*ptr);
+    while(isdigit(*ptr)){
+        ptr++;
     }
-
-    void testCutString() {
-        QByteArray source("123");
-        QByteArray buffer;
-        checkE(QByteArray("123"), RplString::cutString(source, 4, buffer));
-        checkE(QByteArray("123"), RplString::cutString(source, 3, buffer));
-        checkE(QByteArray("12..."), RplString::cutString(source, 2, buffer));
-        checkE(QByteArray("12"), RplString::cutString(source, 2, buffer, ""));
+    if (*ptr == '.'){
+        ptr++;
+        if (isdigit(*ptr)){
+            found = true;
+            while(isdigit(*ptr))
+                ptr++;
+        }
     }
-
-    void testHexDump() {
-        QByteArray data("abc123\nxyz");
-        checkE(QByteArray("61 62 63 31  abc1\n"
-                          "32 33 0a 78  23.x\n"
-                          "79 7a        yz\n"),
-               RplString::hexDump((uint8_t*) data.constData(), data.length(), 4));
-        checkE(QByteArray("61 62 63 31 32 33 0a 78 79 7a  abc123.xyz"),
-               RplString::hexDump((uint8_t*) data.constData(), data.length(), 10));
-        checkE(QByteArray("61 62 63 31 32 33 0a 78 79 7a        abc123.xyz"),
-               RplString::hexDump((uint8_t*) data.constData(), data.length(), 12));
+    if (found && toupper(*ptr) == 'E'){
+        const char* ptrToE = ptr;
+        ptr++;
+        if (*ptr == '+' || *ptr == '-')
+            ptr++;
+        if (! isdigit(*ptr))
+            ptr = ptrToE;
+        else {
+            while(isdigit(*ptr))
+                ptr++;
+        }
     }
-
-    void testReadWrite() {
-        QByteArray fn = getTempFile("test.dat");
-        const char* content = "Hello world\nLine2\n";
-        checkT(RplString::write(fn, content));
-        checkE(content, RplString::read(fn, false));
-        checkE(content, RplString::read(fn, true) + "\n");
+    if (found && skipTrailingSpaces){
+        while(isspace(*ptr)){
+            ptr++;
+        }
     }
+    rc = ! found ? 0 : ptr - text;
+    return rc;
+}
+/**
+ * @brief Adds the count of the possible separators.
+ *
+ * @param countCommas          IN/OUT: number of ','
+ * @param countSemicolons      IN/OUT: number of ';'
+ * @param countPipes           IN/OUT: number of '|'
+ * @param countBlanks          IN/OUT: number of ' '
+ */
+static void addSeparators(const char* line, int& commas, int& semicolons,
+        int& pipes, int& blanks)
+{
+    commas += RplString::countChar(line, ',');
+    semicolons += RplString::countChar(line, ';');
+    pipes += RplString::countChar(line, '|');
+    blanks += RplString::countChar(line, ' ');
+}
 
-    void testToArray() {
-        QVector<QByteArray> array = RplString::toArray("1 abc 3", " ");
-        checkE(3, array.size());
-        checkE("1", array.at(0));
-        checkE("abc", array.at(1));
-        checkE("3", array.at(2));
+/**
+ * @brief Finds the separator of the CSV file.
+ *
+ * If the file contain TABs the result is TAB.
+ * If not:
+ * Inspects the first 5 lines and counts the possible separators.
+ * The most found separator will be returned.
+ *
+ * @param fp                   CSV file
+ * @param buffer               a line buffer
+ * @param bufferSize   the size of <code>buffer[]</code>
+ */
+char RplString::findCsvSeparator(FILE* fp, char* buffer, size_t bufferSize){
+    char rc = '\0';
+    int lineNo = 0;
+    int maxLines = 5;
+    const char* line;
+    int commas = 0;
+    int semicolons = 0;
+    int pipes = 0;
+    int blanks = 0;
+    while(++lineNo < maxLines && (line = fgets(buffer, bufferSize, fp)) != NULL){
+        if (strchr(line, '\t') != NULL){
+            rc = '\t';
+            break;
+        }
+        addSeparators(line, commas, semicolons, pipes, blanks);
     }
-
-    void testToNumber() {
-        checkE("3", RplString::toNumber(3));
-        checkE("-33", RplString::toNumber(-33));
-        checkE("003", RplString::toNumber(3, "%03d"));
+    fseek(fp, 0, SEEK_SET);
+    if (rc != '\t'){
+        if (semicolons > 0 && commas > 0){
+            // if ',' is decimal separator and ';' is the column separator:
+            // Add one semicolon per line because of number of values is
+            // 1 greater than the number of separators
+            semicolons += lineNo;
+        }
+        if (commas + semicolons + pipes == 0) {
+            rc = blanks > 0 ? ' ' : '\0';
+        } else if (semicolons >= commas && semicolons >= pipes)
+            rc = ';';
+        else if (commas > semicolons && commas > pipes)
+            rc = ',';
+        else if (pipes > commas && pipes > semicolons)
+            rc = '|';
     }
+    return rc;
+}
 
-    virtual void doIt() {
-        testCount();
-        testCutString();
-        testToNumber();
-        testToArray();
-        testHexDump();
-        testReadWrite();
-    }
-};
 
-#endif
-void testRplString() {
-#ifdef RPL_TEST
-    TestRplString test;
-#endif
-}
index 39b82665be60b12261928b1359ea5ca55bbe5ff2..d287ff02d402275a7bd1a44dbdfcda235decb7fc 100644 (file)
@@ -10,6 +10,7 @@
 
 class RplString {
 public:
+    static int countChar(const char* line, char cc);
     static int count(const char* source, const char* item);
     static const QByteArray& cutString(const QByteArray& source, int maxLength,
                                        QByteArray& buffer, const char* appendix = "...");
@@ -26,6 +27,9 @@ public:
     static QVector<QByteArray> toArray(const char* source, const char* separator);
     static QByteArray toCString(const char* source, int maxLength = -1);
     static QByteArray toNumber(int value, const char* format = "%d");
+    static int lengthOfNumber(const char* text, bool skipTrailingSpaces = false);
+    static char findCsvSeparator(FILE* fp, char* buffer, size_t bufferSize);
+
 };
 
 #endif // RPLSTRING_HPP
index 86c2a4fdc89f530b42a19f9df9403661bdbaac36..e6cf18f4b1b12ec57b6958b9263892360a7f717a 100644 (file)
@@ -367,50 +367,6 @@ QByteArray RplMatrix::toString(const char* prefix, const char* format,
        rc += "]";
        return rc;
 }
-/**
- * Returns the length of the number string.
- *
- * @param text a text to inspect
- * @return             0: not a number<br>
- *                             otherwise: the length of the number string
- */
-static int lengthOfNumber(const char* text){
-       int rc = 0;
-       bool found = false;
-       const char* ptr = text;
-       while(isspace(*ptr))
-               ptr++;
-       if ( (*ptr == '+' || *ptr == '-'))
-               ptr++;
-       found = isdigit(*ptr);
-       while(isdigit(*ptr))
-               text++;
-       if (*ptr == '.'){
-               ptr++;
-               found = isdigit(*ptr);
-               if (found){
-                       while(isdigit(*ptr))
-                               ptr++;
-               }
-       }
-       if (found && toupper(*ptr) == 'E'){
-               ptr++;
-               if (*ptr == '+' || *ptr == '-')
-                       ptr++;
-               found = isdigit(*ptr);
-               if (found){
-                       while(isdigit(*ptr))
-                               ptr++;
-               }
-       }
-       if (found){
-               while(isspace(*ptr)){
-                       ptr++;
-               }
-       }
-       rc = found ? 0 : ptr - text;
-       return rc;
-}
 /**
  * Finds the length of a column.
  *
@@ -442,77 +398,6 @@ static int lengthOfColumn(const char* text, char separator){
        int rc = ptr - text;
        return rc;
 }
-/**
- * Counts the occurrences of a given char in a string.
- *
- * @param line the text to inspect
- * @param cc   the char to count
- * @return             the number of cc in the text
- */
-static int countChar(const char* line, char cc)
-{
-       const char* ptr = line;
-       int rc = 0;
-       while( (ptr = strchr(ptr, cc)) != NULL){
-               rc++;
-               ptr++;
-       }
-       return rc;
-}
-/**
- * Adds the count of the possible separators.
- *
- * @param countTab                     IN/OUT: number of tabulators
- * @param countCommas          IN/OUT: number of ','
- * @param countSemicolons      IN/OUT: number of ';'
- * @param countPipes           IN/OUT: number of '|'
- * @param countBlanks          IN/OUT: number of ' '
- */
-static void addSeparators(const char* line, int& commas, int& semicolons,
-               int& pipes, int& blanks)
-{
-       commas += countChar(line, ',');
-       semicolons += countChar(line, ';');
-       pipes += countChar(line, '|');
-       blanks += countChar(line, ' ');
-}
-/**
- * Finds the separator of the CSV file.
- *
- * Inspects the first 5 lines and counts the possible separators.
- * The most found separator will be returned.
- *
- * @param fp                   CSV file
- * @param buffer               a line buffer
- * @param bufferSize   the size of <code>buffer[]</code>
- */
-static char findSeparator(FILE* fp, char* buffer, size_t bufferSize){
-       char rc = '\0';
-       int ix = 0;
-       int maxLines = 5;
-       const char* line;
-       int commas = 0;
-       int semicolons = 0;
-       int pipes = 0;
-       int blanks = 0;
-       while(++ix < maxLines && (line = fgets(buffer, bufferSize, fp)) != NULL){
-               if (strchr(line, '\t') != NULL){
-                       rc = '\t';
-                       break;
-               }
-               addSeparators(line, commas, semicolons, pipes, blanks);
-       }
-       fseek(fp, 0, SEEK_SET);
-       if (commas + semicolons + pipes == 0) {
-               rc = blanks > 0 ? ' ' : '\0';
-       } else if (semicolons > commas && semicolons > pipes)
-               rc = ',';
-       else if (commas > semicolons && commas > pipes)
-               rc = ',';
-       else if (pipes > commas && pipes > semicolons)
-               rc = '|';
-       return rc;
-}
 /**
  * Skips all columns with a content other than a numeric value.
  *
@@ -524,9 +409,11 @@ static const char* skipNonNumbers(const char* line, char separator)
 {
        int len1, len2 = 0;
 
-       while ( (len1 = lengthOfNumber(line)) == 0
+    while ( (len1 = RplString::lengthOfNumber(line)) == 0
                && (len2 = lengthOfColumn(line, separator)) > 0)
                line += len2;
+    if (*line == separator)
+        line++;
        return line;
 }
 /**
@@ -536,17 +423,18 @@ static const char* skipNonNumbers(const char* line, char separator)
  * @return             0: not only numbers are in the line<br>
  *                             otherwise: the count of numeric columns in the line
  */
-static int countNumbers(char* line, char separator){
-       skipNonNumbers(line, separator);
+static int countNumbers(const char* line, char separator){
+    line = skipNonNumbers(line, separator);
        bool again = true;
        int rc = 0;
-       while(again && *line != '\0'){
-               int length = lengthOfNumber(line);
+    char cc;
+    while(again && (cc = *line) != '\0' && cc != '\n' && cc != '\r'){
+        int length = RplString::lengthOfNumber(line, true);
                if (length == 0){
                        rc = 0;
                        again = false;
                } else {
-                       line += lengthOfNumber(line);
+            line += length;
                        rc++;
                        if (*line == separator)
                                line++;
@@ -560,51 +448,55 @@ static int countNumbers(char* line, char separator){
  */
 void RplMatrix::readFromCvs(const char* filename, int maxLineLength)
 {
-       FILE* fp = fopen(filename, "r");
-       if (fp == NULL)
+    FILE* fp = fopen(filename, "r");
+    if (fp == NULL)
         throw RplMatrixException(*this, "Cannot open %s (%d)", filename, errno);
-       char* buffer = new char[maxLineLength];
-       char* line;
-       char separator = findSeparator(fp, buffer, maxLineLength);
-       int rows = 0;
-       int cols = 0;
-       // find the count of rows and columns:
-       while( (line = fgets(buffer, sizeof buffer, fp)) != NULL)
-       {
-               int nCols;
-               if ( (nCols = countNumbers(line, separator)) > 0){
-                       rows++;
-                       if (nCols > cols)
-                               cols = nCols;
-               }
-       }
-       resize(rows, cols);
-       // find the values
-       fseek(fp, 0, SEEK_SET);
-       int row = -1;
-       while( (line = fgets(buffer, sizeof buffer, fp)) != NULL)
-       {
-               int nCols;
-               if ( (nCols = countNumbers(line, separator)) > 0){
-                       row++;
-                       skipNonNumbers(line, separator);
-                       int col = -1;
-                       int length;
-            char* ptr = line;
-                       while( (length = lengthOfNumber(ptr)) > 0){
-                               while(*ptr == ' ')
-                                       ptr++;
-                               MatVal value = atof(ptr);
-                               m_values[m_cols*row + col] = value;
-                               ptr += length;
-                               if (*ptr)
-                                       ptr++;
-                       }
-               }
-       }
+    char* buffer = new char[maxLineLength + 1];
+    const char* line;
+    char separator = RplString::findCsvSeparator(fp, buffer, maxLineLength);
+    int rows = 0;
+    int cols = 0;
+    int nCols;
+    // find the count of rows and columns:
+    while( (line = fgets(buffer, maxLineLength, fp)) != NULL)
+    {
+         if ( (nCols = countNumbers(line, separator)) > 0){
+            rows++;
+            if (nCols > cols)
+                cols = nCols;
+        }
+    }
+    resize(rows, cols);
+    // find the values
+    fseek(fp, 0, SEEK_SET);
+    int row = -1;
+    while( (line = fgets(buffer, maxLineLength, fp)) != NULL)
+    {
+        int nCols;
+        if ( (nCols = countNumbers(line, separator)) > 0){
+            row++;
+            line = skipNonNumbers(line, separator);
+            int col = -1;
+            int length;
+            const char* ptr;
+            while( (length = RplString::lengthOfNumber(line, true)) > 0){
+                col++;
+                ptr = line;
+                line += length;
+                while(*ptr == ' ')
+                    ptr++;
+                MatVal value = atof(ptr);
+                m_values[m_cols*row + col] = value;
+                if (*line == separator)
+                    line++;
+                else
+                    break;
+            }
+        }
+    }
 
-       fclose(fp);
-       delete buffer;
+    fclose(fp);
+    delete buffer;
 }
 void RplMatrix::readFromXml(const char* filename, const char* tagCol,
                const char* tagRow, const char* tagTable,
index be1c41cfc72329ed806fea92306e52a1ce0291b9..c3707850d65b79e5d847114fd58755bea2e4cd20 100644 (file)
@@ -14,9 +14,13 @@ int main(int argc, char *argv[])
 {
     if (argc > 1)
         printf("not used: %s\n", argv[1]);
+
     extern void testRplMatrix();
     testRplMatrix();
 
+    extern void testRplString();
+    testRplString();
+
     extern void testRplException();
     testRplException();
 }
index 37a1729cc20b6d2e1f0fe0e5cef6c84462fced60..896dfc00b1ac2063c94c5892768f9c73492aefb5 100644 (file)
@@ -225,11 +225,126 @@ public:
         } catch(RplMatrixException exc){
             checkE("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);
+        checkE(2, m1.getRows());
+        checkE(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();
+        checkE(-98.0, miniMax.m_value1);
+        checkE(9999.0, miniMax.m_value2);
+
+        fillMatrix(m1);
+        checkMatrix(m1);
+        m1.set(1, 1, 7777);
+        m1.set(3, 4, -987);
+        miniMax = m1.minMax();
+        checkE(-987.0, miniMax.m_value1);
+        checkE(7777.0, miniMax.m_value2);
+    }
+
+    void testTranspose()
+    {
+        RplMatrix m1(1, 5, "m1");
+        fillMatrix(m1);
+        RplMatrix m2(m1.transpose());
+
+        checkE(5, m2.getRows());
+        checkE(1, m2.getCols());
+
+        int row, col;
+        col = 0;
+        for (row = 0; row < 5; row++){
+            checkE(qreal(col*100+row), m2.get(row, 0));
+        }
+
+        m1.resize(35, 73);
+        fillMatrix(m1);
+        m2 = m1.transpose();
+
+        checkE(73, m2.getRows());
+        checkE(35, m2.getCols());
+
+        int count = 0;
+        for (row = 0; row < m2.getRows(); row++){
+            for (col = 0; col < m2.getCols(); col++){
+                checkE(qreal(col*100+row), m2.get(row, col));
+                count++;
+            }
+        }
+        checkE(73*35, count);
+    }
+    void testToString(){
+        RplMatrix m1(1, 1, "m1");
+        m1.set(0, 0, 2.34);
+        checkE("[2.340000,\n]", m1.toString().constData());
+        checkE("jonny[2.34000 |]", m1.toString("jonny", "%.5f", "|", " ").constData());
+
+        m1.resize(2, 1);
+        m1.set(0, 0, 2.34);
+        m1.set(1, 0, 55.5);
+
+        checkE("[2.340000,\n55.500000,\n]", m1.toString().constData());
+        checkE("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";
+        RplString::write(fn, content);
+        m1.readFromCvs(fn, 256);
+        checkE(2, m1.getRows());
+        checkE(3, m1.getCols());
+
+        checkE(5.0, m1.get(0, 0));
+        checkE(-3.0E-99, m1.get(0, 1));
+        checkE(0.5, m1.get(0, 2));
+
+        checkE(7.0, m1.get(1, 0));
+        checkE(-22.3, m1.get(1, 1));
+        checkE(44.0, m1.get(1, 2));
+
+        fillMatrix(m1);
+        content = "Port0,Port1,Port2\n"
+                "5,  -3E-99  , 0.5\n";
+        RplString::write(fn, content);
+        m1.readFromCvs(fn, 256);
+        checkE(1, m1.getRows());
+        checkE(3, m1.getCols());
+        checkE(5.0, m1.get(0, 0));
+        checkE(-3.0E-99, m1.get(0, 1));
+        checkE(0.5, m1.get(0, 2));
+
+
 /*
-    void checkDefinition(int rows, int cols) const;
-    void check(int row, int col) const;
-    void checkSameDimension(const RplMatrix& operand) const;
+    void readFromCvs(const char* filename, int maxLineLength = 1024*1024);
+    void readFromXml(const char* filename, const char* tagCol,
+            const char* tagRow, const char* tagTable,
+            int maxLineLength = 1024*1024);
 */
     }
     virtual void doIt(void) {
@@ -239,6 +354,11 @@ public:
         testCheckDefinition();
         testCheck();
         testCheckSameDimension();
+        testResize();
+        testMinMax();
+        testTranspose();
+        testToString();
+        testReadCsv();
     }
 };
 void testRplMatrix() {
diff --git a/unittests/rplstring_test.cpp b/unittests/rplstring_test.cpp
new file mode 100644 (file)
index 0000000..9857e13
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+*/
+// ------------------
+#include "rplcore/rplcore.hpp"
+#include "rplcore/rpltest.hpp"
+/**
+ * @brief Unit test for <code>RplString</code>.
+ */
+class TestRplString : public RplTest {
+public:
+    TestRplString() : RplTest("RplString") {}
+
+public:
+    void testCountChar(){
+        checkE(1, RplString::countChar("x", 'x'));
+        checkE(0, RplString::countChar("X", 'x'));
+        checkE(2, RplString::countChar("xbxxbxx", 'b'));
+    }
+
+    void testCount() {
+        checkE(0, RplString::count("abc", " "));
+        checkE(1, RplString::count("abc", "b"));
+        checkE(2, RplString::count("axx", "x"));
+
+        checkE(0, RplString::count("abbc", "bbb"));
+        checkE(1, RplString::count("\n\n", "\n\n"));
+        checkE(2, RplString::count("  a  ", "  "));
+    }
+
+    void testCutString() {
+        QByteArray source("123");
+        QByteArray buffer;
+        checkE(QByteArray("123"), RplString::cutString(source, 4, buffer));
+        checkE(QByteArray("123"), RplString::cutString(source, 3, buffer));
+        checkE(QByteArray("12..."), RplString::cutString(source, 2, buffer));
+        checkE(QByteArray("12"), RplString::cutString(source, 2, buffer, ""));
+    }
+
+    void testHexDump() {
+        QByteArray data("abc123\nxyz");
+        checkE(QByteArray("61 62 63 31  abc1\n"
+                          "32 33 0a 78  23.x\n"
+                          "79 7a        yz\n"),
+               RplString::hexDump((uint8_t*) data.constData(), data.length(), 4));
+        checkE(QByteArray("61 62 63 31 32 33 0a 78 79 7a  abc123.xyz"),
+               RplString::hexDump((uint8_t*) data.constData(), data.length(), 10));
+        checkE(QByteArray("61 62 63 31 32 33 0a 78 79 7a        abc123.xyz"),
+               RplString::hexDump((uint8_t*) data.constData(), data.length(), 12));
+    }
+
+    void testReadWrite() {
+        QByteArray fn = getTempFile("test.dat");
+        const char* content = "Hello world\nLine2\n";
+        checkT(RplString::write(fn, content));
+        checkE(content, RplString::read(fn, false));
+        checkE(content, RplString::read(fn, true) + "\n");
+    }
+
+    void testToArray() {
+        QVector<QByteArray> array = RplString::toArray("1 abc 3", " ");
+        checkE(3, array.size());
+        checkE("1", array.at(0));
+        checkE("abc", array.at(1));
+        checkE("3", array.at(2));
+    }
+
+    void testToNumber() {
+        checkE("3", RplString::toNumber(3));
+        checkE("-33", RplString::toNumber(-33));
+        checkE("003", RplString::toNumber(3, "%03d"));
+    }
+
+    void testLengthOfNumber(){
+        checkE(3, RplString::lengthOfNumber("0.3xxx"));
+        checkE(5, RplString::lengthOfNumber(" \t0.3xxx"));
+        checkE(3, RplString::lengthOfNumber("-.3xxx"));
+        checkE(2, RplString::lengthOfNumber(".3exxx"));
+        checkE(2, RplString::lengthOfNumber(".3e+xxx"));
+        checkE(16, RplString::lengthOfNumber("1234567.9012E+77"));
+        checkE(17, RplString::lengthOfNumber("-1234567.9012E+77 "));
+        checkE(18, RplString::lengthOfNumber("-1234567.9012E+77 ", true));
+        checkE(18, RplString::lengthOfNumber("-1234567.9012E+77 x", true));
+        checkE(20, RplString::lengthOfNumber("  -1234567.9012E+77 x", true));
+    }
+
+    void checkCsv(const char* content, char expected){
+        QByteArray fn = getTempFile("testrplstring.csv");
+        RplString::write(fn, content);
+        FILE* fp = fopen(fn, "r");
+        checkNN(fp);
+        char buffer[256];
+        checkE(expected, RplString::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, ';');
+    }
+
+    virtual void doIt() {
+        testCountChar();
+        testCount();
+        testCutString();
+        testToNumber();
+        testToArray();
+        testHexDump();
+        testReadWrite();
+        testLengthOfNumber();
+        testFindCsvSeparator();
+    }
+};
+
+void testRplString() {
+    TestRplString test;
+    test.run();
+}
+
+
+
index 3993e6ad0b974928d495d22420a6b63c96c3ef50..742617bd1fbaf44067325168d1b1a45ab13fcbe7 100644 (file)
@@ -23,5 +23,6 @@ SOURCES += main.cpp \
     ../rplcore/rpltest.cpp \
     ../rplcore/rplstring.cpp \
     ../rplcore/rplexception.cpp \
-    rplexception_test.cpp
+    rplexception_test.cpp \
+    rplstring_test.cpp