Kajetan Johannes Hammerle 6 дней назад
Родитель
Сommit
1c7fd3921e

+ 3 - 1
modules/BitArray.cppm

@@ -2,6 +2,8 @@ export module Core.BitArray;
 
 
 import Core.Types;
 import Core.Types;
 
 
+export import Core.ToString;
+
 export namespace Core {
 export namespace Core {
     class BitArray final {
     class BitArray final {
         u64 length : 56;
         u64 length : 56;
@@ -23,7 +25,7 @@ export namespace Core {
         i64 select(size_t index) const;
         i64 select(size_t index) const;
         void resize(size_t newLength, size_t newBits);
         void resize(size_t newLength, size_t newBits);
         void fill(u64 value);
         void fill(u64 value);
-        size_t toString(char* s, size_t n) const;
+        size_t toString(StringBase& b) const;
         void swap(BitArray& other);
         void swap(BitArray& other);
     };
     };
 
 

+ 1 - 1
modules/Box.cppm

@@ -20,6 +20,6 @@ export namespace Core {
         const Vector3& getMin() const;
         const Vector3& getMin() const;
         const Vector3& getMax() const;
         const Vector3& getMax() const;
 
 
-        size_t toString(char* s, size_t n) const;
+        size_t toString(StringBase& b) const;
     };
     };
 }
 }

+ 2 - 6
modules/HashMap.cppm

@@ -41,12 +41,8 @@ export namespace Core {
                 return key;
                 return key;
             }
             }
 
 
-            size_t toString(char* s, size_t n) const {
-                size_t total = 0;
-                addString(key, s, n, total);
-                addString(" = ", s, n, total);
-                addString(value, s, n, total);
-                return total;
+            size_t toString(StringBase& b) const {
+                return b.addFormat("{} = {}", key, value);
             }
             }
 
 
         private:
         private:

+ 1 - 1
modules/HashedString.cppm

@@ -30,7 +30,7 @@ export namespace Core {
         }
         }
 
 
         HashedString(const char* s) : hash(hashString(s)) {
         HashedString(const char* s) : hash(hashString(s)) {
-            toString(s, data, N);
+            Core::StringBase(data, N).add(s);
         }
         }
 
 
         bool operator==(const HashedString& other) const {
         bool operator==(const HashedString& other) const {

+ 20 - 31
modules/Logger.cppm

@@ -22,20 +22,15 @@ export namespace Core {
         const char* format;
         const char* format;
         std::source_location location;
         std::source_location location;
 
 
-        FormatLocation(
-            const char* f,
-            const std::source_location& l = std::source_location::current()) :
-            format(f), location(l) {
+        FormatLocation(const char* f, SOURCE) : format(f), location(sl) {
         }
         }
     };
     };
 
 
     template<typename... Args>
     template<typename... Args>
     void report(LogLevel l, const FormatLocation& format, Args&&... args) {
     void report(LogLevel l, const FormatLocation& format, Args&&... args) {
-        char buffer[512];
-        formatBuffer(
-            buffer, sizeof(buffer), format.format,
-            Core::forward<Args>(args)...);
-        callReportHandler(l, buffer, format.location);
+        String<512> s;
+        s.addFormat(format.format, Core::forward<Args>(args)...);
+        callReportHandler(l, s, format.location);
     }
     }
 
 
     const char* getShortFileName(const char* s);
     const char* getShortFileName(const char* s);
@@ -50,52 +45,46 @@ export namespace Core {
         const char* file = getShortFileName(format.location.file_name());
         const char* file = getShortFileName(format.location.file_name());
         fputs(prefix, stdout);
         fputs(prefix, stdout);
         print("{}:{} | ", file, format.location.line());
         print("{}:{} | ", file, format.location.line());
-        char buffer[512];
-        formatBuffer(
-            buffer, sizeof(buffer), format.format,
-            Core::forward<Args>(args)...);
-        fputs(buffer, stdout);
+        String<512> s;
+        s.addFormat(format.format, Core::forward<Args>(args)...);
+        s.print();
         puts(Terminal::RESET);
         puts(Terminal::RESET);
     }
     }
 
 
     template<typename... Args>
     template<typename... Args>
     void logError(const FormatLocation& format, Args&&... args) {
     void logError(const FormatLocation& format, Args&&... args) {
         if constexpr(LOG_LEVEL >= 1) {
         if constexpr(LOG_LEVEL >= 1) {
-            char buffer[32];
-            formatBuffer(
-                buffer, sizeof(buffer), "{}[ERROR] ", Terminal::FG_RED);
-            log(LogLevel::ERROR, buffer, format, forward<Args>(args)...);
+            String<32> s;
+            s.addFormat("{}[ERROR] ", Terminal::FG_RED);
+            log(LogLevel::ERROR, s, format, forward<Args>(args)...);
         }
         }
     }
     }
 
 
     template<typename... Args>
     template<typename... Args>
     void logWarning(const FormatLocation& format, Args&&... args) {
     void logWarning(const FormatLocation& format, Args&&... args) {
         if constexpr(LOG_LEVEL >= 2) {
         if constexpr(LOG_LEVEL >= 2) {
-            char buffer[32];
-            formatBuffer(
-                buffer, sizeof(buffer), "{}[WARNING] ",
-                Terminal::FG_BRIGHT_YELLOW);
-            log(LogLevel::WARNING, buffer, format, forward<Args>(args)...);
+            String<32> s;
+            s.addFormat("{}[WARNING] ", Terminal::FG_BRIGHT_YELLOW);
+            log(LogLevel::WARNING, s, format, forward<Args>(args)...);
         }
         }
     }
     }
 
 
     template<typename... Args>
     template<typename... Args>
     void logInfo(const FormatLocation& format, Args&&... args) {
     void logInfo(const FormatLocation& format, Args&&... args) {
         if constexpr(LOG_LEVEL >= 3) {
         if constexpr(LOG_LEVEL >= 3) {
-            char buffer[32];
-            formatBuffer(buffer, sizeof(buffer), "{}[INFO] ", Terminal::BOLD);
-            log(LogLevel::INFO, buffer, format, forward<Args>(args)...);
+            String<32> s;
+            s.addFormat("{}[INFO] ", Terminal::BOLD);
+            log(LogLevel::INFO, s, format, forward<Args>(args)...);
         }
         }
     }
     }
 
 
     template<typename... Args>
     template<typename... Args>
     void logDebug(const FormatLocation& format, Args&&... args) {
     void logDebug(const FormatLocation& format, Args&&... args) {
         if constexpr(LOG_LEVEL >= 4) {
         if constexpr(LOG_LEVEL >= 4) {
-            char buffer[32];
-            formatBuffer(
-                buffer, sizeof(buffer), "{}{}[DEBUG] ", Terminal::BOLD,
-                Terminal::FG_BRIGHT_BLACK);
-            log(LogLevel::DEBUG, buffer, format, forward<Args>(args)...);
+            String<32> s;
+            s.addFormat(
+                "{}{}[DEBUG] ", Terminal::BOLD, Terminal::FG_BRIGHT_BLACK);
+            log(LogLevel::DEBUG, s, format, forward<Args>(args)...);
         }
         }
     }
     }
 }
 }

