Skip to content

Commit

Permalink
Move buffer_info to its own header
Browse files Browse the repository at this point in the history
Upcoming changes to buffer_info make it need some things declared in
common.h; it also feels a bit misplaced in common.h (which is arguably
too large already), so move it out.  (Separating this and the subsequent
changes into separate commits to make the changes easier to distinguish
from the move.)
  • Loading branch information
jagerman committed Apr 10, 2017
1 parent 3983a8e commit 83d1a88
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 81 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ set(PYTHON_MODULE_EXTENSION ${PYTHON_MODULE_EXTENSION} CACHE INTERNAL "")

set(PYBIND11_HEADERS
include/pybind11/attr.h
include/pybind11/buffer_info.h
include/pybind11/cast.h
include/pybind11/chrono.h
include/pybind11/class_support.h
Expand Down
96 changes: 96 additions & 0 deletions include/pybind11/buffer_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
pybind11/buffer_info.h: Python buffer object interface
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/

#pragma once

#include "common.h"

NAMESPACE_BEGIN(pybind11)

/// Information record describing a Python buffer object
struct buffer_info {
void *ptr = nullptr; // Pointer to the underlying storage
size_t itemsize = 0; // Size of individual items in bytes
size_t size = 0; // Total number of entries
std::string format; // For homogeneous buffers, this should be set to format_descriptor<T>::format()
size_t ndim = 0; // Number of dimensions
std::vector<size_t> shape; // Shape of the tensor (1 entry per dimension)
std::vector<size_t> strides; // Number of entries between adjacent entries (for each per dimension)

buffer_info() { }

buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t ndim,
const std::vector<size_t> &shape, const std::vector<size_t> &strides)
: ptr(ptr), itemsize(itemsize), size(1), format(format),
ndim(ndim), shape(shape), strides(strides) {
for (size_t i = 0; i < ndim; ++i)
size *= shape[i];
}

buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t size)
: buffer_info(ptr, itemsize, format, 1, std::vector<size_t> { size },
std::vector<size_t> { itemsize }) { }

explicit buffer_info(Py_buffer *view, bool ownview = true)
: ptr(view->buf), itemsize((size_t) view->itemsize), size(1), format(view->format),
ndim((size_t) view->ndim), shape((size_t) view->ndim), strides((size_t) view->ndim), view(view), ownview(ownview) {
for (size_t i = 0; i < (size_t) view->ndim; ++i) {
shape[i] = (size_t) view->shape[i];
strides[i] = (size_t) view->strides[i];
size *= shape[i];
}
}

buffer_info(const buffer_info &) = delete;
buffer_info& operator=(const buffer_info &) = delete;

buffer_info(buffer_info &&other) {
(*this) = std::move(other);
}

buffer_info& operator=(buffer_info &&rhs) {
ptr = rhs.ptr;
itemsize = rhs.itemsize;
size = rhs.size;
format = std::move(rhs.format);
ndim = rhs.ndim;
shape = std::move(rhs.shape);
strides = std::move(rhs.strides);
std::swap(view, rhs.view);
std::swap(ownview, rhs.ownview);
return *this;
}

~buffer_info() {
if (view && ownview) { PyBuffer_Release(view); delete view; }
}

private:
Py_buffer *view = nullptr;
bool ownview = false;
};

NAMESPACE_BEGIN(detail)

template <typename T, typename SFINAE = void> struct compare_buffer_info {
static bool compare(const buffer_info& b) {
return b.format == format_descriptor<T>::format() && b.itemsize == sizeof(T);
}
};

template <typename T> struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> {
static bool compare(const buffer_info& b) {
return b.itemsize == sizeof(T) && (b.format == format_descriptor<T>::value ||
((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned<T>::value ? "L" : "l")) ||
((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned<T>::value ? "N" : "n")));
}
};

NAMESPACE_END(detail)
NAMESPACE_END(pybind11)
81 changes: 0 additions & 81 deletions include/pybind11/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,69 +286,6 @@ enum class return_value_policy : uint8_t {
reference_internal
};

/// Information record describing a Python buffer object
struct buffer_info {
void *ptr = nullptr; // Pointer to the underlying storage
size_t itemsize = 0; // Size of individual items in bytes
size_t size = 0; // Total number of entries
std::string format; // For homogeneous buffers, this should be set to format_descriptor<T>::format()
size_t ndim = 0; // Number of dimensions
std::vector<size_t> shape; // Shape of the tensor (1 entry per dimension)
std::vector<size_t> strides; // Number of entries between adjacent entries (for each per dimension)

buffer_info() { }

buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t ndim,
const std::vector<size_t> &shape, const std::vector<size_t> &strides)
: ptr(ptr), itemsize(itemsize), size(1), format(format),
ndim(ndim), shape(shape), strides(strides) {
for (size_t i = 0; i < ndim; ++i)
size *= shape[i];
}

buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t size)
: buffer_info(ptr, itemsize, format, 1, std::vector<size_t> { size },
std::vector<size_t> { itemsize }) { }

explicit buffer_info(Py_buffer *view, bool ownview = true)
: ptr(view->buf), itemsize((size_t) view->itemsize), size(1), format(view->format),
ndim((size_t) view->ndim), shape((size_t) view->ndim), strides((size_t) view->ndim), view(view), ownview(ownview) {
for (size_t i = 0; i < (size_t) view->ndim; ++i) {
shape[i] = (size_t) view->shape[i];
strides[i] = (size_t) view->strides[i];
size *= shape[i];
}
}

buffer_info(const buffer_info &) = delete;
buffer_info& operator=(const buffer_info &) = delete;

buffer_info(buffer_info &&other) {
(*this) = std::move(other);
}

buffer_info& operator=(buffer_info &&rhs) {
ptr = rhs.ptr;
itemsize = rhs.itemsize;
size = rhs.size;
format = std::move(rhs.format);
ndim = rhs.ndim;
shape = std::move(rhs.shape);
strides = std::move(rhs.strides);
std::swap(view, rhs.view);
std::swap(ownview, rhs.ownview);
return *this;
}

~buffer_info() {
if (view && ownview) { PyBuffer_Release(view); delete view; }
}

private:
Py_buffer *view = nullptr;
bool ownview = false;
};

NAMESPACE_BEGIN(detail)

inline static constexpr int log2(size_t n, int k = 0) { return (n <= 1) ? k : log2(n >> 1, k + 1); }
Expand Down Expand Up @@ -669,24 +606,6 @@ template <typename T> struct format_descriptor<T, detail::enable_if_t<detail::is
template <typename T> constexpr const char format_descriptor<
T, detail::enable_if_t<detail::is_fmt_numeric<T>::value>>::value[2];

NAMESPACE_BEGIN(detail)

template <typename T, typename SFINAE = void> struct compare_buffer_info {
static bool compare(const buffer_info& b) {
return b.format == format_descriptor<T>::format() && b.itemsize == sizeof(T);
}
};

template <typename T> struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> {
static bool compare(const buffer_info& b) {
return b.itemsize == sizeof(T) && (b.format == format_descriptor<T>::value ||
((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned<T>::value ? "L" : "l")) ||
((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned<T>::value ? "N" : "n")));
}
};

NAMESPACE_END(detail)

/// RAII wrapper that temporarily clears any Python error state
struct error_scope {
PyObject *type, *value, *trace;
Expand Down
1 change: 1 addition & 0 deletions include/pybind11/pytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#pragma once

#include "common.h"
#include "buffer_info.h"
#include <utility>
#include <type_traits>

Expand Down

0 comments on commit 83d1a88

Please sign in to comment.