This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/functions/FN_generic_span.hh

175 lines
3.9 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
*/
#include "BLI_span.hh"
#include "FN_cpp_type.hh"
namespace blender::fn {
/**
* A generic span. It behaves just like a blender::Span<T>, but the type is only known at run-time.
*/
class GSpan {
protected:
const CPPType *type_;
const void *data_;
int64_t size_;
public:
GSpan(const CPPType &type, const void *buffer, int64_t size)
: type_(&type), data_(buffer), size_(size)
{
BLI_assert(size >= 0);
BLI_assert(buffer != nullptr || size == 0);
BLI_assert(type.pointer_has_valid_alignment(buffer));
}
GSpan(const CPPType &type) : GSpan(type, nullptr, 0)
{
}
template<typename T>
GSpan(Span<T> array)
: GSpan(CPPType::get<T>(), static_cast<const void *>(array.data()), array.size())
{
}
const CPPType &type() const
{
return *type_;
}
bool is_empty() const
{
return size_ == 0;
}
int64_t size() const
{
return size_;
}
const void *data() const
{
return data_;
}
const void *operator[](int64_t index) const
{
BLI_assert(index < size_);
return POINTER_OFFSET(data_, type_->size() * index);
}
template<typename T> Span<T> typed() const
{
BLI_assert(type_->is<T>());
return Span<T>(static_cast<const T *>(data_), size_);
}
GSpan slice(const int64_t start, int64_t size) const
{
BLI_assert(start >= 0);
BLI_assert(size >= 0);
const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start));
return GSpan(*type_, POINTER_OFFSET(data_, type_->size() * start), new_size);
}
};
/**
* A generic mutable span. It behaves just like a blender::MutableSpan<T>, but the type is only
* known at run-time.
*/
class GMutableSpan {
protected:
const CPPType *type_;
void *data_;
int64_t size_;
public:
GMutableSpan(const CPPType &type, void *buffer, int64_t size)
: type_(&type), data_(buffer), size_(size)
{
BLI_assert(size >= 0);
BLI_assert(buffer != nullptr || size == 0);
BLI_assert(type.pointer_has_valid_alignment(buffer));
}
GMutableSpan(const CPPType &type) : GMutableSpan(type, nullptr, 0)
{
}
template<typename T>
GMutableSpan(MutableSpan<T> array)
: GMutableSpan(CPPType::get<T>(), static_cast<void *>(array.begin()), array.size())
{
}
operator GSpan() const
{
return GSpan(*type_, data_, size_);
}
const CPPType &type() const
{
return *type_;
}
bool is_empty() const
{
return size_ == 0;
}
int64_t size() const
{
return size_;
}
void *data() const
{
return data_;
}
void *operator[](int64_t index) const
{
BLI_assert(index >= 0);
BLI_assert(index < size_);
return POINTER_OFFSET(data_, type_->size() * index);
}
template<typename T> MutableSpan<T> typed() const
{
BLI_assert(type_->is<T>());
return MutableSpan<T>(static_cast<T *>(data_), size_);
}
GMutableSpan slice(const int64_t start, int64_t size) const
{
BLI_assert(start >= 0);
BLI_assert(size >= 0);
const int64_t new_size = std::max<int64_t>(0, std::min(size, size_ - start));
return GMutableSpan(*type_, POINTER_OFFSET(data_, type_->size() * start), new_size);
}
};
} // namespace blender::fn