+ 1 - 1
modules/Matrix.cppm

@@ -26,7 +26,7 @@ export namespace Core {
         Matrix& rotateY(float radians);
         Matrix& rotateY(float radians);
         Matrix& rotateZ(float radians);
         Matrix& rotateZ(float radians);
         Matrix& rotate(const Quaternion& q);
         Matrix& rotate(const Quaternion& q);
-        size_t toString(char* s, size_t n) const;
+        size_t toString(StringBase& b) const;
 
 
     private:
     private:
         Matrix& rotate(float degrees, int a, int b);
         Matrix& rotate(float degrees, int a, int b);

+ 1 - 1
modules/Plane.cppm

@@ -11,6 +11,6 @@ export namespace Core {
         Plane();
         Plane();
         Plane(const Vector3& a, const Vector3& b, const Vector3& c);
         Plane(const Vector3& a, const Vector3& b, const Vector3& c);
         float signedDistance(const Vector3& v) const;
         float signedDistance(const Vector3& v) const;
-        size_t toString(char* s, size_t n) const;
+        size_t toString(StringBase& b) const;
     };
     };
 }
 }

+ 1 - 1
modules/Quaternion.cppm

@@ -13,6 +13,6 @@ export namespace Core {
         Quaternion& operator*=(const Quaternion& other);
         Quaternion& operator*=(const Quaternion& other);
         Quaternion operator*(const Quaternion& other) const;
         Quaternion operator*(const Quaternion& other) const;
         Vector3 operator*(const Vector3& v) const;
         Vector3 operator*(const Vector3& v) const;
-        size_t toString(char* s, size_t n) const;
+        size_t toString(StringBase& b) const;
     };
     };
 }
 }

+ 13 - 9
modules/Queue.cppm

@@ -1,9 +1,13 @@
+module;
+
+#include <iostream>
+
 export module Core.Queue;
 export module Core.Queue;
 
 
 export import Core.New;
 export import Core.New;
+export import Core.ToString;
 
 
 import Core.AlignedData;
 import Core.AlignedData;
-import Core.ToString;
 import Core.Meta;
 import Core.Meta;
 import Core.Utility;
 import Core.Utility;
 import Core.Assert;
 import Core.Assert;
@@ -98,20 +102,20 @@ export namespace Core {
             readIndex = (readIndex + 1) % N;
             readIndex = (readIndex + 1) % N;
         }
         }
 
 
-        size_t toString(char* s, size_t n) const {
-            size_t total = 0;
-            addString("[", s, n, total);
+        size_t toString(StringBase& b) const {
+            size_t oldtotal = b.getTotal();
+            b.add("[");
             size_t end = getLength();
             size_t end = getLength();
             if(end > 0) {
             if(end > 0) {
                 end--;
                 end--;
                 for(size_t i = 0; i < end; i++) {
                 for(size_t i = 0; i < end; i++) {
-                    addString((*this)[i], s, n, total);
-                    addString(", ", s, n, total);
+                    b.add((*this)[i]);
+                    b.add(", ");
                 }
                 }
-                addString((*this)[end], s, n, total);
+                b.add((*this)[end]);
             }
             }
-            addString("]", s, n, total);
-            return total;
+            b.add("]");
+            return b.getTotal() - oldtotal;
         }
         }
 
 
     private:
     private:

