Update std headers

This commit is contained in:
EnderIce2 2023-10-10 06:09:17 +03:00
parent bd04d2bf2f
commit 56358280a7
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
11 changed files with 1133 additions and 1122 deletions

221
include_std/list Normal file
View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <types.h>
#include <stdexcept>
namespace std
{
template <typename T>
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;
}
};
}

View File

@ -22,13 +22,13 @@
#define __FENNIX_KERNEL_STD_H__ #define __FENNIX_KERNEL_STD_H__
#include <types.h> #include <types.h>
#include <stdexcept>
#include <atomic> #include <atomic>
#include <vector> #include <vector>
#include <string>
#include <list>
#include <std/functional.hpp> #include <std/functional.hpp>
#include <std/list.hpp>
#include <std/smart_ptr.hpp> #include <std/smart_ptr.hpp>
#include <std/stdexcept.hpp>
#include <std/string.hpp>
#include <std/unordered_map.hpp> #include <std/unordered_map.hpp>
#include <std/utility.hpp> #include <std/utility.hpp>

View File

@ -23,28 +23,28 @@
namespace std namespace std
{ {
template <typename Key> template <typename Key>
struct hash struct hash
{ {
size_t operator()(const Key &key) const 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 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_offset_basis = 14695981039346656037ull;
const uint64_t fnv_prime = 1099511628211ull; const uint64_t fnv_prime = 1099511628211ull;
const uint8_t *data = reinterpret_cast<const uint8_t *>(&key); const uint8_t *data = reinterpret_cast<const uint8_t *>(&key);
const size_t size = sizeof(Key); const size_t size = sizeof(Key);
uint64_t ret = fnv_offset_basis; uint64_t ret = fnv_offset_basis;
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
{ {
ret ^= static_cast<uint64_t>(data[i]); ret ^= static_cast<uint64_t>(data[i]);
ret *= fnv_prime; ret *= fnv_prime;
} }
return static_cast<size_t>(ret); return static_cast<size_t>(ret);
} }
}; };
} }
#endif // !__FENNIX_KERNEL_STD_FUNCTIONAL_H__ #endif // !__FENNIX_KERNEL_STD_FUNCTIONAL_H__

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_STD_LIST_H__
#define __FENNIX_KERNEL_STD_LIST_H__
#include <types.h>
#include <std/stdexcept.hpp>
namespace std
{
template <typename T>
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__

View File

@ -34,242 +34,242 @@
namespace std namespace std
{ {
/** /**
* @brief A smart pointer class * @brief A smart pointer class
* *
* This class is a smart pointer class. It is used to manage the lifetime of * 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 * objects. It is a reference counted pointer, so when the last reference to
* the object is removed, the object is deleted. * the object is removed, the object is deleted.
* *
* Basic Usage: * Basic Usage:
* smart_ptr<char> pointer(new char()); * smart_ptr<char> pointer(new char());
* *pointer = 'a'; * *pointer = 'a';
* printf("%c", *pointer); // Prints "a" * printf("%c", *pointer); // Prints "a"
*/ */
template <class T> template <class T>
class smart_ptr class smart_ptr
{ {
T *RealPointer; T *RealPointer;
public: public:
explicit smart_ptr(T *Pointer = nullptr) explicit smart_ptr(T *Pointer = nullptr)
{ {
spdbg("Smart pointer created (%#lx)", this->RealPointer); spdbg("Smart pointer created (%#lx)", this->RealPointer);
this->RealPointer = Pointer; this->RealPointer = Pointer;
} }
~smart_ptr() ~smart_ptr()
{ {
spdbg("Smart pointer deleted (%#lx)", this->RealPointer); spdbg("Smart pointer deleted (%#lx)", this->RealPointer);
delete this->RealPointer, this->RealPointer = nullptr; delete this->RealPointer, this->RealPointer = nullptr;
} }
T &operator*() T &operator*()
{ {
spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer); spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer);
return *this->RealPointer; return *this->RealPointer;
} }
T *operator->() T *operator->()
{ {
spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer); spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer);
return this->RealPointer; return this->RealPointer;
} }
T *get() T *get()
{ {
spdbg("Smart pointer returned (%#lx)", this->RealPointer); spdbg("Smart pointer returned (%#lx)", this->RealPointer);
return this->RealPointer; return this->RealPointer;
} }
}; };
template <class T> template <class T>
class auto_ptr class auto_ptr
{ {
}; };
template <class T> template <class T>
class unique_ptr class unique_ptr
{ {
}; };
template <class T> template <class T>
class weak_ptr class weak_ptr
{ {
}; };
template <typename T> template <typename T>
class shared_ptr class shared_ptr
{ {
private: private:
class counter class counter
{ {
private: private:
unsigned int RefCount{}; unsigned int RefCount{};
public: public:
counter() : RefCount(0) { spdbg("Counter %#lx created", this); }; counter() : RefCount(0) { spdbg("Counter %#lx created", this); };
counter(const counter &) = delete; counter(const counter &) = delete;
counter &operator=(const counter &) = delete; counter &operator=(const counter &) = delete;
~counter() { spdbg("Counter %#lx deleted", this); } ~counter() { spdbg("Counter %#lx deleted", this); }
void reset() void reset()
{ {
this->RefCount = 0; this->RefCount = 0;
spdbg("reset"); spdbg("reset");
} }
unsigned int get() unsigned int get()
{ {
return this->RefCount; return this->RefCount;
spdbg("return"); spdbg("return");
} }
void operator++() void operator++()
{ {
this->RefCount++; this->RefCount++;
spdbg("increment"); spdbg("increment");
} }
void operator++(int) void operator++(int)
{ {
this->RefCount++; this->RefCount++;
spdbg("increment"); spdbg("increment");
} }
void operator--() void operator--()
{ {
this->RefCount--; this->RefCount--;
spdbg("decrement"); spdbg("decrement");
} }
void operator--(int) void operator--(int)
{ {
this->RefCount--; this->RefCount--;
spdbg("decrement"); spdbg("decrement");
} }
}; };
counter *ReferenceCounter; counter *ReferenceCounter;
T *RealPointer; T *RealPointer;
public: public:
explicit shared_ptr(T *Pointer = nullptr) explicit shared_ptr(T *Pointer = nullptr)
{ {
this->RealPointer = Pointer; this->RealPointer = Pointer;
this->ReferenceCounter = new counter(); this->ReferenceCounter = new counter();
spdbg("[%#lx] Shared pointer created (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter); spdbg("[%#lx] Shared pointer created (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter);
if (Pointer) if (Pointer)
(*this->ReferenceCounter)++; (*this->ReferenceCounter)++;
} }
shared_ptr(shared_ptr<T> &SPtr) shared_ptr(shared_ptr<T> &SPtr)
{ {
spdbg("[%#lx] Shared pointer copied (ptr=%#lx, ref=%#lx)", this, SPtr.RealPointer, SPtr.ReferenceCounter); spdbg("[%#lx] Shared pointer copied (ptr=%#lx, ref=%#lx)", this, SPtr.RealPointer, SPtr.ReferenceCounter);
this->RealPointer = SPtr.RealPointer; this->RealPointer = SPtr.RealPointer;
this->ReferenceCounter = SPtr.ReferenceCounter; this->ReferenceCounter = SPtr.ReferenceCounter;
(*this->ReferenceCounter)++; (*this->ReferenceCounter)++;
} }
~shared_ptr() ~shared_ptr()
{ {
spdbg("[%#lx] Shared pointer destructor called", this); spdbg("[%#lx] Shared pointer destructor called", this);
(*this->ReferenceCounter)--; (*this->ReferenceCounter)--;
if (this->ReferenceCounter->get() == 0) if (this->ReferenceCounter->get() == 0)
{ {
spdbg("[%#lx] Shared pointer deleted (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter); spdbg("[%#lx] Shared pointer deleted (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter);
delete this->ReferenceCounter, this->ReferenceCounter = nullptr; delete this->ReferenceCounter, this->ReferenceCounter = nullptr;
delete this->RealPointer, this->RealPointer = nullptr; delete this->RealPointer, this->RealPointer = nullptr;
} }
} }
unsigned int get_count() unsigned int get_count()
{ {
spdbg("[%#lx] Shared pointer count (%d)", this, this->ReferenceCounter->get()); spdbg("[%#lx] Shared pointer count (%d)", this, this->ReferenceCounter->get());
return this->ReferenceCounter->get(); return this->ReferenceCounter->get();
} }
T *get() T *get()
{ {
spdbg("[%#lx] Shared pointer get (%#lx)", this, this->RealPointer); spdbg("[%#lx] Shared pointer get (%#lx)", this, this->RealPointer);
return this->RealPointer; return this->RealPointer;
} }
T &operator*() T &operator*()
{ {
spdbg("[%#lx] Shared pointer dereference (ptr*=%#lx)", this, *this->RealPointer); spdbg("[%#lx] Shared pointer dereference (ptr*=%#lx)", this, *this->RealPointer);
return *this->RealPointer; return *this->RealPointer;
} }
T *operator->() T *operator->()
{ {
spdbg("[%#lx] Shared pointer dereference (ptr->%#lx)", this, this->RealPointer); spdbg("[%#lx] Shared pointer dereference (ptr->%#lx)", this, this->RealPointer);
return this->RealPointer; return this->RealPointer;
} }
void reset(T *Pointer = nullptr) void reset(T *Pointer = nullptr)
{ {
if (this->RealPointer == Pointer) if (this->RealPointer == Pointer)
return; return;
spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter); spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter);
(*this->ReferenceCounter)--; (*this->ReferenceCounter)--;
if (this->ReferenceCounter->get() == 0) if (this->ReferenceCounter->get() == 0)
{ {
delete this->RealPointer; delete this->RealPointer;
delete this->ReferenceCounter; delete this->ReferenceCounter;
} }
this->RealPointer = Pointer; this->RealPointer = Pointer;
this->ReferenceCounter = new counter(); this->ReferenceCounter = new counter();
if (Pointer) if (Pointer)
(*this->ReferenceCounter)++; (*this->ReferenceCounter)++;
} }
void reset() void reset()
{ {
spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter); spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter);
if (this->ReferenceCounter->get() == 1) if (this->ReferenceCounter->get() == 1)
{ {
delete this->RealPointer, this->RealPointer = nullptr; delete this->RealPointer, this->RealPointer = nullptr;
delete this->ReferenceCounter, this->ReferenceCounter = nullptr; delete this->ReferenceCounter, this->ReferenceCounter = nullptr;
} }
else else
{ {
(*this->ReferenceCounter)--; (*this->ReferenceCounter)--;
} }
} }
void swap(shared_ptr<T> &Other) void swap(shared_ptr<T> &Other)
{ {
spdbg("[%#lx] Shared pointer swap (ptr=%#lx, ref=%#lx <=> ptr=%#lx, ref=%#lx)", spdbg("[%#lx] Shared pointer swap (ptr=%#lx, ref=%#lx <=> ptr=%#lx, ref=%#lx)",
this, this->RealPointer, this->ReferenceCounter, Other.RealPointer, Other.ReferenceCounter); this, this->RealPointer, this->ReferenceCounter, Other.RealPointer, Other.ReferenceCounter);
T *tempRealPointer = this->RealPointer; T *tempRealPointer = this->RealPointer;
counter *tempReferenceCounter = this->ReferenceCounter; counter *tempReferenceCounter = this->ReferenceCounter;
this->RealPointer = Other.RealPointer; this->RealPointer = Other.RealPointer;
this->ReferenceCounter = Other.ReferenceCounter; this->ReferenceCounter = Other.ReferenceCounter;
Other.RealPointer = tempRealPointer; Other.RealPointer = tempRealPointer;
Other.ReferenceCounter = tempReferenceCounter; Other.ReferenceCounter = tempReferenceCounter;
} }
}; };
template <typename T> template <typename T>
using remove_reference_t = typename remove_reference<T>::type; using remove_reference_t = typename remove_reference<T>::type;
template <typename T> template <typename T>
T &&forward(remove_reference_t<T> &t) { return static_cast<T &&>(t); }; T &&forward(remove_reference_t<T> &t) { return static_cast<T &&>(t); };
template <typename T> template <typename T>
T &&forward(remove_reference_t<T> &&t) { return static_cast<T &&>(t); }; T &&forward(remove_reference_t<T> &&t) { return static_cast<T &&>(t); };
template <typename T, typename... Args> template <typename T, typename... Args>
shared_ptr<T> make_shared(Args &&...args) shared_ptr<T> make_shared(Args &&...args)
{ {
return shared_ptr<T>(new T(forward<Args>(args)...)); return shared_ptr<T>(new T(forward<Args>(args)...));
}; };
template <typename T, typename... Args> template <typename T, typename... Args>
smart_ptr<T> make_smart(Args &&...args) smart_ptr<T> make_smart(Args &&...args)
{ {
return smart_ptr<T>(new T(forward<Args>(args)...)); return smart_ptr<T>(new T(forward<Args>(args)...));
}; };
} }
#endif // !__FENNIX_KERNEL_STD_SMART_POINTER_H__ #endif // !__FENNIX_KERNEL_STD_SMART_POINTER_H__

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_STD_STRING_H__
#define __FENNIX_KERNEL_STD_STRING_H__
#include <types.h>
#include <convert.h>
#include <debug.h>
// 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__

