| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- export module Core.ToString;
- import Core.Math;
- import Core.Meta;
- import Core.Types;
- export import Core.StringFormat;
- export namespace Core {
- class StringBase;
- template<typename T>
- concept ToString = requires(const T& t, StringBase& b) { t.toString(b); };
- class StringBase {
- size_t index = 0;
- size_t capacity = 0;
- char* buffer = nullptr;
- public:
- StringBase() noexcept {
- }
- StringBase(char* s, size_t n) noexcept : capacity(n), buffer(s) {
- }
- StringBase(StringBase&& other) = default;
- StringBase(const StringBase& other) = delete;
- StringBase& operator=(StringBase&& other) = default;
- StringBase& operator=(const StringBase& other) = delete;
- operator const char*() const noexcept {
- return buffer;
- }
- void clear() noexcept {
- index = 0;
- if(buffer != nullptr) {
- *buffer = '\0';
- }
- }
- size_t getCapacity() const noexcept {
- return index >= capacity ? 0 : capacity - index;
- }
- size_t getTotal() const noexcept {
- return index;
- }
- char* getCurrent() const noexcept {
- return buffer + min(index, capacity);
- }
- template<typename... Args>
- size_t addFormat(const char* format, Args&&... args) noexcept {
- 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>
- size_t format(const char* format, Args&&... args) noexcept {
- clear();
- return addFormat<Args...>(format, Core::forward<Args>(args)...);
- }
- template<typename T>
- size_t add(const T& t) noexcept {
- size_t oldIndex = index;
- switcher(t);
- return index - oldIndex;
- }
- void print() const noexcept;
- private:
- void copyFormatUntil(const char*& format, StringFormat& f) noexcept;
- #define TO_STRING(type) \
- void toString(type t, const StringFormat& format) noexcept
- 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(bool);
- template<typename T>
- void switcher(const T& t, const StringFormat& format = {}) noexcept {
- 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 addChar(char c);
- void applyPostFormat(
- size_t startIndex, size_t length,
- const StringFormat& format) noexcept;
- void insertSpace(size_t startIndex) noexcept;
- };
- template<size_t N>
- struct String : public StringBase {
- char data[N]{};
- String() noexcept : StringBase(data, N) {
- }
- };
- template<typename... Args>
- void print(const char* format, Args&&... args) noexcept {
- String<256> s;
- s.addFormat(format, Core::forward<Args>(args)...);
- s.print();
- }
- }
|