+ 4 - 4
modules/Test.cppm

@@ -37,10 +37,10 @@ export namespace Core {
 
 
     template<typename A, typename B>
     template<typename A, typename B>
     bool testString(const A& wanted, const B& actual, SOURCE) {
     bool testString(const A& wanted, const B& actual, SOURCE) {
-        char wantedString[512];
-        size_t lw = toString(wanted, wantedString, sizeof(wantedString));
-        char actualString[512];
-        size_t la = toString(actual, actualString, sizeof(actualString));
+        String<512> wantedString;
+        size_t lw = wantedString.add(wanted);
+        String<512> actualString;
+        size_t la = actualString.add(actual);
         test(lw, la, l);
         test(lw, la, l);
         return testString(
         return testString(
             static_cast<const char*>(wantedString),
             static_cast<const char*>(wantedString),

+ 109 - 105
modules/ToString.cppm

@@ -6,147 +6,151 @@ import Core.Types;
 
 
 export import Core.StringFormat;
 export import Core.StringFormat;
 
 
-#define TO_STRING(type) \
-    size_t toString(type t, char* s, size_t n, const StringFormat& format = {})
-
 export namespace Core {
 export namespace Core {
-    TO_STRING(signed char);
-    TO_STRING(char);
-    TO_STRING(short);
-    TO_STRING(int);
-    TO_STRING(long);
-    TO_STRING(long long);
-    TO_STRING(unsigned char);
-    TO_STRING(unsigned short);
-    TO_STRING(unsigned int);
-    TO_STRING(unsigned long);
-    TO_STRING(unsigned long long);
-    TO_STRING(float);
-    TO_STRING(double);
-    TO_STRING(const char*);
-    TO_STRING(const unsigned char*);
-    TO_STRING(unsigned char*);
-    TO_STRING(bool);
-
-    template<typename T>
-    void addString(
-        const T& t, char*& s, size_t& n, size_t& total,
-        const StringFormat& format = {});
-
-    template<Core::Iterable T>
-    size_t toString(
-        const T& t, char* s, size_t n, const StringFormat& format = {}) {
-        (void)format;
-        size_t total = 0;
-        addString("[", s, n, total);
-        auto current = t.begin();
-        auto end = t.end();
-        if(current != end) {
-            addString(*current, s, n, total);
-            ++current;
-        }
-        while(current != end) {
-            addString(", ", s, n, total);
-            addString(*current, s, n, total);
-            ++current;
-        }
-        addString("]", s, n, total);
-        return total;
-    }
-
-    template<typename T>
-    concept ToString =
-        requires(const T& t, char* s, size_t n) { t.toString(s, n); };
-
-    template<ToString T>
-    size_t toString(
-        const T& t, char* s, size_t n, const StringFormat& format = {}) {
-        (void)format;
-        return t.toString(s, n);
-    }
+    class StringBase;
 
 
     template<typename T>
     template<typename T>
-    void addString(
-        const T& t, char*& s, size_t& n, size_t& total,
-        const StringFormat& format) {
-        size_t w = toString(t, s, n, format);
-        total += w;
-        w = Core::min(n, w);
-        s += w;
-        n -= w;
-    }
+    concept ToString = requires(const T& t, StringBase& b) { t.toString(b); };
 
 
-    size_t copyFormatUntil(
-        const char*& format, char*& s, size_t& n, StringFormat& f);
-
-    template<typename T, typename... Args>
-    void formatR(
-        const char*& format, char*& s, size_t& n, size_t& total, const T& t,
-        Args&&... args) {
-        StringFormat f;
-        total += copyFormatUntil(format, s, n, f);
-        addString(t, s, n, total, f);
-        if constexpr(sizeof...(args) > 0) {
-            formatR(format, s, n, total, Core::forward<Args>(args)...);
-        }
-    }
-
-    template<typename... Args>
-    size_t formatBuffer(char* s, size_t n, const char* format, Args&&... args) {
-        StringFormat f;
-        size_t total = 0;
-        if constexpr(sizeof...(args) > 0) {
-            formatR(format, s, n, total, Core::forward<Args>(args)...);
-        }
-        return total + copyFormatUntil(format, s, n, f);
-    }
-
-    struct StringBase {
+    class StringBase {
+    public:
         size_t index = 0;
         size_t index = 0;
         size_t capacity = 0;
         size_t capacity = 0;
         char* buffer = nullptr;
         char* buffer = nullptr;
 
 
+    public:
         StringBase() {
         StringBase() {
         }
         }
 
 
+        StringBase(char* s, size_t n) : capacity(n), buffer(s) {
+        }
+
         StringBase(StringBase&& other) = default;
         StringBase(StringBase&& other) = default;
         StringBase(const StringBase& other) = delete;
         StringBase(const StringBase& other) = delete;
         StringBase& operator=(StringBase&& other) = default;
         StringBase& operator=(StringBase&& other) = default;
         StringBase& operator=(const StringBase& other) = delete;
         StringBase& operator=(const StringBase& other) = delete;
 
 
+        operator const char*() const {
+            return buffer;
+        }
+
+        void clear() {
+            index = 0;
+            if(buffer != nullptr) {
+                *buffer = '\0';
+            }
+        }
+
+        size_t getCapacity() const {
+            return index >= capacity ? 0 : capacity - index;
+        }
+
+        size_t getTotal() const {
+            return index;
+        }
+
+        char* getCurrent() const {
+            return buffer + min(index, capacity);
+        }
+
+        template<typename... Args>
+        size_t addFormat(const char* format, Args&&... args) {
+            size_t oldIndex = index;
+            (
+                [&] {
+                    StringFormat f;
+                    copyFormatUntil(format, f);
+                    switcher(args, f);
+                }(),
+                ...);
+
+            while(*format != '\0') {
+                StringFormat f;
+                copyFormatUntil(format, f);
+            }
+            return index - oldIndex;
+        }
+
         template<typename... Args>
         template<typename... Args>
         size_t format(const char* format, Args&&... args) {
         size_t format(const char* format, Args&&... args) {
-            size_t total = formatBuffer(
-                buffer + index, capacity - index, format,
-                Core::forward<Args>(args)...);
-            index = Core::min(index + total, capacity);
-            return total;
+            clear();
+            return addFormat<Args...>(format, Core::forward<Args>(args)...);
         }
         }
 
 
         template<typename T>
         template<typename T>
         size_t add(const T& t) {
         size_t add(const T& t) {
-            size_t total = toString(t, buffer + index, capacity - index);
-            index = Core::min(index + total, capacity);
-            return total;
+            size_t oldIndex = index;
+            switcher(t);
+            return index - oldIndex;
+        }
+
+        void print() const;
+
+    private:
+        void copyFormatUntil(const char*& format, StringFormat& f);
+
+#define TO_STRING(type) void toString(type t, const StringFormat& format)
+
+        TO_STRING(signed char);
+        TO_STRING(char);
+        TO_STRING(short);
+        TO_STRING(int);
+        TO_STRING(long);
+        TO_STRING(long long);
+        TO_STRING(unsigned char);
+        TO_STRING(unsigned short);
+        TO_STRING(unsigned int);
+        TO_STRING(unsigned long);
+        TO_STRING(unsigned long long);
+        TO_STRING(float);
+        TO_STRING(double);
+        TO_STRING(const char*);
+        TO_STRING(const unsigned char*);
+        TO_STRING(unsigned char*);
+        TO_STRING(bool);
+
+        template<typename T>
+        void switcher(const T& t, const StringFormat& format = {}) {
+            size_t oldIndex = index;
+            if constexpr(Core::Iterable<T>) {
+                switcher("[");
+                auto current = t.begin();
+                auto end = t.end();
+                if(current != end) {
+                    switcher(*current);
+                    ++current;
+                }
+                while(current != end) {
+                    switcher(", ");
+                    switcher(*current);
+                    ++current;
+                }
+                switcher("]");
+            } else if constexpr(ToString<T>) {
+                t.toString(*this);
+            } else {
+                toString(t, format);
+            }
+            applyPostFormat(oldIndex, index - oldIndex, format);
         }
         }
 
 
-        void print();
+        void applyPostFormat(
+            size_t startIndex, size_t length, const StringFormat& format);
+        void insertSpace(size_t startIndex);
     };
     };
 
 
     template<size_t N>
     template<size_t N>
     struct String : public StringBase {
     struct String : public StringBase {
         char data[N]{};
         char data[N]{};
 
 
-        String() {
-            buffer = data;
-            capacity = N;
+        String() : StringBase(data, N) {
         }
         }
     };
     };
 
 
     template<typename... Args>
     template<typename... Args>
     void print(const char* format, Args&&... args) {
     void print(const char* format, Args&&... args) {
         String<256> s;
         String<256> s;
-        s.format(format, Core::forward<Args>(args)...);
+        s.addFormat(format, Core::forward<Args>(args)...);
         s.print();
         s.print();
     }
     }
 }
 }

+ 8 - 9
modules/Vector.cppm

@@ -1,10 +1,10 @@
 export module Core.Vector;
 export module Core.Vector;
 
 
 export import Core.Types;
 export import Core.Types;
+export import Core.ToString;
 
 
 import Core.Math;
 import Core.Math;
 import Core.Meta;
 import Core.Meta;
-import Core.ToString;
 import Core.Std;
 import Core.Std;
 
 
 export namespace Core {
 export namespace Core {
@@ -163,18 +163,17 @@ export namespace Core {
             return to<float>();
             return to<float>();
         }
         }
 
 
-        size_t toString(char* s, size_t n) const {
-            size_t total = 0;
-            addString("[", s, n, total);
+        size_t toString(StringBase& b) const {
+            b.add("[");
             for(size_t i = 0; i < N - 1; i++) {
             for(size_t i = 0; i < N - 1; i++) {
-                addString(values[i], s, n, total);
-                addString(", ", s, n, total);
+                b.add(values[i]);
+                b.add(", ");
             }
             }
             if constexpr(N > 0) {
             if constexpr(N > 0) {
-                addString(values[N - 1], s, n, total);
+                b.add(values[N - 1]);
             }
             }
-            addString("]", s, n, total);
-            return total;
+            b.add("]");
+            return b.getTotal();
         }
         }
 
 
         bool operator==(const Vector& other) const {
         bool operator==(const Vector& other) const {

+ 7 - 9
src/BitArray.cpp

@@ -1,6 +1,5 @@
 module Core.BitArray;
 module Core.BitArray;
 
 
-import Core.ToString;
 import Core.Math;
 import Core.Math;
 import Core.Meta;
 import Core.Meta;
 import Core.Utility;
 import Core.Utility;
@@ -154,20 +153,19 @@ void BitArray::resize(size_t newLength, size_t newBits) {
     bits = newBits & 0xFF;
     bits = newBits & 0xFF;
 }
 }
 
 
-size_t BitArray::toString(char* s, size_t n) const {
-    size_t total = 0;
-    addString("[", s, n, total);
+size_t BitArray::toString(StringBase& b) const {
+    b.add("[");
     size_t l = length;
     size_t l = length;
     if(l > 0) {
     if(l > 0) {
         l--;
         l--;
         for(size_t i = 0; i < l; i++) {
         for(size_t i = 0; i < l; i++) {
-            addString(get(i), s, n, total);
-            addString(", ", s, n, total);
+            b.add(get(i));
+            b.add(", ");
         }
         }
-        addString(get(l), s, n, total);
+        b.add(get(l));
     }
     }
-    addString("]", s, n, total);
-    return total;
+    b.add("]");
+    return b.getTotal();
 }
 }
 
 
 void BitArray::swap(BitArray& other) {
 void BitArray::swap(BitArray& other) {

+ 4 - 4
src/Box.cpp

@@ -61,8 +61,8 @@ const Core::Vector3& Box::getMax() const {
     return max;
     return max;
 }
 }
 
 
-size_t Box::toString(char* s, size_t n) const {
-    return formatBuffer(
-        s, n, "Box([{.2}, {.2}, {.2}], [{.2}, {.2}, {.2}])", min[0], min[1],
-        min[2], max[0], max[1], max[2]);
+size_t Box::toString(StringBase& b) const {
+    return b.addFormat(
+        "Box([{.2}, {.2}, {.2}], [{.2}, {.2}, {.2}])", min[0], min[1], min[2],
+        max[0], max[1], max[2]);
 }
 }

+ 2 - 12
src/Matrix.cpp

@@ -125,16 +125,6 @@ Core::Matrix& Core::Matrix::rotate(const Quaternion& q) {
     return *this;
     return *this;
 }
 }
 
 
-size_t Core::Matrix::toString(char* s, size_t n) const {
-    size_t total = 0;
-    addString("[", s, n, total);
-    addString(data[0], s, n, total);
-    addString(", ", s, n, total);
-    addString(data[1], s, n, total);
-    addString(", ", s, n, total);
-    addString(data[2], s, n, total);
-    addString(", ", s, n, total);
-    addString(data[3], s, n, total);
-    addString("]", s, n, total);
-    return total;
+size_t Core::Matrix::toString(StringBase& b) const {
+    return b.addFormat("[{}, {}, {}, {}]", data[0], data[1], data[2], data[3]);
 }
 }

+ 3 - 4
src/Plane.cpp

@@ -1,7 +1,6 @@
 module Core.Plane;
 module Core.Plane;
 
 
 import Core.Std;
 import Core.Std;
-import Core.ToString;
 
 
 using Core::Plane;
 using Core::Plane;
 
 
@@ -16,7 +15,7 @@ float Plane::signedDistance(const Vector3& v) const {
     return abc.dot(v) + d;
     return abc.dot(v) + d;
 }
 }
 
 
-size_t Plane::toString(char* s, size_t n) const {
-    return formatBuffer(
-        s, n, "({.3} x + {.3} y + {.3} z + {.3})", abc[0], abc[1], abc[2], d);
+size_t Plane::toString(StringBase& b) const {
+    return b.addFormat(
+        "({.3} x + {.3} y + {.3} z + {.3})", abc[0], abc[1], abc[2], d);
 }
 }

+ 3 - 3
src/Quaternion.cpp

@@ -42,7 +42,7 @@ Core::Vector3 Core::Quaternion::operator*(const Vector3& v3) const {
     return v.xyz() * v.xyz().dot(v3) + qv * v[3] - cross(qv, v.xyz());
     return v.xyz() * v.xyz().dot(v3) + qv * v[3] - cross(qv, v.xyz());
 }
 }
 
 
-size_t Core::Quaternion::toString(char* s, size_t n) const {
-    return formatBuffer(
-        s, n, "({.3} i + {.3} j + {.3} k + {.3})", v[0], v[1], v[2], v[3]);
+size_t Core::Quaternion::toString(StringBase& b) const {
+    return b.addFormat(
+        "({.3} i + {.3} j + {.3} k + {.3})", v[0], v[1], v[2], v[3]);
 }
 }

+ 1 - 1
src/ReadLine.cpp

@@ -221,7 +221,7 @@ bool Core::readLine(char* buffer_, size_t n) {
         return false;
         return false;
     }
     }
     Core::MutexGuard mg(bufferMutex);
     Core::MutexGuard mg(bufferMutex);
-    toString(buffer[0].data.begin(), buffer_, n);
+    Core::StringBase(buffer_, n).add(buffer[0].data.begin());
     buffer.remove();
     buffer.remove();
     return true;
     return true;
 }
 }

+ 57 - 25
src/ToString.cpp

@@ -6,15 +6,15 @@ module Core.ToString;
 
 
 import Core.Std;
 import Core.Std;
 
 
-#define TO_STRING(type, format)                                               \
-    size_t Core::toString(type v, char* s, size_t n, const StringFormat& f) { \
-        (void)f;                                                              \
-        int e = snprintf(s, n, format, v);                                    \
-        return e < 0 ? 0 : static_cast<size_t>(e);                            \
+#define TO_STRING(type, format)                                      \
+    void Core::StringBase::toString(type v, const StringFormat& f) { \
+        (void)f;                                                     \
+        int e = snprintf(getCurrent(), getCapacity(), format, v);    \
+        index += e < 0 ? 0 : static_cast<size_t>(e);                 \
     }
     }
-#define TO_STRING_LINK(from, to)                                              \
-    size_t Core::toString(from v, char* s, size_t n, const StringFormat& f) { \
-        return toString(static_cast<to>(v), s, n, f);                         \
+#define TO_STRING_LINK(from, to)                                     \
+    void Core::StringBase::toString(from v, const StringFormat& f) { \
+        toString(static_cast<to>(v), f);                             \
     }
     }
 
 
 TO_STRING(char, "%c")
 TO_STRING(char, "%c")
@@ -33,15 +33,17 @@ TO_STRING(const char*, "%s")
 TO_STRING(const unsigned char*, "%s")
 TO_STRING(const unsigned char*, "%s")
 TO_STRING_LINK(unsigned char*, const unsigned char*)
 TO_STRING_LINK(unsigned char*, const unsigned char*)
 
 
-size_t Core::toString(double v, char* s, size_t n, const StringFormat& f) {
-    int e = snprintf(s, n, "%.*f", f.precision < 0 ? 2 : f.precision, v);
-    return e < 0 ? 0 : static_cast<size_t>(e);
+void Core::StringBase::toString(double v, const StringFormat& f) {
+    int e = snprintf(
+        getCurrent(), getCapacity(), "%.*f", f.precision < 0 ? 2 : f.precision,
+        v);
+    index += e < 0 ? 0 : static_cast<size_t>(e);
 }
 }
 
 
-size_t Core::toString(bool v, char* s, size_t n, const StringFormat& f) {
+void Core::StringBase::toString(bool v, const StringFormat& f) {
     (void)f;
     (void)f;
-    int e = snprintf(s, n, "%s", v ? "true" : "false");
-    return e < 0 ? 0 : static_cast<size_t>(e);
+    int e = snprintf(getCurrent(), getCapacity(), "%s", v ? "true" : "false");
+    index += e < 0 ? 0 : static_cast<size_t>(e);
 }
 }
 
 
 static int parseFormatNumber(const char*& from, const char* to) {
 static int parseFormatNumber(const char*& from, const char* to) {
@@ -76,9 +78,8 @@ static void parseFormat(
     }
     }
 }
 }
 
 
-size_t Core::copyFormatUntil(
-    const char*& format, char*& s, size_t& n, StringFormat& f) {
-    size_t w = 0;
+void Core::StringBase::copyFormatUntil(const char*& format, StringFormat& f) {
+    // char* s = getCurrent();
     while(*format != '\0') {
     while(*format != '\0') {
         char u = *(format++);
         char u = *(format++);
         if(u == '{') {
         if(u == '{') {
@@ -93,20 +94,51 @@ size_t Core::copyFormatUntil(
             }
             }
             format++;
             format++;
         }
         }
-        if(n > 1) {
-            *(s++) = u;
-            n--;
+        index++;
+        if(index < capacity) {
+            //*(s++) = u;
+            buffer[index - 1] = u;
         }
         }
-        w++;
     }
     }
-    if(n > 0) {
-        *s = '\0';
+    if(capacity > 0) {
+        buffer[min(index, capacity - 1)] = '\0';
     }
     }
-    return w;
 }
 }
 
 
