File indexing completed on 2025-01-18 10:06:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #pragma once
0011
0012 #include "detail/common.h"
0013
0014 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0015
0016 PYBIND11_NAMESPACE_BEGIN(detail)
0017
0018
0019 inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
0020 auto ndim = shape.size();
0021 std::vector<ssize_t> strides(ndim, itemsize);
0022 if (ndim > 0) {
0023 for (size_t i = ndim - 1; i > 0; --i) {
0024 strides[i - 1] = strides[i] * shape[i];
0025 }
0026 }
0027 return strides;
0028 }
0029
0030
0031 inline std::vector<ssize_t> f_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
0032 auto ndim = shape.size();
0033 std::vector<ssize_t> strides(ndim, itemsize);
0034 for (size_t i = 1; i < ndim; ++i) {
0035 strides[i] = strides[i - 1] * shape[i - 1];
0036 }
0037 return strides;
0038 }
0039
0040 template <typename T, typename SFINAE = void>
0041 struct compare_buffer_info;
0042
0043 PYBIND11_NAMESPACE_END(detail)
0044
0045
0046 struct buffer_info {
0047 void *ptr = nullptr;
0048 ssize_t itemsize = 0;
0049 ssize_t size = 0;
0050 std::string format;
0051
0052 ssize_t ndim = 0;
0053 std::vector<ssize_t> shape;
0054 std::vector<ssize_t> strides;
0055
0056 bool readonly = false;
0057
0058 buffer_info() = default;
0059
0060 buffer_info(void *ptr,
0061 ssize_t itemsize,
0062 const std::string &format,
0063 ssize_t ndim,
0064 detail::any_container<ssize_t> shape_in,
0065 detail::any_container<ssize_t> strides_in,
0066 bool readonly = false)
0067 : ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
0068 shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) {
0069 if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size()) {
0070 pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length");
0071 }
0072 for (size_t i = 0; i < (size_t) ndim; ++i) {
0073 size *= shape[i];
0074 }
0075 }
0076
0077 template <typename T>
0078 buffer_info(T *ptr,
0079 detail::any_container<ssize_t> shape_in,
0080 detail::any_container<ssize_t> strides_in,
0081 bool readonly = false)
0082 : buffer_info(private_ctr_tag(),
0083 ptr,
0084 sizeof(T),
0085 format_descriptor<T>::format(),
0086 static_cast<ssize_t>(shape_in->size()),
0087 std::move(shape_in),
0088 std::move(strides_in),
0089 readonly) {}
0090
0091 buffer_info(void *ptr,
0092 ssize_t itemsize,
0093 const std::string &format,
0094 ssize_t size,
0095 bool readonly = false)
0096 : buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}, readonly) {}
0097
0098 template <typename T>
0099 buffer_info(T *ptr, ssize_t size, bool readonly = false)
0100 : buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size, readonly) {}
0101
0102 template <typename T>
0103 buffer_info(const T *ptr, ssize_t size, bool readonly = true)
0104 : buffer_info(
0105 const_cast<T *>(ptr), sizeof(T), format_descriptor<T>::format(), size, readonly) {}
0106
0107 explicit buffer_info(Py_buffer *view, bool ownview = true)
0108 : buffer_info(
0109 view->buf,
0110 view->itemsize,
0111 view->format,
0112 view->ndim,
0113 {view->shape, view->shape + view->ndim},
0114
0115
0116
0117 view->strides
0118 ? std::vector<ssize_t>(view->strides, view->strides + view->ndim)
0119 : detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize),
0120 (view->readonly != 0)) {
0121
0122 this->m_view = view;
0123
0124 this->ownview = ownview;
0125 }
0126
0127 buffer_info(const buffer_info &) = delete;
0128 buffer_info &operator=(const buffer_info &) = delete;
0129
0130 buffer_info(buffer_info &&other) noexcept { (*this) = std::move(other); }
0131
0132 buffer_info &operator=(buffer_info &&rhs) noexcept {
0133 ptr = rhs.ptr;
0134 itemsize = rhs.itemsize;
0135 size = rhs.size;
0136 format = std::move(rhs.format);
0137 ndim = rhs.ndim;
0138 shape = std::move(rhs.shape);
0139 strides = std::move(rhs.strides);
0140 std::swap(m_view, rhs.m_view);
0141 std::swap(ownview, rhs.ownview);
0142 readonly = rhs.readonly;
0143 return *this;
0144 }
0145
0146 ~buffer_info() {
0147 if (m_view && ownview) {
0148 PyBuffer_Release(m_view);
0149 delete m_view;
0150 }
0151 }
0152
0153 Py_buffer *view() const { return m_view; }
0154 Py_buffer *&view() { return m_view; }
0155
0156
0157
0158
0159
0160
0161
0162 template <typename T>
0163 bool item_type_is_equivalent_to() const {
0164 return detail::compare_buffer_info<T>::compare(*this);
0165 }
0166
0167 private:
0168 struct private_ctr_tag {};
0169
0170 buffer_info(private_ctr_tag,
0171 void *ptr,
0172 ssize_t itemsize,
0173 const std::string &format,
0174 ssize_t ndim,
0175 detail::any_container<ssize_t> &&shape_in,
0176 detail::any_container<ssize_t> &&strides_in,
0177 bool readonly)
0178 : buffer_info(
0179 ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), readonly) {}
0180
0181 Py_buffer *m_view = nullptr;
0182 bool ownview = false;
0183 };
0184
0185 PYBIND11_NAMESPACE_BEGIN(detail)
0186
0187 template <typename T, typename SFINAE>
0188 struct compare_buffer_info {
0189 static bool compare(const buffer_info &b) {
0190
0191 return b.format == format_descriptor<T>::format() && b.itemsize == (ssize_t) sizeof(T);
0192 }
0193 };
0194
0195 template <typename T>
0196 struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> {
0197 static bool compare(const buffer_info &b) {
0198 return (size_t) b.itemsize == sizeof(T)
0199 && (b.format == format_descriptor<T>::value
0200 || ((sizeof(T) == sizeof(long))
0201 && b.format == (std::is_unsigned<T>::value ? "L" : "l"))
0202 || ((sizeof(T) == sizeof(size_t))
0203 && b.format == (std::is_unsigned<T>::value ? "N" : "n")));
0204 }
0205 };
0206
0207 PYBIND11_NAMESPACE_END(detail)
0208 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)