Vector and string

This commit is contained in:
2023-10-21 18:19:44 +02:00
parent 65a118a68b
commit 467f7b3e35
17 changed files with 1336 additions and 17 deletions

View File

@@ -3,5 +3,18 @@
<clangFormatSettings>
<option name="ENABLED" value="true" />
</clangFormatSettings>
<files>
<extensions>
<pair source="cpp" header="hpp" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
<pair source="cu" header="cuh" fileNamingConvention="NONE" />
<pair source="ixx" header="" fileNamingConvention="NONE" />
<pair source="mxx" header="" fileNamingConvention="NONE" />
<pair source="cppm" header="" fileNamingConvention="NONE" />
<pair source="ccm" header="" fileNamingConvention="NONE" />
<pair source="cxxm" header="" fileNamingConvention="NONE" />
<pair source="c++m" header="" fileNamingConvention="NONE" />
</extensions>
</files>
</code_scheme>
</component>

View File

@@ -3,6 +3,7 @@
//
#include <cstddef>
#include "TestTemplates.hpp"
#include "globals.hpp"
#include "kmem.hpp"
#include "limine_fb.hpp"
@@ -115,24 +116,34 @@ void stress() {
char buf[69];
itoa(curi, buf, 10);
all_tty_putstr("stress ");
all_tty_putstr(buf);
all_tty_putstr("\n");
remove_self();
}
void templates_tester() {
all_tty_putstr("Testing templates\n");
test_templates();
all_tty_putstr("Testing templates OK\n");
remove_self();
}
void stress_tester() {
for (int i = 0; i < 2000; i++)
new_ktask(stress, "stress");
all_tty_putstr("Finished stress\n");
remove_self();
}
void ktask_main() {
new_ktask(ktask, "one");
new_ktask(freeprinter, "freeprinter");
new_ktask(mtest1, "mtest1");
new_ktask(mtest2, "mtest2");
new_ktask(mtest3, "mtest3");
for (int i = 0; i < 2000; i++)
new_ktask(stress, "stress");
all_tty_putstr("Finished stress");
new_ktask(templates_tester, "templates_tester");
new_ktask(stress_tester, "stress_tester");
remove_self();
}

View File

@@ -8,7 +8,7 @@
#include "serial.hpp"
#include "task.hpp"
#include "string.hpp"
#include "string.h"
struct HeapEntry *KERN_HeapBegin;
uintptr_t KERN_HeapEnd;// Past the end

View File

