Library of Assembled Shared Sources
 
Loading...
Searching...
No Matches
py_tuple.h
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2026 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_PY_TUPLE_H
44#define LASS_GUARDIAN_OF_INCLUSION_UTIL_PY_TUPLE_H
45
46#include "python_common.h"
47#include "pyobject_plus.h"
48#include <utility>
49#include <tuple>
50
51#if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
52# pragma warning(push)
53# pragma warning(disable: 4267) // conversion from 'size_t' to 'unsigned int', possible loss of data
54#endif
55
56namespace lass
57{
58namespace python
59{
60namespace impl
61{
62 /** @ingroup Python
63 * @internal
64 */
65 template <typename P>
66 inline bool tupleSetItems(PyObject* tuple, Py_ssize_t index, const P& p)
67 {
68 PyObject* value = pyBuildSimpleObject(p);
69 return value && (PyTuple_SetItem(tuple, index, value) == 0);
70 }
71
72 /** @ingroup Python
73 * @internal
74 */
75 template <typename P, typename... Ptail>
76 inline bool tupleSetItems(PyObject* tuple, Py_ssize_t index, const P& p, Ptail&... tail)
77 {
78 PyObject* value = pyBuildSimpleObject(p);
79 return value && (PyTuple_SetItem(tuple, index, value) == 0)
80 && tupleSetItems(tuple, index + 1, tail...);
81 }
82
83 /** @ingroup Python
84 * @internal
85 */
86 template <typename P>
87 inline bool decodeObject(PyObject* in, Py_ssize_t index, P& out)
88 {
89 if (lass::python::pyGetSimpleObject(in, out) != 0)
90 {
91 std::ostringstream buffer;
92 buffer << "Bad Argument on " << (index + 1) << "th position";
93 impl::addMessageHeader(buffer.str().c_str());
94 return false;
95 }
96 return true;
97 }
98
99 /** @ingroup Python
100 * @internal
101 */
102 template <typename P>
103 inline bool decodeObjects(PyObject** objects, Py_ssize_t index, P& p)
104 {
105 return impl::decodeObject(objects[index], index, p);
106 }
107
108 /** @ingroup Python
109 * @internal
110 */
111 template <typename P, typename... Ptail>
112 inline bool decodeObjects(PyObject** objects, Py_ssize_t index, P& p, Ptail&... tail)
113 {
114 return impl::decodeObject(objects[index], index, p)
115 && decodeObjects(objects, index + 1, tail...);
116 }
117
118 /** @ingroup Python
119 * @internal
120 */
121 template <typename P>
122 inline bool decodeObjectsMinimum(PyObject** objects, Py_ssize_t index, Py_ssize_t size, P& p)
123 {
124 return index >= size
125 || impl::decodeObject(objects[index], index, p);
126 }
127
128 /** @ingroup Python
129 * @internal
130 */
131 template <typename P, typename... Ptail>
132 inline bool decodeObjectsMinimum(PyObject** objects, Py_ssize_t index, Py_ssize_t size, P& p, Ptail&... tail)
133 {
134 return index >= size
135 || (impl::decodeObject(objects[index], index, p)
136 && decodeObjectsMinimum(objects, index + 1, size, tail...));
137 }
138}
139
140
141
142/** @ingroup Python
143 */
144inline const TPyObjPtr makeTuple()
145{
146 LockGIL lock;
147 return TPyObjPtr(PyTuple_New(0));
148}
149
150/** @ingroup Python
151 */
152template <typename... P>
153const TPyObjPtr makeTuple(const P&... p)
154{
155 LockGIL lock;
156 TPyObjPtr tuple(PyTuple_New(sizeof...(P)));
157 return tuple && impl::tupleSetItems(tuple.get(), 0, p...)
158 ? tuple
159 : TPyObjPtr();
160}
161
162
163
164/** @ingroup Python
165 */
166inline int decodeTuple(PyObject* obj)
167{
168 LASS_ASSERT(obj);
169 return impl::checkSequenceSize(obj, 0) ? 0 : 1;
170}
171
172/** @ingroup Python
173 */
174template <typename... P>
175int decodeTuple(PyObject* obj, P&... p)
176{
177 LockGIL lock;
178 const TPyObjPtr tuple = impl::checkedFastSequence(obj, sizeof...(P));
179 if (!tuple)
180 {
181 return 1;
182 }
183 PyObject** objects = PySequence_Fast_ITEMS(tuple.get());
184 return impl::decodeObjects(objects, 0, p...)
185 ? 0
186 : 1;
187}
188
189
190
191/** @ingroup Python
192 */
193inline int decodeTuple(const TPyObjPtr& obj)
194{
195 return decodeTuple(obj.get());
196}
197
198/** @ingroup Python
199 */
200template <typename... P>
201inline int decodeTuple(const TPyObjPtr& obj, P&... p)
202{
203 return decodeTuple(obj.get(), p...);
204}
205
206
207
208/** @ingroup Python
209 */
210template <typename... P>
211int decodeTupleMinimum(PyObject* obj, Py_ssize_t minumumLength, P&... p)
212{
213 LockGIL lock;
214 const TPyObjPtr tuple = impl::checkedFastSequence(obj, minumumLength, sizeof...(P));
215 if (!tuple)
216 {
217 return 1;
218 }
219 const Py_ssize_t size = PySequence_Fast_GET_SIZE(tuple.get());
220 PyObject** objects = PySequence_Fast_ITEMS(tuple.get());
221 return impl::decodeObjectsMinimum(objects, 0, size, p...)
222 ? 0
223 : 1;
224}
225
226
227
228/** @ingroup Python
229 */
230template <typename... P>
231int decodeTupleMinimum(const TPyObjPtr& obj, Py_ssize_t minumumLength, P&... p)
232{
233 return decodeTupleMinimum(obj.get(), minumumLength, p...);
234}
235
236
237
238// --- pairs ---------------------------------------------------------------------------------------
239
240/** std::pair translates to a tuple by copy.
241 * @ingroup PyExportTraits
242 */
243template <typename T1, typename T2>
244struct PyExportTraits< std::pair<T1, T2> >
245{
246 constexpr static const char* py_typing = "tuple[T1, T2]";
247
248 static PyObject* build(const std::pair<T1, T2>& v)
249 {
250 return fromSharedPtrToNakedCast(makeTuple(v.first, v.second));
251
252 }
253 static int get(PyObject* obj, std::pair<T1, T2>& v)
254 {
255 if (decodeTuple(obj, v.first, v.second) != 0)
256 {
258 return 1;
259 }
260 return 0;
261 }
262};
263
264
265/** std::tuple translates to a tuple by copy.
266 * @ingroup PyExportTraits
267 */
268template <typename... T>
269struct PyExportTraits< std::tuple<T...> >
270{
271 constexpr static const char* py_typing = "tuple[T...]";
272
273 static PyObject* build(const std::tuple<T...>& v)
274 {
275 return doBuild(v, std::index_sequence_for<T...>());
276 }
277 static int get(PyObject* obj, std::tuple<T...>& v)
278 {
279 return doGet(obj, v, std::index_sequence_for<T...>());
280 }
281
282private:
283 template <std::size_t... I>
284 static PyObject* doBuild(const std::tuple<T...>& v, std::index_sequence<I...>)
285 {
286 return fromSharedPtrToNakedCast(makeTuple(std::get<I>(v)...));
287 }
288 template <std::size_t... I>
289 static int doGet(PyObject* obj, std::tuple<T...>& v, std::index_sequence<I...>)
290 {
291 if (decodeTuple(obj, std::get<I>(v)...) != 0)
292 {
293 impl::addMessageHeader("tuple");
294 return 1;
295 }
296 return 0;
297 }
298};
299
300}
301
302}
303
304#if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
305# pragma warning(pop)
306#endif
307
308#endif
309
310// EOF
acquire the GIL for the current scope.
Definition gil.h:56
void addMessageHeader(const char *header)
Prepend a message to the current Python exception value.
PyObjectPtr< PyObject >::Type TPyObjPtr
PyObjectPtr to a PyObject.
PyObject * fromSharedPtrToNakedCast(const util::SharedPtr< T, PyObjectStorage, PyObjectCounter > &object)
fromSharedPtrToNakedCast.
Comprehensive C++ to Python binding library.
Library for Assembled Shared Sources.
Definition config.h:53
by copy, general case assumes shadow type or PyObjectPlus based type.