Archiver Initial

This commit is contained in:
IlyaShurupov 2023-07-25 18:47:00 +03:00 committed by Ilya Shurupov
parent 4a5877784b
commit 31e420b311
25 changed files with 652 additions and 124 deletions

BIN
Modules/.vs/slnx.sqlite Normal file

Binary file not shown.

View file

@ -12,7 +12,8 @@ target_include_directories(${PROJECT_NAME} PUBLIC ./public/)
### -------------------------- Tests -------------------------- ###
enable_testing()
add_executable(${PROJECT_NAME}Tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/Tests.cpp)
file(GLOB SOURCES_TEST "./tests/*.cpp")
add_executable(${PROJECT_NAME}Tests ${SOURCES_TEST})
target_link_libraries(${PROJECT_NAME}Tests ${PROJECT_NAME})
add_test(NAME ${PROJECT_NAME}Tests COMMAND ${PROJECT_NAME}Tests)

146
Modules/public/Archiver.hpp Normal file
View file

@ -0,0 +1,146 @@
#pragma once
#include "Common.hpp"
namespace tp {
// Used to transfer data to or from some sort of archive
// Abstracts interface so that actual archive must only overload readBytes and writeBytes
// The main idea is that it transfers data as bytes only if this type of data does not have special API functions
template <bool tRead>
class ArchiverTemplate {
public:
struct HasFunc {
typedef ArchiverTemplate& ArchRef;
template <typename T, typename = void> struct Write : FalseType {};
template <typename T> struct Write<T, VoidType<decltype(DeclareValue<T>()().archiveWrite(DeclareValue<ArchRef>()()))>> : TrueType {};
template <typename T, typename = void> struct Read : FalseType {};
template <typename T> struct Read<T, VoidType<decltype(DeclareValue<T>()().archiveRead(DeclareValue<ArchRef>()()))>> : TrueType {};
template <typename T, typename = void> struct Archive : FalseType {};
template <typename T> struct Archive<T, VoidType<decltype(DeclareValue<T>()().archive(DeclareValue<ArchRef>()()))>> : TrueType {};
template <typename T>
struct AssertCombinations {
static constexpr auto assert() {
if (HasFunc::template Read<T>::value != HasFunc::template Write<T>::value) return false;
if (HasFunc::template Read<T>::value) {
if (HasFunc::template Read<T>::value == HasFunc::template Archive<T>::value) return false;
}
return true;
}
};
};
public:
virtual void writeBytes(const int1* val, ualni size) = 0;
virtual void readBytes(int1* val, ualni size) = 0;
public:
ArchiverTemplate() = default;
// check if type has explicit write method. if not write as bytes
template<typename Type>
void operator <<(const Type& val) {
static_assert(!tRead);
static_assert(HasFunc::template AssertCombinations<Type>::assert());
if constexpr (HasFunc::template Write<Type>::value) {
val.archiveWrite(*this);
} else {
writeBytes((const int1*) &val, sizeof(val));
}
}
// check if type has explicit read method. if not read as bytes
template<typename Type>
void operator >>(Type& val) {
static_assert(tRead);
static_assert(HasFunc::template AssertCombinations<Type>::assert());
if constexpr (HasFunc::template Read<Type>::value) {
val.archiveRead(*this);
} else {
readBytes((int1*) &val, sizeof(val));
}
}
// check if type has explicit archive method. if not read/write as bytes
template<typename Type>
void operator %(Type& val) {
static_assert(HasFunc::template AssertCombinations<Type>::assert());
if constexpr (HasFunc::template Archive<Type>::value) {
val.archive(*this);
} else {
if constexpr (tRead) {
operator>>(val);
} else {
operator<<(val);
}
}
}
template<typename Type>
void operator %(const Type& val) {
static_assert(HasFunc::template AssertCombinations<Type>::assert());
if constexpr (HasFunc::template Archive<Type>::value) {
((Type&)val).archive(*this);
} else {
if constexpr (tRead) {
operator>>(val);
} else {
operator<<(val);
}
}
}
};
template<ualni tMaxMemory, bool tRead>
class ArchiverExample : public ArchiverTemplate<tRead> {
public:
ArchiverExample() = default;
protected:
void incrementAddresses(ualni size) {
if (mFirstNotWritten == mAddress) mFirstNotWritten += size;
mAddress += size;
}
void writeBytes(const int1* val, ualni size) override {
for (auto i = 0; i < size; i++) mBuff[mAddress + i] = val[i];
incrementAddresses(size);
}
void readBytes(int1* val, ualni size) override {
for (auto i = 0; i < size; i++) val[i] = mBuff[mAddress + i];
incrementAddresses(size);
}
template<typename tType>
static void test() {
const tType val;
tType res;
res.change();
ArchiverExample<tMaxMemory, false> write;
ArchiverExample<tMaxMemory, true> read;
write % val;
for (auto i = 0; i < tMaxMemory; i++) read.mBuff[i] = write.mBuff[i];
read % res;
if (val != res) {
throw "test failed";
}
}
public:
int1 mBuff[tMaxMemory]{};
private:
ualni mAddress = 0;
ualni mFirstNotWritten = 0;
};
}