@@ -6,7 +6,7 @@
#include <stddef.h>
#include "string.hpp"
#include "string.h"
static volatile struct limine_framebuffer_request framebuffer_request = {
.id = LIMINE_FRAMEBUFFER_REQUEST,

View File

@@ -6,7 +6,7 @@
#include "kmem.hpp"
#include "limine.h"
#include "string.hpp"
#include "string.h"
static volatile struct limine_memmap_request memmap_request = {
.id = LIMINE_MEMMAP_REQUEST,

View File

@@ -12,7 +12,7 @@
#include "mutex.hpp"
#include "paging.hpp"
#include "serial.hpp"
#include "string.hpp"
#include "string.h"
#include "timer.hpp"
#include "tty.hpp"

View File

@@ -1,3 +1,5 @@
target_include_directories(kernel.elf PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_sources(kernel.elf PRIVATE mutex.cpp cv.cpp cppsupport.cpp Spinlock.cpp LockGuard.cpp)
target_sources(kernel.elf PRIVATE mutex.cpp cv.cpp cppsupport.cpp Spinlock.cpp LockGuard.cpp)
add_subdirectory(templates)

View File

@@ -2,8 +2,8 @@
// Created by Stepan Usatiuk on 21.10.2023.
//
#ifndef OS2_STRING_HPP
#define OS2_STRING_HPP
#ifndef OS2_STRING_H
#define OS2_STRING_H
#include <cstddef>
#include <cstdint>
@@ -98,4 +98,4 @@ inline void strcpy(const char *src, char *dst) {
dst[i] = '\0';
}
#endif//OS2_STRING_HPP
#endif//OS2_STRING_H

View File

@@ -0,0 +1,3 @@
target_include_directories(kernel.elf PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_sources(kernel.elf PRIVATE TestTemplates.cpp)

View File

@@ -0,0 +1,25 @@
//
// Created by Stepan Usatiuk on 21.10.2023.
//
#ifndef OS2_LISTQUEUE_HPP
#define OS2_LISTQUEUE_HPP
template<typename T>
class ListQueue {
public:
ListQueue() {
}
private:
struct Node {
T val;
Node *next;
};
Node *head;
Node *tail;
};
#endif//OS2_LISTQUEUE_HPP

View File

@@ -0,0 +1,108 @@
#ifndef POINTERS_H
#define POINTERS_H
namespace SUSTL {
class SharedPtrTester;
template<typename T>
class SharedPtr {
friend SharedPtrTester;
public:
SharedPtr() = default;
SharedPtr(T *data) : ptr(data), uses(new int(1)) {}
~SharedPtr() {
if (ptr == nullptr || uses == nullptr) return;
--(*uses);
if (*uses == 0) {
delete ptr;
delete uses;
}
}
SharedPtr(SharedPtr const &other) : ptr(other.ptr), uses(other.uses) {
++(*uses);
}
SharedPtr(SharedPtr &&other) {
uses = other.uses;
ptr = other.ptr;
other.uses = nullptr;
other.ptr = nullptr;
}
SharedPtr &operator=(SharedPtr other) {
std::swap(ptr, other.ptr);
std::swap(uses, other.uses);
return *this;
}
T *operator->() const { return ptr; }
T &operator*() const { return *ptr; }
T *get() const noexcept { return ptr; }
int useCount() const { return *uses; }
private:
T *ptr = nullptr;
int *uses = nullptr;
};
class COWTester;
template<typename T>
class COWPointer {
private:
friend COWTester;
SharedPtr<T> ptr;
void copy() {
if (ptr.get() && ptr.useCount() > 1) {
ptr = SharedPtr<T>(new T(*ptr));
}
}
public:
COWPointer() = default;
COWPointer(T *data) : ptr(data) {}
COWPointer(SharedPtr<T> data) : ptr(std::move(data)) {}
COWPointer(COWPointer &&other) = default;
COWPointer(COWPointer const &data) = default;
COWPointer &operator=(COWPointer other) {
std::swap(ptr, other.ptr);
return *this;
}
~COWPointer() = default;
T *get() const {
return ptr.get();
}
T *getRW() {
copy();
return ptr.get();
}
int useCount() { return ptr.useCount(); };
const T &operator*() const {
return *ptr;
}
const T *operator->() const {
return ptr.operator->();
}
};
}
#endif

View File

@@ -0,0 +1,420 @@
#ifndef SKIPLIST_H
#define SKIPLIST_H
static bool seedSet = false;
class SeedSetter {
public:
SeedSetter() noexcept {
if (!seedSet) {
std::cout << "seed set!" << std::endl;
srand(time(nullptr));// NOLINT
seedSet = true;
}
}
};
[[maybe_unused]] static SeedSetter seedSetter;
template<typename K, typename V>
class SkipList {
static constexpr size_t maxL{31};
friend SkipListTester;
public:
struct Node {
Node *next[maxL + 1] = {nullptr};
Node *before = nullptr;
bool end = false;
K key = K();
V data = V();
};
private:
class NodeAllocator {
static constexpr int size{64};
Node *nodes[size];
int top = -1;
public:
NodeAllocator() noexcept = default;
~NodeAllocator() noexcept {
for (int i = top; i >= 0; i--) {
delete nodes[i];
}
}
void push(Node *&e) {
if (top >= size - 1) {
delete e;
return;
}
nodes[++top] = e;
}
Node *get() {
if (top == -1) {
return new Node;
}
Node *node = nodes[top--];
node->end = false;
node->before = nullptr;
node->next[0] = nullptr;
node->key = K();
// node->data = V();
return node;
}
};
static int randomL() {
return ffs(rand()) - 1;// NOLINT
}
static inline NodeAllocator nodeAllocator;
Node *root;
Node *endnode;
mutable Node *toUpdate[maxL + 1];
size_t curL = 0;
public:
SkipList() noexcept {
root = (Node *) nodeAllocator.get();
root->end = true;
endnode = (Node *) nodeAllocator.get();
endnode->end = true;
endnode->before = root;
for (size_t i = 0; i <= maxL; i++) {
root->next[i] = endnode;
}
};
~SkipList() noexcept {
auto cur = root;
while (cur != nullptr) {
auto prev = cur;
cur = cur->next[0];
nodeAllocator.push(prev);
}
}
SkipList(SkipList const &l) noexcept : SkipList() {
toUpdate[0] = root;
for (auto n = l.root->next[0]; n != nullptr && !n->end; n = n->next[0]) {
size_t newLevel = randomL();
if (newLevel > curL) {
for (size_t i = curL + 1; i <= newLevel; i++)
toUpdate[i] = root;
curL = newLevel;
}
auto newNode = (Node *) nodeAllocator.get();
newNode->key = n->key;
newNode->data = n->data;
newNode->before = toUpdate[0];
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
for (size_t i = 0; i <= newLevel; i++) {
newNode->next[i] = toUpdate[i]->next[i];
toUpdate[i]->next[i] = newNode;
toUpdate[i] = newNode;
}
}
}
SkipList(SkipList &&l) noexcept {
this->root = l.root;
l.root = nullptr;
this->endnode = l.endnode;
l.endnode = nullptr;
this->curL = l.curL;
l.curL = 0;
}
SkipList &operator=(SkipList l) noexcept {
std::swap(l.root, root);
std::swap(l.endnode, endnode);
std::swap(l.curL, curL);
return *this;
}
void add(V *p, size_t n, bool reuseUpdate) {
if (!reuseUpdate) {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < p->l && !cur->next[i]->end)
cur = cur->next[i];
toUpdate[i] = cur;
}
}
for (size_t i = 0; i < n; i++, p++) {
size_t newLevel = randomL();
if (newLevel > curL) {
for (size_t j = curL + 1; j <= newLevel; j++)
toUpdate[j] = root;
curL = newLevel;
}
auto newNode = (Node *) nodeAllocator.get();
newNode->key = p->l;
newNode->data = *p;
newNode->before = toUpdate[0];
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
for (size_t j = 0; j <= newLevel; j++) {
newNode->next[j] = toUpdate[j]->next[j];
toUpdate[j]->next[j] = newNode;
toUpdate[j] = newNode;
}
}
}
bool erase(Node *begin, Node *end, bool reuseUpdate) {
if (begin == end) return false;
if (!reuseUpdate) {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < begin->key && !cur->next[i]->end)
cur = cur->next[i];
toUpdate[i] = cur;
}
}
Node *prev = nullptr;
for (auto cur = begin; cur != end; cur = cur->next[0]) {
if (prev)
nodeAllocator.push(prev);
cur->next[0]->before = toUpdate[0];
for (size_t i = 0; i <= curL; i++) {
if (toUpdate[i]->next[i] != cur)
break;
toUpdate[i]->next[i] = cur->next[i];
}
while (curL > 0 &&
root->next[curL] == nullptr)
curL--;
prev = cur;
}
if (prev)
nodeAllocator.push(prev);
return true;
}
Node *add(K const &k, V const &v, bool reuseUpdate) {
if (!reuseUpdate) {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < k && !cur->next[i]->end)
cur = cur->next[i];
toUpdate[i] = cur;
}
cur = cur->next[0];
if (cur->key == k && !cur->end) return nullptr;
}
size_t newLevel = randomL();
if (newLevel > curL) {
for (size_t i = curL + 1; i <= newLevel; i++)
toUpdate[i] = root;
curL = newLevel;
}
auto newNode = (Node *) nodeAllocator.get();
newNode->key = k;
newNode->data = v;
newNode->before = toUpdate[0];
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
for (size_t i = 0; i <= newLevel; i++) {
newNode->next[i] = toUpdate[i]->next[i];
toUpdate[i]->next[i] = newNode;
toUpdate[i] = newNode;
}
return newNode;
}
bool erase(K const &k) {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < k && !cur->next[i]->end)
cur = cur->next[i];
toUpdate[i] = cur;
}
cur = cur->next[0];
if (cur->end || cur->key != k) return false;
cur->next[0]->before = toUpdate[0];
for (size_t i = 0; i <= curL; i++) {
if (toUpdate[i]->next[i] != cur)
break;
toUpdate[i]->next[i] = cur->next[i];
}
while (curL > 0 &&
root->next[curL] == nullptr)
curL--;
nodeAllocator.push(cur);
return true;
};
// Returns the node PRECEDING the node with a key that is GREATER than k
Node *find(K const &k) const {
Node *cur = root;
for (int i = curL; i >= 0; i--)
while (cur->next[i]->key <= k && !cur->next[i]->end)
cur = cur->next[i];
return cur;
}
Node *upper_bound(K const &k) const {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key <= k && !cur->next[i]->end)
cur = cur->next[i];
}
cur = cur->next[0];
return cur;
}
Node *lower_bound_update(K const &k) const {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < k && !cur->next[i]->end)
cur = cur->next[i];
toUpdate[i] = cur;
}
cur = cur->next[0];
return cur;
}
Node *lower_bound(K const &k) const {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < k && !cur->next[i]->end)
cur = cur->next[i];
}
cur = cur->next[0];
return cur;
}
bool operator==(SkipList const &r) const {
auto n = root->next[0];
auto n2 = r.root->next[0];
while (!n->end && !n2->end) {
if (!(n->data == n2->data)) return false;
n = n->next[0];
n2 = n2->next[0];
}
if ((n->end || n2->end) && n->end != n2->end) return false;
return true;
}
struct SkipListIterator {
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = const V;
using pointer = value_type *;
using reference = value_type &;
explicit SkipListIterator(Node *n) : n(std::move(n)){};
reference operator*() const { return n->data; }
pointer operator->() const { return &(n->data); }
SkipListIterator &operator--() {
if (!n->end)
n = n->before;
return *this;
}
SkipListIterator &operator++() {
if (!n->end)
n = n->next[0];
return *this;
}
SkipListIterator operator++(int) {
SkipListIterator tmp = *this;
++(*this);
return tmp;
}
friend bool operator==(const SkipListIterator &a, const SkipListIterator &b) { return a.n == b.n; };
friend bool operator!=(const SkipListIterator &a, const SkipListIterator &b) { return a.n != b.n; };
private:
Node *n;
};
// using iterator = SkipListIterator;
using const_iterator = SkipListIterator;
const_iterator begin() const { return SkipListIterator(root->next[0]); }
const_iterator end() const { return SkipListIterator(endnode); }
void print() const {
std::cout << "LIST STATUS" << std::endl;
for (size_t i = 0; i <= curL; i++) {
Node *n = root->next[i];
std::cout << "L " << i << ": ";
while (n != nullptr && n->next[0]) {
std::cout << "GUARD: " << n->end << " KEY: " << n->key << " RANGE: " << n->data
<< " <<<<<";
n = n->next[i];
}
std::cout << std::endl;
}
};
};
#endif