-void Core::StringBase::print() {
+void Core::StringBase::print() const {
     if(buffer != nullptr) {
     if(buffer != nullptr) {
         fputs(buffer, stdout);
         fputs(buffer, stdout);
     }
     }
 }
 }
+
+void Core::StringBase::applyPostFormat(
+    size_t startIndex, size_t length, const StringFormat& format) {
+    if(format.width <= 0) {
+        return;
+    }
+    size_t w = static_cast<size_t>(format.width);
+    if(format.alignment == StringAlignment::LEFT) {
+        while(length < w) {
+            add(" ");
+            length++;
+        }
+    } else if(format.alignment == StringAlignment::RIGHT) {
+        while(length < w) {
+            insertSpace(startIndex);
+            length++;
+        }
+    }
+}
+
+void Core::StringBase::insertSpace(size_t k) {
+    index++;
+    if(k >= capacity) {
+        return;
+    }
+    size_t lastValidIndex = min(index, capacity - 1);
+    while(lastValidIndex > k) {
+        buffer[lastValidIndex] = buffer[lastValidIndex - 1];
+        lastValidIndex--;
+    }
+    buffer[k] = ' ';
+}

+ 2 - 2
src/Utility.cpp

@@ -101,8 +101,8 @@ static void addMemoryInfo(
     i->previous = nullptr;
     i->previous = nullptr;
     i->size = n;
     i->size = n;
     i->line = l.line();
     i->line = l.line();
-    Core::toString(
-        Core::getShortFileName(l.file_name()), i->buffer, sizeof(i->buffer));
+    Core::StringBase(i->buffer, sizeof(i->buffer))
+        .add(Core::getShortFileName(l.file_name()));
     memcpy(i->canary, CANARY, sizeof(CANARY));
     memcpy(i->canary, CANARY, sizeof(CANARY));
     memcpy(reinterpret_cast<char*>(i) + n, CANARY, sizeof(CANARY));
     memcpy(reinterpret_cast<char*>(i) + n, CANARY, sizeof(CANARY));
     Core::MutexGuard mg(memoryInfoMutex);
     Core::MutexGuard mg(memoryInfoMutex);

+ 4 - 18
test/modules/HashMapTests.cpp

@@ -107,25 +107,11 @@ struct ProbingTest final {
     }
     }
 
 
     ProbingTest& operator=(const ProbingTest& o) = delete;
     ProbingTest& operator=(const ProbingTest& o) = delete;
