Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions Framework/Core/include/Framework/Array2D.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,29 @@ struct Array2D {

Array2D& operator=(Array2D<T> const& other)
{
this->rows = other.rows;
this->cols = other.cols;
data = new T[rows * cols];
for (auto i = 0U; i < rows; ++i) {
for (auto j = 0U; j < cols; ++j) {
data[i * cols + j] = *(other.data + (i * cols + j));
if (this == &other) {
return *this;
}
// Copy into a new buffer first, so that a throwing copy leaves this array untouched
auto* newData = new T[other.rows * other.cols];
for (auto i = 0U; i < other.rows; ++i) {
for (auto j = 0U; j < other.cols; ++j) {
newData[i * other.cols + j] = other.data[i * other.cols + j];
}
}
delete[] data;
data = newData;
this->rows = other.rows;
this->cols = other.cols;
return *this;
}

Array2D& operator=(Array2D<T>&& other)
{
if (this == &other) {
return *this;
}
delete[] data;
this->rows = other.rows;
this->cols = other.cols;
data = other.data;
Expand Down
42 changes: 25 additions & 17 deletions Framework/Core/include/Framework/Variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "Framework/RuntimeError.h"
#include "Framework/Array2D.h"
#include "Framework/Traits.h"
#include <type_traits>
#include <cstring>
#include <cstdint>
Expand Down Expand Up @@ -261,9 +262,9 @@ struct variant_helper {
new (reinterpret_cast<T*>(store)) T{};
*(reinterpret_cast<T*>(store)) = value;
}
static void set(void* store, T values, size_t size)
static void set(void* store, std::remove_pointer_t<T> const* values, size_t size)
{
*reinterpret_cast<T*>(store) = reinterpret_cast<T>(std::memcpy(std::malloc(size * sizeof(std::remove_pointer_t<T>)), reinterpret_cast<void*>(values), size * sizeof(std::remove_pointer_t<T>)));
*reinterpret_cast<T*>(store) = reinterpret_cast<T>(std::memcpy(std::malloc(size * sizeof(std::remove_pointer_t<T>)), reinterpret_cast<void const*>(values), size * sizeof(std::remove_pointer_t<T>)));
}

static T get(const void* store) { return *(reinterpret_cast<const T*>(store)); }
Expand Down Expand Up @@ -317,9 +318,10 @@ struct variant_helper<std::string> {
class Variant
{
public:
Variant(VariantType type = VariantType::Unknown) : mType{type} {}
Variant(VariantType type = VariantType::Unknown);

template <typename T>
requires(!is_specialization_v<T, std::vector>)
Variant(T value) : mType{variant_trait_v<T>}
{
variant_helper<decltype(value)>::set(&mStore, value);
Expand All @@ -331,17 +333,23 @@ class Variant
variant_helper<T>::set(&mStore, values, mSize);
}

// A Variant owns what it stores: the content of vectors is copied
template <typename T>
Variant(std::vector<T>& values) : mType{variant_trait_v<T*>}, mSize{values.size()}
Variant(std::vector<T> const& values) : mType{variant_trait_v<T*>}, mSize{values.size()}
{
variant_helper<T*>::set(&mStore, values.data(), mSize);
}

Variant(std::vector<std::string>& values) : mType{VariantType::ArrayString}, mSize{values.size()}
Variant(std::vector<std::string> const& values) : mType{VariantType::ArrayString}, mSize{values.size()}
{
variant_helper<std::vector<std::string>>::set(&mStore, values);
}

// A temporary vector cannot hand over its buffer to a Variant,
// so creating one only to copy it is an error
template <typename T>
Variant(std::vector<T>&&) = delete;

template <typename T>
Variant(std::initializer_list<T>)
{
Expand All @@ -355,6 +363,8 @@ class Variant
~Variant();
Variant& operator=(const Variant& other);
Variant& operator=(Variant&& other) noexcept;
// Assignment from a temporary vector has to be allowed because it is used, but copies
// to make sure Variant owns its content
template <typename T>
Variant& operator=(std::vector<T>&& other) noexcept
{
Expand All @@ -381,31 +391,25 @@ class Variant
return variant_helper<T>::get(&mStore);
}

// The setters replace the current content, releasing it first.
template <typename T>
void set(T value)
{
return variant_helper<T>::set(&mStore, value);
*this = Variant(value);
}

template <typename T>
void set(T value, size_t size)
{
mSize = size;
return variant_helper<T>::set(&mStore, value, mSize);
}

template <typename T>
void set(std::vector<T>& values)
requires(std::is_pod_v<T>)
{
return variant_helper<T*>::set(&mStore, values.data(), values.size());
*this = Variant(value, size);
}

/// FIXME: set for vector of strings is not used anywhere, why?
template <typename T>
void set(std::vector<T>& values)
requires(std::is_same_v<T, std::string>)
requires(std::is_pod_v<T> || std::is_same_v<T, std::string>)
{
return variant_helper<T*>::set(&mStore, values);
*this = Variant(values);
}

[[nodiscard]] VariantType type() const { return mType; }
Expand All @@ -414,6 +418,10 @@ class Variant

private:
friend std::ostream& operator<<(std::ostream& oss, Variant const& val);
// Helpers to manage the store depending on the actual content
void copyStore(Variant const& other);
void moveStore(Variant& other) noexcept;
void destroyStore() noexcept;
using storage_t = std::aligned_union<8, int, int8_t, int16_t, int64_t,
uint8_t, uint16_t, uint32_t, uint64_t,
const char*, float, double, bool,
Expand Down
Loading
Loading