View File

@@ -0,0 +1,321 @@
#ifndef SkipListSetSET_H
#define SkipListSetSET_H
template<typename K>
class SkipListSet {
static constexpr size_t maxL{31};
friend SkipListSetTester;
public:
struct Node {
Node *next[maxL + 1] = {nullptr};
Node *before = nullptr;
bool end = false;
K key = K();
};
private:
class NodeAllocator {
static constexpr int size{64};
Node *nodes[size];
int top = -1;
public:
NodeAllocator() noexcept = default;
~NodeAllocator() noexcept {
for (int i = top; i >= 0; i--) {
delete nodes[i];
}
}
void push(Node *&e) {
if (top >= size - 1) {
delete e;
return;
}
nodes[++top] = e;
}
Node *get() {
if (top == -1) {
return new Node;
}
Node *node = nodes[top--];
node->end = false;
node->before = nullptr;
node->next[0] = nullptr;
node->key = K();
// node->data = V();
return node;
}
};
static int randomL() {
return ffs(rand()) - 1;// NOLINT
}
static inline NodeAllocator nodeAllocator;
Node *root;
Node *endnode;
mutable Node *toUpdate[maxL + 1];
size_t curL = 0;
public:
SkipListSet() noexcept {
root = (Node *) nodeAllocator.get();
root->end = true;
endnode = (Node *) nodeAllocator.get();
endnode->end = true;
endnode->before = root;
for (size_t i = 0; i <= maxL; i++) {
root->next[i] = endnode;
}
};
~SkipListSet() noexcept {
auto cur = root;
while (cur != nullptr) {
auto prev = cur;
cur = cur->next[0];
nodeAllocator.push(prev);
}
}
SkipListSet(SkipListSet const &l) noexcept : SkipListSet() {
toUpdate[0] = root;
for (auto n = l.root->next[0]; n != nullptr && !n->end; n = n->next[0]) {
size_t newLevel = randomL();
if (newLevel > curL) {
for (size_t i = curL + 1; i <= newLevel; i++)
toUpdate[i] = root;
curL = newLevel;
}
auto newNode = (Node *) nodeAllocator.get();
newNode->key = n->key;
newNode->data = n->data;
newNode->before = toUpdate[0];
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
for (size_t i = 0; i <= newLevel; i++) {
newNode->next[i] = toUpdate[i]->next[i];
toUpdate[i]->next[i] = newNode;
toUpdate[i] = newNode;
}
}
}
SkipListSet(SkipListSet &&l) noexcept {
this->root = l.root;
l.root = nullptr;
this->endnode = l.endnode;
l.endnode = nullptr;
this->curL = l.curL;
l.curL = 0;
}
SkipListSet &operator=(SkipListSet l) noexcept {
std::swap(l.root, root);
std::swap(l.endnode, endnode);
std::swap(l.curL, curL);
return *this;
}
bool erase(Node *begin, Node *end, bool reuseUpdate) {
if (begin == end) return false;
if (!reuseUpdate) {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < begin->key && !cur->next[i]->end)
cur = cur->next[i];
toUpdate[i] = cur;
}
}
Node *prev = nullptr;
for (auto cur = begin; cur != end; cur = cur->next[0]) {
if (prev)
nodeAllocator.push(prev);
cur->next[0]->before = toUpdate[0];
for (size_t i = 0; i <= curL; i++) {
if (toUpdate[i]->next[i] != cur)
break;
toUpdate[i]->next[i] = cur->next[i];
}
while (curL > 0 &&
root->next[curL] == nullptr)
curL--;
prev = cur;
}
if (prev)
nodeAllocator.push(prev);
return true;
}
Node *add(K const &k, bool reuseUpdate) {
if (!reuseUpdate) {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < k && !cur->next[i]->end)
cur = cur->next[i];
toUpdate[i] = cur;
}
cur = cur->next[0];
if (cur->key == k) return nullptr;
}
size_t newLevel = randomL();
if (newLevel > curL) {
for (size_t i = curL + 1; i <= newLevel; i++)
toUpdate[i] = root;
curL = newLevel;
}
auto newNode = (Node *) nodeAllocator.get();
newNode->key = k;
newNode->before = toUpdate[0];
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
for (size_t i = 0; i <= newLevel; i++) {
newNode->next[i] = toUpdate[i]->next[i];
toUpdate[i]->next[i] = newNode;
toUpdate[i] = newNode;
}
return newNode;
}
bool erase(K const &k) {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < k && !cur->next[i]->end)
cur = cur->next[i];
toUpdate[i] = cur;
}
cur = cur->next[0];
if (cur->end || cur->key != k) return false;
cur->next[0]->before = toUpdate[0];
for (size_t i = 0; i <= curL; i++) {
if (toUpdate[i]->next[i] != cur)
break;
toUpdate[i]->next[i] = cur->next[i];
}
while (curL > 0 &&
root->next[curL] == nullptr)
curL--;
nodeAllocator.push(cur);
return true;
};
// Returns the node PRECEDING the node with a key that is GREATER than k
Node *find(K const &k) const {
Node *cur = root;
for (int i = curL; i >= 0; i--)
while (cur->next[i]->key <= k && !cur->next[i]->end)
cur = cur->next[i];
return cur;
}
Node *upper_bound(K const &k) const {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key <= k && !cur->next[i]->end)
cur = cur->next[i];
}
cur = cur->next[0];
return cur;
}
Node *lower_bound_update(K const &k) const {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < k && !cur->next[i]->end)
cur = cur->next[i];
toUpdate[i] = cur;
}
cur = cur->next[0];
return cur;
}
Node *lower_bound(K const &k) const {
Node *cur = root;
for (int i = curL; i >= 0; i--) {
while (cur->next[i]->key < k && !cur->next[i]->end)
cur = cur->next[i];
}
cur = cur->next[0];
return cur;
}
bool operator==(SkipListSet const &r) const {
auto n = root->next[0];
auto n2 = r.root->next[0];
while (!n->end && !n2->end) {
if (!(n->data == n2->data)) return false;
n = n->next[0];
n2 = n2->next[0];
}
if ((n->end || n2->end) && n->end != n2->end) return false;
return true;
}
void print() const {
std::cout << "LIST STATUS" << std::endl;
for (size_t i = 0; i <= curL; i++) {
Node *n = root->next[i];
std::cout << "L " << i << ": ";
while (n != nullptr && n->next[0]) {
std::cout << "GUARD: " << n->end << " KEY: " << n->key << " RANGE: " << n->data
<< " <<<<<";
n = n->next[i];
}
std::cout << std::endl;
}
};
};
#endif

