diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..15617f4 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +# libstadium makefile + +CC = g++ +CFLAGS_DEFAULT = -Wall -Wpedantic -Wno-uninitialized -std=c++23 -static-libgcc -static-libstdc++ -static +CFLAGS_DEBUG = -Og -fanalyzer -ggdb +CFLAGS_RELEASE = -Ofast -fdevirtualize-speculatively -fdata-sections -ffunction-sections -Wl,-gc-sections -Wl,-strip-all -Wl,-strip-discarded -flto -s + +SOURCES = src/stadium.hpp src/stadium.cpp src/kldr.hpp +SOURCES_TEST = src/test.cpp +#LINKED_LIBS = -l +OUTPUT_LIB = libstadium.so +OUTPUT_TEST_BIN = libstadiumtest + + +default: clean debug_test + + +debug_test: $(SOURCES) $(SOURCES_TEST) + $(CC) $(CFLAGS_DEFAULT) $(CFLAGS_DEBUG) $(SOURCES) $(SOURCES_TEST) -o $(OUTPUT_TEST_BIN) + #$(LINKED_LIBS) + +debug: $(SOURCES) + echo "NYI" + +release_test: $(SOURCES) + echo "NYI" + +release: $(SOURCES) + echo "NYI" + + +clean: + rm -f $(OUTPUT_LIB) + rm -f $(OUTPUT_TEST_BIN) \ No newline at end of file diff --git a/README.md b/README.md index 8679167..57d866b 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,9 @@ _Эталонная имплементация библиотеки с реализацией протокола Stadium на языке C++._ -**В процессе активной разработки!/Under active development!** \ No newline at end of file +**В процессе активной разработки!/Under active development!** + + +## Пространства имён + +`Stadium::Base`: базовые инструменты, не подлежащие принципиальному изменению в будущем. \ No newline at end of file diff --git a/src/_trash/kldr.cpp b/src/_trash/kldr.cpp new file mode 100644 index 0000000..3f9bb34 --- /dev/null +++ b/src/_trash/kldr.cpp @@ -0,0 +1,102 @@ +/* + * kldr.cpp + * Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms. + * + */ + +#include "kldr.hpp" + + + +namespace Stadium { +namespace Base { + +// Destructor +template +KLDRArray::~KLDRArray () { + // Freeing all pointers if vector is not empty + for (size_t i = 0; i < this->Values.size(); i++) { + operator delete(this->Values[i]); + } +} + +// Print all contents of array to stdout +template +void KLDRArray::Print () { + for (size_t i = 0; i < this->Keys.size(); i++) { + std::cout << "Key: " << std::hex << std::setw(sizeof(KeyT) * 2) << this->Keys[i] << "; "; + std::cout << "Length: " << std::dec << this->Lengths[i] << "; "; + std::cout << "Value: " << std::hex << std::setfill('0') << std::setw(2); + for (LengthT j = 0; j < this->Lengths[i]; j++) + std::cout << this->Values[j] << " "; + std::cout << std::dec << std::endl; + } +} + +// Add new cell to array +template +void KLDRArray::Add (KeyT key, LengthT length, void* data) { + this->Keys.push_back(key); + this->Lengths.push_back(length); + void* newData = operator new(length); // Yes, allocating memory for void pointer really looks like this + std::copy(data, data + length, newData); // ATTENTION: may be we should not copy, but rather use pointer to already allocated mem + this->Values.push_back(std::move(newData)); // NOTICE: move or not to move... + // NOTICE: there is `std::is_pod()`, so may be we can use one more template to make this a little more safe +} + +// Get just value from array by key +template +void* KLDRArray::Get (KeyT key) { + for (size_t i = 0; i < this->Keys.size(); i++) { + if (this->Keys[i] == key) { + return this->Values[i]; + } + } + throw std::invalid_argument("invalid KLDRArray key"); +} + +// Get value and length from array by key +template +void* KLDRArray::Get (KeyT key, LengthT* length) { + for (size_t i = 0; i < this->Keys.size(); i++) { + if (this->Keys[i] == key) { + *length = this->Lengths[i]; + return this->Values[i]; + } + } + throw std::invalid_argument("invalid KLDRArray key"); +} + +// Delete cell from array by key +template +void KLDRArray::Del (KeyT key) { + for (size_t i = 0; i < this->Keys.size(); i++) { + if (this->Keys[i] == key) { + this->Keys.erase(this->Keys.begin() + i); + this->Lengths.erase(this->Lengths.begin() + i); + this->Values.erase(this->Values.begin() + i); + return; + } + } + throw std::invalid_argument("invalid KLDRArray key"); +} + +// Shuffle array +template +void KLDRArray::Shuffle () { + std::random_device seed; + std::mt19937 gen{seed()}; + std::uniform_int_distribution dist{0, this->Keys.size()}; + size_t pickedIndex = 0; + for (size_t i = 0; i < this->Keys.size(); i++) { + do + pickedIndex = dist(gen); + while (pickedIndex == i); + std::swap(this->Keys[i], this->Keys[pickedIndex]); + std::swap(this->Lengths[i], this->Length[pickedIndex]); + std::swap(this->Values[i], this->Values[pickedIndex]); + } +} + +} +} \ No newline at end of file diff --git a/src/_trash/kldr.hpp b/src/_trash/kldr.hpp new file mode 100644 index 0000000..0a29356 --- /dev/null +++ b/src/_trash/kldr.hpp @@ -0,0 +1,128 @@ +/* + * kldr.hpp + * Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms. + * + */ + +#ifndef LIBSTADIUM_KLDR_HPP +#define LIBSTADIUM_KLDR_HPP + + + +#include +#include +#include +#include +#include + + + +namespace Stadium { +namespace Base { + +// NOTICE: This can be more optimized +template +class KLDRArray { + protected: + std::vector Keys; + std::vector Lengths; + std::vector Values; // We should use void* as it is more abstract, BUT! Then we need to deal with schizophrenical errors, like segfault when valid void pointer is freed + + public: + //KLDRArray (); // TODO: check used types + + // Destructor + ~KLDRArray () { + // Freeing all pointers if vector is not empty + for (size_t i = 0; i < this->Keys.size(); i++) { + operator delete(this->Values[i]); + } + } + + // Print all contents of array to stdout + void Print () { + printf("Elements amount: %lu\n", this->Keys.size()); + for (size_t i = 0; i < this->Keys.size(); i++) { + printf("Key: 0x%.2X; ", (KeyT)this->Keys[i]); + printf("Length: %u; ", (LengthT)this->Lengths[i]); + printf("Value: "); + for (LengthT j = 0; j < this->Lengths[i]; j++) + printf("%.2X ", ((uint8_t*)this->Values[i])[j]); + printf("\n"); + // std::cout << "Key: " << std::hex << std::setw(sizeof(KeyT) * 2) << this->Keys[i] << "; "; + // std::cout << "Length: " << std::dec << this->Lengths[i] << "; "; + // std::cout << "Value: " << std::hex; + // for (LengthT j = 0; j < this->Lengths[i]; j++) + // std::cout << std::setfill('0') << std::setw(2) << this->Values[j] << " "; + // std::cout << std::dec << std::endl; + } + } + + // Add new cell to array + // WARNING: pointer supplied as "data" may be invalid after this function call + void Add (KeyT key, LengthT length, void* data) { + this->Keys.push_back(key); + this->Lengths.push_back(length); + //void* newData = operator new(length); // Yes, allocating memory for void pointer really looks like this + //std::copy(data, data + length, newData); + this->Values.push_back(std::move(data)); // NOTICE: move or not to move... + // NOTICE: there is `std::is_pod()`, so may be we can use one more template to make this a little more safe + } + + // Get just value from array by key + void* Get (KeyT key) { + for (size_t i = 0; i < this->Keys.size(); i++) { + if (this->Keys[i] == key) { + return this->Values[i]; + } + } + throw std::invalid_argument("invalid KLDRArray key"); + } + + // Get value and length from array by key + void* Get (KeyT key, LengthT* length) { + for (size_t i = 0; i < this->Keys.size(); i++) { + if (this->Keys[i] == key) { + *length = this->Lengths[i]; + return this->Values[i]; + } + } + throw std::invalid_argument("invalid KLDRArray key"); + } + + // Delete cell from array by key + void Del (KeyT key) { + for (size_t i = 0; i < this->Keys.size(); i++) { + if (this->Keys[i] == key) { + this->Keys.erase(this->Keys.begin() + i); + this->Lengths.erase(this->Lengths.begin() + i); + this->Values.erase(this->Values.begin() + i); + return; + } + } + throw std::invalid_argument("invalid KLDRArray key"); + } + + // Shuffle array + void Shuffle () { + std::random_device seed; + std::mt19937 gen{seed()}; + std::uniform_int_distribution dist{0, this->Keys.size()}; + size_t pickedIndex = 0; + for (size_t i = 0; i < this->Keys.size(); i++) { + do + pickedIndex = dist(gen); + while (pickedIndex == i); + std::swap(this->Keys[i], this->Keys[pickedIndex]); + std::swap(this->Lengths[i], this->Length[pickedIndex]); + std::swap(this->Values[i], this->Values[pickedIndex]); + } + } +}; + +} +} + + + +#endif \ No newline at end of file diff --git a/src/event.cpp b/src/event.cpp new file mode 100644 index 0000000..40e71ea --- /dev/null +++ b/src/event.cpp @@ -0,0 +1,10 @@ +/* + * event.cpp + * Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms. + * + */ + +#include "event.hpp" + + + diff --git a/src/event.hpp b/src/event.hpp new file mode 100644 index 0000000..c60e808 --- /dev/null +++ b/src/event.hpp @@ -0,0 +1,32 @@ +/* + * event.hpp + * Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms. + * + */ + +#ifndef LIBSTADIUM_EVENT_HPP +#define LIBSTADIUM_EVENT_HPP + + + +namespace Stadium { +namespace Base { + +template +class Event { + public: + struct { + CategoryT Category; + SubcategoryT Subcategory; + } Type; // ??? + uint32_t ServerSession; + // TODO: payload hash + // TODO: payload +}; + +} +} + + + +#endif \ No newline at end of file diff --git a/src/kldr.hpp b/src/kldr.hpp new file mode 100644 index 0000000..5243ff4 --- /dev/null +++ b/src/kldr.hpp @@ -0,0 +1,131 @@ +/* + * kldr.hpp + * Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms. + * + */ + +#ifndef LIBSTADIUM_KLDR_HPP +#define LIBSTADIUM_KLDR_HPP + + + +#include +#include +#include +#include +#include + + + +namespace Stadium { +namespace Base { + +// NOTICE: This can be more optimized +template +class KLDRArray { + protected: + std::vector Keys; + std::vector Lengths; + std::vector Values; + + public: + //KLDRArray (); // TODO: check used types + + // Destructor + ~KLDRArray () { + // Freeing all pointers if vector is not empty + for (size_t i = 0; i < this->Keys.size(); i++) { + operator delete(this->Values[i]); + } + } + + // Print all contents of array to stdout + void Print () { + printf("Elements amount: %lu\n", this->Keys.size()); + for (size_t i = 0; i < this->Keys.size(); i++) { + printf("Key: 0x%.2X; ", (KeyT)this->Keys[i]); + printf("Length: %u; ", (LengthT)this->Lengths[i]); + printf("Value: "); + for (LengthT j = 0; j < this->Lengths[i]; j++) + printf("%.2X ", ((uint8_t*)this->Values[i])[j]); + printf("\n"); + } + } + + // Add new cell to array, fast version without keys check + void AddF (KeyT key, LengthT length, void* data) { + this->Keys.push_back(key); + this->Lengths.push_back(length); + void* newData = operator new(length); // Yes, allocating memory for void pointer really looks like this + std::copy((uint8_t*)data, (uint8_t*)data + length, (uint8_t*)newData); // Dirty hacks, YES! + this->Values.push_back(newData); + // NOTICE: there is `std::is_pod()`, so may be we can use one more template to make this a little more safe (may be) + } + + void Add (KeyT key, LengthT length, void* data) { + for (size_t i = 0; i < this->Keys.size(); i++) { + if (this->Keys[i] == key) { + throw std::invalid_argument("supplied key already exist"); + } + } + this->AddF(key, length, data); + } + + // Get just value from array by key + void* Get (KeyT key) { + for (size_t i = 0; i < this->Keys.size(); i++) { + if (this->Keys[i] == key) { + return this->Values[i]; + } + } + throw std::invalid_argument("invalid KLDRArray key"); + } + + // Get value and length from array by key + void* Get (KeyT key, LengthT* length) { + for (size_t i = 0; i < this->Keys.size(); i++) { + if (this->Keys[i] == key) { + *length = this->Lengths[i]; + return this->Values[i]; + } + } + throw std::invalid_argument("invalid KLDRArray key"); + } + + // Delete cell from array by key + void Del (KeyT key) { + for (size_t i = 0; i < this->Keys.size(); i++) { + if (this->Keys[i] == key) { + this->Keys.erase(this->Keys.begin() + i); + this->Lengths.erase(this->Lengths.begin() + i); + this->Values.erase(this->Values.begin() + i); + return; + } + } + throw std::invalid_argument("invalid KLDRArray key"); + } + + // Shuffle array + void Shuffle () { + size_t elements = this->Keys.size(); + std::random_device seed; + std::mt19937 gen{seed()}; + std::uniform_int_distribution dist{0, elements-1}; + size_t pickedIndex = 0; + for (size_t i = 0; i < elements; i++) { + do + pickedIndex = dist(gen); + while (pickedIndex == i); + std::swap(this->Keys[i], this->Keys[pickedIndex]); + std::swap(this->Lengths[i], this->Lengths[pickedIndex]); + std::swap(this->Values[i], this->Values[pickedIndex]); + } + } +}; + +} +} + + + +#endif \ No newline at end of file diff --git a/src/stadium.cpp b/src/stadium.cpp new file mode 100644 index 0000000..2d5c16e --- /dev/null +++ b/src/stadium.cpp @@ -0,0 +1,17 @@ +/* + * stadium.cpp + * Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms. + * + * -> [ Incoming Events Queue ] --> [ Base Event Handlers ] + * / \-> [ Custom Event Handlers ] + * [ Transport ] <-> [ StadiumCrypto (optional) ] <- -> [ Expected Event Handlers ] + * \ + * <- [ Outcoming Events Queue ] <--- [ Base Methods ] + * \ + * <- [ Custom Methods ] + */ + +#include "stadium.hpp" + + + diff --git a/src/stadium.hpp b/src/stadium.hpp new file mode 100644 index 0000000..28ab551 --- /dev/null +++ b/src/stadium.hpp @@ -0,0 +1,30 @@ +/* + * stadium.hpp + * Copyright (c) 2023 Cyclone Team. Licensed under GNU GPLv3-only terms. + * + */ + +#ifndef LIBSTADIUM_HPP +#define LIBSTADIUM_HPP + + + +#include "kldr.hpp" + + + +namespace Stadium { +namespace v1 { + +// class EventsQueue { +// public: +// void Add (); // TODO +// void Pop (); // TODO +// }; + +} +} + + + +#endif \ No newline at end of file diff --git a/src/test.cpp b/src/test.cpp new file mode 100644 index 0000000..182717f --- /dev/null +++ b/src/test.cpp @@ -0,0 +1,22 @@ +#include +#include "stadium.hpp" + + +int main () { + Stadium::Base::KLDRArray<> arr; + char str1[] = "goodbye, var?\n"; + char str2[] = "hello, world!\n"; + char str3[] = "fisting\n"; + char str4[] = "IS 300$!!!!!!!!!!!!!!!!!!\n"; + char str5[] = "a)\n"; + arr.Add(0x01, sizeof(str1), (void*)&str1); + arr.Add(0x02, sizeof(str2), (void*)&str2); + arr.Add(0xF4, sizeof(str3), (void*)&str3); + arr.Add(0x6a, sizeof(str4), (void*)&str4); + arr.Add(0x6c, sizeof(str5), (void*)&str5); + arr.Print(); + arr.Shuffle(); + arr.Print(); + + return 0; +} \ No newline at end of file