+    ProbingTest& operator=(ProbingTest&& o) noexcept = default;
+    bool operator==(const ProbingTest& other) const = default;
 
 
-    ProbingTest& operator=(ProbingTest&& o) noexcept {
-        a = o.a;
-        b = o.b;
-        return *this;
-    }
-
-    bool operator==(const ProbingTest& other) const {
-        return a == other.a && b == other.b;
-    }
-
-    size_t toString(char* s, size_t n) const {
-        size_t total = 0;
-        Core::addString("A(", s, n, total);
-        Core::addString(a, s, n, total);
-        Core::addString(", ", s, n, total);
-        Core::addString(b, s, n, total);
-        Core::addString(")", s, n, total);
-        return total;
+    size_t toString(Core::StringBase& s) const {
+        return s.addFormat("A({}, {})", a, b);
     }
     }
 };
 };
 
 

+ 5 - 3
test/modules/MatrixTests.cpp

@@ -171,13 +171,15 @@ static void testToString() {
     m.set(2, Core::Vector4(9.0f, 10.0f, 11.0f, 12.0f));
     m.set(2, Core::Vector4(9.0f, 10.0f, 11.0f, 12.0f));
     m.set(3, Core::Vector4(13.0f, 14.0f, 15.0f, 16.0f));
     m.set(3, Core::Vector4(13.0f, 14.0f, 15.0f, 16.0f));
     char buffer[1024];
     char buffer[1024];
-    size_t n = toString(m, buffer, sizeof(buffer));
+    Core::StringBase s(buffer, sizeof(buffer));
+    size_t n = s.add(m);
     Core::test(111, n);
     Core::test(111, n);
     Core::testString(
     Core::testString(
         "[[1.00, 2.00, 3.00, 4.00], [5.00, 6.00, 7.00, 8.00], "
         "[[1.00, 2.00, 3.00, 4.00], [5.00, 6.00, 7.00, 8.00], "
         "[9.00, 10.00, 11.00, 12.00], [13.00, 14.00, 15.00, 16.00]]",
         "[9.00, 10.00, 11.00, 12.00], [13.00, 14.00, 15.00, 16.00]]",
-        buffer);
-    n = toString(m, buffer, 20);
+        s);
+    s = Core::StringBase(buffer, 20);
+    n = s.add(m);
     Core::test(111, n);
     Core::test(111, n);
     Core::testString("[[1.00, 2.00, 3.00,", buffer);
     Core::testString("[[1.00, 2.00, 3.00,", buffer);
 }
 }