View File

@@ -0,0 +1,90 @@
#ifndef STRING_H
#define STRING_H
#include <cstdlib>
#include <utility>
#include "kmem.hpp"
#include "serial.hpp"
#include "string.h"
class String {
public:
String() noexcept {
data = static_cast<char *>(kmalloc(1 * sizeof(char)));
data[0] = '\0';
}
String(const char *in) noexcept {
unsigned int curLen = strlen(in);
data = static_cast<char *>(kmalloc((curLen + 1) * sizeof(char)));
data[0] = '\0';
strcat(data, in);
}
String(String const &str) noexcept {
unsigned int curLen = strlen(str.data);
data = static_cast<char *>(kmalloc((curLen + 1) * sizeof(char)));
data[0] = '\0';
strcat(data, str.data);
}
String(String &&str) noexcept {
data = str.data;
str.data = nullptr;
}
String &operator=(String str) noexcept {
std::swap(data, str.data);
return *this;
}
~String() noexcept {
if (data == nullptr) return;
kfree(data);
data = nullptr;
}
String &operator+=(String const &rhs) {
data = static_cast<char *>(krealloc(data, sizeof(char) * (strlen(data) + strlen(rhs.data) + 1)));
assert(data != nullptr);
strcat(data, rhs.data);
return *this;
}
const char *c_str() {
return data;
}
bool operator==(String const &rhs) const {
return strcmp(data, rhs.data) == 0;
}
bool operator!=(String const &rhs) const {
return strcmp(data, rhs.data) != 0;
}
bool operator<(String const &rhs) const {
return strcmp(data, rhs.data) < 0;
}
bool operator<=(String const &rhs) const {
return strcmp(data, rhs.data) <= 0;
}
bool operator>(String const &rhs) const {
return strcmp(data, rhs.data) > 0;
}
private:
// unsigned int curLen = 0;
char *data;
};
#endif

