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