112391Sjason@lowepower.com/* 212391Sjason@lowepower.com pybind11/buffer_info.h: Python buffer object interface 312391Sjason@lowepower.com 412391Sjason@lowepower.com Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 512391Sjason@lowepower.com 612391Sjason@lowepower.com All rights reserved. Use of this source code is governed by a 712391Sjason@lowepower.com BSD-style license that can be found in the LICENSE file. 812391Sjason@lowepower.com*/ 912391Sjason@lowepower.com 1012391Sjason@lowepower.com#pragma once 1112391Sjason@lowepower.com 1212391Sjason@lowepower.com#include "detail/common.h" 1312391Sjason@lowepower.com 1412391Sjason@lowepower.comNAMESPACE_BEGIN(PYBIND11_NAMESPACE) 1512391Sjason@lowepower.com 1612391Sjason@lowepower.com/// Information record describing a Python buffer object 1712391Sjason@lowepower.comstruct buffer_info { 1812391Sjason@lowepower.com void *ptr = nullptr; // Pointer to the underlying storage 1912391Sjason@lowepower.com ssize_t itemsize = 0; // Size of individual items in bytes 2012391Sjason@lowepower.com ssize_t size = 0; // Total number of entries 2112391Sjason@lowepower.com std::string format; // For homogeneous buffers, this should be set to format_descriptor<T>::format() 2212391Sjason@lowepower.com ssize_t ndim = 0; // Number of dimensions 2312391Sjason@lowepower.com std::vector<ssize_t> shape; // Shape of the tensor (1 entry per dimension) 2412391Sjason@lowepower.com std::vector<ssize_t> strides; // Number of entries between adjacent entries (for each per dimension) 2512391Sjason@lowepower.com 2612391Sjason@lowepower.com buffer_info() { } 2712391Sjason@lowepower.com 2812391Sjason@lowepower.com buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim, 2912391Sjason@lowepower.com detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in) 3012391Sjason@lowepower.com : ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim), 3112391Sjason@lowepower.com shape(std::move(shape_in)), strides(std::move(strides_in)) { 3212391Sjason@lowepower.com if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size()) 3312391Sjason@lowepower.com pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length"); 3412391Sjason@lowepower.com for (size_t i = 0; i < (size_t) ndim; ++i) 3512391Sjason@lowepower.com size *= shape[i]; 3612391Sjason@lowepower.com } 3712391Sjason@lowepower.com 3812391Sjason@lowepower.com template <typename T> 3912391Sjason@lowepower.com buffer_info(T *ptr, detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in) 4012391Sjason@lowepower.com : buffer_info(private_ctr_tag(), ptr, sizeof(T), format_descriptor<T>::format(), static_cast<ssize_t>(shape_in->size()), std::move(shape_in), std::move(strides_in)) { } 4112391Sjason@lowepower.com 4212391Sjason@lowepower.com buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size) 4312391Sjason@lowepower.com : buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}) { } 4412391Sjason@lowepower.com 4512391Sjason@lowepower.com template <typename T> 4612391Sjason@lowepower.com buffer_info(T *ptr, ssize_t size) 4712391Sjason@lowepower.com : buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size) { } 4812391Sjason@lowepower.com 4912391Sjason@lowepower.com explicit buffer_info(Py_buffer *view, bool ownview = true) 5012391Sjason@lowepower.com : buffer_info(view->buf, view->itemsize, view->format, view->ndim, 5112391Sjason@lowepower.com {view->shape, view->shape + view->ndim}, {view->strides, view->strides + view->ndim}) { 5212391Sjason@lowepower.com this->view = view; 5312391Sjason@lowepower.com this->ownview = ownview; 5412391Sjason@lowepower.com } 5512391Sjason@lowepower.com 5612391Sjason@lowepower.com buffer_info(const buffer_info &) = delete; 5712391Sjason@lowepower.com buffer_info& operator=(const buffer_info &) = delete; 5812391Sjason@lowepower.com 5912391Sjason@lowepower.com buffer_info(buffer_info &&other) { 6012391Sjason@lowepower.com (*this) = std::move(other); 6112391Sjason@lowepower.com } 6212391Sjason@lowepower.com 6312391Sjason@lowepower.com buffer_info& operator=(buffer_info &&rhs) { 6412391Sjason@lowepower.com ptr = rhs.ptr; 6512391Sjason@lowepower.com itemsize = rhs.itemsize; 6612391Sjason@lowepower.com size = rhs.size; 6712391Sjason@lowepower.com format = std::move(rhs.format); 6812391Sjason@lowepower.com ndim = rhs.ndim; 6912391Sjason@lowepower.com shape = std::move(rhs.shape); 7012391Sjason@lowepower.com strides = std::move(rhs.strides); 7112391Sjason@lowepower.com std::swap(view, rhs.view); 7212391Sjason@lowepower.com std::swap(ownview, rhs.ownview); 7312391Sjason@lowepower.com return *this; 7412391Sjason@lowepower.com } 7512391Sjason@lowepower.com 7612391Sjason@lowepower.com ~buffer_info() { 7712391Sjason@lowepower.com if (view && ownview) { PyBuffer_Release(view); delete view; } 7812391Sjason@lowepower.com } 7912391Sjason@lowepower.com 8012391Sjason@lowepower.comprivate: 8112391Sjason@lowepower.com struct private_ctr_tag { }; 8212391Sjason@lowepower.com 8312391Sjason@lowepower.com buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim, 8412391Sjason@lowepower.com detail::any_container<ssize_t> &&shape_in, detail::any_container<ssize_t> &&strides_in) 8512391Sjason@lowepower.com : buffer_info(ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in)) { } 8612391Sjason@lowepower.com 8712391Sjason@lowepower.com Py_buffer *view = nullptr; 8812391Sjason@lowepower.com bool ownview = false; 8912391Sjason@lowepower.com}; 9012391Sjason@lowepower.com 9112391Sjason@lowepower.comNAMESPACE_BEGIN(detail) 9212391Sjason@lowepower.com 9312391Sjason@lowepower.comtemplate <typename T, typename SFINAE = void> struct compare_buffer_info { 9412391Sjason@lowepower.com static bool compare(const buffer_info& b) { 9512391Sjason@lowepower.com return b.format == format_descriptor<T>::format() && b.itemsize == (ssize_t) sizeof(T); 9612391Sjason@lowepower.com } 9712391Sjason@lowepower.com}; 9812391Sjason@lowepower.com 9912391Sjason@lowepower.comtemplate <typename T> struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> { 10012391Sjason@lowepower.com static bool compare(const buffer_info& b) { 10112391Sjason@lowepower.com return (size_t) b.itemsize == sizeof(T) && (b.format == format_descriptor<T>::value || 10212391Sjason@lowepower.com ((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned<T>::value ? "L" : "l")) || 10312391Sjason@lowepower.com ((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned<T>::value ? "N" : "n"))); 10412391Sjason@lowepower.com } 10512391Sjason@lowepower.com}; 10612391Sjason@lowepower.com 10712391Sjason@lowepower.comNAMESPACE_END(detail) 10812391Sjason@lowepower.comNAMESPACE_END(PYBIND11_NAMESPACE) 109