+ 2 - 2
test/modules/QueueTests.cpp

@@ -38,8 +38,8 @@ struct Tester final {
         sum -= id;
         sum -= id;
     }
     }
 
 
-    size_t toString(char* s, size_t n) const {
-        return Core::formatBuffer(s, n, "{}", id);
+    size_t toString(Core::StringBase& b) const {
+        return b.addFormat("{}", id);
     }
     }
 };
 };
 
 

+ 55 - 22
test/modules/UtilityTests.cpp

@@ -80,39 +80,71 @@ static void testSort() {
 
 
 static void testToString() {
 static void testToString() {
     char buffer[512];
     char buffer[512];
-    Core::test(
-        10, Core::formatBuffer(buffer, sizeof(buffer), "a{}a#a", 1.0, 2, 3));
-    Core::testString("a1.00a#a23", buffer);
-    Core::test(5, Core::formatBuffer(buffer, sizeof(buffer), "aa#ab"));
-    Core::testString("aa#ab", buffer);
-    Core::test(7, Core::formatBuffer(buffer, sizeof(buffer), "{{a}{}{{b}", 1));
-    Core::testString("{a}1{b}", buffer);
-    Core::test(6, Core::formatBuffer(buffer, 3, "aaaaaa"));
-    Core::testString("aa", buffer);
-    Core::test(4, Core::formatBuffer(buffer, 4, "a{}", 456));
-    Core::testString("a45", buffer);
-    Core::test(10, Core::formatBuffer(buffer, 4, "{} {} {}", 456, 567, 78));
-    Core::testString("456", buffer);
-    Core::test(10, Core::formatBuffer(buffer, 1, "{} {} {}", 456, 567, 78));
-    Core::testString("", buffer);
-    Core::test(
-        10, Core::formatBuffer(nullptr, 0, "{} {} {}", 456ll, 567l, 78ull));
+    Core::StringBase b(buffer, sizeof(buffer));
+    Core::test(10, b.format("a{}a#a", 1.0, 2, 3));
+    Core::testString("a1.00a#a23", b);
+    Core::test(5, b.format("aa#ab"));
+    Core::testString("aa#ab", b);
+    Core::test(7, b.format("{{a}{}{{b}", 1));
+    Core::testString("{a}1{b}", b);
+
+    b = Core::StringBase(buffer, 3);
+    Core::test(6, b.format("aaaaaa"));
+    Core::testString("aa", b);
+
+    b = Core::StringBase(buffer, 4);
+    Core::test(4, b.format("a{}", 456));
+    Core::testString("a45", b);
+
+    b = Core::StringBase(buffer, 4);
+    Core::test(10, b.format("{} {} {}", 456, 567, 78));
+    Core::testString("456", b);
+
+    b = Core::StringBase(buffer, 1);
+    Core::test(10, b.format("{} {} {}", 456, 567, 78));
+    Core::testString("", b);
+
+    b = Core::StringBase(nullptr, 0);
+    Core::test(10, b.format("{} {} {}", 456ll, 567l, 78ull));
 
 
     char c = 'a';
     char c = 'a';
     short s = 4;
     short s = 4;
     unsigned char cu = 'h';
     unsigned char cu = 'h';
     unsigned short su = 67;
     unsigned short su = 67;
     signed char cs = 'x';
     signed char cs = 'x';
-    Core::test(
-        10, Core::formatBuffer(
-                buffer, sizeof(buffer), "{} {} {} {} {}", c, s, cu, su, cs));
-    Core::testString("a 4 h 67 x", buffer);
+    b = Core::StringBase(buffer, sizeof(buffer));
+    Core::test(10, b.format("{} {} {} {} {}", c, s, cu, su, cs));
+    Core::testString("a 4 h 67 x", b);
 
 
     unsigned char text[] = "fgsdf";
     unsigned char text[] = "fgsdf";
-    Core::test(5, Core::toString(text, buffer, sizeof(buffer)));
+    b.clear();
+    Core::test(5, b.add(text));
     Core::testString("fgsdf", buffer);
     Core::testString("fgsdf", buffer);
 }
 }
 
 
+static void testStringFormat() {
+    char buffer[256];
+    Core::StringBase s(buffer, sizeof(buffer));
+    Core::test(3, s.format("X{}X", 5));
+    Core::testString("X5X", s);
+    Core::test(7, s.format("X{5}X", 5));
+    Core::testString("X    5X", s);
+    Core::test(7, s.format("X{r5}X", 5));
+    Core::testString("X    5X", s);
+    Core::test(7, s.format("X{l5}X", 5));
+    Core::testString("X5    X", s);
+
+    s = Core::StringBase(buffer, 0);
+    Core::test(3, s.format("X{}X", 5));
+    Core::testString("", s);
+    Core::test(7, s.format("X{5}X", 5));
+    Core::testString("", s);
+    Core::test(7, s.format("X{r5}X", 5));
+    Core::testString("", s);
+    Core::test(7, s.format("X{l5}X", 5));
+    Core::testString("", s);
+}
+
 void testUtility() {
 void testUtility() {
     testPopCount();
     testPopCount();
     testIf();
     testIf();
@@ -122,6 +154,7 @@ void testUtility() {
     testSwap();
     testSwap();
     testSort();
     testSort();
     testToString();
     testToString();
+    testStringFormat();
 }
 }
 
 
 static void outOfMemory(void*) {
 static void outOfMemory(void*) {

+ 5 - 5
test/modules/VectorTests.cpp

@@ -207,11 +207,11 @@ static void testCast() {
 }
 }
 
 
 static void testToString() {
 static void testToString() {
-    char buffer[200];
-    formatBuffer(
-        buffer, sizeof(buffer), "{} {} {}", Core::Vector<1, float>(),
-        Core::Vector2(2.0f, 3.0f), V3(4.0f, 5.0f, 6.0f));
-    Core::testString("[0.00] [2.00, 3.00] [4.00, 5.00, 6.00]", buffer);
+    Core::String<200> s;
+    s.addFormat(
+        "{} {} {}", Core::Vector<1, float>(), Core::Vector2(2.0f, 3.0f),
+        V3(4.0f, 5.0f, 6.0f));
+    Core::testString("[0.00] [2.00, 3.00] [4.00, 5.00, 6.00]", s);
 }
 }
 
 
 static void testNormalizeIntVector() {
 static void testNormalizeIntVector() {