Skip to content

Commit 55dff4d

Browse files
committed
slicing
[SVN r14219]
1 parent 693b211 commit 55dff4d

File tree

13 files changed

+549
-78
lines changed

13 files changed

+549
-78
lines changed

include/boost/python/converter/object_manager.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ class object;
2121
namespace boost { namespace python { namespace converter {
2222

2323
template <class T>
24-
class is_object_manager
24+
struct is_object_manager
2525
{
26+
private:
2627
BOOST_STATIC_CONSTANT(bool, hdl = is_handle<T>::value);
2728
BOOST_STATIC_CONSTANT(bool, borrowed = python::detail::is_borrowed_ptr<T>::value);
2829
public:

include/boost/python/object.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# include <boost/python/object_core.hpp>
1010
# include <boost/python/object_attributes.hpp>
1111
# include <boost/python/object_items.hpp>
12+
# include <boost/python/object_slices.hpp>
1213
# include <boost/python/object_operators.hpp>
1314

1415
namespace boost { namespace python {

include/boost/python/object_attributes.hpp

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ namespace boost { namespace python { namespace api {
1414

1515
struct const_attribute_policies
1616
{
17-
static object get(object const& target, object const& key);
17+
typedef char const* key_type;
18+
static object get(object const& target, char const* key);
1819
};
1920

2021
struct attribute_policies : const_attribute_policies
2122
{
22-
static object const& set(object const& target, object const& key, object const& value);
23+
static object const& set(object const& target, char const* key, object const& value);
24+
static void del(object const&target, char const* key);
2325
};
2426

2527
//
@@ -28,55 +30,38 @@ struct attribute_policies : const_attribute_policies
2830
template <class U>
2931
inline object_attribute object_operators<U>::attr(char const* name)
3032
{
31-
object const& x = *static_cast<U*>(this);
32-
return object_attribute(x, object(name));
33+
object_cref x = *static_cast<U*>(this);
34+
return object_attribute(x, name);
3335
}
3436

3537
template <class U>
3638
inline const_object_attribute object_operators<U>::attr(char const* name) const
3739
{
38-
object const& x = *static_cast<U const*>(this);
39-
return const_object_attribute(x, object(name));
40+
object_cref x = *static_cast<U const*>(this);
41+
return const_object_attribute(x, name);
4042
}
4143

42-
43-
inline object const_attribute_policies::get(object const& target, object const& key)
44+
inline object const_attribute_policies::get(object const& target, char const* key)
4445
{
4546
return python::getattr(target, key);
4647
}
4748

4849
inline object const& attribute_policies::set(
4950
object const& target
50-
, object const& key
51+
, char const* key
5152
, object const& value)
5253
{
5354
python::setattr(target, key, value);
5455
return value;
5556
}
5657

57-
} // namespace api
58-
59-
namespace converter
58+
inline void attribute_policies::del(
59+
object const& target
60+
, char const* key)
6061
{
61-
// These specializations are a lie; the proxies do not directly
62-
// manage an object. What actually happens is that the implicit
63-
// conversion to object takes hold and its conversion to_python is
64-
// used. That's OK in part because the object temporary *is*
65-
// actually managing the object during the duration of the
66-
// conversion.
67-
template <>
68-
struct is_object_manager<api::object_attribute>
69-
{
70-
BOOST_STATIC_CONSTANT(bool, value = true);
71-
};
72-
73-
template <>
74-
struct is_object_manager<api::const_object_attribute>
75-
{
76-
BOOST_STATIC_CONSTANT(bool, value = true);
77-
};
62+
python::delattr(target, key);
7863
}
7964

80-
}} // namespace boost::python
65+
}}} // namespace boost::python::api
8166

8267
#endif // OBJECT_ATTRIBUTES_DWA2002615_HPP

include/boost/python/object_core.hpp

Lines changed: 125 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
# include <boost/python/detail/preprocessor.hpp>
1111
# include <boost/python/call.hpp>
1212
# include <boost/preprocessor/max.hpp>
13+
# include <boost/python/slice_nil.hpp>
14+
# include <boost/type.hpp>
1315

1416
namespace boost { namespace python {
1517

@@ -27,12 +29,74 @@ namespace api
2729
struct attribute_policies;
2830
struct const_item_policies;
2931
struct item_policies;
32+
struct const_slice_policies;
33+
struct slice_policies;
3034

3135
typedef proxy<const_attribute_policies> const_object_attribute;
3236
typedef proxy<attribute_policies> object_attribute;
3337
typedef proxy<const_item_policies> const_object_item;
3438
typedef proxy<item_policies> object_item;
39+
typedef proxy<const_slice_policies> const_object_slice;
40+
typedef proxy<slice_policies> object_slice;
41+
42+
//
43+
// is_proxy -- proxy type detection
44+
//
45+
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
46+
template <class T>
47+
struct is_proxy
48+
{
49+
BOOST_STATIC_CONSTANT(bool, value = false);
50+
};
51+
template <class T>
52+
struct is_proxy<proxy<T> >
53+
{
54+
BOOST_STATIC_CONSTANT(bool, value = true);
55+
};
56+
# else
57+
typedef char yes_proxy;
58+
typedef char (&no_proxy)[2];
59+
template <class T>
60+
yes_proxy is_proxy_helper(boost::type<proxy<T> >*);
61+
no_proxy is_proxy_helper(...);
62+
template <class T>
63+
struct is_proxy
64+
{
65+
BOOST_STATIC_CONSTANT(
66+
bool, value = (sizeof(is_proxy_helper((boost::type<T>*)0))
67+
== sizeof(yes_proxy)));
68+
};
69+
# endif
3570

71+
//
72+
// object_handle -- get the handle to construct the object with,
73+
// based on whether T is a proxy or not
74+
//
75+
template <bool = false>
76+
struct object_handle
77+
{
78+
template <class T>
79+
static handle<> get(T const& x)
80+
{
81+
return handle<>(
82+
python::borrowed(
83+
python::allow_null( // null check is already done
84+
converter::arg_to_python<T>(x).get())
85+
)
86+
);
87+
}
88+
};
89+
90+
template <>
91+
struct object_handle<true>
92+
{
93+
template <class Policies>
94+
static handle<> get(proxy<Policies> const& x)
95+
{
96+
return x.operator object().ptr();
97+
}
98+
};
99+
36100
// A way to turn a conrete type T into a type dependent on U. This
37101
// keeps conforming compilers from complaining about returning an
38102
// incomplete T from a template member function (which must be
@@ -54,12 +118,19 @@ namespace api
54118
# else
55119
typedef object self_cref;
56120
# endif
121+
122+
// there appears to be a codegen bug here. We prevent the early
123+
// destruction of a temporary in CWPro8 by binding a named
124+
// object instead.
125+
# if __MWERKS__ != 0x3000
126+
typedef object const& object_cref;
127+
# else
128+
typedef object const object_cref;
129+
# endif
57130

58131
public:
59-
// Attribute access via x.attr("attribute_name")
60-
const_object_attribute attr(char const*) const;
61-
object_attribute attr(char const*);
62-
132+
// function call
133+
//
63134
object operator()() const;
64135

65136
# ifndef BOOST_PYTHON_GENERATE_CODE
@@ -81,10 +152,17 @@ namespace api
81152
, BOOST_PYTHON_OBJECT_CALL, ignored)
82153

83154
// truth value testing
155+
//
84156
operator bool_type() const;
85157
bool operator!() const; // needed for vc6
86158

159+
// Attribute access
160+
//
161+
const_object_attribute attr(char const*) const;
162+
object_attribute attr(char const*);
163+
87164
// item access
165+
//
88166
const_object_item operator[](self_cref) const;
89167
object_item operator[](self_cref);
90168

@@ -110,6 +188,47 @@ namespace api
110188
}
111189
# endif
112190

191+
// slicing
192+
//
193+
const_object_slice slice(self_cref, self_cref) const;
194+
object_slice slice(self_cref, self_cref);
195+
196+
const_object_slice slice(slice_nil, self_cref) const;
197+
object_slice slice(slice_nil, self_cref);
198+
199+
const_object_slice slice(self_cref, slice_nil) const;
200+
object_slice slice(self_cref, slice_nil);
201+
202+
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
203+
template <class T, class V>
204+
const_object_slice
205+
slice(T const& start, V const& end) const;
206+
207+
template <class T, class V>
208+
object_slice
209+
slice(T const& start, V const& end);
210+
211+
# else
212+
template <class T, class V>
213+
const_object_slice
214+
slice(T const& start, V const& end) const
215+
{
216+
return this->slice(
217+
slice_bound<T>::type(start)
218+
, slice_bound<V>::type(end));
219+
}
220+
221+
template <class T, class V>
222+
object_slice
223+
slice(T const& start, V const& end)
224+
{
225+
return this->slice(
226+
slice_bound<T>::type(start)
227+
, slice_bound<V>::type(end));
228+
}
229+
# endif
230+
231+
113232
# if BOOST_MSVC == 1200
114233
// For whatever reason, VC6 generates incorrect code unless we
115234
// define this
@@ -128,25 +247,15 @@ namespace api
128247
// explicit conversion from any C++ object to Python
129248
template <class T>
130249
explicit object(T const& x)
131-
: m_ptr(
132-
python::borrowed(
133-
python::allow_null( // null check is already done
134-
converter::arg_to_python<T>(x).get())
135-
)
136-
)
250+
: m_ptr(object_handle<is_proxy<T>::value>::get(x))
137251
{
138252
}
139253

140254
// capture this case explicitly to handle string
141255
// literals. Otherwise, they get deduced as char[N]const& above
142256
// and conversion fails at runtime.
143257
explicit object(char const* x)
144-
: m_ptr(
145-
python::borrowed(
146-
python::allow_null( // null check is already done
147-
converter::arg_to_python<char const*>(x).get())
148-
)
149-
)
258+
: m_ptr(object_handle<>::get(x))
150259
{
151260
}
152261

include/boost/python/object_items.hpp

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ namespace boost { namespace python { namespace api {
1414

1515
struct const_item_policies
1616
{
17+
typedef object key_type;
1718
static object get(object const& target, object const& key);
1819
};
1920

2021
struct item_policies : const_item_policies
2122
{
2223
static object const& set(object const& target, object const& key, object const& value);
24+
static void del(object const& target, object const& key);
2325
};
2426

2527
//
@@ -29,15 +31,15 @@ template <class U>
2931
inline object_item
3032
object_operators<U>::operator[](self_cref key)
3133
{
32-
object const& x = *static_cast<U*>(this);
34+
object_cref x = *static_cast<U*>(this);
3335
return object_item(x, key);
3436
}
3537

3638
template <class U>
3739
inline const_object_item
3840
object_operators<U>::operator[](self_cref key) const
3941
{
40-
object const& x = *static_cast<U const*>(this);
42+
object_cref x = *static_cast<U const*>(this);
4143
return const_object_item(x, key);
4244
}
4345

@@ -62,41 +64,25 @@ object_operators<U>::operator[](T const& key)
6264

6365
inline object const_item_policies::get(object const& target, object const& key)
6466
{
65-
return python::getitem(target, key);
67+
return getitem(target, key);
6668
}
6769

6870
inline object const& item_policies::set(
6971
object const& target
7072
, object const& key
7173
, object const& value)
7274
{
73-
python::setitem(target, key, value);
75+
setitem(target, key, value);
7476
return value;
7577
}
7678

77-
} // namespace api
78-
79-
namespace converter
79+
inline void item_policies::del(
80+
object const& target
81+
, object const& key)
8082
{
81-
// These specializations are a lie; the proxies do not directly
82-
// manage an object. What actually happens is that the implicit
83-
// conversion to object takes hold and its conversion to_python is
84-
// used. That's OK in part because the object temporary *is*
85-
// actually managing the object during the duration of the
86-
// conversion.
87-
template <>
88-
struct is_object_manager<api::object_item>
89-
{
90-
BOOST_STATIC_CONSTANT(bool, value = true);
91-
};
92-
93-
template <>
94-
struct is_object_manager<api::const_object_item>
95-
{
96-
BOOST_STATIC_CONSTANT(bool, value = true);
97-
};
83+
delitem(target, key);
9884
}
9985

100-
}} // namespace boost::python
86+
}}} // namespace boost::python::api
10187

10288
#endif // OBJECT_ITEMS_DWA2002615_HPP

0 commit comments

Comments
 (0)