Browse Source

Pass storage to char string

Kajetan Johannes Hammerle 1 week ago
parent
commit
4dafb76e04
2 changed files with 113 additions and 73 deletions
  1. 89 58
      include/core/utils/ArrayString.hpp
  2. 24 15
      test/modules/ArrayStringTests.cpp

+ 89 - 58
include/core/utils/ArrayString.hpp

@@ -3,6 +3,8 @@
 
 #include "core/math/Math.hpp"
 #include "core/utils/Check.hpp"
+#include "core/utils/Error.hpp"
+#include "core/utils/Meta.hpp"
 #include "core/utils/Types.hpp"
 #include "core/utils/Utility.hpp"
 
@@ -19,18 +21,27 @@ namespace Core {
     template<int N>
     class Char32String;
 
-    template<int N>
-    class CharString final {
-        int length;
+    class CharString {
+    protected:
+        i32 length;
+        i32 capacity;
         u32 hash;
-        static_assert(N > 0, "size of array string must be positive");
-        char data[static_cast<unsigned int>(N)];
+        char* data;
 
     public:
-        CharString() : length(0), hash(0) {
+        CharString(char* buffer, i32 bufferSize)
+            : length(0), capacity(bufferSize), hash(0), data(buffer) {
             data[0] = '\0';
         }
 
+        CharString(const CharString&) = delete;
+        CharString& operator=(const CharString&) = delete;
+
+        check_return Error copyFrom(const CharString& s) {
+            clear();
+            return s.toString(*this);
+        }
+
         bool operator==(const char* s) const {
             const char* p = data;
             while(*s == *p && *s != '\0') {
@@ -40,8 +51,7 @@ namespace Core {
             return *s == *p;
         }
 
-        template<int L>
-        bool operator==(const CharString<L>& other) const {
+        bool operator==(const CharString& other) const {
             if(length != other.getLength()) {
                 return false;
             }
@@ -57,8 +67,7 @@ namespace Core {
             return !((*this) == s);
         }
 
-        template<int L>
-        bool operator!=(const CharString<L>& other) const {
+        bool operator!=(const CharString& other) const {
             return !((*this) == other);
         }
 
@@ -71,7 +80,7 @@ namespace Core {
         }
 
         constexpr int getCapacity() const {
-            return N - 1;
+            return capacity - 1;
         }
 
         check_return Error append(char c) {
@@ -177,8 +186,7 @@ namespace Core {
             return t.toString(*this);
         }
 
-        template<int L>
-        check_return Error toString(CharString<L>& s) const {
+        check_return Error toString(CharString& s) const {
             int l = length; // length changes if &s == this
             for(int i = 0; i < l; i++) {
                 CORE_RETURN_ERROR(s.append(data[i]));
@@ -188,7 +196,7 @@ namespace Core {
 
         template<int L>
         check_return Error toString(Char32String<L>& s) const {
-            return s.append(data);
+            return s.append(static_cast<const char*>(data));
         }
 
         void clear() {
@@ -215,17 +223,17 @@ namespace Core {
         }
 
         template<typename... Args>
-        check_return Error format(Args&&... args) {
-            CharString s;
+        check_return Error format(CharString& s, Args&&... args) {
             Error e = formatBuffer(s, 0, Core::forward<Args>(args)...);
-            if(e == Error::NONE || e == Error::CAPACITY_REACHED) {
-                *this = s;
+            if(e == Error::NONE) {
+                return copyFrom(s);
+            } else if(e == Error::CAPACITY_REACHED) {
+                (void)copyFrom(s);
             }
             return e;
         }
 
-        template<int L>
-        bool startsWidth(const CharString<L>& other, int from = 0) const {
+        bool startsWidth(const CharString& other, int from = 0) const {
             if(from > length - other.getLength()) {
                 return false;
             }
@@ -237,8 +245,7 @@ namespace Core {
             return true;
         }
 
-        template<int L>
-        int search(const CharString<L>& other, int from = 0) const {
+        int search(const CharString& other, int from = 0) const {
             for(int i = from; i < length; i++) {
                 if(startsWidth(other, i)) {
                     return i;
@@ -247,8 +254,7 @@ namespace Core {
             return -1;
         }
 
-        template<int L>
-        bool contains(const CharString<L>& other, int from = 0) const {
+        bool contains(const CharString& other, int from = 0) const {
             return search(other, from) >= 0;
         }
 
@@ -265,24 +271,22 @@ namespace Core {
             return search(u, from) >= 0;
         }
 
-        CharString substring(int from, int to) const {
+        check_return Error substring(CharString& s, int from, int to) const {
+            s.clear();
             from = Math::max(from, 0);
             to = Math::min(to, length - 1);
-            CharString s;
             for(int i = from; i <= to; i++) {
-                (void)s.append(data[i]);
+                CORE_RETURN_ERROR(s.append(data[i]));
             }
-            return s;
+            return Error::NONE;
         }
 
-        CharString substring(int from = 0) const {
-            return substring(from, length - 1);
+        check_return Error substring(CharString& s, int from = 0) const {
+            return substring(s, from, length - 1);
         }
 
-        template<int L1, int L2>
-        check_return Error replace(const CharString<L1>& search,
-                                   const CharString<L2>& replace) {
-            CharString<N> s;
+        check_return Error replace(CharString& s, const CharString& search,
+                                   const CharString& replace) {
             int i = 0;
             while(i < length) {
                 if(startsWidth(search, i)) {
@@ -293,8 +297,7 @@ namespace Core {
                     i++;
                 }
             }
-            *this = s;
-            return Error::NONE;
+            return copyFrom(s);
         }
 
         void replace(char search, char replace) {
@@ -313,7 +316,7 @@ namespace Core {
 
     private:
         Error add(char c) {
-            if(length >= N - 1) {
+            if(length >= capacity - 1) {
                 return Error::CAPACITY_REACHED;
             }
             data[length++] = c;
@@ -388,6 +391,45 @@ namespace Core {
         }
     };
 
+    template<int N>
+    class ArrayCharString final : public CharString {
+        static_assert(N > 0, "size of array string must be positive");
+        char data[static_cast<unsigned int>(N)];
+
+    public:
+        ArrayCharString() : CharString(data, N) {
+        }
+
+        ArrayCharString(const ArrayCharString& other) : CharString(data, N) {
+            Core::memoryCopy(data, other.data, N);
+            length = other.length;
+            hash = other.hash;
+        }
+
+        ArrayCharString& operator=(const ArrayCharString& other) {
+            if(this != &other) {
+                Core::memoryCopy(data, other.data, N);
+                length = other.length;
+                hash = other.hash;
+            }
+            return *this;
+        }
+
+        template<typename... Args>
+        check_return Error format(Args&&... args) {
+            ArrayCharString s;
+            return CharString::format(s, Core::forward<Args>(args)...);
+        }
+
+        check_return Error replace(const CharString& search,
+                                   const CharString& replace) {
+            ArrayCharString s;
+            return CharString::replace(s, search, replace);
+        }
+
+        using CharString::replace;
+    };
+
     template<int N>
     class Char32String final {
         int length;
@@ -470,21 +512,13 @@ namespace Core {
         }
 
         check_return Error append(const char* s) {
-            if constexpr(IsSame<c32, char>) {
-                // stringLength as s could be some part of data
-                for(int i = stringLength(s); i > 0; i--) {
-                    CORE_RETURN_ERROR(append(*(s++)));
-                }
-                return Error::NONE;
-            } else {
-                while(true) {
-                    c32 u = 0;
-                    CORE_RETURN_ERROR(readUnicode(u, s));
-                    if(u == 0) {
-                        return Error::NONE;
-                    }
-                    CORE_RETURN_ERROR(append(u));
+            while(true) {
+                c32 u = 0;
+                CORE_RETURN_ERROR(readUnicode(u, s));
+                if(u == 0) {
+                    return Error::NONE;
                 }
+                CORE_RETURN_ERROR(append(u));
             }
         }
 
@@ -561,8 +595,7 @@ namespace Core {
             return t.toString(*this);
         }
 
-        template<int L>
-        check_return Error toString(CharString<L>& s) const {
+        check_return Error toString(CharString& s) const {
             int l = length; // length changes if &s == this
             for(int i = 0; i < l; i++) {
                 CORE_RETURN_ERROR(s.append(data[i]));
@@ -814,7 +847,7 @@ namespace Core {
     }
 
     template<int N>
-    using String8 = CharString<N>;
+    using String8 = ArrayCharString<N>;
 
     template<int N>
     using String32 = Char32String<N>;
@@ -830,13 +863,11 @@ bool operator!=(const c32* cs, const Core::Char32String<N>& s) {
     return s != cs;
 }
 
-template<int N>
-bool operator==(const char* cs, const Core::CharString<N>& s) {
+inline bool operator==(const char* cs, const Core::CharString& s) {
     return s == cs;
 }
 
-template<int N>
-bool operator!=(const char* cs, const Core::CharString<N>& s) {
+inline bool operator!=(const char* cs, const Core::CharString& s) {
     return s != cs;
 }
 

+ 24 - 15
test/modules/ArrayStringTests.cpp

@@ -2,7 +2,6 @@
 #include "core/data/HashMap.hpp"
 #include "core/utils/ArrayString.hpp"
 
-template class Core::CharString<128>;
 template class Core::Char32String<128>;
 
 using String8 = Core::String8<128>;
@@ -51,7 +50,7 @@ static void testStringAppend8() {
 }
 
 static void testStringAppendOverflow8() {
-    Core::CharString<6> s;
+    Core::ArrayCharString<6> s;
     CORE_TEST_ERROR(s.append("te"));
     CORE_TEST_EQUAL(Core::Error::CAPACITY_REACHED, s.append("23334444"));
     CORE_TEST_TRUE(build("te23334444") != s);
@@ -193,7 +192,7 @@ static void testBool8() {
 }
 
 static void testIntOverflow8() {
-    Core::CharString<4> s;
+    Core::ArrayCharString<4> s;
     CORE_TEST_EQUAL(Core::Error::CAPACITY_REACHED, s.append(123456));
 
     String8 o;
@@ -377,18 +376,28 @@ static void testSubString8() {
     String8 s;
     CORE_TEST_ERROR(s.append("01üää3ä"));
 
-    CORE_TEST_STRING("01üää3ä", s.substring(-2));
-    CORE_TEST_STRING("1üää3ä", s.substring(1));
-    CORE_TEST_STRING("üää3ä", s.substring(2));
-    CORE_TEST_STRING("ää3ä", s.substring(4));
-    CORE_TEST_STRING("ä3ä", s.substring(6));
-
-    CORE_TEST_STRING("01üää3ä", s.substring(0, 10));
-    CORE_TEST_STRING("1üää3", s.substring(1, 8));
-    CORE_TEST_STRING("üää", s.substring(2, 7));
-    CORE_TEST_STRING("ä", s.substring(4, 5));
-    CORE_TEST_STRING("", s.substring(4, 2));
-    CORE_TEST_STRING("ä3ä", s.substring(6, 23));
+    String8 sub;
+    CORE_TEST_ERROR(s.substring(sub, -2));
+    CORE_TEST_STRING("01üää3ä", sub);
+    CORE_TEST_ERROR(s.substring(sub, 2));
+    CORE_TEST_STRING("üää3ä", sub);
+    CORE_TEST_ERROR(s.substring(sub, 4));
+    CORE_TEST_STRING("ää3ä", sub);
+    CORE_TEST_ERROR(s.substring(sub, 6));
+    CORE_TEST_STRING("ä3ä", sub);
+
+    CORE_TEST_ERROR(s.substring(sub, 0, 10));
+    CORE_TEST_STRING("01üää3ä", sub);
+    CORE_TEST_ERROR(s.substring(sub, 1, 8));
+    CORE_TEST_STRING("1üää3", sub);
+    CORE_TEST_ERROR(s.substring(sub, 2, 7));
+    CORE_TEST_STRING("üää", sub);
+    CORE_TEST_ERROR(s.substring(sub, 4, 5));
+    CORE_TEST_STRING("ä", sub);
+    CORE_TEST_ERROR(s.substring(sub, 4, 2));
+    CORE_TEST_STRING("", sub);
+    CORE_TEST_ERROR(s.substring(sub, 6, 23));
+    CORE_TEST_STRING("ä3ä", sub);
 }
 
 static void testReplace8() {