View File

@@ -0,0 +1,191 @@
//
// Created by Stepan Usatiuk on 21.10.2023.
//
#include "TestTemplates.hpp"
#include "String.hpp"
#include "Vector.hpp"
#include "serial.hpp"
//#include "String.hpp"
//#include "String.hpp"
//template<typename T>
//std::string toString(const T &x) {
// std::ostringstream oss;
// oss << x;
// return oss.str();
//}
//
//class SharedPtrTester {
//private:
// auto getThingy() {
// return SharedPtr<Vector<String>>(
// new Vector<String>{"Thingy1", "Thingy2", "Thingy3"});
// }
//
//public:
// bool test() {
// SharedPtr<Vector<String>> test1(
// new Vector<String>{"hello1", "hello2", "hello3"});
// SharedPtr<Vector<String>> test2(getThingy());
// assert((*test2 == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
// auto test22 = test2;
// auto test12 = test1;
// test12->emplace_back("hello4");
// assert((*test1)[3] == "hello4");
// test22->erase(2);
// assert(test2->size() == 2);
// assert((*test2)[1] == "Thingy2");
// return true;
// }
//};
//
//class COWTester {
//private:
// auto getThingy() const {
// return COWPointer<Vector<String>>(
// new Vector<String>{"Thingy1", "Thingy2", "Thingy3"});
// }
//
//public:
// bool test() const {
// COWPointer<Vector<String>> test1(
// new Vector<String>{"hello1", "hello2", "hello3"});
// COWPointer<Vector<String>> test2(getThingy());
// assert((*test2.get() == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
//
// auto test22 = test2;
// auto test12 = test1;
//
// assert(test12.ptr.get() == test1.ptr.get());
// assert(test22.ptr.get() == test2.ptr.get());
// assert((*test2.get() == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
// assert((*test22.get() == Vector<String>{"Thingy1", "Thingy2", "Thingy3"}));
// assert((*test1.get() == Vector<String>{"hello1", "hello2", "hello3"}));
// assert((*test12.get() == Vector<String>{"hello1", "hello2", "hello3"}));
// assert(test12.ptr.get() == test1.ptr.get());
// assert(test22.ptr.get() == test2.ptr.get());
//
// test12.getRW()->emplace_back("hello4");
// assert(test1.get()->size() == 3);
// assert(test12.get()->size() == 4);
// assert((*test12.get())[3] == "hello4");
// test22.getRW()->erase(2);
// assert(test2.get()->size() == 3);
// assert(test22.get()->size() == 2);
// assert((*test22.get())[1] == "Thingy2");
// assert((*test2.get())[1] == "Thingy2");
//
// assert(test12.ptr.get() != test1.ptr.get());
// assert(test22.ptr.get() != test2.ptr.get());
//
// return true;
// }
//};
class VectorTester {
public:
bool test() {
Vector<String> testv1;
testv1.emplace_back("H1");
testv1.emplace_back("H2");
testv1.emplace_back("H3");
testv1.emplace_back("H4");
assert(testv1.size() == 4);
assert(testv1.capacity >= 4);
assert(testv1[0] == "H1");
assert(testv1[1] == "H2");
assert(testv1[2] == "H3");
assert(testv1[3] == "H4");
testv1.erase(1);
assert(testv1.size() == 3);
assert(testv1[0] == "H1");
assert(testv1[1] == "H3");
assert(testv1[3] == "H4");
testv1.erase(1);
assert(testv1.size() == 2);
assert(testv1[0] == "H1");
assert(testv1[1] == "H4");
testv1.emplace_back("H5");
auto testv2 = testv1;
assert(testv1 == testv2);
testv1.erase(2);
assert(testv1 != testv2);
testv1.emplace_back("H6");
assert(testv1 != testv2);
assert(testv1[2] == "H6");
assert(testv2[2] == "H5");
return true;
}
};
class StringTester {
public:
bool test() {
String str1("hello");
assert(str1 == "hello");
str1 += "Hello!";
assert(str1 == "helloHello!");
str1 = String("abcd");
String str2("dcba");
assert(str2 > str1);
assert(str1 < str2);
assert(str1 <= str2);
str2 = "abcd";
assert(str1 <= str2);
return true;
}
};
//class SkipListTester {
//public:
// bool test() {
// SkipList<int, std::string> test1;
//
// test1.add(5, "test5", false);
// test1.add(999, "test999", false);
// test1.add(5, "test5", false);
// test1.add(1, "test1", false);
// test1.add(999, "test999", false);
//
// assert(test1.find(5)->data == "test5");
// assert(test1.find(1)->data == "test1");
// assert(test1.find(999)->data == "test999");
//
// test1.erase(1);
// assert(test1.find(1)->data != "test1");
// test1.add(87, "test87", false);
// assert(test1.find(87)->data == "test87");
//
// auto p2 = test1.lower_bound_update(78);
// assert(p2->data == "test87");
// test1.add(78, "test78", true);
// assert(test1.find(78)->data == "test78");
//
// assert(IT::test());
//
// return true;
// }
//};
//
int test_templates() {
// SkipListTester SLTester;
// SLTester.test();
StringTester stringTester;
stringTester.test();
VectorTester vectorTester;
vectorTester.test();
// SharedPtrTester sharedPtrTester;
// sharedPtrTester.test();
// COWTester cowTester;
// cowTester.test();
return 0;
}

