mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-29 07:47:59 +00:00
Update std headers
This commit is contained in:
parent
bd04d2bf2f
commit
56358280a7
221
include_std/list
Normal file
221
include_std/list
Normal 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -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>
|
||||||
|
|
||||||
|
@ -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__
|
||||||
|
@ -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__
|
|
@ -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__
|
||||||
|
@ -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__
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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__
|
||||||
|
@ -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__
|
|
@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -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()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user