From 56358280a7dc6ec70103910e460a7c27ffb45a15 Mon Sep 17 00:00:00 2001 From: EnderIce2 Date: Tue, 10 Oct 2023 06:09:17 +0300 Subject: [PATCH] Update std headers --- include_std/list | 221 ++++++ include_std/std.hpp | 6 +- include_std/std/functional.hpp | 38 +- include_std/std/list.hpp | 224 ------- include_std/std/smart_ptr.hpp | 410 ++++++------ include_std/std/string.hpp | 644 ------------------ include_std/std/unordered_map.hpp | 2 +- include_std/std/utility.hpp | 20 +- include_std/{std/stdexcept.hpp => stdexcept} | 23 +- include_std/string | 665 ++++++++++++++++++- tests/std_string.cpp | 2 +- 11 files changed, 1133 insertions(+), 1122 deletions(-) create mode 100644 include_std/list delete mode 100644 include_std/std/list.hpp delete mode 100644 include_std/std/string.hpp rename include_std/{std/stdexcept.hpp => stdexcept} (65%) diff --git a/include_std/list b/include_std/list new file mode 100644 index 0000000..a15d258 --- /dev/null +++ b/include_std/list @@ -0,0 +1,221 @@ +/* + This file is part of Fennix Kernel. + + Fennix Kernel is free software: you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + Fennix Kernel is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fennix Kernel. If not, see . +*/ + +#pragma once + +#include +#include + +namespace std +{ + template + class list + { + private: + struct lNode + { + T value; + lNode *prev; + lNode *next; + + lNode(const T &v, lNode *p = nullptr, lNode *n = nullptr) + : value(v), prev(p), next(n) {} + }; + + lNode *head; + lNode *tail; + size_t size; + + public: + list() : head(nullptr), tail(nullptr), size(0) {} + ~list() { clear(); } + list(const list &other) : head(nullptr), tail(nullptr), size(0) { *this = other; } + + void push_back(const T &value) + { + lNode *new_node = new lNode(value, tail, nullptr); + if (empty()) + { + head = tail = new_node; + } + else + { + tail->next = new_node; + tail = new_node; + } + ++size; + } + + void pop_back() + { + if (empty()) + { + throw std::runtime_error("list is empty"); + } + else if (head == tail) + { + delete tail; + head = tail = nullptr; + --size; + } + else + { + lNode *old_tail = tail; + tail = tail->prev; + tail->next = nullptr; + delete old_tail; + --size; + } + } + + void push_front(const T &value) + { + lNode *new_node = new lNode(value, nullptr, head); + if (empty()) + { + head = tail = new_node; + } + else + { + head->prev = new_node; + head = new_node; + } + ++size; + } + + void pop_front() + { + if (empty()) + { + throw std::runtime_error("list is empty"); + } + else if (head == tail) + { + delete head; + head = tail = nullptr; + --size; + } + else + { + lNode *old_head = head; + head = head->next; + head->prev = nullptr; + delete old_head; + --size; + } + } + + bool empty() const { return size == 0; } + + void clear() + { + while (!empty()) + pop_back(); + } + + list &operator=(const list &other) + { + if (this != &other) + { + clear(); + for (const T &value : other) + { + push_back(value); + } + } + return *this; + } + + class iterator + { + private: + lNode *node; + friend class list; + + public: + iterator(lNode *p = nullptr) : node(p) {} + T &operator*() const { return node->value; } + T *operator->() const { return &node->value; } + + iterator &operator++() + { + node = node->next; + return *this; + } + + iterator &operator--() + { + node = node->prev; + return *this; + } + + iterator operator++(int) + { + iterator tmp = *this; + ++*this; + return tmp; + } + + iterator operator--(int) + { + iterator tmp = *this; + --*this; + return tmp; + } + + bool operator==(const iterator &rhs) const { return node == rhs.node; } + bool operator!=(const iterator &rhs) const { return node != rhs.node; } + }; + + iterator begin() { return iterator(head); } + iterator end() { return iterator(nullptr); } + + iterator insert(iterator pos, const T &value) + { + if (pos == end()) + { + push_back(value); + return iterator(tail); + } + else if (pos == begin()) + { + push_front(value); + return iterator(head); + } + else + { + lNode *p = pos.node; + lNode *new_node = new lNode(value, p->prev, p); + p->prev->next = new_node; + p->prev = new_node; + ++size; + return iterator(new_node); + } + } + + iterator erase(iterator pos) + { + lNode *p = pos.node; + iterator next(p->next); + p->prev->next = p->next; + p->next->prev = p->prev; + delete p; + --size; + return next; + } + }; +} diff --git a/include_std/std.hpp b/include_std/std.hpp index 61e32f7..181436e 100644 --- a/include_std/std.hpp +++ b/include_std/std.hpp @@ -22,13 +22,13 @@ #define __FENNIX_KERNEL_STD_H__ #include +#include #include #include +#include +#include #include -#include #include -#include -#include #include #include diff --git a/include_std/std/functional.hpp b/include_std/std/functional.hpp index 12c6a4e..bd8cfd1 100644 --- a/include_std/std/functional.hpp +++ b/include_std/std/functional.hpp @@ -23,28 +23,28 @@ namespace std { - template - struct hash - { - size_t operator()(const Key &key) const - { - static_assert(sizeof(size_t) == sizeof(uint64_t)); // size_t and uint64_t must have the same size - const uint64_t fnv_offset_basis = 14695981039346656037ull; - const uint64_t fnv_prime = 1099511628211ull; + template + struct hash + { + size_t operator()(const Key &key) const + { + static_assert(sizeof(size_t) == sizeof(uint64_t)); // size_t and uint64_t must have the same size + const uint64_t fnv_offset_basis = 14695981039346656037ull; + const uint64_t fnv_prime = 1099511628211ull; - const uint8_t *data = reinterpret_cast(&key); - const size_t size = sizeof(Key); - uint64_t ret = fnv_offset_basis; + const uint8_t *data = reinterpret_cast(&key); + const size_t size = sizeof(Key); + uint64_t ret = fnv_offset_basis; - for (size_t i = 0; i < size; ++i) - { - ret ^= static_cast(data[i]); - ret *= fnv_prime; - } + for (size_t i = 0; i < size; ++i) + { + ret ^= static_cast(data[i]); + ret *= fnv_prime; + } - return static_cast(ret); - } - }; + return static_cast(ret); + } + }; } #endif // !__FENNIX_KERNEL_STD_FUNCTIONAL_H__ diff --git a/include_std/std/list.hpp b/include_std/std/list.hpp deleted file mode 100644 index 5869cb0..0000000 --- a/include_std/std/list.hpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#ifndef __FENNIX_KERNEL_STD_LIST_H__ -#define __FENNIX_KERNEL_STD_LIST_H__ - -#include -#include - -namespace std -{ - template - class list - { - private: - struct Node - { - T value; - Node *prev; - Node *next; - - Node(const T &v, Node *p = nullptr, Node *n = nullptr) - : value(v), prev(p), next(n) {} - }; - - Node *head; - Node *tail; - size_t size; - - public: - list() : head(nullptr), tail(nullptr), size(0) {} - ~list() { clear(); } - list(const list &other) : head(nullptr), tail(nullptr), size(0) { *this = other; } - - void push_back(const T &value) - { - Node *new_node = new Node(value, tail, nullptr); - if (empty()) - { - head = tail = new_node; - } - else - { - tail->next = new_node; - tail = new_node; - } - ++size; - } - - void pop_back() - { - if (empty()) - { - throw std::runtime_error("list is empty"); - } - else if (head == tail) - { - delete tail; - head = tail = nullptr; - --size; - } - else - { - Node *old_tail = tail; - tail = tail->prev; - tail->next = nullptr; - delete old_tail; - --size; - } - } - - void push_front(const T &value) - { - Node *new_node = new Node(value, nullptr, head); - if (empty()) - { - head = tail = new_node; - } - else - { - head->prev = new_node; - head = new_node; - } - ++size; - } - - void pop_front() - { - if (empty()) - { - throw std::runtime_error("list is empty"); - } - else if (head == tail) - { - delete head; - head = tail = nullptr; - --size; - } - else - { - Node *old_head = head; - head = head->next; - head->prev = nullptr; - delete old_head; - --size; - } - } - - bool empty() const { return size == 0; } - - void clear() - { - while (!empty()) - pop_back(); - } - - list &operator=(const list &other) - { - if (this != &other) - { - clear(); - for (const T &value : other) - { - push_back(value); - } - } - return *this; - } - - class iterator - { - private: - Node *node; - friend class list; - - public: - iterator(Node *p = nullptr) : node(p) {} - T &operator*() const { return node->value; } - T *operator->() const { return &node->value; } - - iterator &operator++() - { - node = node->next; - return *this; - } - - iterator &operator--() - { - node = node->prev; - return *this; - } - - iterator operator++(int) - { - iterator tmp = *this; - ++*this; - return tmp; - } - - iterator operator--(int) - { - iterator tmp = *this; - --*this; - return tmp; - } - - bool operator==(const iterator &rhs) const { return node == rhs.node; } - bool operator!=(const iterator &rhs) const { return node != rhs.node; } - }; - - iterator begin() { return iterator(head); } - iterator end() { return iterator(nullptr); } - - iterator insert(iterator pos, const T &value) - { - if (pos == end()) - { - push_back(value); - return iterator(tail); - } - else if (pos == begin()) - { - push_front(value); - return iterator(head); - } - else - { - Node *p = pos.node; - Node *new_node = new Node(value, p->prev, p); - p->prev->next = new_node; - p->prev = new_node; - ++size; - return iterator(new_node); - } - } - - iterator erase(iterator pos) - { - Node *p = pos.node; - iterator next(p->next); - p->prev->next = p->next; - p->next->prev = p->prev; - delete p; - --size; - return next; - } - }; -} - -#endif // !__FENNIX_KERNEL_STD_LIST_H__ diff --git a/include_std/std/smart_ptr.hpp b/include_std/std/smart_ptr.hpp index f6bc275..996fd59 100644 --- a/include_std/std/smart_ptr.hpp +++ b/include_std/std/smart_ptr.hpp @@ -34,242 +34,242 @@ namespace std { - /** - * @brief A smart pointer class - * - * This class is a smart pointer class. It is used to manage the lifetime of - * objects. It is a reference counted pointer, so when the last reference to - * the object is removed, the object is deleted. - * - * Basic Usage: - * smart_ptr pointer(new char()); - * *pointer = 'a'; - * printf("%c", *pointer); // Prints "a" - */ - template - class smart_ptr - { - T *RealPointer; + /** + * @brief A smart pointer class + * + * This class is a smart pointer class. It is used to manage the lifetime of + * objects. It is a reference counted pointer, so when the last reference to + * the object is removed, the object is deleted. + * + * Basic Usage: + * smart_ptr pointer(new char()); + * *pointer = 'a'; + * printf("%c", *pointer); // Prints "a" + */ + template + class smart_ptr + { + T *RealPointer; - public: - explicit smart_ptr(T *Pointer = nullptr) - { - spdbg("Smart pointer created (%#lx)", this->RealPointer); - this->RealPointer = Pointer; - } + public: + explicit smart_ptr(T *Pointer = nullptr) + { + spdbg("Smart pointer created (%#lx)", this->RealPointer); + this->RealPointer = Pointer; + } - ~smart_ptr() - { - spdbg("Smart pointer deleted (%#lx)", this->RealPointer); - delete this->RealPointer, this->RealPointer = nullptr; - } + ~smart_ptr() + { + spdbg("Smart pointer deleted (%#lx)", this->RealPointer); + delete this->RealPointer, this->RealPointer = nullptr; + } - T &operator*() - { - spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer); - return *this->RealPointer; - } + T &operator*() + { + spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer); + return *this->RealPointer; + } - T *operator->() - { - spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer); - return this->RealPointer; - } + T *operator->() + { + spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer); + return this->RealPointer; + } - T *get() - { - spdbg("Smart pointer returned (%#lx)", this->RealPointer); - return this->RealPointer; - } - }; + T *get() + { + spdbg("Smart pointer returned (%#lx)", this->RealPointer); + return this->RealPointer; + } + }; - template - class auto_ptr - { - }; + template + class auto_ptr + { + }; - template - class unique_ptr - { - }; + template + class unique_ptr + { + }; - template - class weak_ptr - { - }; + template + class weak_ptr + { + }; - template - class shared_ptr - { - private: - class counter - { - private: - unsigned int RefCount{}; + template + class shared_ptr + { + private: + class counter + { + private: + unsigned int RefCount{}; - public: - counter() : RefCount(0) { spdbg("Counter %#lx created", this); }; - counter(const counter &) = delete; - counter &operator=(const counter &) = delete; - ~counter() { spdbg("Counter %#lx deleted", this); } - void reset() - { - this->RefCount = 0; - spdbg("reset"); - } + public: + counter() : RefCount(0) { spdbg("Counter %#lx created", this); }; + counter(const counter &) = delete; + counter &operator=(const counter &) = delete; + ~counter() { spdbg("Counter %#lx deleted", this); } + void reset() + { + this->RefCount = 0; + spdbg("reset"); + } - unsigned int get() - { - return this->RefCount; - spdbg("return"); - } + unsigned int get() + { + return this->RefCount; + spdbg("return"); + } - void operator++() - { - this->RefCount++; - spdbg("increment"); - } + void operator++() + { + this->RefCount++; + spdbg("increment"); + } - void operator++(int) - { - this->RefCount++; - spdbg("increment"); - } + void operator++(int) + { + this->RefCount++; + spdbg("increment"); + } - void operator--() - { - this->RefCount--; - spdbg("decrement"); - } + void operator--() + { + this->RefCount--; + spdbg("decrement"); + } - void operator--(int) - { - this->RefCount--; - spdbg("decrement"); - } - }; + void operator--(int) + { + this->RefCount--; + spdbg("decrement"); + } + }; - counter *ReferenceCounter; - T *RealPointer; + counter *ReferenceCounter; + T *RealPointer; - public: - explicit shared_ptr(T *Pointer = nullptr) - { - this->RealPointer = Pointer; - this->ReferenceCounter = new counter(); - spdbg("[%#lx] Shared pointer created (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter); - if (Pointer) - (*this->ReferenceCounter)++; - } + public: + explicit shared_ptr(T *Pointer = nullptr) + { + this->RealPointer = Pointer; + this->ReferenceCounter = new counter(); + spdbg("[%#lx] Shared pointer created (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter); + if (Pointer) + (*this->ReferenceCounter)++; + } - shared_ptr(shared_ptr &SPtr) - { - spdbg("[%#lx] Shared pointer copied (ptr=%#lx, ref=%#lx)", this, SPtr.RealPointer, SPtr.ReferenceCounter); - this->RealPointer = SPtr.RealPointer; - this->ReferenceCounter = SPtr.ReferenceCounter; - (*this->ReferenceCounter)++; - } + shared_ptr(shared_ptr &SPtr) + { + spdbg("[%#lx] Shared pointer copied (ptr=%#lx, ref=%#lx)", this, SPtr.RealPointer, SPtr.ReferenceCounter); + this->RealPointer = SPtr.RealPointer; + this->ReferenceCounter = SPtr.ReferenceCounter; + (*this->ReferenceCounter)++; + } - ~shared_ptr() - { - spdbg("[%#lx] Shared pointer destructor called", this); - (*this->ReferenceCounter)--; - if (this->ReferenceCounter->get() == 0) - { - spdbg("[%#lx] Shared pointer deleted (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter); - delete this->ReferenceCounter, this->ReferenceCounter = nullptr; - delete this->RealPointer, this->RealPointer = nullptr; - } - } + ~shared_ptr() + { + spdbg("[%#lx] Shared pointer destructor called", this); + (*this->ReferenceCounter)--; + if (this->ReferenceCounter->get() == 0) + { + spdbg("[%#lx] Shared pointer deleted (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter); + delete this->ReferenceCounter, this->ReferenceCounter = nullptr; + delete this->RealPointer, this->RealPointer = nullptr; + } + } - unsigned int get_count() - { - spdbg("[%#lx] Shared pointer count (%d)", this, this->ReferenceCounter->get()); - return this->ReferenceCounter->get(); - } + unsigned int get_count() + { + spdbg("[%#lx] Shared pointer count (%d)", this, this->ReferenceCounter->get()); + return this->ReferenceCounter->get(); + } - T *get() - { - spdbg("[%#lx] Shared pointer get (%#lx)", this, this->RealPointer); - return this->RealPointer; - } + T *get() + { + spdbg("[%#lx] Shared pointer get (%#lx)", this, this->RealPointer); + return this->RealPointer; + } - T &operator*() - { - spdbg("[%#lx] Shared pointer dereference (ptr*=%#lx)", this, *this->RealPointer); - return *this->RealPointer; - } + T &operator*() + { + spdbg("[%#lx] Shared pointer dereference (ptr*=%#lx)", this, *this->RealPointer); + return *this->RealPointer; + } - T *operator->() - { - spdbg("[%#lx] Shared pointer dereference (ptr->%#lx)", this, this->RealPointer); - return this->RealPointer; - } + T *operator->() + { + spdbg("[%#lx] Shared pointer dereference (ptr->%#lx)", this, this->RealPointer); + return this->RealPointer; + } - void reset(T *Pointer = nullptr) - { - if (this->RealPointer == Pointer) - return; - spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter); - (*this->ReferenceCounter)--; - if (this->ReferenceCounter->get() == 0) - { - delete this->RealPointer; - delete this->ReferenceCounter; - } - this->RealPointer = Pointer; - this->ReferenceCounter = new counter(); - if (Pointer) - (*this->ReferenceCounter)++; - } + void reset(T *Pointer = nullptr) + { + if (this->RealPointer == Pointer) + return; + spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter); + (*this->ReferenceCounter)--; + if (this->ReferenceCounter->get() == 0) + { + delete this->RealPointer; + delete this->ReferenceCounter; + } + this->RealPointer = Pointer; + this->ReferenceCounter = new counter(); + if (Pointer) + (*this->ReferenceCounter)++; + } - void reset() - { - spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter); - if (this->ReferenceCounter->get() == 1) - { - delete this->RealPointer, this->RealPointer = nullptr; - delete this->ReferenceCounter, this->ReferenceCounter = nullptr; - } - else - { - (*this->ReferenceCounter)--; - } - } + void reset() + { + spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter); + if (this->ReferenceCounter->get() == 1) + { + delete this->RealPointer, this->RealPointer = nullptr; + delete this->ReferenceCounter, this->ReferenceCounter = nullptr; + } + else + { + (*this->ReferenceCounter)--; + } + } - void swap(shared_ptr &Other) - { - spdbg("[%#lx] Shared pointer swap (ptr=%#lx, ref=%#lx <=> ptr=%#lx, ref=%#lx)", - this, this->RealPointer, this->ReferenceCounter, Other.RealPointer, Other.ReferenceCounter); - T *tempRealPointer = this->RealPointer; - counter *tempReferenceCounter = this->ReferenceCounter; - this->RealPointer = Other.RealPointer; - this->ReferenceCounter = Other.ReferenceCounter; - Other.RealPointer = tempRealPointer; - Other.ReferenceCounter = tempReferenceCounter; - } - }; + void swap(shared_ptr &Other) + { + spdbg("[%#lx] Shared pointer swap (ptr=%#lx, ref=%#lx <=> ptr=%#lx, ref=%#lx)", + this, this->RealPointer, this->ReferenceCounter, Other.RealPointer, Other.ReferenceCounter); + T *tempRealPointer = this->RealPointer; + counter *tempReferenceCounter = this->ReferenceCounter; + this->RealPointer = Other.RealPointer; + this->ReferenceCounter = Other.ReferenceCounter; + Other.RealPointer = tempRealPointer; + Other.ReferenceCounter = tempReferenceCounter; + } + }; - template - using remove_reference_t = typename remove_reference::type; + template + using remove_reference_t = typename remove_reference::type; - template - T &&forward(remove_reference_t &t) { return static_cast(t); }; + template + T &&forward(remove_reference_t &t) { return static_cast(t); }; - template - T &&forward(remove_reference_t &&t) { return static_cast(t); }; + template + T &&forward(remove_reference_t &&t) { return static_cast(t); }; - template - shared_ptr make_shared(Args &&...args) - { - return shared_ptr(new T(forward(args)...)); - }; + template + shared_ptr make_shared(Args &&...args) + { + return shared_ptr(new T(forward(args)...)); + }; - template - smart_ptr make_smart(Args &&...args) - { - return smart_ptr(new T(forward(args)...)); - }; + template + smart_ptr make_smart(Args &&...args) + { + return smart_ptr(new T(forward(args)...)); + }; } #endif // !__FENNIX_KERNEL_STD_SMART_POINTER_H__ diff --git a/include_std/std/string.hpp b/include_std/std/string.hpp deleted file mode 100644 index f0dd0ad..0000000 --- a/include_std/std/string.hpp +++ /dev/null @@ -1,644 +0,0 @@ -/* - This file is part of Fennix Kernel. - - Fennix Kernel is free software: you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - Fennix Kernel is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Fennix Kernel. If not, see . -*/ - -#ifndef __FENNIX_KERNEL_STD_STRING_H__ -#define __FENNIX_KERNEL_STD_STRING_H__ - -#include -#include -#include - -// Show debug messages -// #define DEBUG_CPP_STRING 1 -// #define DEBUG_CPP_STRING_VERBOSE 1 - -#ifdef DEBUG_CPP_STRING -#define strdbg(m, ...) debug(m, ##__VA_ARGS__) -#else -#define strdbg(m, ...) -#endif - -#ifdef DEBUG_CPP_STRING_VERBOSE -#define v_strdbg(m, ...) debug(m, ##__VA_ARGS__) -#else -#define v_strdbg(m, ...) -#endif - -// TODO: Somewhere the delete is called twice, causing a double free error. - -namespace std -{ - /** - * @brief String class - * String class that can be used to store strings. - */ - class string - { - private: - char *Data{}; - size_t Length{}; - size_t Capacity{}; - - public: - static const size_t npos = -1; - - string(const char *Str = "") - { - this->Length = strlen(Str); - this->Capacity = this->Length + 1; - this->Data = new char[this->Capacity]; - strcpy(this->Data, Str); - strdbg("%#lx: New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - } - - ~string() - { - strdbg("%#lx: String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - delete[] this->Data, this->Data = nullptr; - } - - size_t length() const - { - v_strdbg("%#lx: String length: %d", - this, this->Length); - return this->Length; - } - - size_t capacity() const - { - v_strdbg("%#lx: String capacity: %d", - this, this->Capacity); - return this->Capacity; - } - - const char *c_str() const - { - v_strdbg("%#lx: String data: \"%s\"", - this, this->Data); - return this->Data; - } - - void resize(size_t NewLength) - { - strdbg("%#lx: String resize: %d", - this, NewLength); - if (NewLength < this->Capacity) - { - this->Length = NewLength; - this->Data[this->Length] = '\0'; - - strdbg("%#lx: String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - return; - } - - size_t newCapacity = NewLength + 1; - char *newData = new char[newCapacity]; - strcpy(newData, this->Data); - - strdbg("%#lx: old: %#lx, new: %#lx", - this, this->Data, newData); - - delete[] this->Data; - this->Data = newData; - this->Length = NewLength; - this->Capacity = newCapacity; - - strdbg("%#lx: String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - } - - void concat(const string &Other) - { - size_t NewLength = this->Length + Other.Length; - this->resize(NewLength); - - strcat(this->Data, Other.Data); - strdbg("%#lx: String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - } - - bool empty() const - { - strdbg("%#lx: String empty: %d", - this, this->Length == 0); - return this->Length == 0; - } - - size_t size() const - { - strdbg("%#lx: String size: %d", - this, this->Length); - return this->Length; - } - - void clear() - { - strdbg("%#lx: String clear", this); - this->resize(0); - } - - size_t find(const char *Str, size_t Pos = 0) const - { - strdbg("%#lx: String find: \"%s\", %d", - this, Str, Pos); - if (Pos >= this->Length) - return npos; - - for (size_t i = Pos; i < this->Length; i++) - { - bool found = true; - for (size_t j = 0; Str[j] != '\0'; j++) - { - if (this->Data[i + j] != Str[j]) - { - found = false; - break; - } - } - if (found) - return i; - } - return npos; - } - - size_t find(const string &Str, size_t Pos = 0) const - { - strdbg("%#lx: String find: \"%s\", %d", - this, Str.c_str(), Pos); - return this->find(Str.c_str(), Pos); - } - - void erase(int Index, int Count = 1) - { - strdbg("%#lx: String erase: %d, %d", - this, Index, Count); - if (Index < 0 || (size_t)Index >= this->Length) - return; - - if (Count < 0) - return; - - if ((size_t)(Index + Count) > this->Length) - Count = (int)this->Length - Index; - - for (size_t i = Index; i < this->Length - Count; i++) - this->Data[i] = this->Data[i + Count]; - - this->Length -= Count; - this->Data[this->Length] = '\0'; - strdbg("%#lx: String erased: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - } - - size_t find_last_not_of(const char *Str, size_t Pos = npos) const - { - strdbg("%#lx: String find_last_not_of: \"%s\", %d", - this, Str, Pos); - if (Pos == npos) - Pos = this->Length - 1; - - for (int i = (int)Pos; i >= 0; i--) - { - bool found = false; - for (size_t j = 0; Str[j] != '\0'; j++) - { - if (this->Data[i] == Str[j]) - { - found = true; - break; - } - } - if (!found) - return i; - } - return npos; - } - - size_t find_first_not_of(const char *Str, size_t Pos = 0) const - { - strdbg("%#lx: String find_first_not_of: \"%s\", %d", - this, Str, Pos); - if (Pos >= this->Length) - return npos; - - for (size_t i = Pos; i < this->Length; i++) - { - bool found = false; - for (size_t j = 0; Str[j] != '\0'; j++) - { - if (this->Data[i] == Str[j]) - { - found = true; - break; - } - } - if (!found) - return i; - } - return npos; - } - - size_t find_first_of(const char *Str, size_t Pos = 0) const - { - strdbg("%#lx: String find_first_of: \"%s\", %d", - this, Str, Pos); - if (Pos >= this->Length) - return npos; - - for (size_t i = Pos; i < this->Length; i++) - { - bool found = false; - for (size_t j = 0; Str[j] != '\0'; j++) - { - if (this->Data[i] == Str[j]) - { - found = true; - break; - } - } - if (found) - return i; - } - return npos; - } - - size_t find_last_of(const char *Str, size_t Pos = npos) const - { - strdbg("%#lx: String find_last_of: \"%s\", %d", - this, Str, Pos); - if (Pos == npos) - Pos = this->Length - 1; - - for (int i = (int)Pos; i >= 0; i--) - { - bool found = false; - for (int j = 0; Str[j] != '\0'; j++) - { - if (this->Data[i] == Str[j]) - { - found = true; - break; - } - } - if (found) - return i; - } - return npos; - } - - size_t find_first_of(char C, size_t Pos = 0) const - { - strdbg("%#lx: String find_first_of: '%c', %d", - this, C, Pos); - if (Pos >= this->Length) - return npos; - - for (size_t i = Pos; i < this->Length; i++) - { - if (this->Data[i] == C) - return i; - } - return npos; - } - - size_t find_last_of(char C, size_t Pos = npos) const - { - strdbg("%#lx: String find_last_of: '%c', %d", - this, C, Pos); - if (Pos == npos) - Pos = this->Length - 1; - - for (int i = (int)Pos; i >= 0; i--) - { - if (this->Data[i] == C) - return i; - } - return npos; - } - - size_t substr(const char *Str, size_t Pos = 0) const - { - strdbg("%#lx: String substr: \"%s\", %d", - this, Str, Pos); - if (Pos >= this->Length) - return npos; - - for (size_t i = Pos; i < this->Length; i++) - { - bool found = true; - for (size_t j = 0; Str[j] != '\0'; j++) - { - if (this->Data[i + j] != Str[j]) - { - found = false; - break; - } - } - if (found) - return i; - } - return npos; - } - - size_t substr(const string &Str, size_t Pos = 0) const - { - strdbg("%#lx: String substr: \"%s\", %d", - this, Str.c_str(), Pos); - return this->substr(Str.c_str(), Pos); - } - - string substr(size_t Pos = 0, size_t Count = npos) const - { - strdbg("%#lx: String substr: %d, %d", - this, Pos, Count); - if (Pos >= this->Length) - return string(); - - if (Count == npos) - Count = this->Length - Pos; - - if (Pos + Count > this->Length) - Count = this->Length - Pos; - - string ret; - ret.resize(Count); - for (size_t i = 0; i < Count; i++) - ret.Data[i] = this->Data[Pos + i]; - ret.Data[Count] = '\0'; - return ret; - } - - void replace(size_t Pos, size_t Count, const char *Str) - { - strdbg("%#lx: String replace: %d, %d, \"%s\"", - this, Pos, Count, Str); - if (Pos >= this->Length) - return; - - if ((int64_t)Count <= 0) - return; - - if (Pos + Count > this->Length) - Count = this->Length - Pos; - - size_t NewLength = this->Length - Count + strlen(Str); - this->resize(NewLength); - - for (size_t i = this->Length - 1; i >= Pos + strlen(Str); i--) - this->Data[i] = this->Data[i - strlen(Str) + Count]; - - for (unsigned long i = 0; i < strlen(Str); i++) - this->Data[Pos + i] = Str[i]; - - strdbg("%#lx: String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - } - - void replace(size_t Pos, size_t Count, const string &Str) - { - strdbg("%#lx: String replace: %d, %d, \"%s\"", - this, Pos, Count, Str.Data); - if (Pos >= this->Length) - return; - - if ((int64_t)Count <= 0) - return; - - if (Pos + Count > this->Length) - Count = this->Length - Pos; - - size_t NewLength = this->Length - Count + Str.Length; - this->resize(NewLength); - - for (size_t i = this->Length - 1; i >= Pos + Str.Length; i--) - this->Data[i] = this->Data[i - Str.Length + Count]; - - for (size_t i = 0; i < Str.Length; i++) - this->Data[Pos + i] = Str.Data[i]; - - strdbg("%#lx: String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - } - - void pop_back() - { - strdbg("%#lx: String pop_back", this); - if (this->Length > 0) - { - this->Data[this->Length - 1] = '\0'; - this->Length--; - } - } - - string operator+(const string &Other) const - { - string result = *this; - result.concat(Other); - strdbg("%#lx: String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, result.Data, result.Data, result.Length, result.Capacity); - return result; - } - - string operator+(const char *Other) const - { - string result = *this; - result.concat(Other); - strdbg("%#lx: String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, result.Data, result.Data, result.Length, result.Capacity); - return result; - } - - string &operator+=(const string &Other) - { - this->concat(Other); - strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - return *this; - } - - string &operator+=(const char *Other) - { - this->concat(Other); - strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - return *this; - } - - string &operator+=(char Other) - { - const char str[2] = {Other, '\0'}; - this->concat(str); - strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - return *this; - } - - /* warning: implicitly-declared ‘constexpr String::String(const String&)’ is deprecated [-Wdeprecated-copy] */ - string &operator=(const string &Other) = default; - - // string &operator=(const string &Other) - // { - // if (this != &Other) - // { - // delete[] this->Data; - // this->Data = Other.Data; - // this->Length = Other.Length; - // this->Capacity = Other.Capacity; - // strdbg("%#lx: String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", - // this, this->Data, this->Data, this->Length, this->Capacity); - // } - // return *this; - // } - - string &operator=(const char *Other) - { - this->Length = strlen(Other); - this->Capacity = this->Length + 1; - delete[] this->Data; - this->Data = new char[this->Capacity]; - strcpy(this->Data, Other); - strdbg("%#lx: String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - return *this; - } - - string &operator<<(const string &Other) - { - this->concat(Other); - strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - return *this; - } - - string &operator<<(const char *Other) - { - this->concat(Other); - strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", - this, this->Data, this->Data, this->Length, this->Capacity); - return *this; - } - - char &operator[](int Index) - { - strdbg("%#lx: String index: %d", this, Index); - return this->Data[Index]; - } - - const char &operator[](int Index) const - { - strdbg("%#lx: String index: %d", this, Index); - return this->Data[Index]; - } - - char &operator[](size_t Index) - { - strdbg("%#lx: String index: %d", this, Index); - return this->Data[Index]; - } - - const char &operator[](size_t Index) const - { - strdbg("%#lx: String index: %d", this, Index); - return this->Data[Index]; - } - - bool operator==(const string &Other) const - { - strdbg("%#lx: String compared: \"%s\" == \"%s\"", - this, this->Data, Other.Data); - return strcmp(this->Data, Other.Data) == 0; - } - - bool operator!=(const char *Other) const - { - strdbg("%#lx: String compared: \"%s\" != \"%s\"", - this, this->Data, Other); - return strcmp(this->Data, Other) != 0; - } - - bool operator!=(const string &Other) const - { - strdbg("%#lx: String compared: \"%s\" != \"%s\"", - this, this->Data, Other.Data); - return strcmp(this->Data, Other.Data) != 0; - } - - bool operator==(const char *Other) const - { - strdbg("%#lx: String compared: \"%s\" == \"%s\"", - this, this->Data, Other); - return strcmp(this->Data, Other) == 0; - } - - class iterator - { - private: - char *Pointer; - - public: - iterator(char *Pointer) : Pointer(Pointer) {} - - iterator &operator++() - { - ++this->Pointer; - strdbg("%#lx: String iterator incremented: %#lx", - this, this->Pointer); - return *this; - } - - char &operator*() - { - strdbg("%#lx: String iterator dereferenced: %#lx", - this, this->Pointer); - return *this->Pointer; - } - - bool operator!=(const iterator &Other) const - { - strdbg("%#lx: String iterator compared: %#lx != %#lx", - this, this->Pointer, Other.Pointer); - return this->Pointer != Other.Pointer; - } - - bool operator==(const iterator &Other) const - { - strdbg("%#lx: String iterator compared: %#lx == %#lx", - this, this->Pointer, Other.Pointer); - return this->Pointer == Other.Pointer; - } - }; - - iterator begin() - { - strdbg("%#lx: String iterator begin: %#lx", - this, this->Data); - return iterator(this->Data); - } - - iterator end() - { - strdbg("%#lx: String iterator end: %#lx", - this, this->Data + this->Length); - return iterator(this->Data + this->Length); - } - }; -} - -#endif // !__FENNIX_KERNEL_STD_STRING_H__ diff --git a/include_std/std/unordered_map.hpp b/include_std/std/unordered_map.hpp index 84ae6e7..1532b16 100644 --- a/include_std/std/unordered_map.hpp +++ b/include_std/std/unordered_map.hpp @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include namespace std { diff --git a/include_std/std/utility.hpp b/include_std/std/utility.hpp index 518fdfe..9c2b16e 100644 --- a/include_std/std/utility.hpp +++ b/include_std/std/utility.hpp @@ -22,18 +22,18 @@ namespace std { - template - struct pair - { - typedef T1 first_type; - typedef T2 second_type; + template + struct pair + { + typedef T1 first_type; + typedef T2 second_type; - T1 first; - T2 second; + T1 first; + T2 second; - pair() : first(T1()), second(T2()) {} - pair(const T1 &x, const T2 &y) : first(x), second(y) {} - }; + pair() : first(T1()), second(T2()) {} + pair(const T1 &x, const T2 &y) : first(x), second(y) {} + }; } #endif // !__FENNIX_KERNEL_STD_UTILITY_H__ diff --git a/include_std/std/stdexcept.hpp b/include_std/stdexcept similarity index 65% rename from include_std/std/stdexcept.hpp rename to include_std/stdexcept index 5f35d50..c5aef13 100644 --- a/include_std/std/stdexcept.hpp +++ b/include_std/stdexcept @@ -15,22 +15,17 @@ along with Fennix Kernel. If not, see . */ -#ifndef __FENNIX_KERNEL_STD_STDEXCEPT_H__ -#define __FENNIX_KERNEL_STD_STDEXCEPT_H__ - -#include +#pragma once namespace std { - class runtime_error - { - private: - const char *m_what; + class runtime_error + { + private: + const char *m_what; - public: - runtime_error(const char *what_arg) : m_what(what_arg) {} - const char *what() const { return this->m_what; } - }; + public: + runtime_error(const char *what_arg) : m_what(what_arg) {} + const char *what() const { return this->m_what; } + }; } - -#endif // !__FENNIX_KERNEL_STD_STDEXCEPT_H__ diff --git a/include_std/string b/include_std/string index 928ea3f..a1ba00d 100644 --- a/include_std/string +++ b/include_std/string @@ -16,4 +16,667 @@ */ #pragma once -#include +#include +#include +#include + +// Show debug messages +// #define DEBUG_CPP_STRING 1 +// #define DEBUG_CPP_STRING_VERBOSE 1 + +#ifdef DEBUG_CPP_STRING +#define strdbg(m, ...) debug(m, ##__VA_ARGS__) +#else +#define strdbg(m, ...) +#endif + +#ifdef DEBUG_CPP_STRING_VERBOSE +#define v_strdbg(m, ...) debug(m, ##__VA_ARGS__) +#else +#define v_strdbg(m, ...) +#endif + +// TODO: Somewhere the delete is called twice, causing a double free error. + +namespace std +{ + template + char *to_string(T value) + { + static char buffer[1024]; + bool isNegative = false; + int index = 0; + + if (value < 0) + { + isNegative = true; + value = -value; + } + + if (value == 0) + buffer[index++] = '0'; + else + { + while (value > 0) + { + buffer[index++] = (char)(48 /*'0'*/ + (value % 10)); + value /= 10; + } + } + + if (isNegative) + buffer[index++] = '-'; + + int start = isNegative ? 1 : 0; + int end = index - 1; + while (start < end) + { + char temp = buffer[start]; + buffer[start] = buffer[end]; + buffer[end] = temp; + start++; + end--; + } + + buffer[index] = '\0'; + return buffer; + } + + /** + * @brief String class + * String class that can be used to store strings. + */ + class string + { + private: + char *Data{}; + size_t Length{}; + size_t Capacity{}; + + public: + static const size_t npos = -1; + + string(const char *Str = "") + { + this->Length = strlen(Str); + this->Capacity = this->Length + 1; + this->Data = new char[this->Capacity]; + strcpy(this->Data, Str); + strdbg("%#lx: New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + } + + ~string() + { + strdbg("%#lx: String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + delete[] this->Data, this->Data = nullptr; + } + + size_t length() const + { + v_strdbg("%#lx: String length: %d", + this, this->Length); + return this->Length; + } + + size_t capacity() const + { + v_strdbg("%#lx: String capacity: %d", + this, this->Capacity); + return this->Capacity; + } + + const char *c_str() const + { + v_strdbg("%#lx: String data: \"%s\"", + this, this->Data); + return this->Data; + } + + void resize(size_t NewLength) + { + strdbg("%#lx: String resize: %d", + this, NewLength); + if (NewLength < this->Capacity) + { + this->Length = NewLength; + this->Data[this->Length] = '\0'; + + strdbg("%#lx: String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + return; + } + + size_t newCapacity = NewLength + 1; + char *newData = new char[newCapacity]; + strcpy(newData, this->Data); + + strdbg("%#lx: old: %#lx, new: %#lx", + this, this->Data, newData); + + delete[] this->Data; + this->Data = newData; + this->Length = NewLength; + this->Capacity = newCapacity; + + strdbg("%#lx: String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + } + + void concat(const string &Other) + { + size_t NewLength = this->Length + Other.Length; + this->resize(NewLength); + + strcat(this->Data, Other.Data); + strdbg("%#lx: String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + } + + bool empty() const + { + strdbg("%#lx: String empty: %d", + this, this->Length == 0); + return this->Length == 0; + } + + size_t size() const + { + strdbg("%#lx: String size: %d", + this, this->Length); + return this->Length; + } + + void clear() + { + strdbg("%#lx: String clear", this); + this->resize(0); + } + + size_t find(const char *Str, size_t Pos = 0) const + { + strdbg("%#lx: String find: \"%s\", %d", + this, Str, Pos); + if (Pos >= this->Length) + return npos; + + for (size_t i = Pos; i < this->Length; i++) + { + bool found = true; + for (size_t j = 0; Str[j] != '\0'; j++) + { + if (this->Data[i + j] != Str[j]) + { + found = false; + break; + } + } + if (found) + return i; + } + return npos; + } + + size_t find(const string &Str, size_t Pos = 0) const + { + strdbg("%#lx: String find: \"%s\", %d", + this, Str.c_str(), Pos); + return this->find(Str.c_str(), Pos); + } + + void erase(int Index, int Count = 1) + { + strdbg("%#lx: String erase: %d, %d", + this, Index, Count); + if (Index < 0 || (size_t)Index >= this->Length) + return; + + if (Count < 0) + return; + + if ((size_t)(Index + Count) > this->Length) + Count = (int)this->Length - Index; + + for (size_t i = Index; i < this->Length - Count; i++) + this->Data[i] = this->Data[i + Count]; + + this->Length -= Count; + this->Data[this->Length] = '\0'; + strdbg("%#lx: String erased: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + } + + size_t find_last_not_of(const char *Str, size_t Pos = npos) const + { + strdbg("%#lx: String find_last_not_of: \"%s\", %d", + this, Str, Pos); + if (Pos == npos) + Pos = this->Length - 1; + + for (int i = (int)Pos; i >= 0; i--) + { + bool found = false; + for (size_t j = 0; Str[j] != '\0'; j++) + { + if (this->Data[i] == Str[j]) + { + found = true; + break; + } + } + if (!found) + return i; + } + return npos; + } + + size_t find_first_not_of(const char *Str, size_t Pos = 0) const + { + strdbg("%#lx: String find_first_not_of: \"%s\", %d", + this, Str, Pos); + if (Pos >= this->Length) + return npos; + + for (size_t i = Pos; i < this->Length; i++) + { + bool found = false; + for (size_t j = 0; Str[j] != '\0'; j++) + { + if (this->Data[i] == Str[j]) + { + found = true; + break; + } + } + if (!found) + return i; + } + return npos; + } + + size_t find_first_of(const char *Str, size_t Pos = 0) const + { + strdbg("%#lx: String find_first_of: \"%s\", %d", + this, Str, Pos); + if (Pos >= this->Length) + return npos; + + for (size_t i = Pos; i < this->Length; i++) + { + bool found = false; + for (size_t j = 0; Str[j] != '\0'; j++) + { + if (this->Data[i] == Str[j]) + { + found = true; + break; + } + } + if (found) + return i; + } + return npos; + } + + size_t find_last_of(const char *Str, size_t Pos = npos) const + { + strdbg("%#lx: String find_last_of: \"%s\", %d", + this, Str, Pos); + if (Pos == npos) + Pos = this->Length - 1; + + for (int i = (int)Pos; i >= 0; i--) + { + bool found = false; + for (int j = 0; Str[j] != '\0'; j++) + { + if (this->Data[i] == Str[j]) + { + found = true; + break; + } + } + if (found) + return i; + } + return npos; + } + + size_t find_first_of(char C, size_t Pos = 0) const + { + strdbg("%#lx: String find_first_of: '%c', %d", + this, C, Pos); + if (Pos >= this->Length) + return npos; + + for (size_t i = Pos; i < this->Length; i++) + { + if (this->Data[i] == C) + return i; + } + return npos; + } + + size_t find_last_of(char C, size_t Pos = npos) const + { + strdbg("%#lx: String find_last_of: '%c', %d", + this, C, Pos); + if (Pos == npos) + Pos = this->Length - 1; + + for (int i = (int)Pos; i >= 0; i--) + { + if (this->Data[i] == C) + return i; + } + return npos; + } + + size_t substr(const char *Str, size_t Pos = 0) const + { + strdbg("%#lx: String substr: \"%s\", %d", + this, Str, Pos); + if (Pos >= this->Length) + return npos; + + for (size_t i = Pos; i < this->Length; i++) + { + bool found = true; + for (size_t j = 0; Str[j] != '\0'; j++) + { + if (this->Data[i + j] != Str[j]) + { + found = false; + break; + } + } + if (found) + return i; + } + return npos; + } + + size_t substr(const string &Str, size_t Pos = 0) const + { + strdbg("%#lx: String substr: \"%s\", %d", + this, Str.c_str(), Pos); + return this->substr(Str.c_str(), Pos); + } + + string substr(size_t Pos = 0, size_t Count = npos) const + { + strdbg("%#lx: String substr: %d, %d", + this, Pos, Count); + if (Pos >= this->Length) + return string(); + + if (Count == npos) + Count = this->Length - Pos; + + if (Pos + Count > this->Length) + Count = this->Length - Pos; + + string ret; + ret.resize(Count); + for (size_t i = 0; i < Count; i++) + ret.Data[i] = this->Data[Pos + i]; + ret.Data[Count] = '\0'; + return ret; + } + + void replace(size_t Pos, size_t Count, const char *Str) + { + strdbg("%#lx: String replace: %d, %d, \"%s\"", + this, Pos, Count, Str); + if (Pos >= this->Length) + return; + + if ((int64_t)Count <= 0) + return; + + if (Pos + Count > this->Length) + Count = this->Length - Pos; + + size_t NewLength = this->Length - Count + strlen(Str); + this->resize(NewLength); + + for (size_t i = this->Length - 1; i >= Pos + strlen(Str); i--) + this->Data[i] = this->Data[i - strlen(Str) + Count]; + + for (unsigned long i = 0; i < strlen(Str); i++) + this->Data[Pos + i] = Str[i]; + + strdbg("%#lx: String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + } + + void replace(size_t Pos, size_t Count, const string &Str) + { + strdbg("%#lx: String replace: %d, %d, \"%s\"", + this, Pos, Count, Str.Data); + if (Pos >= this->Length) + return; + + if ((int64_t)Count <= 0) + return; + + if (Pos + Count > this->Length) + Count = this->Length - Pos; + + size_t NewLength = this->Length - Count + Str.Length; + this->resize(NewLength); + + for (size_t i = this->Length - 1; i >= Pos + Str.Length; i--) + this->Data[i] = this->Data[i - Str.Length + Count]; + + for (size_t i = 0; i < Str.Length; i++) + this->Data[Pos + i] = Str.Data[i]; + + strdbg("%#lx: String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + } + + void pop_back() + { + strdbg("%#lx: String pop_back", this); + if (this->Length > 0) + { + this->Data[this->Length - 1] = '\0'; + this->Length--; + } + } + + string operator+(const string &Other) const + { + string result = *this; + result.concat(Other); + strdbg("%#lx: String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, result.Data, result.Data, result.Length, result.Capacity); + return result; + } + + string operator+(const char *Other) const + { + string result = *this; + result.concat(Other); + strdbg("%#lx: String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, result.Data, result.Data, result.Length, result.Capacity); + return result; + } + + string &operator+=(const string &Other) + { + this->concat(Other); + strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + return *this; + } + + string &operator+=(const char *Other) + { + this->concat(Other); + strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + return *this; + } + + string &operator+=(char Other) + { + const char str[2] = {Other, '\0'}; + this->concat(str); + strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + return *this; + } + + /* warning: implicitly-declared ‘constexpr String::String(const String&)’ is deprecated [-Wdeprecated-copy] */ + string &operator=(const string &Other) = default; + + // string &operator=(const string &Other) + // { + // if (this != &Other) + // { + // delete[] this->Data; + // this->Data = Other.Data; + // this->Length = Other.Length; + // this->Capacity = Other.Capacity; + // strdbg("%#lx: String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", + // this, this->Data, this->Data, this->Length, this->Capacity); + // } + // return *this; + // } + + string &operator=(const char *Other) + { + this->Length = strlen(Other); + this->Capacity = this->Length + 1; + delete[] this->Data; + this->Data = new char[this->Capacity]; + strcpy(this->Data, Other); + strdbg("%#lx: String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + return *this; + } + + string &operator<<(const string &Other) + { + this->concat(Other); + strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + return *this; + } + + string &operator<<(const char *Other) + { + this->concat(Other); + strdbg("%#lx: String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", + this, this->Data, this->Data, this->Length, this->Capacity); + return *this; + } + + char &operator[](int Index) + { + strdbg("%#lx: String index: %d", this, Index); + return this->Data[Index]; + } + + const char &operator[](int Index) const + { + strdbg("%#lx: String index: %d", this, Index); + return this->Data[Index]; + } + + char &operator[](size_t Index) + { + strdbg("%#lx: String index: %d", this, Index); + return this->Data[Index]; + } + + const char &operator[](size_t Index) const + { + strdbg("%#lx: String index: %d", this, Index); + return this->Data[Index]; + } + + bool operator==(const string &Other) const + { + strdbg("%#lx: String compared: \"%s\" == \"%s\"", + this, this->Data, Other.Data); + return strcmp(this->Data, Other.Data) == 0; + } + + bool operator!=(const char *Other) const + { + strdbg("%#lx: String compared: \"%s\" != \"%s\"", + this, this->Data, Other); + return strcmp(this->Data, Other) != 0; + } + + bool operator!=(const string &Other) const + { + strdbg("%#lx: String compared: \"%s\" != \"%s\"", + this, this->Data, Other.Data); + return strcmp(this->Data, Other.Data) != 0; + } + + bool operator==(const char *Other) const + { + strdbg("%#lx: String compared: \"%s\" == \"%s\"", + this, this->Data, Other); + return strcmp(this->Data, Other) == 0; + } + + class iterator + { + private: + char *Pointer; + + public: + iterator(char *Pointer) : Pointer(Pointer) {} + + iterator &operator++() + { + ++this->Pointer; + strdbg("%#lx: String iterator incremented: %#lx", + this, this->Pointer); + return *this; + } + + char &operator*() + { + strdbg("%#lx: String iterator dereferenced: %#lx", + this, this->Pointer); + return *this->Pointer; + } + + bool operator!=(const iterator &Other) const + { + strdbg("%#lx: String iterator compared: %#lx != %#lx", + this, this->Pointer, Other.Pointer); + return this->Pointer != Other.Pointer; + } + + bool operator==(const iterator &Other) const + { + strdbg("%#lx: String iterator compared: %#lx == %#lx", + this, this->Pointer, Other.Pointer); + return this->Pointer == Other.Pointer; + } + }; + + iterator begin() + { + strdbg("%#lx: String iterator begin: %#lx", + this, this->Data); + return iterator(this->Data); + } + + iterator end() + { + strdbg("%#lx: String iterator end: %#lx", + this, this->Data + this->Length); + return iterator(this->Data + this->Length); + } + }; +} diff --git a/tests/std_string.cpp b/tests/std_string.cpp index 8163cc5..af506c7 100644 --- a/tests/std_string.cpp +++ b/tests/std_string.cpp @@ -17,9 +17,9 @@ #ifdef DEBUG -#include #include #include +#include void TestString() {