View File

@@ -0,0 +1,10 @@
//
// Created by Stepan Usatiuk on 21.10.2023.
//
#ifndef OS2_TESTTEMPLATES_HPP
#define OS2_TESTTEMPLATES_HPP
int test_templates();
#endif//OS2_TESTTEMPLATES_HPP

View File

@@ -0,0 +1,125 @@
#ifndef VECTOR_H
#define VECTOR_H
#include <new>
#include "kmem.hpp"
#include "serial.hpp"
#include "string.h"
class VectorTester;
template<typename T>
class Vector {
friend VectorTester;
public:
Vector() noexcept {
data = static_cast<T *>(kmalloc(capacity * sizeof(T)));
}
Vector(std::initializer_list<T> l) noexcept {
curSize = l.size();
capacity = curSize > 0 ? curSize : 2;
data = static_cast<T *>(kmalloc(capacity * sizeof(T)));
size_t i = 0;
for (auto const &el: l) {
new (data + (i++)) T(el);
}
}
Vector(Vector const &vec) noexcept {
curSize = vec.curSize;
capacity = curSize > 0 ? curSize : 2;
data = static_cast<T *>(kmalloc(capacity * sizeof(T)));
for (size_t i = 0; i < curSize; i++)
new (data + i) T(vec.data[i]);
}
Vector(Vector &&v) noexcept {
curSize = v.curSize;
capacity = v.capacity;
data = v.data;
v.data = nullptr;
}
Vector &operator=(Vector vec) noexcept {
std::swap(vec.data, data);
std::swap(vec.curSize, curSize);
std::swap(vec.capacity, capacity);
return *this;
}
~Vector() noexcept {
if (data == nullptr) return;
if constexpr (!std::is_trivially_destructible<T>::value)
for (size_t i = 0; i < curSize; i++) data[i].~T();
kfree(data);
data = nullptr;
}
template<class... Args>
void emplace_back(Args &&...args) {
if (capacity == curSize) {
capacity *= 2;
//Ugly hack to get around g++ warnings
data = (T *) krealloc(reinterpret_cast<char *>(data), capacity * sizeof(T));
assert(data != nullptr);
}
new (data + (curSize++)) T(std::forward<Args>(args)...);
}
void compact() {
data = (T *) krealloc(reinterpret_cast<char *>(data), curSize * sizeof(T));
capacity = curSize;
}
void erase(size_t idx) {
if constexpr (!std::is_trivially_destructible<T>::value)
(data + idx)->~T();
//Ugly hack to get around g++ warnings
memmove(reinterpret_cast<char *>(data + idx), reinterpret_cast<char *>(data + idx + 1),
sizeof(T) * (curSize - idx - 1));
curSize--;
}
T &operator[](size_t idx) {
return data[idx];
}
T const &operator[](size_t idx) const {
return data[idx];
}
bool operator==(Vector const &rhs) const {
if (curSize != rhs.curSize) return false;
else
for (size_t i = 0; i < curSize; i++)
if (data[i] != rhs.data[i]) return false;
return true;
}
bool operator!=(Vector const &rhs) const {
if (curSize != rhs.curSize) return true;
else
for (size_t i = 0; i < curSize; i++)
if (data[i] != rhs.data[i]) return true;
return false;
}
size_t size() const {
return curSize;
}
private:
size_t capacity = 2;
size_t curSize = 0;
T *data;
};
#endif