Browse Source

string splitting and tests

Kajetan Johannes Hammerle 3 years ago
parent
commit
e1478f0bd2
6 changed files with 191 additions and 2 deletions
  1. 2 0
      Main.cpp
  2. 1 1
      meson.build
  3. 95 0
      tests/SplitStringTests.cpp
  4. 8 0
      tests/SplitStringTests.h
  5. 84 0
      utils/SplitString.h
  6. 1 1
      utils/StringBuffer.h

+ 2 - 0
Main.cpp

@@ -5,6 +5,7 @@
 #include "tests/StringBufferTests.h"
 #include "tests/RandomTests.h"
 #include "tests/RingBufferTests.h"
+#include "tests/SplitStringTests.h"
 
 int main() {
     ArrayTests::test();
@@ -14,5 +15,6 @@ int main() {
     StringBufferTests::test();
     RandomTests::test();
     RingBufferTests::test();
+    SplitStringTests::test();
     return 0;
 }

+ 1 - 1
meson.build

@@ -1,6 +1,6 @@
 project('gaming core tests', 'cpp')
 
-sources = ['Main.cpp', 'tests/Test.cpp', 'tests/ArrayTests.cpp', 'tests/HashMapTests.cpp', 'tests/ListTests.cpp', 'tests/BitArrayTests.cpp', 'tests/StringBufferTests.cpp', 'tests/RandomTests.cpp', 'utils/Random.cpp', 'tests/RingBufferTests.cpp']
+sources = ['Main.cpp', 'tests/Test.cpp', 'tests/ArrayTests.cpp', 'tests/HashMapTests.cpp', 'tests/ListTests.cpp', 'tests/BitArrayTests.cpp', 'tests/StringBufferTests.cpp', 'tests/RandomTests.cpp', 'utils/Random.cpp', 'tests/RingBufferTests.cpp', 'tests/SplitStringTests.cpp']
 
 executable('tests', 
     sources: sources,

+ 95 - 0
tests/SplitStringTests.cpp

@@ -0,0 +1,95 @@
+#include "tests/SplitStringTests.h"
+#include "tests/Test.h"
+#include "utils/SplitString.h"
+#include "utils/List.h"
+
+typedef StringBuffer<60> String;
+typedef SplitString<60> Split;
+
+typedef List<String, 10> StringList;
+
+static void checkList(Test& test, const char* str, const StringList& list, const char* message) {
+    Split split(str);
+    test.checkEqual(list.getLength(), split.getLength(), String(message).append(" - split amount"));
+    for(int i = 0; i < list.getLength() && i < split.getLength(); i++) {
+        test.checkEqual(list[i], String(split[i]), String(message).append(" ").append(i));
+    }
+}
+
+static void testOneArgument(Test& test) {
+    StringList list;
+    list.add("test");
+    checkList(test, "test", list, "one argument");
+}
+
+static void testThreeArguments(Test& test) {
+    StringList list;
+    list.add("test").add("aaa").add("bbbb");
+    checkList(test, "test aaa bbbb", list, "three arguments");
+}
+
+static void testFourArguments(Test& test) {
+    StringList list;
+    list.add("test").add("aaa").add("bbbb").add("ccccc");
+    checkList(test, "test aaa bbbb ccccc", list, "four arguments");
+}
+
+static void testOneArgumentWithSpaces(Test& test) {
+    StringList list;
+    list.add("test");
+    checkList(test, "test    ", list, "spaces");
+}
+
+static void testThreeArgumentsWithSpaces(Test& test) {
+    StringList list;
+    list.add("test").add("aaa").add("bbbb");
+    checkList(test, "test  aaa   bbbb", list, "three arguments and spaces");
+}
+
+static void testTwoArgumentsWithQuotationMarks(Test& test) {
+    StringList list;
+    list.add("test").add("aaa bbbb");
+    checkList(test, "test \"aaa bbbb\"", list, "two arguments and quotation marks");
+}
+
+static void testThreeArgumentsWithQuotationMarks(Test& test) {
+    StringList list;
+    list.add("test").add("aaa bbbb").add("ccc");
+    checkList(test, "test \"aaa bbbb\" ccc", list, "three arguments and quotation marks");
+}
+
+static void testFourArgumentsWithQuotationMarks(Test& test) {
+    StringList list;
+    list.add("test").add("ddd").add("aaa bbbb").add("ccc");
+    checkList(test, "test ddd \"aaa bbbb\" ccc", list, "four arguments and quotation marks");
+}
+
+static void testEmptyArgument(Test& test) {
+    StringList list;
+    list.add("test").add("");
+    checkList(test, "test \"\"", list, "empty argument");
+}
+
+static void testSyntaxException(Test& test) {
+    StringList list;
+    checkList(test, "test \"", list, "syntax exception 1");
+    checkList(test, "test aaa\"", list, "syntax exception 2");
+    checkList(test, "test aaa\"bbb\"", list, "syntax exception 3");
+    checkList(test, "test aaa \"bbb\"ccc", list, "syntax exception 4");
+    checkList(test, "test aaa \"bbb ccc", list, "syntax exception 5");
+}
+
+void SplitStringTests::test() {
+    Test test("SplitString");
+    testOneArgument(test);
+    testThreeArguments(test);
+    testFourArguments(test);
+    testOneArgumentWithSpaces(test);
+    testThreeArgumentsWithSpaces(test);
+    testTwoArgumentsWithQuotationMarks(test);
+    testThreeArgumentsWithQuotationMarks(test);
+    testFourArgumentsWithQuotationMarks(test);
+    testEmptyArgument(test);
+    testSyntaxException(test);
+    test.finalize();
+}

+ 8 - 0
tests/SplitStringTests.h

@@ -0,0 +1,8 @@
+#ifndef SPLITSTRINGTESTS_H
+#define SPLITSTRINGTESTS_H
+
+namespace SplitStringTests {
+    void test();
+}
+
+#endif

+ 84 - 0
utils/SplitString.h

@@ -0,0 +1,84 @@
+#ifndef SPLITSTRING_H
+#define SPLITSTRING_H
+
+#include "utils/List.h"
+#include "utils/StringBuffer.h"
+
+template<int N>
+class SplitString final {
+    List<int, N> entries;
+    List<char, N> data;
+
+    bool fill(const StringBuffer<N>& s) {
+        for(int i = 0; i < s.getLength(); i++) {
+            switch(s[i]) {
+                case ' ':
+                    handleSpace(s, i);
+                    break;
+                case '"':
+                    if(handleQuotation(s, i)) {
+                        return true;
+                    }
+                    break;
+                default:
+                    data.add(s[i]);
+            }
+        }
+        data.add('\0');
+        return false;
+    }
+
+    void handleSpace(const StringBuffer<N>& s, int& i) {
+        while(i + 1 < s.getLength() && s[i + 1] == ' ') {
+            i++;
+        }
+        if(i + 1 < s.getLength()) {
+            data.add('\0');
+        }
+    }
+
+    bool handleQuotation(const StringBuffer<N>& s, int& i) {
+        if(i != 0 && s[i - 1] != ' ') {
+            return true;
+        }
+        i++;
+        while(i < s.getLength() && s[i] != '"') {
+            data.add(s[i++]);
+        }
+        if(i >= s.getLength() || (i != s.getLength() - 1 && s[i + 1] != ' ')) {
+            return true;
+        }
+        return false;
+    }
+    
+    void addEntries() {
+        int lastIndex = 0;
+        for(int i = 0; i < data.getLength(); i++) {
+            if(data[i] == '\0') {
+                entries.add(lastIndex);
+                lastIndex = i + 1;
+            }
+        }
+    }
+
+public:
+
+    SplitString(const StringBuffer<N>& s) {
+        if(fill(s)) {
+            return;
+        }
+        addEntries();
+    }
+
+    int getLength() const {
+        return entries.getLength();
+    }
+
+    const char* operator[](int index) const {
+        return &(data[entries[index]]);
+    }
+
+private:
+};
+
+#endif

+ 1 - 1
utils/StringBuffer.h

@@ -25,7 +25,7 @@ public:
     StringBuffer() : length(0), hash(0) {
         data[0] = '\0';
     }
-    
+
     template<typename T>
     StringBuffer(const T& t) : StringBuffer() {
         append(t);