View file

@ -4,15 +4,40 @@
#include "Environment.hpp"
#include "TypeInfo.hpp"
#include <initializer_list>
#include <typeinfo>
#include <utility>
namespace tp {
template<typename Type>
using init_list = std::initializer_list<Type>;
using InitialierList = std::initializer_list<Type>;
// Selects whether to pass by constant reference or by value
template <typename tType>
using SelCopyArg = typename TypeSelect<(sizeof(tType) > sizeof(tp::alni)), const tType&, tType>::Result;
using SelectValueOrReference = typename TypeSelect<(sizeof(tType) > sizeof(tp::alni)), const tType&, tType>::Result;
template <typename tType>
using VoidType = void;
template <typename tType>
struct Reference {
tType& operator()() {}
};
template <typename tType>
struct DeclareValue {
tType operator()() {}
};
struct TrueType {
static constexpr auto value = true;
};
struct FalseType {
static constexpr auto value = false;
};
}
namespace tp {
ualni next2pow(ualni v);
uhalni next2pow(uhalni v);
ufalni next2pow(ufalni v);

View file

@ -0,0 +1,50 @@
#pragma once
#include "Common.hpp"
namespace tp {
// TODO
template <bool tRecursive>
class SizeCounter {
typedef SizeCounter& ArchRef;
template <typename T, typename = void> struct HasSizeCounter : FalseType {};
template <typename T> struct HasSizeCounter<T, VoidType<decltype(DeclareValue<T>()().count(DeclareValue<ArchRef>()()))>> : TrueType {};
public:
SizeCounter() = default;
template<typename Type>
void count(const Type& val) {
if constexpr (HasSizeCounter<Type>::value) {
val.count(*this);
} else {
if constexpr (tRecursive) {
count(sizeof(val));
} else {
mSize += sizeof(Type);
}
}
}
void countSizeUnused(ualni size) {
mSizeUnused += size;
}
void countSize(ualni size) {
mSize += size;
}
[[nodiscard]] ualni getSizeUnused() const {
return mSizeUnused;
}
[[nodiscard]] ualni getSize() const {
return mSize;
}
private:
ualni mSize = 0;
ualni mSizeUnused = 0;
};
}

View file

@ -0,0 +1,202 @@
#include "Archiver.hpp"
#include <cstdio>
#include <cstdlib>
using namespace tp;
bool sFailed = false;
struct Undef {
char character1 = 'a';
bool boolean = true;
ualni integer = 321;
char character2 = 'a';
void change() {
character1++;
character2--;
integer++;
boolean = !boolean;
}
[[nodiscard]] bool operator!=(const Undef& in) const {
if (character1 != in.character1) return true;
if (character2 != in.character2) return true;
if (integer != in.integer) return true;
if (boolean != in.boolean) return true;
return false;
}
};
struct SimpleArchive {
char character = 'a';
ualni integer = 123;
bool boolean = true;
Undef undef;
template<typename tArchiver>
void archive(tArchiver& ar) {
ar % character;
ar % integer;
ar % boolean;
ar % undef;
}
void change() {
character++;
integer++;
boolean = !boolean;
undef.change();
}
[[nodiscard]] bool operator!=(const SimpleArchive& in) const {
if (character != in.character) return true;
if (integer != in.integer) return true;
if (boolean != in.boolean) return true;
if (undef != in.undef) return true;
return false;
}
};
struct Simple {
char character = 'a';
ualni integer = 123;
bool boolean = true;
Undef undef;
template<typename tArchiver>
void archiveRead(tArchiver& ar) {
ar >> character;
ar >> integer;
ar >> boolean;
ar >> undef;
}
template<typename tArchiver>
void archiveWrite(tArchiver& ar) const {
ar << character;
ar << integer;
ar << boolean;
ar << undef;
}
void change() {
character++;
integer++;
boolean = !boolean;
undef.change();
}
[[nodiscard]] bool operator!=(const Simple& in) const {
if (character != in.character) return true;
if (integer != in.integer) return true;
if (boolean != in.boolean) return true;
if (undef != in.undef) return true;
return false;
}
};
template<typename tType>
struct Set {
tType buff[10];
ualni len = 5;
template<typename tArchiver>
void archiveRead(tArchiver& ar) {
ar >> len;
for (auto i = 0; i < len; i++) {
ar >> buff[i];
}
}
template<typename tArchiver>
void archiveWrite(tArchiver& ar) const {
ar << len;
for (auto i = 0; i < len; i++) {
ar << buff[i];
}
}
void change() {
len = 2;
for (auto i = 0; i < len; i++) {
buff[i].change();
}
}
[[nodiscard]] bool operator!=(const Set& in) const {
for (auto i = 0; i < len; i++) {
if (buff[i] != in.buff[i]) return true;
}
if (len != in.len) return true;
return false;
}
};
template<typename tType>
struct Complex {
Undef undef;
Set<tType> set;
template<typename tArchiver>
void archive(tArchiver& ar) {
ar % set;
ar % undef;
}
void change() {
undef.change();
set.change();
}
[[nodiscard]] bool operator!=(const Complex& in) const {
return undef != in.undef || set != in.set;
}
};
template<typename tType>
void test() {
constexpr auto size = 1024;
const tType val;
tType res;
res.change();
ArchiverExample<size, false> write;
ArchiverExample<size, true> read;
write % val;
for (auto i = 0; i < size; i++) read.mBuff[i] = write.mBuff[i];
read % res;
if (val != res) {
printf("Test %s Failed\n", typeid(tType).name());
sFailed = true;
}
}
template <typename T, typename A, typename = void> struct HasArchive : FalseType {};
template <typename T, typename A> struct HasArchive<T, A, VoidType<decltype(DeclareValue<T>()().archive(DeclareValue<A&>()()))>> : TrueType {};
void testArchiver() {
printf("has archive method - %i\n", HasArchive<SimpleArchive, ArchiverExample<10, false>>::value);
printf("has archive method - %i\n", ArchiverExample<10, false>::HasFunc::Archive<SimpleArchive>::value);
printf("has archive method - %i\n", ArchiverExample<10, false>::HasFunc::Archive<Simple>::value);
test<SimpleArchive>();
test<Simple>();
test<Set<Simple>>();
test<Complex<Simple>>();
if (sFailed) {
exit(1);
}
}

View file

@ -1,7 +1,7 @@
#include "Module.hpp"
#include "Common.hpp"
void testArchiver();
int main() {
tp::ModuleManifest* ModuleDependencies[] = { &tp::gModuleBase, nullptr };
@ -13,10 +13,12 @@ int main() {
ASSERT(tp::gEnvironment.mWidth == tp::Environment::ArchWidth::X64);
ASSERT(tp::max(2, 1) == 2);
ASSERT(tp::max(-1, 0) == 0);
ASSERT(tp::max(0, -1) == 0);
ASSERT(tp::min(0, -1) == -1);
ASSERT(tp::max(2, 1) == 2)
ASSERT(tp::max(-1, 0) == 0)
ASSERT(tp::max(0, -1) == 0)
ASSERT(tp::min(0, -1) == -1)
testArchiver();
TestModule.deinitialize();
}