stl.h 4.38 KB
Newer Older
1
/*
2
    pybind11/complex.h: Complex number support
3
4
5
6
7
8
9
10
11

    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.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

12
#include "pybind11.h"
13
#include <map>
14
#include <set>
15
16
17
18
19
20
21
22
#include <iostream>


#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
#endif

23
NAMESPACE_BEGIN(pybind11)
24
25
NAMESPACE_BEGIN(detail)

26
27
template <typename Value, typename Alloc> struct type_caster<std::vector<Value, Alloc>> {
    typedef std::vector<Value, Alloc> type;
28
29
30
31
32
33
34
35
    typedef type_caster<Value> value_conv;
public:
    bool load(PyObject *src, bool convert) {
        if (!PyList_Check(src))
            return false;
        size_t size = (size_t) PyList_GET_SIZE(src);
        value.reserve(size);
        value.clear();
36
        value_conv conv;
37
38
39
40
41
42
43
44
45
        for (size_t i=0; i<size; ++i) {
            if (!conv.load(PyList_GetItem(src, (ssize_t) i), convert))
                return false;
            value.push_back((Value) conv);
        }
        return true;
    }

    static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
46
47
        object list(PyList_New(src.size()), false);
        if (!list)
48
            return nullptr;
49
50
        size_t index = 0;
        for (auto const &value: src) {
51
52
            object value_ (value_conv::cast(value, policy, parent), false);
            if (!value_)
53
                return nullptr;
54
            PyList_SET_ITEM(list.ptr(), index++, value_.release()); // steals a reference
55
        }
56
        return list.release();
57
    }
58
    PYBIND11_TYPE_CASTER(type, _("list<") + value_conv::name() + _(">"));
59
60
};

61
62
63
template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>> {
    typedef std::set<Key, Compare, Alloc> type;
    typedef type_caster<Key> key_conv;
64
65
66
67
68
69
public:
    bool load(PyObject *src, bool convert) {
        pybind11::set s(src, true);
        if (!s.check())
            return false;
        value.clear();
70
        key_conv conv;
71
72
73
        for (const object &o: s) {
            if (!conv.load((PyObject *) o.ptr(), convert))
                return false;
74
            value.insert((Key) conv);
75
76
77
78
79
        }
        return true;
    }

    static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
80
81
        object set(PySet_New(nullptr), false);
        if (!set)
82
            return nullptr;
83
        for (auto const &value: src) {
84
            object value_(key_conv::cast(value, policy, parent), false);
85
            if (!value_ || PySet_Add(set.ptr(), value_.ptr()) != 0)
86
87
                return nullptr;
        }
88
        return set.release();
89
    }
90
    PYBIND11_TYPE_CASTER(type, _("set<") + key_conv::name() + _(">"));
91
92
93
};

template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>> {
94
public:
95
    typedef std::map<Key, Value, Compare, Alloc>  type;
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
    typedef type_caster<Key>   key_conv;
    typedef type_caster<Value> value_conv;

    bool load(PyObject *src, bool convert) {
        if (!PyDict_Check(src))
            return false;

        value.clear();
        PyObject *key_, *value_;
        ssize_t pos = 0;
        key_conv kconv;
        value_conv vconv;
        while (PyDict_Next(src, &pos, &key_, &value_)) {
            if (!kconv.load(key_, convert) || !vconv.load(value_, convert))
                return false;
111
            value[(Key) kconv] = (Value) vconv;
112
113
114
115
116
        }
        return true;
    }

    static PyObject *cast(const type &src, return_value_policy policy, PyObject *parent) {
117
118
        object dict(PyDict_New(), false);
        if (!dict)
119
            return nullptr;
120
        for (auto const &kv: src) {
121
122
123
            object key(key_conv::cast(kv.first, policy, parent), false);
            object value(value_conv::cast(kv.second, policy, parent), false);
            if (!key || !value || PyDict_SetItem(dict.ptr(), key.ptr(), value.ptr()) != 0)
124
125
                return nullptr;
        }
126
        return dict.release();
127
    }
128

129
    PYBIND11_TYPE_CASTER(type, _("dict<") + key_conv::name() + _(", ") + value_conv::name() + _(">"));
130
131
};

132
133
NAMESPACE_END(detail)

134
inline std::ostream &operator<<(std::ostream &os, const object &obj) { os << (std::string) obj.str(); return os; }
135

136
NAMESPACE_END(pybind11)
137
138
139
140

#if defined(_MSC_VER)
#pragma warning(pop)
#endif