diff --git a/.clang-format b/.clang-format index 8e0fd8b014..2b4ace25af 100644 --- a/.clang-format +++ b/.clang-format @@ -3,17 +3,9 @@ # clang-format --style=llvm --dump-config BasedOnStyle: LLVM AccessModifierOffset: -4 -AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: false -BinPackParameters: false -BreakBeforeBinaryOperators: All -BreakConstructorInitializers: BeforeColon ColumnLimit: 99 -IndentCaseLabels: true -IndentPPDirectives: AfterHash IndentWidth: 4 Language: Cpp -SpaceAfterCStyleCast: true Standard: Cpp11 TabWidth: 4 ... diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 85d575464f..6ace8f75bb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -101,6 +101,19 @@ repos: entry: PyBind|Numpy|Cmake|CCache exclude: .pre-commit-config.yaml +- repo: local + hooks: + - id: docker-clang-format + name: Docker Clang Format + language: docker_image + types: + - c++ + entry: silkeh/clang:12 + args: + - clang-format + - -style=file + - -i + - repo: local hooks: - id: check-style diff --git a/include/pybind11/attr.h b/include/pybind11/attr.h index 97147904ce..cb70e13e5c 100644 --- a/include/pybind11/attr.h +++ b/include/pybind11/attr.h @@ -18,65 +18,86 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) /// @{ /// Annotation for methods -struct is_method { handle class_; is_method(const handle &c) : class_(c) { } }; +struct is_method { + handle class_; + is_method(const handle &c) : class_(c) {} +}; /// Annotation for operators -struct is_operator { }; +struct is_operator {}; /// Annotation for classes that cannot be subclassed -struct is_final { }; +struct is_final {}; /// Annotation for parent scope -struct scope { handle value; scope(const handle &s) : value(s) { } }; +struct scope { + handle value; + scope(const handle &s) : value(s) {} +}; /// Annotation for documentation -struct doc { const char *value; doc(const char *value) : value(value) { } }; +struct doc { + const char *value; + doc(const char *value) : value(value) {} +}; /// Annotation for function names -struct name { const char *value; name(const char *value) : value(value) { } }; +struct name { + const char *value; + name(const char *value) : value(value) {} +}; /// Annotation indicating that a function is an overload associated with a given "sibling" -struct sibling { handle value; sibling(const handle &value) : value(value.ptr()) { } }; +struct sibling { + handle value; + sibling(const handle &value) : value(value.ptr()) {} +}; /// Annotation indicating that a class derives from another given type template struct base { - PYBIND11_DEPRECATED("base() was deprecated in favor of specifying 'T' as a template argument to class_") - base() { } // NOLINT(modernize-use-equals-default): breaks MSVC 2015 when adding an attribute + PYBIND11_DEPRECATED( + "base() was deprecated in favor of specifying 'T' as a template argument to class_") + base() {} // NOLINT(modernize-use-equals-default): breaks MSVC 2015 when adding an attribute }; /// Keep patient alive while nurse lives -template struct keep_alive { }; +template struct keep_alive {}; /// Annotation indicating that a class is involved in a multiple inheritance relationship -struct multiple_inheritance { }; +struct multiple_inheritance {}; /// Annotation which enables dynamic attributes, i.e. adds `__dict__` to a class -struct dynamic_attr { }; +struct dynamic_attr {}; /// Annotation which enables the buffer protocol for a type -struct buffer_protocol { }; +struct buffer_protocol {}; /// Annotation which requests that a special metaclass is created for a type struct metaclass { handle value; PYBIND11_DEPRECATED("py::metaclass() is no longer required. It's turned on by default now.") - metaclass() { } // NOLINT(modernize-use-equals-default): breaks MSVC 2015 when adding an attribute + // NOLINTNEXTLINE(modernize-use-equals-default): breaks MSVC 2015 when adding an attribute + metaclass() {} /// Override pybind11's default metaclass - explicit metaclass(handle value) : value(value) { } + explicit metaclass(handle value) : value(value) {} }; /// Annotation that marks a class as local to the module: -struct module_local { const bool value; constexpr module_local(bool v = true) : value(v) { } }; +struct module_local { + const bool value; + constexpr module_local(bool v = true) : value(v) {} +}; /// Annotation to mark enums as an arithmetic type -struct arithmetic { }; +struct arithmetic {}; /// Mark a function for addition at the beginning of the existing overload chain instead of the end -struct prepend { }; +struct prepend {}; +// clang-format off /** \rst A call policy which places one or more guard variables (``Ts...``) around the function call. @@ -94,21 +115,20 @@ struct prepend { }; T scope_guard; return foo(args...); // forwarded arguments }); - \endrst */ +\endrst */ +// clang-format on template struct call_guard; template <> struct call_guard<> { using type = detail::void_type; }; -template -struct call_guard { +template struct call_guard { static_assert(std::is_default_constructible::value, "The guard type must be default constructible"); using type = T; }; -template -struct call_guard { +template struct call_guard { struct type { T guard{}; // Compose multiple guard types with left-to-right default-constructor order typename call_guard::type next{}; @@ -134,15 +154,16 @@ struct argument_record { bool none : 1; ///< True if None is allowed when loading argument_record(const char *name, const char *descr, handle value, bool convert, bool none) - : name(name), descr(descr), value(value), convert(convert), none(none) { } + : name(name), descr(descr), value(value), convert(convert), none(none) {} }; -/// Internal data structure which holds metadata about a bound function (signature, overloads, etc.) +/// Internal data structure which holds metadata about a bound function (signature, overloads, +/// etc.) struct function_record { function_record() : is_constructor(false), is_new_style_constructor(false), is_stateless(false), - is_operator(false), is_method(false), has_args(false), - has_kwargs(false), has_kw_only_args(false), prepend(false) { } + is_operator(false), is_method(false), has_args(false), has_kwargs(false), + has_kw_only_args(false), prepend(false) {} /// Function name char *name = nullptr; /* why no C++ strings? They generate heavier code.. */ @@ -157,13 +178,13 @@ struct function_record { std::vector args; /// Pointer to lambda function which converts arguments and performs the actual call - handle (*impl) (function_call &) = nullptr; + handle (*impl)(function_call &) = nullptr; /// Storage for the wrapped function pointer and captured data, if any - void *data[3] = { }; + void *data[3] = {}; /// Pointer to custom destructor for 'data' (if needed) - void (*free_data) (function_record *ptr) = nullptr; + void (*free_data)(function_record *ptr) = nullptr; /// Return value policy associated with this function return_value_policy policy = return_value_policy::automatic; @@ -221,7 +242,7 @@ struct function_record { struct type_record { PYBIND11_NOINLINE type_record() : multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false), - default_holder(true), module_local(false), is_final(false) { } + default_holder(true), module_local(false), is_final(false) {} /// Handle to the parent scope handle scope; @@ -290,12 +311,12 @@ struct type_record { std::string tname(base.name()); detail::clean_type_id(tname); pybind11_fail("generic_type: type \"" + std::string(name) + "\" " + - (default_holder ? "does not have" : "has") + - " a non-default holder type while its base \"" + tname + "\" " + - (base_info->default_holder ? "does not" : "does")); + (default_holder ? "does not have" : "has") + + " a non-default holder type while its base \"" + tname + "\" " + + (base_info->default_holder ? "does not" : "does")); } - bases.append((PyObject *) base_info->type); + bases.append((PyObject *)base_info->type); if (base_info->type->tp_dictoffset != 0) dynamic_attr = true; @@ -305,14 +326,13 @@ struct type_record { } }; -inline function_call::function_call(const function_record &f, handle p) : - func(f), parent(p) { +inline function_call::function_call(const function_record &f, handle p) : func(f), parent(p) { args.reserve(f.nargs); args_convert.reserve(f.nargs); } /// Tag for a new-style `__init__` defined in `detail/init.h` -struct is_new_style_constructor { }; +struct is_new_style_constructor {}; /** * Partial template specializations to process custom attributes provided to @@ -324,10 +344,10 @@ template struct process_attribute; template struct process_attribute_default { /// Default implementation: do nothing - static void init(const T &, function_record *) { } - static void init(const T &, type_record *) { } - static void precall(function_call &) { } - static void postcall(function_call &, handle) { } + static void init(const T &, function_record *) {} + static void init(const T &, type_record *) {} + static void precall(function_call &) {} + static void postcall(function_call &, handle) {} }; /// Process an attribute specifying the function's name @@ -345,21 +365,26 @@ template <> struct process_attribute : process_attribute_defaultdoc = const_cast(d); } static void init(const char *d, type_record *r) { r->doc = const_cast(d); } }; -template <> struct process_attribute : process_attribute { }; +template <> struct process_attribute : process_attribute {}; /// Process an attribute indicating the function's return value policy -template <> struct process_attribute : process_attribute_default { +template <> +struct process_attribute : process_attribute_default { static void init(const return_value_policy &p, function_record *r) { r->policy = p; } }; -/// Process an attribute which indicates that this is an overloaded function associated with a given sibling +/// Process an attribute which indicates that this is an overloaded function associated with a +/// given sibling template <> struct process_attribute : process_attribute_default { static void init(const sibling &s, function_record *r) { r->sibling = s.value; } }; /// Process an attribute which indicates that this function is a method template <> struct process_attribute : process_attribute_default { - static void init(const is_method &s, function_record *r) { r->is_method = true; r->scope = s.class_; } + static void init(const is_method &s, function_record *r) { + r->is_method = true; + r->scope = s.class_; + } }; /// Process an attribute which indicates the parent scope of a method @@ -372,8 +397,12 @@ template <> struct process_attribute : process_attribute_defaultis_operator = true; } }; -template <> struct process_attribute : process_attribute_default { - static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; } +template <> +struct process_attribute + : process_attribute_default { + static void init(const is_new_style_constructor &, function_record *r) { + r->is_new_style_constructor = true; + } }; inline void process_kw_only_arg(const arg &a, function_record *r) { @@ -386,10 +415,12 @@ inline void process_kw_only_arg(const arg &a, function_record *r) { template <> struct process_attribute : process_attribute_default { static void init(const arg &a, function_record *r) { if (r->is_method && r->args.empty()) - r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/); + r->args.emplace_back("self", nullptr, handle(), true /*convert*/, + false /*none not allowed*/); r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none); - if (r->has_kw_only_args) process_kw_only_arg(a, r); + if (r->has_kw_only_args) + process_kw_only_arg(a, r); } }; @@ -397,23 +428,26 @@ template <> struct process_attribute : process_attribute_default { template <> struct process_attribute : process_attribute_default { static void init(const arg_v &a, function_record *r) { if (r->is_method && r->args.empty()) - r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/, false /*none not allowed*/); + r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/, + false /*none not allowed*/); if (!a.value) { #if !defined(NDEBUG) std::string descr("'"); - if (a.name) descr += std::string(a.name) + ": "; + if (a.name) + descr += std::string(a.name) + ": "; descr += a.type + "'"; if (r->is_method) { if (r->name) - descr += " in method '" + (std::string) str(r->scope) + "." + (std::string) r->name + "'"; + descr += " in method '" + (std::string)str(r->scope) + "." + + (std::string)r->name + "'"; else - descr += " in method of '" + (std::string) str(r->scope) + "'"; + descr += " in method of '" + (std::string)str(r->scope) + "'"; } else if (r->name) { - descr += " in function '" + (std::string) r->name + "'"; + descr += " in function '" + (std::string)r->name + "'"; } - pybind11_fail("arg(): could not convert default argument " - + descr + " into a Python object (type not registered yet?)"); + pybind11_fail("arg(): could not convert default argument " + descr + + " into a Python object (type not registered yet?)"); #else pybind11_fail("arg(): could not convert default argument " "into a Python object (type not registered yet?). " @@ -422,15 +456,14 @@ template <> struct process_attribute : process_attribute_default { } r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none); - if (r->has_kw_only_args) process_kw_only_arg(a, r); + if (r->has_kw_only_args) + process_kw_only_arg(a, r); } }; /// Process a keyword-only-arguments-follow pseudo argument template <> struct process_attribute : process_attribute_default { - static void init(const kw_only &, function_record *r) { - r->has_kw_only_args = true; - } + static void init(const kw_only &, function_record *r) { r->has_kw_only_args = true; } }; /// Process a positional-only-argument maker @@ -440,31 +473,32 @@ template <> struct process_attribute : process_attribute_default -struct process_attribute::value>> : process_attribute_default { +struct process_attribute::value>> + : process_attribute_default { static void init(const handle &h, type_record *r) { r->bases.append(h); } }; /// Process a parent class attribute (deprecated, does not support multiple inheritance) -template -struct process_attribute> : process_attribute_default> { +template struct process_attribute> : process_attribute_default> { static void init(const base &, type_record *r) { r->add_base(typeid(T), nullptr); } }; /// Process a multiple inheritance attribute template <> struct process_attribute : process_attribute_default { - static void init(const multiple_inheritance &, type_record *r) { r->multiple_inheritance = true; } + static void init(const multiple_inheritance &, type_record *r) { + r->multiple_inheritance = true; + } }; -template <> -struct process_attribute : process_attribute_default { +template <> struct process_attribute : process_attribute_default { static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; } }; -template <> -struct process_attribute : process_attribute_default { +template <> struct process_attribute : process_attribute_default { static void init(const is_final &, type_record *r) { r->is_final = true; } }; @@ -473,76 +507,80 @@ struct process_attribute : process_attribute_defaultbuffer_protocol = true; } }; -template <> -struct process_attribute : process_attribute_default { +template <> struct process_attribute : process_attribute_default { static void init(const metaclass &m, type_record *r) { r->metaclass = m.value; } }; -template <> -struct process_attribute : process_attribute_default { +template <> struct process_attribute : process_attribute_default { static void init(const module_local &l, type_record *r) { r->module_local = l.value; } }; /// Process a 'prepend' attribute, putting this at the beginning of the overload chain -template <> -struct process_attribute : process_attribute_default { +template <> struct process_attribute : process_attribute_default { static void init(const prepend &, function_record *r) { r->prepend = true; } }; /// Process an 'arithmetic' attribute for enums (does nothing here) -template <> -struct process_attribute : process_attribute_default {}; +template <> struct process_attribute : process_attribute_default {}; template -struct process_attribute> : process_attribute_default> { }; +struct process_attribute> : process_attribute_default> {}; /** * Process a keep_alive call policy -- invokes keep_alive_impl during the * pre-call handler if both Nurse, Patient != 0 and use the post-call handler * otherwise */ -template struct process_attribute> : public process_attribute_default> { +template +struct process_attribute> + : public process_attribute_default> { template = 0> - static void precall(function_call &call) { keep_alive_impl(Nurse, Patient, call, handle()); } + static void precall(function_call &call) { + keep_alive_impl(Nurse, Patient, call, handle()); + } template = 0> - static void postcall(function_call &, handle) { } + static void postcall(function_call &, handle) {} template = 0> - static void precall(function_call &) { } + static void precall(function_call &) {} template = 0> - static void postcall(function_call &call, handle ret) { keep_alive_impl(Nurse, Patient, call, ret); } + static void postcall(function_call &call, handle ret) { + keep_alive_impl(Nurse, Patient, call, ret); + } }; /// Recursively iterate over variadic template arguments template struct process_attributes { - static void init(const Args&... args, function_record *r) { - int unused[] = { 0, (process_attribute::type>::init(args, r), 0) ... }; + static void init(const Args &...args, function_record *r) { + int unused[] = {0, + (process_attribute::type>::init(args, r), 0)...}; ignore_unused(unused); } - static void init(const Args&... args, type_record *r) { - int unused[] = { 0, (process_attribute::type>::init(args, r), 0) ... }; + static void init(const Args &...args, type_record *r) { + int unused[] = {0, + (process_attribute::type>::init(args, r), 0)...}; ignore_unused(unused); } static void precall(function_call &call) { - int unused[] = { 0, (process_attribute::type>::precall(call), 0) ... }; + int unused[] = {0, + (process_attribute::type>::precall(call), 0)...}; ignore_unused(unused); } static void postcall(function_call &call, handle fn_ret) { - int unused[] = { 0, (process_attribute::type>::postcall(call, fn_ret), 0) ... }; + int unused[] = { + 0, (process_attribute::type>::postcall(call, fn_ret), 0)...}; ignore_unused(unused); } }; -template -using is_call_guard = is_instantiation; +template using is_call_guard = is_instantiation; /// Extract the ``type`` from the first `call_guard` in `Extras...` (or `void_type` if none found) template using extract_guard_t = typename exactly_one_t, Extra...>::type; /// Check the number of named arguments at compile time -template ::value...), - size_t self = constexpr_sum(std::is_same::value...)> +template ::value...), + size_t self = constexpr_sum(std::is_same::value...)> constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) { return named == 0 || (self + named + size_t(has_args) + size_t(has_kwargs)) == nargs; } diff --git a/include/pybind11/buffer_info.h b/include/pybind11/buffer_info.h index 47dc39d4ea..8ca681cbfd 100644 --- a/include/pybind11/buffer_info.h +++ b/include/pybind11/buffer_info.h @@ -38,58 +38,67 @@ PYBIND11_NAMESPACE_END(detail) /// Information record describing a Python buffer object struct buffer_info { - void *ptr = nullptr; // Pointer to the underlying storage - ssize_t itemsize = 0; // Size of individual items in bytes - ssize_t size = 0; // Total number of entries - std::string format; // For homogeneous buffers, this should be set to format_descriptor::format() - ssize_t ndim = 0; // Number of dimensions - std::vector shape; // Shape of the tensor (1 entry per dimension) - std::vector strides; // Number of bytes between adjacent entries (for each per dimension) - bool readonly = false; // flag to indicate if the underlying storage may be written to + void *ptr = nullptr; // Pointer to the underlying storage + ssize_t itemsize = 0; // Size of individual items in bytes + ssize_t size = 0; // Total number of entries + std::string + format; // For homogeneous buffers, this should be set to format_descriptor::format() + ssize_t ndim = 0; // Number of dimensions + std::vector shape; // Shape of the tensor (1 entry per dimension) + std::vector + strides; // Number of bytes between adjacent entries (for each per dimension) + bool readonly = false; // flag to indicate if the underlying storage may be written to buffer_info() = default; buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim, - detail::any_container shape_in, detail::any_container strides_in, bool readonly=false) - : ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim), - shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) { - if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size()) + detail::any_container shape_in, detail::any_container strides_in, + bool readonly = false) + : ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim), + shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) { + if (ndim != (ssize_t)shape.size() || ndim != (ssize_t)strides.size()) pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length"); - for (size_t i = 0; i < (size_t) ndim; ++i) + for (size_t i = 0; i < (size_t)ndim; ++i) size *= shape[i]; } template - buffer_info(T *ptr, detail::any_container shape_in, detail::any_container strides_in, bool readonly=false) - : buffer_info(private_ctr_tag(), ptr, sizeof(T), format_descriptor::format(), static_cast(shape_in->size()), std::move(shape_in), std::move(strides_in), readonly) { } + buffer_info(T *ptr, detail::any_container shape_in, + detail::any_container strides_in, bool readonly = false) + : buffer_info(private_ctr_tag(), ptr, sizeof(T), format_descriptor::format(), + static_cast(shape_in->size()), std::move(shape_in), + std::move(strides_in), readonly) {} - buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size, bool readonly=false) - : buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}, readonly) { } + buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size, + bool readonly = false) + : buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}, readonly) {} template - buffer_info(T *ptr, ssize_t size, bool readonly=false) - : buffer_info(ptr, sizeof(T), format_descriptor::format(), size, readonly) { } + buffer_info(T *ptr, ssize_t size, bool readonly = false) + : buffer_info(ptr, sizeof(T), format_descriptor::format(), size, readonly) {} template - buffer_info(const T *ptr, ssize_t size, bool readonly=true) - : buffer_info(const_cast(ptr), sizeof(T), format_descriptor::format(), size, readonly) { } + buffer_info(const T *ptr, ssize_t size, bool readonly = true) + : buffer_info(const_cast(ptr), sizeof(T), format_descriptor::format(), size, + readonly) {} explicit buffer_info(Py_buffer *view, bool ownview = true) - : buffer_info(view->buf, view->itemsize, view->format, view->ndim, - {view->shape, view->shape + view->ndim}, - /* Though buffer::request() requests PyBUF_STRIDES, ctypes objects - * ignore this flag and return a view with NULL strides. - * When strides are NULL, build them manually. */ - view->strides - ? std::vector(view->strides, view->strides + view->ndim) - : detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize), - view->readonly) { + : buffer_info( + view->buf, view->itemsize, view->format, view->ndim, + {view->shape, view->shape + view->ndim}, + /* Though buffer::request() requests PyBUF_STRIDES, ctypes objects + * ignore this flag and return a view with NULL strides. + * When strides are NULL, build them manually. */ + view->strides + ? std::vector(view->strides, view->strides + view->ndim) + : detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize), + view->readonly) { this->m_view = view; this->ownview = ownview; } buffer_info(const buffer_info &) = delete; - buffer_info& operator=(const buffer_info &) = delete; + buffer_info &operator=(const buffer_info &) = delete; buffer_info(buffer_info &&other) noexcept { (*this) = std::move(other); } @@ -108,17 +117,23 @@ struct buffer_info { } ~buffer_info() { - if (m_view && ownview) { PyBuffer_Release(m_view); delete m_view; } + if (m_view && ownview) { + PyBuffer_Release(m_view); + delete m_view; + } } Py_buffer *view() const { return m_view; } Py_buffer *&view() { return m_view; } + private: - struct private_ctr_tag { }; + struct private_ctr_tag {}; - buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim, - detail::any_container &&shape_in, detail::any_container &&strides_in, bool readonly) - : buffer_info(ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), readonly) { } + buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, + ssize_t ndim, detail::any_container &&shape_in, + detail::any_container &&strides_in, bool readonly) + : buffer_info(ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), + readonly) {} Py_buffer *m_view = nullptr; bool ownview = false; @@ -127,16 +142,20 @@ struct buffer_info { PYBIND11_NAMESPACE_BEGIN(detail) template struct compare_buffer_info { - static bool compare(const buffer_info& b) { - return b.format == format_descriptor::format() && b.itemsize == (ssize_t) sizeof(T); + static bool compare(const buffer_info &b) { + return b.format == format_descriptor::format() && b.itemsize == (ssize_t)sizeof(T); } }; -template struct compare_buffer_info::value>> { - static bool compare(const buffer_info& b) { - return (size_t) b.itemsize == sizeof(T) && (b.format == format_descriptor::value || - ((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned::value ? "L" : "l")) || - ((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned::value ? "N" : "n"))); +template +struct compare_buffer_info::value>> { + static bool compare(const buffer_info &b) { + return (size_t)b.itemsize == sizeof(T) && + (b.format == format_descriptor::value || + ((sizeof(T) == sizeof(long)) && + b.format == (std::is_unsigned::value ? "L" : "l")) || + ((sizeof(T) == sizeof(size_t)) && + b.format == (std::is_unsigned::value ? "N" : "n"))); } }; diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index a748c77c0f..19ef96cbd8 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -10,11 +10,11 @@ #pragma once -#include "pytypes.h" #include "detail/common.h" #include "detail/descr.h" #include "detail/type_caster_base.h" #include "detail/typeid.h" +#include "pytypes.h" #include #include #include @@ -28,56 +28,62 @@ #include #if defined(PYBIND11_CPP17) -# if defined(__has_include) -# if __has_include() -# define PYBIND11_HAS_STRING_VIEW -# endif -# elif defined(_MSC_VER) -# define PYBIND11_HAS_STRING_VIEW -# endif +#if defined(__has_include) +#if __has_include() +#define PYBIND11_HAS_STRING_VIEW +#endif +#elif defined(_MSC_VER) +#define PYBIND11_HAS_STRING_VIEW +#endif #endif #ifdef PYBIND11_HAS_STRING_VIEW #include #endif #if defined(__cpp_lib_char8_t) && __cpp_lib_char8_t >= 201811L -# define PYBIND11_HAS_U8STRING +#define PYBIND11_HAS_U8STRING #endif PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) -template class type_caster : public type_caster_base { }; +template +class type_caster : public type_caster_base {}; template using make_caster = type_caster>; // Shortcut for calling a caster's `cast_op_type` cast operator for casting a type_caster to a T -template typename make_caster::template cast_op_type cast_op(make_caster &caster) { +template +typename make_caster::template cast_op_type cast_op(make_caster &caster) { return caster.operator typename make_caster::template cast_op_type(); } -template typename make_caster::template cast_op_type::type> +template +typename make_caster::template cast_op_type::type> cast_op(make_caster &&caster) { - return std::move(caster).operator - typename make_caster::template cast_op_type::type>(); + return std::move(caster).operator typename make_caster:: + template cast_op_type::type>(); } template class type_caster> { private: using caster_t = make_caster; caster_t subcaster; - using reference_t = type&; - using subcaster_cast_op_type = - typename caster_t::template cast_op_type; - - static_assert(std::is_same::type &, subcaster_cast_op_type>::value || - std::is_same::value, - "std::reference_wrapper caster requires T to have a caster with an " - "`operator T &()` or `operator const T &()`"); + using reference_t = type &; + using subcaster_cast_op_type = typename caster_t::template cast_op_type; + + static_assert( + std::is_same::type &, subcaster_cast_op_type>::value || + std::is_same::value, + "std::reference_wrapper caster requires T to have a caster with an " + "`operator T &()` or `operator const T &()`"); + public: bool load(handle src, bool convert) { return subcaster.load(src, convert); } static constexpr auto name = caster_t::name; - static handle cast(const std::reference_wrapper &src, return_value_policy policy, handle parent) { + static handle cast(const std::reference_wrapper &src, return_value_policy policy, + handle parent) { // It is definitely wrong to take ownership of this pointer, so mask that rvp - if (policy == return_value_policy::take_ownership || policy == return_value_policy::automatic) + if (policy == return_value_policy::take_ownership || + policy == return_value_policy::automatic) policy = return_value_policy::automatic_reference; return caster_t::cast(&src.get(), policy, parent); } @@ -105,27 +111,26 @@ public: operator type *() { return &value; } \ operator type &() { return value; } \ operator type &&() && { return std::move(value); } \ - template \ - using cast_op_type = pybind11::detail::movable_cast_op_type + template using cast_op_type = pybind11::detail::movable_cast_op_type -template using is_std_char_type = any_of< - std::is_same, /* std::string */ +template +using is_std_char_type = any_of, /* std::string */ #if defined(PYBIND11_HAS_U8STRING) - std::is_same, /* std::u8string */ + std::is_same, /* std::u8string */ #endif - std::is_same, /* std::u16string */ - std::is_same, /* std::u32string */ - std::is_same /* std::wstring */ ->; - + std::is_same, /* std::u16string */ + std::is_same, /* std::u32string */ + std::is_same /* std::wstring */ + >; template struct type_caster::value && !is_std_char_type::value>> { using _py_type_0 = conditional_t; - using _py_type_1 = conditional_t::value, _py_type_0, typename std::make_unsigned<_py_type_0>::type>; + using _py_type_1 = conditional_t::value, _py_type_0, + typename std::make_unsigned<_py_type_0>::type>; using py_type = conditional_t::value, double, _py_type_1>; -public: +public: bool load(handle src, bool convert) { py_type py_value; @@ -142,7 +147,7 @@ struct type_caster::value && !is_std_char_t if (std::is_floating_point::value) { if (convert || PyFloat_Check(src.ptr())) - py_value = (py_type) PyFloat_AsDouble(src.ptr()); + py_value = (py_type)PyFloat_AsDouble(src.ptr()); else return false; } else if (PyFloat_Check(src.ptr())) { @@ -153,14 +158,13 @@ struct type_caster::value && !is_std_char_t handle src_or_index = src; #if PY_VERSION_HEX < 0x03080000 object index; - if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr()) + if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr()) index = reinterpret_steal(PyNumber_Index(src.ptr())); if (!index) { PyErr_Clear(); if (!convert) return false; - } - else { + } else { src_or_index = index; } } @@ -169,66 +173,77 @@ struct type_caster::value && !is_std_char_t py_value = as_unsigned(src_or_index.ptr()); } else { // signed integer: py_value = sizeof(T) <= sizeof(long) - ? (py_type) PyLong_AsLong(src_or_index.ptr()) - : (py_type) PYBIND11_LONG_AS_LONGLONG(src_or_index.ptr()); + ? (py_type)PyLong_AsLong(src_or_index.ptr()) + : (py_type)PYBIND11_LONG_AS_LONGLONG(src_or_index.ptr()); } } // Python API reported an error - bool py_err = py_value == (py_type) -1 && PyErr_Occurred(); + bool py_err = py_value == (py_type)-1 && PyErr_Occurred(); // Check to see if the conversion is valid (integers should match exactly) // Signed/unsigned checks happen elsewhere - if (py_err || (std::is_integral::value && sizeof(py_type) != sizeof(T) && py_value != (py_type) (T) py_value)) { + if (py_err || (std::is_integral::value && sizeof(py_type) != sizeof(T) && + py_value != (py_type)(T)py_value)) { PyErr_Clear(); if (py_err && convert && PyNumber_Check(src.ptr())) { auto tmp = reinterpret_steal(std::is_floating_point::value - ? PyNumber_Float(src.ptr()) - : PyNumber_Long(src.ptr())); + ? PyNumber_Float(src.ptr()) + : PyNumber_Long(src.ptr())); PyErr_Clear(); return load(tmp, false); } return false; } - value = (T) py_value; + value = (T)py_value; return true; } - template + template static typename std::enable_if::value, handle>::type cast(U src, return_value_policy /* policy */, handle /* parent */) { - return PyFloat_FromDouble((double) src); + return PyFloat_FromDouble((double)src); } - template - static typename std::enable_if::value && std::is_signed::value && (sizeof(U) <= sizeof(long)), handle>::type + template + static typename std::enable_if::value && std::is_signed::value && + (sizeof(U) <= sizeof(long)), + handle>::type cast(U src, return_value_policy /* policy */, handle /* parent */) { - return PYBIND11_LONG_FROM_SIGNED((long) src); + return PYBIND11_LONG_FROM_SIGNED((long)src); } - template - static typename std::enable_if::value && std::is_unsigned::value && (sizeof(U) <= sizeof(unsigned long)), handle>::type - cast(U src, return_value_policy /* policy */, handle /* parent */) { - return PYBIND11_LONG_FROM_UNSIGNED((unsigned long) src); + template + static + typename std::enable_if::value && std::is_unsigned::value && + (sizeof(U) <= sizeof(unsigned long)), + handle>::type + cast(U src, return_value_policy /* policy */, handle /* parent */) { + return PYBIND11_LONG_FROM_UNSIGNED((unsigned long)src); } - template - static typename std::enable_if::value && std::is_signed::value && (sizeof(U) > sizeof(long)), handle>::type + template + static typename std::enable_if::value && std::is_signed::value && + (sizeof(U) > sizeof(long)), + handle>::type cast(U src, return_value_policy /* policy */, handle /* parent */) { - return PyLong_FromLongLong((long long) src); + return PyLong_FromLongLong((long long)src); } - template - static typename std::enable_if::value && std::is_unsigned::value && (sizeof(U) > sizeof(unsigned long)), handle>::type - cast(U src, return_value_policy /* policy */, handle /* parent */) { - return PyLong_FromUnsignedLongLong((unsigned long long) src); + template + static + typename std::enable_if::value && std::is_unsigned::value && + (sizeof(U) > sizeof(unsigned long)), + handle>::type + cast(U src, return_value_policy /* policy */, handle /* parent */) { + return PyLong_FromUnsignedLongLong((unsigned long long)src); } PYBIND11_TYPE_CASTER(T, _::value>("int", "float")); }; -template struct void_caster { +template struct void_caster { public: bool load(handle src, bool) { if (src && src.is_none()) @@ -263,7 +278,7 @@ template <> class type_caster : public type_caster { } /* Check if this is a C++ type */ - auto &bases = all_type_info((PyTypeObject *) type::handle_of(h).ptr()); + auto &bases = all_type_info((PyTypeObject *)type::handle_of(h).ptr()); if (bases.size() == 1) { // Only allowing loading from a single-value type value = values_and_holders(reinterpret_cast(h.ptr())).begin()->value_ptr(); return true; @@ -279,19 +294,21 @@ template <> class type_caster : public type_caster { return none().inc_ref(); } - template using cast_op_type = void*&; + template using cast_op_type = void *&; operator void *&() { return value; } static constexpr auto name = _("capsule"); + private: void *value = nullptr; }; -template <> class type_caster : public void_caster { }; +template <> class type_caster : public void_caster {}; template <> class type_caster { public: bool load(handle src, bool convert) { - if (!src) return false; + if (!src) + return false; if (src.ptr() == Py_True) { value = true; return true; @@ -305,14 +322,14 @@ template <> class type_caster { Py_ssize_t res = -1; if (src.is_none()) { - res = 0; // None is implicitly converted to False + res = 0; // None is implicitly converted to False } - #if defined(PYPY_VERSION) +#if defined(PYPY_VERSION) // On PyPy, check that "__bool__" (or "__nonzero__" on Python 2.7) attr exists else if (hasattr(src, PYBIND11_BOOL_ATTR)) { res = PyObject_IsTrue(src.ptr()); } - #else +#else // Alternate approach for CPython: this does the same as the above, but optimized // using the CPython API so as to avoid an unneeded attribute lookup. else if (auto tp_as_number = src.ptr()->ob_type->tp_as_number) { @@ -320,9 +337,9 @@ template <> class type_caster { res = (*PYBIND11_NB_BOOL(tp_as_number))(src.ptr()); } } - #endif +#endif if (res == 0 || res == 1) { - value = (bool) res; + value = (bool)res; return true; } PyErr_Clear(); @@ -341,15 +358,19 @@ template struct string_caster { // Simplify life by being able to assume standard char sizes (the standard only guarantees // minimums, but Python requires exact sizes) - static_assert(!std::is_same::value || sizeof(CharT) == 1, "Unsupported char size != 1"); + static_assert(!std::is_same::value || sizeof(CharT) == 1, + "Unsupported char size != 1"); #if defined(PYBIND11_HAS_U8STRING) - static_assert(!std::is_same::value || sizeof(CharT) == 1, "Unsupported char8_t size != 1"); + static_assert(!std::is_same::value || sizeof(CharT) == 1, + "Unsupported char8_t size != 1"); #endif - static_assert(!std::is_same::value || sizeof(CharT) == 2, "Unsupported char16_t size != 2"); - static_assert(!std::is_same::value || sizeof(CharT) == 4, "Unsupported char32_t size != 4"); + static_assert(!std::is_same::value || sizeof(CharT) == 2, + "Unsupported char16_t size != 2"); + static_assert(!std::is_same::value || sizeof(CharT) == 4, + "Unsupported char32_t size != 4"); // wchar_t can be either 16 bits (Windows) or 32 (everywhere else) static_assert(!std::is_same::value || sizeof(CharT) == 2 || sizeof(CharT) == 4, - "Unsupported wchar_t size != 2/4"); + "Unsupported wchar_t size != 2/4"); static constexpr size_t UTF_N = 8 * sizeof(CharT); bool load(handle src, bool) { @@ -373,18 +394,32 @@ template struct string_caster { return false; temp = reinterpret_steal(PyUnicode_FromObject(load_src.ptr())); - if (!temp) { PyErr_Clear(); return false; } + if (!temp) { + PyErr_Clear(); + return false; + } load_src = temp; #endif } - auto utfNbytes = reinterpret_steal(PyUnicode_AsEncodedString( - load_src.ptr(), UTF_N == 8 ? "utf-8" : UTF_N == 16 ? "utf-16" : "utf-32", nullptr)); - if (!utfNbytes) { PyErr_Clear(); return false; } + auto utfNbytes = + reinterpret_steal(PyUnicode_AsEncodedString(load_src.ptr(), + UTF_N == 8 ? "utf-8" + : UTF_N == 16 ? "utf-16" + : "utf-32", + nullptr)); + if (!utfNbytes) { + PyErr_Clear(); + return false; + } - const auto *buffer = reinterpret_cast(PYBIND11_BYTES_AS_STRING(utfNbytes.ptr())); - size_t length = (size_t) PYBIND11_BYTES_SIZE(utfNbytes.ptr()) / sizeof(CharT); - if (UTF_N > 8) { buffer++; length--; } // Skip BOM for UTF-16/32 + const auto *buffer = + reinterpret_cast(PYBIND11_BYTES_AS_STRING(utfNbytes.ptr())); + size_t length = (size_t)PYBIND11_BYTES_SIZE(utfNbytes.ptr()) / sizeof(CharT); + if (UTF_N > 8) { + buffer++; + length--; + } // Skip BOM for UTF-16/32 value = StringType(buffer, length); // If we're loading a string_view we need to keep the encoded Python object alive: @@ -394,11 +429,13 @@ template struct string_caster { return true; } - static handle cast(const StringType &src, return_value_policy /* policy */, handle /* parent */) { + static handle cast(const StringType &src, return_value_policy /* policy */, + handle /* parent */) { const char *buffer = reinterpret_cast(src.data()); auto nbytes = ssize_t(src.size() * sizeof(CharT)); handle s = decode_utfN(buffer, nbytes); - if (!s) throw error_already_set(); + if (!s) + throw error_already_set(); return s; } @@ -407,14 +444,18 @@ template struct string_caster { private: static handle decode_utfN(const char *buffer, ssize_t nbytes) { #if !defined(PYPY_VERSION) - return - UTF_N == 8 ? PyUnicode_DecodeUTF8(buffer, nbytes, nullptr) : - UTF_N == 16 ? PyUnicode_DecodeUTF16(buffer, nbytes, nullptr, nullptr) : - PyUnicode_DecodeUTF32(buffer, nbytes, nullptr, nullptr); + return UTF_N == 8 ? PyUnicode_DecodeUTF8(buffer, nbytes, nullptr) + : UTF_N == 16 ? PyUnicode_DecodeUTF16(buffer, nbytes, nullptr, nullptr) + : PyUnicode_DecodeUTF32(buffer, nbytes, nullptr, nullptr); #else - // PyPy segfaults when on PyUnicode_DecodeUTF16 (and possibly on PyUnicode_DecodeUTF32 as well), - // so bypass the whole thing by just passing the encoding as a string value, which works properly: - return PyUnicode_Decode(buffer, nbytes, UTF_N == 8 ? "utf-8" : UTF_N == 16 ? "utf-16" : "utf-32", nullptr); + // PyPy segfaults when on PyUnicode_DecodeUTF16 (and possibly on PyUnicode_DecodeUTF32 as + // well), so bypass the whole thing by just passing the encoding as a string value, which + // works properly: + return PyUnicode_Decode(buffer, nbytes, + UTF_N == 8 ? "utf-8" + : UTF_N == 16 ? "utf-16" + : "utf-32", + nullptr); #endif } @@ -428,7 +469,7 @@ template struct string_caster { // without any encoding attempt. const char *bytes = PYBIND11_BYTES_AS_STRING(src.ptr()); if (bytes) { - value = StringType(bytes, (size_t) PYBIND11_BYTES_SIZE(src.ptr())); + value = StringType(bytes, (size_t)PYBIND11_BYTES_SIZE(src.ptr())); return true; } } @@ -437,16 +478,20 @@ template struct string_caster { } template - bool load_bytes(enable_if_t::value, handle>) { return false; } + bool load_bytes(enable_if_t::value, handle>) { + return false; + } }; template -struct type_caster, enable_if_t::value>> +struct type_caster, + enable_if_t::value>> : string_caster> {}; #ifdef PYBIND11_HAS_STRING_VIEW template -struct type_caster, enable_if_t::value>> +struct type_caster, + enable_if_t::value>> : string_caster, true> {}; #endif @@ -458,12 +503,15 @@ template struct type_caster struct type_caster::value) { - handle s = PyUnicode_DecodeLatin1((const char *) &src, 1, nullptr); - if (!s) throw error_already_set(); + handle s = PyUnicode_DecodeLatin1((const char *)&src, 1, nullptr); + if (!s) + throw error_already_set(); return s; } return StringCaster::cast(StringType(1, src), policy, parent); } - operator CharT*() { return none ? nullptr : const_cast(static_cast(str_caster).c_str()); } - operator CharT&() { + operator CharT *() { + return none ? nullptr : const_cast(static_cast(str_caster).c_str()); + } + operator CharT &() { if (none) throw value_error("Cannot convert None to a character"); @@ -495,21 +547,24 @@ template struct type_caster 1 && str_len <= 4) { auto v0 = static_cast(value[0]); size_t char0_bytes = !(v0 & 0x80) ? 1 : // low bits only: 0-127 - (v0 & 0xE0) == 0xC0 ? 2 : // 0b110xxxxx - start of 2-byte sequence - (v0 & 0xF0) == 0xE0 ? 3 : // 0b1110xxxx - start of 3-byte sequence - 4; // 0b11110xxx - start of 4-byte sequence + (v0 & 0xE0) == 0xC0 ? 2 + : // 0b110xxxxx - start of 2-byte sequence + (v0 & 0xF0) == 0xE0 ? 3 + : // 0b1110xxxx - start of 3-byte sequence + 4; // 0b11110xxx - start of 4-byte sequence if (char0_bytes == str_len) { // If we have a 128-255 value, we can decode it into a single char: if (char0_bytes == 2 && (v0 & 0xFC) == 0xC0) { // 0x110000xx 0x10xxxxxx - one_char = static_cast(((v0 & 3) << 6) + (static_cast(value[1]) & 0x3F)); + one_char = static_cast(((v0 & 3) << 6) + + (static_cast(value[1]) & 0x3F)); return one_char; } // Otherwise we have a single character, but it's > U+00FF @@ -538,12 +593,12 @@ template struct type_caster class Tuple, typename... Ts> class tuple_caster { +template