File indexing completed on 2026-09-13 09:19:33
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 != static_cast<ssize_t>(shape.size())
0070 || ndim != static_cast<ssize_t>(strides.size())) {
0071 pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length");
0072 }
0073 for (size_t i = 0; i < static_cast<size_t>(ndim); ++i) {
0074 size *= shape[i];
0075 }
0076 }
0077
0078 template <typename T>
0079 buffer_info(T *ptr,
0080 detail::any_container<ssize_t> shape_in,
0081 detail::any_container<ssize_t> strides_in,
0082 bool readonly = false)
0083 : buffer_info(private_ctr_tag(),
0084 ptr,
0085 sizeof(T),
0086 format_descriptor<T>::format(),
0087 static_cast<ssize_t>(shape_in->size()),
0088 std::move(shape_in),
0089 std::move(strides_in),
0090 readonly) {}
0091
0092 buffer_info(void *ptr,
0093 ssize_t itemsize,
0094 const std::string &format,
0095 ssize_t size,
0096 bool readonly = false)
0097 : buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}, readonly) {}
0098
0099 template <typename T>
0100 buffer_info(T *ptr, ssize_t size, bool readonly = false)
0101 : buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size, readonly) {}
0102
0103 template <typename T>
0104 buffer_info(const T *ptr, ssize_t size, bool readonly = true)
0105 : buffer_info(
0106 const_cast<T *>(ptr), sizeof(T), format_descriptor<T>::format(), size, readonly) {}
0107
0108 explicit buffer_info(Py_buffer *view, bool ownview = true)
0109 : buffer_info(
0110 view->buf,
0111 view->itemsize,
0112 view->format,
0113 view->ndim,
0114 {view->shape, view->shape + view->ndim},
0115
0116
0117
0118 view->strides
0119 ? std::vector<ssize_t>(view->strides, view->strides + view->ndim)
0120 : detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize),
0121 (view->readonly != 0)) {
0122
0123 this->m_view = view;
0124
0125 this->ownview = ownview;
0126 }
0127
0128 buffer_info(const buffer_info &) = delete;
0129 buffer_info &operator=(const buffer_info &) = delete;
0130
0131 buffer_info(buffer_info &&other) noexcept { (*this) = std::move(other); }
0132
0133 buffer_info &operator=(buffer_info &&rhs) noexcept {
0134 ptr = rhs.ptr;
0135 itemsize = rhs.itemsize;
0136 size = rhs.size;
0137 format = std::move(rhs.format);
0138 ndim = rhs.ndim;
0139 shape = std::move(rhs.shape);
0140 strides = std::move(rhs.strides);
0141 std::swap(m_view, rhs.m_view);
0142 std::swap(ownview, rhs.ownview);
0143 readonly = rhs.readonly;
0144 return *this;
0145 }
0146
0147 ~buffer_info() {
0148 if (m_view && ownview) {
0149 PyBuffer_Release(m_view);
0150 delete m_view;
0151 }
0152 }
0153
0154 Py_buffer *view() const { return m_view; }
0155 Py_buffer *&view() { return m_view; }
0156
0157
0158
0159
0160
0161
0162
0163 template <typename T>
0164 bool item_type_is_equivalent_to() const {
0165 return detail::compare_buffer_info<T>::compare(*this);
0166 }
0167
0168 private:
0169 struct private_ctr_tag {};
0170
0171 buffer_info(private_ctr_tag,
0172 void *ptr,
0173 ssize_t itemsize,
0174 const std::string &format,
0175 ssize_t ndim,
0176 detail::any_container<ssize_t> &&shape_in,
0177 detail::any_container<ssize_t> &&strides_in,
0178 bool readonly)
0179 : buffer_info(
0180 ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), readonly) {}
0181
0182 Py_buffer *m_view = nullptr;
0183 bool ownview = false;
0184 };
0185
0186 PYBIND11_NAMESPACE_BEGIN(detail)
0187
0188 template <typename T, typename SFINAE>
0189 struct compare_buffer_info {
0190 static bool compare(const buffer_info &b) {
0191
0192 return b.format == format_descriptor<T>::format() && b.itemsize == (ssize_t) sizeof(T);
0193 }
0194 };
0195
0196 template <typename T>
0197 struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> {
0198 static bool compare(const buffer_info &b) {
0199 return static_cast<size_t>(b.itemsize) == sizeof(T)
0200 && (b.format == format_descriptor<T>::value
0201 || ((sizeof(T) == sizeof(long))
0202 && b.format == (std::is_unsigned<T>::value ? "L" : "l"))
0203 || ((sizeof(T) == sizeof(size_t))
0204 && b.format == (std::is_unsigned<T>::value ? "N" : "n")));
0205 }
0206 };
0207
0208 PYBIND11_NAMESPACE_END(detail)
0209 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)