View File

@ -21,8 +21,8 @@
#include <types.h> #include <types.h>
#include <std/functional.hpp> #include <std/functional.hpp>
#include <std/utility.hpp> #include <std/utility.hpp>
#include <std/list.hpp>
#include <vector> #include <vector>
#include <list>
namespace std namespace std
{ {

View File

@ -22,18 +22,18 @@
namespace std namespace std
{ {
template <typename T1, typename T2> template <typename T1, typename T2>
struct pair struct pair
{ {
typedef T1 first_type; typedef T1 first_type;
typedef T2 second_type; typedef T2 second_type;
T1 first; T1 first;
T2 second; T2 second;
pair() : first(T1()), second(T2()) {} pair() : first(T1()), second(T2()) {}
pair(const T1 &x, const T2 &y) : first(x), second(y) {} pair(const T1 &x, const T2 &y) : first(x), second(y) {}
}; };
} }
#endif // !__FENNIX_KERNEL_STD_UTILITY_H__ #endif // !__FENNIX_KERNEL_STD_UTILITY_H__

View File

@ -15,22 +15,17 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>. along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/ */
#ifndef __FENNIX_KERNEL_STD_STDEXCEPT_H__ #pragma once
#define __FENNIX_KERNEL_STD_STDEXCEPT_H__
#include <types.h>
namespace std namespace std
{ {
class runtime_error class runtime_error
{ {
private: private:
const char *m_what; const char *m_what;
public: public:
runtime_error(const char *what_arg) : m_what(what_arg) {} runtime_error(const char *what_arg) : m_what(what_arg) {}
const char *what() const { return this->m_what; } const char *what() const { return this->m_what; }
}; };
} }
#endif // !__FENNIX_KERNEL_STD_STDEXCEPT_H__

View File

@ -16,4 +16,667 @@
*/ */
#pragma once #pragma once
#include <std/string.hpp> #include <types.h>
#include <convert.h>
#include <debug.h>
// 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 <typename T>
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);
}
};
}

View File

@ -17,9 +17,9 @@
#ifdef DEBUG #ifdef DEBUG
#include <std/string.hpp>
#include <memory.hpp> #include <memory.hpp>
#include <debug.h> #include <debug.h>
#include <string>
void TestString() void TestString()
{ {