export module Core.ToString; import Core.Math; import Core.Meta; import Core.Types; export import Core.StringFormat; #define TO_STRING(type) \ size_t toString(type t, char* s, size_t n, const StringFormat& format = {}) 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 void addString( const T& t, char*& s, size_t& n, size_t& total, const StringFormat& format = {}); template 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 concept ToString = requires(const T& t, char* s, size_t n) { t.toString(s, n); }; template size_t toString( const T& t, char* s, size_t n, const StringFormat& format = {}) { (void)format; return t.toString(s, n); } template 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; } size_t copyFormatUntil( const char*& format, char*& s, size_t& n, StringFormat& f); template 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)...); } } template 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)...); } return total + copyFormatUntil(format, s, n, f); } struct StringBase { size_t index = 0; size_t capacity = 0; char* buffer = nullptr; StringBase() { } StringBase(StringBase&& other) = default; StringBase(const StringBase& other) = delete; StringBase& operator=(StringBase&& other) = default; StringBase& operator=(const StringBase& other) = delete; template size_t format(const char* format, Args&&... args) { size_t total = formatBuffer( buffer + index, capacity - index, format, Core::forward(args)...); index = Core::min(index + total, capacity); return total; } template size_t add(const T& t) { size_t total = toString(t, buffer + index, capacity - index); index = Core::min(index + total, capacity); return total; } void print(); }; template struct String : public StringBase { char data[N]{}; String() { buffer = data; capacity = N; } }; template void print(const char* format, Args&&... args) { String<256> s; s.format(format, Core::forward(args)...); s.print(); } }