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
Campbell Barton c434782e3a File headers: SPDX License migration
Use a shorter/simpler license convention, stops the header taking so
much space.

Follow the SPDX license specification: https://spdx.org/licenses

- C/C++/objc/objc++
- Python
- Shell Scripts
- CMake, GNUmakefile

While most of the source tree has been included

- `./extern/` was left out.
- `./intern/cycles` & `./intern/atomic` are also excluded because they
  use different header conventions.

doc/license/SPDX-license-identifiers.txt has been added to list SPDX all
used identifiers.

See P2788 for the script that automated these edits.

Reviewed By: brecht, mont29, sergey

Ref D14069
2022-02-11 09:14:36 +11:00

171 lines
3.4 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
#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);
}
GSpan slice(const IndexRange range) const
{
return this->slice(range.start(), range.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);
}
GMutableSpan slice(IndexRange range) const
{
return this->slice(range.start(), range.size());
}
};
} // namespace blender::fn