Archiver Initial

This commit is contained in:
IlyaShurupov 2023-07-25 18:47:00 +03:00 committed by IlushaShurupov
parent 01ba8160ef
commit 3575cbc543
25 changed files with 652 additions and 124 deletions

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;
};
}