680 lines
23 KiB
C++
680 lines
23 KiB
C++
/*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
/** \file
|
|
* \ingroup fn
|
|
*
|
|
* The CPPType class is the core of the runtime-type-system used by the functions system. It can
|
|
* represent C++ types that are default-constructible, destructible, movable, copyable,
|
|
* equality comparable and hashable. In the future we might want to make some of these properties
|
|
* optional.
|
|
*
|
|
* Every type has a size and an alignment. Every function dealing with C++ types in a generic way,
|
|
* has to make sure that alignment rules are followed. The methods provided by a CPPType instance
|
|
* will check for correct alignment as well.
|
|
*
|
|
* Every type has a name that is for debugging purposes only. It should not be used as identifier.
|
|
*
|
|
* To check if two instances of CPPType represent the same type, only their pointers have to be
|
|
* compared. Any C++ type has at most one corresponding CPPType instance.
|
|
*
|
|
* A CPPType instance comes with many methods that allow dealing with types in a generic way. Most
|
|
* methods come in three variants. Using the construct-default methods as example:
|
|
* - construct_default(void *ptr):
|
|
* Constructs a single instance of that type at the given pointer.
|
|
* - construct_default_n(void *ptr, int64_t n):
|
|
* Constructs n instances of that type in an array that starts at the given pointer.
|
|
* - construct_default_indices(void *ptr, IndexMask mask):
|
|
* Constructs multiple instances of that type in an array that starts at the given pointer.
|
|
* Only the indices referenced by `mask` will by constructed.
|
|
*
|
|
* In some cases default-construction does nothing (e.g. for trivial types like int). The
|
|
* `default_value` method provides some default value anyway that can be copied instead. What the
|
|
* default value is, depends on the type. Usually it is something like 0 or an empty string.
|
|
*
|
|
*
|
|
* Implementation Considerations
|
|
* -----------------------------
|
|
*
|
|
* Concepts like inheritance are currently not captured by this system. This is not because it is
|
|
* not possible, but because it was not necessary to add this complexity yet.
|
|
*
|
|
* One could also implement CPPType itself using virtual inheritance. However, I found the approach
|
|
* used now with explicit function pointers to work better. Here are some reasons:
|
|
* - If CPPType would be inherited once for every used C++ type, we would get a lot of classes
|
|
* that would only be instanced once each.
|
|
* - Methods like `construct_default` that operate on a single instance have to be fast. Even this
|
|
* one necessary indirection using function pointers adds a lot of overhead. If all methods were
|
|
* virtual, there would be a second level of indirection that increases the overhead even more.
|
|
* - If it becomes necessary, we could pass the function pointers to C functions more easily than
|
|
* pointers to virtual member functions.
|
|
*/
|
|
|
|
#include "BLI_hash.hh"
|
|
#include "BLI_index_mask.hh"
|
|
#include "BLI_math_base.h"
|
|
#include "BLI_string_ref.hh"
|
|
#include "BLI_utility_mixins.hh"
|
|
|
|
namespace blender::fn {
|
|
|
|
class CPPType : NonCopyable, NonMovable {
|
|
public:
|
|
using ConstructDefaultF = void (*)(void *ptr);
|
|
using ConstructDefaultNF = void (*)(void *ptr, int64_t n);
|
|
using ConstructDefaultIndicesF = void (*)(void *ptr, IndexMask mask);
|
|
|
|
using DestructF = void (*)(void *ptr);
|
|
using DestructNF = void (*)(void *ptr, int64_t n);
|
|
using DestructIndicesF = void (*)(void *ptr, IndexMask mask);
|
|
|
|
using CopyToInitializedF = void (*)(const void *src, void *dst);
|
|
using CopyToInitializedNF = void (*)(const void *src, void *dst, int64_t n);
|
|
using CopyToInitializedIndicesF = void (*)(const void *src, void *dst, IndexMask mask);
|
|
|
|
using CopyToUninitializedF = void (*)(const void *src, void *dst);
|
|
using CopyToUninitializedNF = void (*)(const void *src, void *dst, int64_t n);
|
|
using CopyToUninitializedIndicesF = void (*)(const void *src, void *dst, IndexMask mask);
|
|
|
|
using MoveToInitializedF = void (*)(void *src, void *dst);
|
|
using MoveToInitializedNF = void (*)(void *src, void *dst, int64_t n);
|
|
using MoveToInitializedIndicesF = void (*)(void *src, void *dst, IndexMask mask);
|
|
|
|
using MoveToUninitializedF = void (*)(void *src, void *dst);
|
|
using MoveToUninitializedNF = void (*)(void *src, void *dst, int64_t n);
|
|
using MoveToUninitializedIndicesF = void (*)(void *src, void *dst, IndexMask mask);
|
|
|
|
using RelocateToInitializedF = void (*)(void *src, void *dst);
|
|
using RelocateToInitializedNF = void (*)(void *src, void *dst, int64_t n);
|
|
using RelocateToInitializedIndicesF = void (*)(void *src, void *dst, IndexMask mask);
|
|
|
|
using RelocateToUninitializedF = void (*)(void *src, void *dst);
|
|
using RelocateToUninitializedNF = void (*)(void *src, void *dst, int64_t n);
|
|
using RelocateToUninitializedIndicesF = void (*)(void *src, void *dst, IndexMask mask);
|
|
|
|
using FillInitializedF = void (*)(const void *value, void *dst, int64_t n);
|
|
using FillInitializedIndicesF = void (*)(const void *value, void *dst, IndexMask mask);
|
|
|
|
using FillUninitializedF = void (*)(const void *value, void *dst, int64_t n);
|
|
using FillUninitializedIndicesF = void (*)(const void *value, void *dst, IndexMask mask);
|
|
|
|
using DebugPrintF = void (*)(const void *value, std::stringstream &ss);
|
|
using IsEqualF = bool (*)(const void *a, const void *b);
|
|
using HashF = uint64_t (*)(const void *value);
|
|
|
|
private:
|
|
int64_t size_;
|
|
int64_t alignment_;
|
|
uintptr_t alignment_mask_;
|
|
bool is_trivially_destructible_;
|
|
|
|
ConstructDefaultF construct_default_;
|
|
ConstructDefaultNF construct_default_n_;
|
|
ConstructDefaultIndicesF construct_default_indices_;
|
|
|
|
DestructF destruct_;
|
|
DestructNF destruct_n_;
|
|
DestructIndicesF destruct_indices_;
|
|
|
|
CopyToInitializedF copy_to_initialized_;
|
|
CopyToInitializedNF copy_to_initialized_n_;
|
|
CopyToInitializedIndicesF copy_to_initialized_indices_;
|
|
|
|
CopyToUninitializedF copy_to_uninitialized_;
|
|
CopyToUninitializedNF copy_to_uninitialized_n_;
|
|
CopyToUninitializedIndicesF copy_to_uninitialized_indices_;
|
|
|
|
MoveToInitializedF move_to_initialized_;
|
|
MoveToInitializedNF move_to_initialized_n_;
|
|
MoveToInitializedIndicesF move_to_initialized_indices_;
|
|
|
|
MoveToUninitializedF move_to_uninitialized_;
|
|
MoveToUninitializedNF move_to_uninitialized_n_;
|
|
MoveToUninitializedIndicesF move_to_uninitialized_indices_;
|
|
|
|
RelocateToInitializedF relocate_to_initialized_;
|
|
RelocateToInitializedNF relocate_to_initialized_n_;
|
|
RelocateToInitializedIndicesF relocate_to_initialized_indices_;
|
|
|
|
RelocateToUninitializedF relocate_to_uninitialized_;
|
|
RelocateToUninitializedNF relocate_to_uninitialized_n_;
|
|
RelocateToUninitializedIndicesF relocate_to_uninitialized_indices_;
|
|
|
|
FillInitializedF fill_initialized_;
|
|
FillInitializedIndicesF fill_initialized_indices_;
|
|
|
|
FillUninitializedF fill_uninitialized_;
|
|
FillUninitializedIndicesF fill_uninitialized_indices_;
|
|
|
|
DebugPrintF debug_print_;
|
|
IsEqualF is_equal_;
|
|
HashF hash_;
|
|
|
|
const void *default_value_;
|
|
std::string name_;
|
|
|
|
public:
|
|
CPPType(std::string name,
|
|
int64_t size,
|
|
int64_t alignment,
|
|
bool is_trivially_destructible,
|
|
ConstructDefaultF construct_default,
|
|
ConstructDefaultNF construct_default_n,
|
|
ConstructDefaultIndicesF construct_default_indices,
|
|
DestructF destruct,
|
|
DestructNF destruct_n,
|
|
DestructIndicesF destruct_indices,
|
|
CopyToInitializedF copy_to_initialized,
|
|
CopyToInitializedNF copy_to_initialized_n,
|
|
CopyToInitializedIndicesF copy_to_initialized_indices,
|
|
CopyToUninitializedF copy_to_uninitialized,
|
|
CopyToUninitializedNF copy_to_uninitialized_n,
|
|
CopyToUninitializedIndicesF copy_to_uninitialized_indices,
|
|
MoveToInitializedF move_to_initialized,
|
|
MoveToInitializedNF move_to_initialized_n,
|
|
MoveToInitializedIndicesF move_to_initialized_indices,
|
|
MoveToUninitializedF move_to_uninitialized,
|
|
MoveToUninitializedNF move_to_uninitialized_n,
|
|
MoveToUninitializedIndicesF move_to_uninitialized_indices,
|
|
RelocateToInitializedF relocate_to_initialized,
|
|
RelocateToInitializedNF relocate_to_initialized_n,
|
|
RelocateToInitializedIndicesF relocate_to_initialized_indices,
|
|
RelocateToUninitializedF relocate_to_uninitialized,
|
|
RelocateToUninitializedNF relocate_to_uninitialized_n,
|
|
RelocateToUninitializedIndicesF relocate_to_uninitialized_indices,
|
|
FillInitializedF fill_initialized,
|
|
FillInitializedIndicesF fill_initialized_indices,
|
|
FillUninitializedF fill_uninitialized,
|
|
FillUninitializedIndicesF fill_uninitialized_indices,
|
|
DebugPrintF debug_print,
|
|
IsEqualF is_equal,
|
|
HashF hash,
|
|
const void *default_value)
|
|
: size_(size),
|
|
alignment_(alignment),
|
|
is_trivially_destructible_(is_trivially_destructible),
|
|
construct_default_(construct_default),
|
|
construct_default_n_(construct_default_n),
|
|
construct_default_indices_(construct_default_indices),
|
|
destruct_(destruct),
|
|
destruct_n_(destruct_n),
|
|
destruct_indices_(destruct_indices),
|
|
copy_to_initialized_(copy_to_initialized),
|
|
copy_to_initialized_n_(copy_to_initialized_n),
|
|
copy_to_initialized_indices_(copy_to_initialized_indices),
|
|
copy_to_uninitialized_(copy_to_uninitialized),
|
|
copy_to_uninitialized_n_(copy_to_uninitialized_n),
|
|
copy_to_uninitialized_indices_(copy_to_uninitialized_indices),
|
|
move_to_initialized_(move_to_initialized),
|
|
move_to_initialized_n_(move_to_initialized_n),
|
|
move_to_initialized_indices_(move_to_initialized_indices),
|
|
move_to_uninitialized_(move_to_uninitialized),
|
|
move_to_uninitialized_n_(move_to_uninitialized_n),
|
|
move_to_uninitialized_indices_(move_to_uninitialized_indices),
|
|
relocate_to_initialized_(relocate_to_initialized),
|
|
relocate_to_initialized_n_(relocate_to_initialized_n),
|
|
relocate_to_initialized_indices_(relocate_to_initialized_indices),
|
|
relocate_to_uninitialized_(relocate_to_uninitialized),
|
|
relocate_to_uninitialized_n_(relocate_to_uninitialized_n),
|
|
relocate_to_uninitialized_indices_(relocate_to_uninitialized_indices),
|
|
fill_initialized_(fill_initialized),
|
|
fill_initialized_indices_(fill_initialized_indices),
|
|
fill_uninitialized_(fill_uninitialized),
|
|
fill_uninitialized_indices_(fill_uninitialized_indices),
|
|
debug_print_(debug_print),
|
|
is_equal_(is_equal),
|
|
hash_(hash),
|
|
default_value_(default_value),
|
|
name_(name)
|
|
{
|
|
BLI_assert(is_power_of_2_i(alignment_));
|
|
alignment_mask_ = (uintptr_t)alignment_ - (uintptr_t)1;
|
|
}
|
|
|
|
/**
|
|
* Two types only compare equal when their pointer is equal. No two instances of CPPType for the
|
|
* same C++ type should be created.
|
|
*/
|
|
friend bool operator==(const CPPType &a, const CPPType &b)
|
|
{
|
|
return &a == &b;
|
|
}
|
|
|
|
friend bool operator!=(const CPPType &a, const CPPType &b)
|
|
{
|
|
return !(&a == &b);
|
|
}
|
|
|
|
template<typename T> static const CPPType &get();
|
|
|
|
/**
|
|
* Returns the name of the type for debugging purposes. This name should not be used as
|
|
* identifier.
|
|
*/
|
|
StringRefNull name() const
|
|
{
|
|
return name_;
|
|
}
|
|
|
|
/**
|
|
* Required memory in bytes for an instance of this type.
|
|
*
|
|
* C++ equivalent:
|
|
* sizeof(T);
|
|
*/
|
|
int64_t size() const
|
|
{
|
|
return size_;
|
|
}
|
|
|
|
/**
|
|
* Required memory alignment for an instance of this type.
|
|
*
|
|
* C++ equivalent:
|
|
* alignof(T);
|
|
*/
|
|
int64_t alignment() const
|
|
{
|
|
return alignment_;
|
|
}
|
|
|
|
/**
|
|
* When true, the destructor does not have to be called on this type. This can sometimes be used
|
|
* for optimization purposes.
|
|
*
|
|
* C++ equivalent:
|
|
* std::is_trivially_destructible_v<T>;
|
|
*/
|
|
bool is_trivially_destructible() const
|
|
{
|
|
return is_trivially_destructible_;
|
|
}
|
|
|
|
/**
|
|
* Returns true, when the given pointer fulfills the alignment requirement of this type.
|
|
*/
|
|
bool pointer_has_valid_alignment(const void *ptr) const
|
|
{
|
|
return ((uintptr_t)ptr & alignment_mask_) == 0;
|
|
}
|
|
|
|
bool pointer_can_point_to_instance(const void *ptr) const
|
|
{
|
|
return ptr != nullptr && pointer_has_valid_alignment(ptr);
|
|
}
|
|
|
|
/**
|
|
* Call the default constructor at the given memory location.
|
|
* The memory should be uninitialized before this method is called.
|
|
* For some trivial types (like int), this method does nothing.
|
|
*
|
|
* C++ equivalent:
|
|
* new (ptr) T;
|
|
*/
|
|
void construct_default(void *ptr) const
|
|
{
|
|
BLI_assert(this->pointer_can_point_to_instance(ptr));
|
|
|
|
construct_default_(ptr);
|
|
}
|
|
|
|
void construct_default_n(void *ptr, int64_t n) const
|
|
{
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(ptr));
|
|
|
|
construct_default_n_(ptr, n);
|
|
}
|
|
|
|
void construct_default_indices(void *ptr, IndexMask mask) const
|
|
{
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr));
|
|
|
|
construct_default_indices_(ptr, mask);
|
|
}
|
|
|
|
/**
|
|
* Call the destructor on the given instance of this type. The pointer must not be nullptr.
|
|
*
|
|
* For some trivial types, this does nothing.
|
|
*
|
|
* C++ equivalent:
|
|
* ptr->~T();
|
|
*/
|
|
void destruct(void *ptr) const
|
|
{
|
|
BLI_assert(this->pointer_can_point_to_instance(ptr));
|
|
|
|
destruct_(ptr);
|
|
}
|
|
|
|
void destruct_n(void *ptr, int64_t n) const
|
|
{
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(ptr));
|
|
|
|
destruct_n_(ptr, n);
|
|
}
|
|
|
|
void destruct_indices(void *ptr, IndexMask mask) const
|
|
{
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(ptr));
|
|
|
|
destruct_indices_(ptr, mask);
|
|
}
|
|
|
|
DestructF destruct_cb() const
|
|
{
|
|
return destruct_;
|
|
}
|
|
|
|
/**
|
|
* Copy an instance of this type from src to dst.
|
|
*
|
|
* C++ equivalent:
|
|
* dst = src;
|
|
*/
|
|
void copy_to_initialized(const void *src, void *dst) const
|
|
{
|
|
BLI_assert(src != dst);
|
|
BLI_assert(this->pointer_can_point_to_instance(src));
|
|
BLI_assert(this->pointer_can_point_to_instance(dst));
|
|
|
|
copy_to_initialized_(src, dst);
|
|
}
|
|
|
|
void copy_to_initialized_n(const void *src, void *dst, int64_t n) const
|
|
{
|
|
BLI_assert(n == 0 || src != dst);
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
copy_to_initialized_n_(src, dst, n);
|
|
}
|
|
|
|
void copy_to_initialized_indices(const void *src, void *dst, IndexMask mask) const
|
|
{
|
|
BLI_assert(mask.size() == 0 || src != dst);
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
copy_to_initialized_indices_(src, dst, mask);
|
|
}
|
|
|
|
/**
|
|
* Copy an instance of this type from src to dst.
|
|
*
|
|
* The memory pointed to by dst should be uninitialized.
|
|
*
|
|
* C++ equivalent:
|
|
* new (dst) T(src);
|
|
*/
|
|
void copy_to_uninitialized(const void *src, void *dst) const
|
|
{
|
|
BLI_assert(src != dst);
|
|
BLI_assert(this->pointer_can_point_to_instance(src));
|
|
BLI_assert(this->pointer_can_point_to_instance(dst));
|
|
|
|
copy_to_uninitialized_(src, dst);
|
|
}
|
|
|
|
void copy_to_uninitialized_n(const void *src, void *dst, int64_t n) const
|
|
{
|
|
BLI_assert(n == 0 || src != dst);
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
copy_to_uninitialized_n_(src, dst, n);
|
|
}
|
|
|
|
void copy_to_uninitialized_indices(const void *src, void *dst, IndexMask mask) const
|
|
{
|
|
BLI_assert(mask.size() == 0 || src != dst);
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
copy_to_uninitialized_indices_(src, dst, mask);
|
|
}
|
|
|
|
/**
|
|
* Move an instance of this type from src to dst.
|
|
*
|
|
* The memory pointed to by dst should be initialized.
|
|
*
|
|
* C++ equivalent:
|
|
* dst = std::move(src);
|
|
*/
|
|
void move_to_initialized(void *src, void *dst) const
|
|
{
|
|
BLI_assert(src != dst);
|
|
BLI_assert(this->pointer_can_point_to_instance(src));
|
|
BLI_assert(this->pointer_can_point_to_instance(dst));
|
|
|
|
move_to_initialized_(src, dst);
|
|
}
|
|
|
|
void move_to_initialized_n(void *src, void *dst, int64_t n) const
|
|
{
|
|
BLI_assert(n == 0 || src != dst);
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
move_to_initialized_n_(src, dst, n);
|
|
}
|
|
|
|
void move_to_initialized_indices(void *src, void *dst, IndexMask mask) const
|
|
{
|
|
BLI_assert(mask.size() == 0 || src != dst);
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
move_to_initialized_indices_(src, dst, mask);
|
|
}
|
|
|
|
/**
|
|
* Move an instance of this type from src to dst.
|
|
*
|
|
* The memory pointed to by dst should be uninitialized.
|
|
*
|
|
* C++ equivalent:
|
|
* new (dst) T(std::move(src));
|
|
*/
|
|
void move_to_uninitialized(void *src, void *dst) const
|
|
{
|
|
BLI_assert(src != dst);
|
|
BLI_assert(this->pointer_can_point_to_instance(src));
|
|
BLI_assert(this->pointer_can_point_to_instance(dst));
|
|
|
|
move_to_uninitialized_(src, dst);
|
|
}
|
|
|
|
void move_to_uninitialized_n(void *src, void *dst, int64_t n) const
|
|
{
|
|
BLI_assert(n == 0 || src != dst);
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
move_to_uninitialized_n_(src, dst, n);
|
|
}
|
|
|
|
void move_to_uninitialized_indices(void *src, void *dst, IndexMask mask) const
|
|
{
|
|
BLI_assert(mask.size() == 0 || src != dst);
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
move_to_uninitialized_indices_(src, dst, mask);
|
|
}
|
|
|
|
/**
|
|
* Relocates an instance of this type from src to dst. src will point to uninitialized memory
|
|
* afterwards.
|
|
*
|
|
* C++ equivalent:
|
|
* dst = std::move(src);
|
|
* src->~T();
|
|
*/
|
|
void relocate_to_initialized(void *src, void *dst) const
|
|
{
|
|
BLI_assert(src != dst);
|
|
BLI_assert(this->pointer_can_point_to_instance(src));
|
|
BLI_assert(this->pointer_can_point_to_instance(dst));
|
|
|
|
relocate_to_initialized_(src, dst);
|
|
}
|
|
|
|
void relocate_to_initialized_n(void *src, void *dst, int64_t n) const
|
|
{
|
|
BLI_assert(n == 0 || src != dst);
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
relocate_to_initialized_n_(src, dst, n);
|
|
}
|
|
|
|
void relocate_to_initialized_indices(void *src, void *dst, IndexMask mask) const
|
|
{
|
|
BLI_assert(mask.size() == 0 || src != dst);
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
relocate_to_initialized_indices_(src, dst, mask);
|
|
}
|
|
|
|
/**
|
|
* Relocates an instance of this type from src to dst. src will point to uninitialized memory
|
|
* afterwards.
|
|
*
|
|
* C++ equivalent:
|
|
* new (dst) T(std::move(src))
|
|
* src->~T();
|
|
*/
|
|
void relocate_to_uninitialized(void *src, void *dst) const
|
|
{
|
|
BLI_assert(src != dst);
|
|
BLI_assert(this->pointer_can_point_to_instance(src));
|
|
BLI_assert(this->pointer_can_point_to_instance(dst));
|
|
|
|
relocate_to_uninitialized_(src, dst);
|
|
}
|
|
|
|
void relocate_to_uninitialized_n(void *src, void *dst, int64_t n) const
|
|
{
|
|
BLI_assert(n == 0 || src != dst);
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
relocate_to_uninitialized_n_(src, dst, n);
|
|
}
|
|
|
|
void relocate_to_uninitialized_indices(void *src, void *dst, IndexMask mask) const
|
|
{
|
|
BLI_assert(mask.size() == 0 || src != dst);
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(src));
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
relocate_to_uninitialized_indices_(src, dst, mask);
|
|
}
|
|
|
|
/**
|
|
* Copy the given value to the first n elements in an array starting at dst.
|
|
*
|
|
* Other instances of the same type should live in the array before this method is called.
|
|
*/
|
|
void fill_initialized(const void *value, void *dst, int64_t n) const
|
|
{
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(value));
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
fill_initialized_(value, dst, n);
|
|
}
|
|
|
|
void fill_initialized_indices(const void *value, void *dst, IndexMask mask) const
|
|
{
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(value));
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
fill_initialized_indices_(value, dst, mask);
|
|
}
|
|
|
|
/**
|
|
* Copy the given value to the first n elements in an array starting at dst.
|
|
*
|
|
* The array should be uninitialized before this method is called.
|
|
*/
|
|
void fill_uninitialized(const void *value, void *dst, int64_t n) const
|
|
{
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(value));
|
|
BLI_assert(n == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
fill_uninitialized_(value, dst, n);
|
|
}
|
|
|
|
void fill_uninitialized_indices(const void *value, void *dst, IndexMask mask) const
|
|
{
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(value));
|
|
BLI_assert(mask.size() == 0 || this->pointer_can_point_to_instance(dst));
|
|
|
|
fill_uninitialized_indices_(value, dst, mask);
|
|
}
|
|
|
|
void debug_print(const void *value, std::stringstream &ss) const
|
|
{
|
|
BLI_assert(this->pointer_can_point_to_instance(value));
|
|
debug_print_(value, ss);
|
|
}
|
|
|
|
bool is_equal(const void *a, const void *b) const
|
|
{
|
|
BLI_assert(this->pointer_can_point_to_instance(a));
|
|
BLI_assert(this->pointer_can_point_to_instance(b));
|
|
return is_equal_(a, b);
|
|
}
|
|
|
|
uint64_t hash(const void *value) const
|
|
{
|
|
BLI_assert(this->pointer_can_point_to_instance(value));
|
|
return hash_(value);
|
|
}
|
|
|
|
/**
|
|
* Get a pointer to a constant value of this type. The specific value depends on the type.
|
|
* It is usually a zero-initialized or default constructed value.
|
|
*/
|
|
const void *default_value() const
|
|
{
|
|
return default_value_;
|
|
}
|
|
|
|
uint64_t hash() const
|
|
{
|
|
return get_default_hash(this);
|
|
}
|
|
|
|
template<typename T> bool is() const
|
|
{
|
|
return this == &CPPType::get<T>();
|
|
}
|
|
};
|
|
|
|
} // namespace blender::fn
|
|
|
|
/* Utility for allocating an uninitialized buffer for a single value of the given #CPPType. */
|
|
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name) \
|
|
blender::DynamicStackBuffer<64, 64> stack_buffer_for_##variable_name((type).size(), \
|
|
(type).alignment()); \
|
|
void *variable_name = stack_buffer_for_##variable_name.buffer();
|