1/*
2    pybind11/stl.h: Transparent conversion for STL data types
3
4    Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
6    All rights reserved. Use of this source code is governed by a
7    BSD-style license that can be found in the LICENSE file.
8*/
9
10#pragma once
11
12#include "pybind11.h"
13#include <set>
14#include <unordered_set>
15#include <map>
16#include <unordered_map>
17#include <iostream>
18#include <list>
19#include <deque>
20#include <valarray>
21
22#if defined(_MSC_VER)
23#pragma warning(push)
24#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
25#endif
26
27#ifdef __has_include
28// std::optional (but including it in c++14 mode isn't allowed)
29#  if defined(PYBIND11_CPP17) && __has_include(<optional>)
30#    include <optional>
31#    define PYBIND11_HAS_OPTIONAL 1
32#  endif
33// std::experimental::optional (but not allowed in c++11 mode)
34#  if defined(PYBIND11_CPP14) && (__has_include(<experimental/optional>) && \
35                                 !__has_include(<optional>))
36#    include <experimental/optional>
37#    define PYBIND11_HAS_EXP_OPTIONAL 1
38#  endif
39// std::variant
40#  if defined(PYBIND11_CPP17) && __has_include(<variant>)
41#    include <variant>
42#    define PYBIND11_HAS_VARIANT 1
43#  endif
44#elif defined(_MSC_VER) && defined(PYBIND11_CPP17)
45#  include <optional>
46#  include <variant>
47#  define PYBIND11_HAS_OPTIONAL 1
48#  define PYBIND11_HAS_VARIANT 1
49#endif
50
51NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
52NAMESPACE_BEGIN(detail)
53
54/// Extracts an const lvalue reference or rvalue reference for U based on the type of T (e.g. for
55/// forwarding a container element).  Typically used indirect via forwarded_type(), below.
56template <typename T, typename U>
57using forwarded_type = conditional_t<
58    std::is_lvalue_reference<T>::value, remove_reference_t<U> &, remove_reference_t<U> &&>;
59
60/// Forwards a value U as rvalue or lvalue according to whether T is rvalue or lvalue; typically
61/// used for forwarding a container's elements.
62template <typename T, typename U>
63forwarded_type<T, U> forward_like(U &&u) {
64    return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
65}
66
67template <typename Type, typename Key> struct set_caster {
68    using type = Type;
69    using key_conv = make_caster<Key>;
70
71    bool load(handle src, bool convert) {
72        if (!isinstance<pybind11::set>(src))
73            return false;
74        auto s = reinterpret_borrow<pybind11::set>(src);
75        value.clear();
76        for (auto entry : s) {
77            key_conv conv;
78            if (!conv.load(entry, convert))
79                return false;
80            value.insert(cast_op<Key &&>(std::move(conv)));
81        }
82        return true;
83    }
84
85    template <typename T>
86    static handle cast(T &&src, return_value_policy policy, handle parent) {
87        if (!std::is_lvalue_reference<T>::value)
88            policy = return_value_policy_override<Key>::policy(policy);
89        pybind11::set s;
90        for (auto &&value : src) {
91            auto value_ = reinterpret_steal<object>(key_conv::cast(forward_like<T>(value), policy, parent));
92            if (!value_ || !s.add(value_))
93                return handle();
94        }
95        return s.release();
96    }
97
98    PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name + _("]"));
99};
100
101template <typename Type, typename Key, typename Value> struct map_caster {
102    using key_conv   = make_caster<Key>;
103    using value_conv = make_caster<Value>;
104
105    bool load(handle src, bool convert) {
106        if (!isinstance<dict>(src))
107            return false;
108        auto d = reinterpret_borrow<dict>(src);
109        value.clear();
110        for (auto it : d) {
111            key_conv kconv;
112            value_conv vconv;
113            if (!kconv.load(it.first.ptr(), convert) ||
114                !vconv.load(it.second.ptr(), convert))
115                return false;
116            value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv)));
117        }
118        return true;
119    }
120
121    template <typename T>
122    static handle cast(T &&src, return_value_policy policy, handle parent) {
123        dict d;
124        return_value_policy policy_key = policy;
125        return_value_policy policy_value = policy;
126        if (!std::is_lvalue_reference<T>::value) {
127            policy_key = return_value_policy_override<Key>::policy(policy_key);
128            policy_value = return_value_policy_override<Value>::policy(policy_value);
129        }
130        for (auto &&kv : src) {
131            auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy_key, parent));
132            auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy_value, parent));
133            if (!key || !value)
134                return handle();
135            d[key] = value;
136        }
137        return d.release();
138    }
139
140    PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name + _(", ") + value_conv::name + _("]"));
141};
142
143template <typename Type, typename Value> struct list_caster {
144    using value_conv = make_caster<Value>;
145
146    bool load(handle src, bool convert) {
147        if (!isinstance<sequence>(src) || isinstance<str>(src))
148            return false;
149        auto s = reinterpret_borrow<sequence>(src);
150        value.clear();
151        reserve_maybe(s, &value);
152        for (auto it : s) {
153            value_conv conv;
154            if (!conv.load(it, convert))
155                return false;
156            value.push_back(cast_op<Value &&>(std::move(conv)));
157        }
158        return true;
159    }
160
161private:
162    template <typename T = Type,
163              enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0>
164    void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); }
165    void reserve_maybe(sequence, void *) { }
166
167public:
168    template <typename T>
169    static handle cast(T &&src, return_value_policy policy, handle parent) {
170        if (!std::is_lvalue_reference<T>::value)
171            policy = return_value_policy_override<Value>::policy(policy);
172        list l(src.size());
173        size_t index = 0;
174        for (auto &&value : src) {
175            auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));
176            if (!value_)
177                return handle();
178            PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference
179        }
180        return l.release();
181    }
182
183    PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name + _("]"));
184};
185
186template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>>
187 : list_caster<std::vector<Type, Alloc>, Type> { };
188
189template <typename Type, typename Alloc> struct type_caster<std::deque<Type, Alloc>>
190 : list_caster<std::deque<Type, Alloc>, Type> { };
191
192template <typename Type, typename Alloc> struct type_caster<std::list<Type, Alloc>>
193 : list_caster<std::list<Type, Alloc>, Type> { };
194
195template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> struct array_caster {
196    using value_conv = make_caster<Value>;
197
198private:
199    template <bool R = Resizable>
200    bool require_size(enable_if_t<R, size_t> size) {
201        if (value.size() != size)
202            value.resize(size);
203        return true;
204    }
205    template <bool R = Resizable>
206    bool require_size(enable_if_t<!R, size_t> size) {
207        return size == Size;
208    }
209
210public:
211    bool load(handle src, bool convert) {
212        if (!isinstance<sequence>(src))
213            return false;
214        auto l = reinterpret_borrow<sequence>(src);
215        if (!require_size(l.size()))
216            return false;
217        size_t ctr = 0;
218        for (auto it : l) {
219            value_conv conv;
220            if (!conv.load(it, convert))
221                return false;
222            value[ctr++] = cast_op<Value &&>(std::move(conv));
223        }
224        return true;
225    }
226
227    template <typename T>
228    static handle cast(T &&src, return_value_policy policy, handle parent) {
229        list l(src.size());
230        size_t index = 0;
231        for (auto &&value : src) {
232            auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));
233            if (!value_)
234                return handle();
235            PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference
236        }
237        return l.release();
238    }
239
240    PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]"));
241};
242
243template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
244 : array_caster<std::array<Type, Size>, Type, false, Size> { };
245
246template <typename Type> struct type_caster<std::valarray<Type>>
247 : array_caster<std::valarray<Type>, Type, true> { };
248
249template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>>
250  : set_caster<std::set<Key, Compare, Alloc>, Key> { };
251
252template <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
253  : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { };
254
255template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>>
256  : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { };
257
258template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
259  : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { };
260
261// This type caster is intended to be used for std::optional and std::experimental::optional
262template<typename T> struct optional_caster {
263    using value_conv = make_caster<typename T::value_type>;
264
265    template <typename T_>
266    static handle cast(T_ &&src, return_value_policy policy, handle parent) {
267        if (!src)
268            return none().inc_ref();
269        policy = return_value_policy_override<typename T::value_type>::policy(policy);
270        return value_conv::cast(*std::forward<T_>(src), policy, parent);
271    }
272
273    bool load(handle src, bool convert) {
274        if (!src) {
275            return false;
276        } else if (src.is_none()) {
277            return true;  // default-constructed value is already empty
278        }
279        value_conv inner_caster;
280        if (!inner_caster.load(src, convert))
281            return false;
282
283        value.emplace(cast_op<typename T::value_type &&>(std::move(inner_caster)));
284        return true;
285    }
286
287    PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name + _("]"));
288};
289
290#ifdef PYBIND11_HAS_OPTIONAL
291template<typename T> struct type_caster<std::optional<T>>
292    : public optional_caster<std::optional<T>> {};
293
294template<> struct type_caster<std::nullopt_t>
295    : public void_caster<std::nullopt_t> {};
296#endif
297
298#ifdef PYBIND11_HAS_EXP_OPTIONAL
299template<typename T> struct type_caster<std::experimental::optional<T>>
300    : public optional_caster<std::experimental::optional<T>> {};
301
302template<> struct type_caster<std::experimental::nullopt_t>
303    : public void_caster<std::experimental::nullopt_t> {};
304#endif
305
306/// Visit a variant and cast any found type to Python
307struct variant_caster_visitor {
308    return_value_policy policy;
309    handle parent;
310
311    using result_type = handle; // required by boost::variant in C++11
312
313    template <typename T>
314    result_type operator()(T &&src) const {
315        return make_caster<T>::cast(std::forward<T>(src), policy, parent);
316    }
317};
318
319/// Helper class which abstracts away variant's `visit` function. `std::variant` and similar
320/// `namespace::variant` types which provide a `namespace::visit()` function are handled here
321/// automatically using argument-dependent lookup. Users can provide specializations for other
322/// variant-like classes, e.g. `boost::variant` and `boost::apply_visitor`.
323template <template<typename...> class Variant>
324struct visit_helper {
325    template <typename... Args>
326    static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) {
327        return visit(std::forward<Args>(args)...);
328    }
329};
330
331/// Generic variant caster
332template <typename Variant> struct variant_caster;
333
334template <template<typename...> class V, typename... Ts>
335struct variant_caster<V<Ts...>> {
336    static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative.");
337
338    template <typename U, typename... Us>
339    bool load_alternative(handle src, bool convert, type_list<U, Us...>) {
340        auto caster = make_caster<U>();
341        if (caster.load(src, convert)) {
342            value = cast_op<U>(caster);
343            return true;
344        }
345        return load_alternative(src, convert, type_list<Us...>{});
346    }
347
348    bool load_alternative(handle, bool, type_list<>) { return false; }
349
350    bool load(handle src, bool convert) {
351        // Do a first pass without conversions to improve constructor resolution.
352        // E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int`
353        // slot of the variant. Without two-pass loading `double` would be filled
354        // because it appears first and a conversion is possible.
355        if (convert && load_alternative(src, false, type_list<Ts...>{}))
356            return true;
357        return load_alternative(src, convert, type_list<Ts...>{});
358    }
359
360    template <typename Variant>
361    static handle cast(Variant &&src, return_value_policy policy, handle parent) {
362        return visit_helper<V>::call(variant_caster_visitor{policy, parent},
363                                     std::forward<Variant>(src));
364    }
365
366    using Type = V<Ts...>;
367    PYBIND11_TYPE_CASTER(Type, _("Union[") + detail::concat(make_caster<Ts>::name...) + _("]"));
368};
369
370#ifdef PYBIND11_HAS_VARIANT
371template <typename... Ts>
372struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> { };
373#endif
374
375NAMESPACE_END(detail)
376
377inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
378    os << (std::string) str(obj);
379    return os;
380}
381
382NAMESPACE_END(PYBIND11_NAMESPACE)
383
384#if defined(_MSC_VER)
385#pragma warning(pop)
386#endif
387