43#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_PYSEQUENCE_H
44#define LASS_GUARDIAN_OF_INCLUSION_UTIL_PYSEQUENCE_H
66 class LASS_PYTHON_DLL PySequenceImplBase:
public ContainerImplBase
69 typedef std::unique_ptr<PySequenceImplBase> TPimpl;
70 using ContainerImplBase::ContainerImplBase;
71 virtual TPimpl copy()
const = 0;
72 virtual bool reserve(Py_ssize_t n) = 0;
73 virtual bool append(
const TPyObjPtr& i) = 0;
74 virtual bool pop(Py_ssize_t i) = 0;
75 virtual PyObject* item(Py_ssize_t i)
const = 0;
76 virtual PyObject* slice(Slice slice)
const = 0;
77 virtual int assItem(Py_ssize_t i, PyObject* obj) = 0;
78 virtual int assSlice(Slice slice, PyObject* obj) = 0;
79 virtual int contains(PyObject* obj)
const = 0;
80 virtual bool inplaceConcat(PyObject* obj) = 0;
81 virtual bool inplaceRepeat(Py_ssize_t n) = 0;
84 template<
typename Container>
85 class PySequenceContainer:
public ContainerImpl<Container, PySequenceImplBase>
88 typedef ContainerImpl<Container, PySequenceImplBase> TBase;
89 typedef typename TBase::TContainerPtr TContainerPtr;
90 typedef typename TBase::TConstContainerPtr TConstContainerPtr;
91 typedef typename TBase::TContainerTraits TContainerTraits;
92 typedef typename TContainerTraits::iterator TIterator;
93 typedef typename TContainerTraits::const_iterator TConstIterator;
94 typedef ArgumentTraits<typename TContainerTraits::value_type> TArgTraits;
95 typedef PySequenceImplBase::TPimpl TPimpl;
97 PySequenceContainer(
const TContainerPtr& container,
bool readOnly =
false):
98 TBase(container, readOnly)
101 ~PySequenceContainer()
104 const TPyObjPtr asNative()
const override
106 return pyBuildList(this->begin(), this->next(this->begin(), this->length()));
108 TPimpl copy()
const override
110 TContainerPtr copy = TContainerTraits::copy(this->container());
111 return TPimpl(
new PySequenceContainer(copy));
113 bool reserve(Py_ssize_t n)
override
115 if (!this->checkWritable())
119 TContainerTraits::reserve(this->container(), n);
122 bool append(
const TPyObjPtr& obj)
override
124 if (!this->checkWritable())
128 typename TArgTraits::TStorage value;
129 if (pyGetSimpleObject(obj.get(), value) != 0)
133 TIterator end = this->next(this->begin(), this->length());
134 TContainerTraits::insert(this->container(), end, TArgTraits::arg(value));
137 bool pop(Py_ssize_t i)
override
139 if (!this->checkWritable())
143 if (!this->checkIndex(i))
147 TContainerTraits::erase(this->container(), this->next(this->begin(), i), this->next(this->begin(), i + 1));
150 PyObject* item(Py_ssize_t i)
const override
152 if (!this->checkIndex(i))
156 return pyBuildSimpleObject(*this->next(this->begin(), i));
158 PyObject* slice(Slice slice)
const override
160 Py_ssize_t sliceLength = slice.adjustIndices(this->length());
166 TConstIterator first = this->next(this->begin(), slice.start);
167 for (Py_ssize_t i = 0; i < sliceLength; ++i)
172 first = this->next(first, slice.step);
174 PyObject* item = pyBuildSimpleObject(*first);
179 PyList_SET_ITEM(s.get(), i, item);
183 int assItem(Py_ssize_t i, PyObject* obj)
override
185 if (!this->checkWritable() || !this->checkIndex(i))
191 Slice slice { i, i + 1, 1 };
192 return assSlice(slice,
nullptr);
194 if (pyGetSimpleObject(obj, *this->next(this->begin(), i)) != 0)
200 int assSlice(Slice slice, PyObject* other)
override
202 if (!this->checkWritable())
207 TConstContainerPtr b;
210 if (pyGetSimpleObject(other, b) != 0)
214 if (&this->container() == b.get())
216 b = TContainerTraits::copy(*b);
220 Py_ssize_t sliceLength = slice.adjustIndices(this->length());
223 LASS_ASSERT(slice.start + sliceLength <= this->length());
224 const TIterator first = this->next(this->begin(), slice.start);
225 const TIterator last = this->next(first, sliceLength);
226 TContainerTraits::erase(this->container(), first, last);
229 const TIterator pos = this->next(this->begin(), slice.start);
230 const TConstIterator bFirst = TContainerTraits::begin(*b);
231 const TConstIterator bLast = this->next(bFirst, TContainerTraits::size(*b));
232 TContainerTraits::insert(this->container(), pos, bFirst, bLast);
239 const Py_ssize_t bLength = TContainerTraits::size(*b);
240 if (sliceLength != bLength)
242 std::ostringstream buffer;
243 buffer <<
"cannot assign sequence of length " << bLength <<
" to an extended slice of length " << sliceLength;
244 PyErr_SetString(PyExc_ValueError, buffer.str().c_str());
247 TIterator left = this->next(this->begin(), slice.start);
248 TConstIterator right = TContainerTraits::begin(*b);
249 for (Py_ssize_t i = 0; i < sliceLength; ++i)
254 left = this->next(left, slice.step);
261 Py_ssize_t index = slice.start;
262 Py_ssize_t step = slice.step;
263 if (step > 0 && sliceLength > 0)
266 index += (sliceLength - 1) * step;
269 for (Py_ssize_t i = 0; i < sliceLength; ++i, index += step)
273 TContainerTraits::erase(this->container(), this->next(this->begin(), index));
279 int contains(PyObject* obj)
const override
281 typename TArgTraits::TStorage value;
282 if (pyGetSimpleObject(obj, value) != 0)
284 if (PyErr_ExceptionMatches(PyExc_TypeError))
293 TConstIterator end = this->next(this->begin(), this->length());
294 if (std::find(this->begin(), end, TArgTraits::arg(value)) != end)
300 bool inplaceConcat(PyObject* other)
override
302 if (!this->checkWritable())
306 TConstContainerPtr b;
307 if (pyGetSimpleObject(other, b) != 0)
311 if (&this->container() == b.get())
313 b = TContainerTraits::copy(*b);
315 const TIterator end = this->next(this->begin(), this->length());
316 const TConstIterator first = TContainerTraits::begin(*b);
317 const TConstIterator last = this->next(first, TContainerTraits::size(*b));
318 TContainerTraits::insert(this->container(), end, first, last);
321 bool inplaceRepeat(Py_ssize_t n)
override
323 if (!this->checkWritable())
327 TContainerTraits::inplace_repeat(this->container(),n);
331 bool checkIndex(Py_ssize_t& i)
const
333 const Py_ssize_t size = this->length();
334 if (i < 0 || i >= size)
336 PyErr_SetString(PyExc_IndexError,
"list assignment index out of range");
344 typedef PyObjectPtr<Sequence>::Type TSequencePtr;
353 template<
typename Container> Sequence(
const util::SharedPtr<Container>& container )
355 TPimpl pimpl(
new PySequenceContainer<Container>(
356 LASS_ENFORCE_POINTER(container)));
357 init(std::move(pimpl));
359 template<
typename Container> Sequence(
const util::SharedPtr<const Container>& container )
361 TPimpl pimpl(
new PySequenceContainer<Container>(
362 (LASS_ENFORCE_POINTER(container)).
template constCast<Container>(),
true));
363 init(std::move(pimpl));
365 template<
typename Container> Sequence(
const Container& container )
367 util::SharedPtr<Container> p(ContainerTraits<Container>::copy(container));
368 TPimpl pimpl(
new PySequenceContainer<Container>(p,
true));
369 init(std::move(pimpl));
372 const TSequencePtr copy()
const;
374 void reserve(Py_ssize_t n);
380 std::string repr()
const;
382 const std::type_info& type()
const;
383 void* raw(
bool writable)
const;
385 static Py_ssize_t length(PyObject* self);
386 static PyObject* concat(PyObject* self, PyObject* other);
387 static PyObject* repeat(PyObject* self, Py_ssize_t n);
388 static PyObject* item(PyObject* self, Py_ssize_t i);
389 static int assItem(PyObject* self, Py_ssize_t i, PyObject* obj);
390 static int contains(PyObject* a, PyObject* obj);
391 static PyObject* inplaceConcat(PyObject* self, PyObject* other);
392 static PyObject* inplaceRepeat(PyObject* self, Py_ssize_t n);
393 static PyObject* subscript(PyObject* self, PyObject* key);
394 static int assSubscript(PyObject* self, PyObject* key, PyObject* value);
397 typedef PySequenceImplBase::TPimpl TPimpl;
399 Sequence(TPimpl&& pimpl);
400 void init(TPimpl&& pimpl);
406 struct ShadowTraits<
Sequence>:
public ShadowTraitsContainer< Sequence, ShadowTraits<Sequence> >
408 template <
typename Container>
static int getObjectImpl(PyObject* obj, util::SharedPtr<Container>& value,
bool writable)
410 if (!PySequence_Check(obj))
412 PyErr_SetString(PyExc_TypeError,
"not a sequence");
417 if (obj->ob_type == Sequence::_lassPyClassDef.type())
419 const Sequence*
const sequence =
static_cast<Sequence*
>(obj);
420 void*
const raw = sequence->raw(writable);
421 if (raw &&
typeid(value) == sequence->type())
423 value = *
static_cast< util::SharedPtr<Container>*
>(raw);
428 const util::SharedPtr<Container> result(
new Container);
429 const Py_ssize_t size = PySequence_Length(obj);
430 ContainerTraits<Container>::reserve(*result, size);
431 typedef ArgumentTraits<typename Container::value_type> TArgTraits;
432 for (Py_ssize_t i = 0; i < size; ++i)
434 typename TArgTraits::TStorage temp;
435 TPyObjPtr item( PySequence_ITEM(obj, i) );
436 if (pyGetSimpleObject( item.get() , temp ) != 0)
438 std::ostringstream buffer;
439 buffer <<
"sequence element " << i;
443 result->emplace_back(TArgTraits::arg(temp));
445 value = std::move(result);
451template <
typename ContainerType>
452struct ShadoweeTraitsSequence: meta::True
454 typedef impl::Sequence TShadow;
455 typedef impl::ShadowTraits<impl::Sequence> TShadowTraits;
456 typedef SharedPointerTraits<ContainerType> TPointerTraits;
462template<
typename C,
typename A>
463struct ShadoweeTraits< std::vector< C, A > >:
464 public ShadoweeTraitsSequence< std::vector< C, A > >
471template<
typename C,
typename A>
472struct ShadoweeTraits< std::list< C, A > >:
473 public ShadoweeTraitsSequence< std::list< C, A > >
480template<
typename C,
typename A>
481struct ShadoweeTraits< std::deque< C, A > >:
482 public ShadoweeTraitsSequence< std::deque< C, A > >
491#ifdef LASS_GUARDIAN_OF_INCLUSION_STDE_STATIC_VECTOR_H
500template<
typename C,
size_t maxsize>
501struct ShadoweeTraits< stde::static_vector< C, maxsize > >:
502 public ShadoweeTraitsSequence< stde::static_vector< C, maxsize > >
Object for interfacing sequence-like objects with Python.
use as base class if derived should not be copyable
void addMessageHeader(const char *header)
Prepend a message to the current Python exception value.
PyObjectPtr< PyObject >::Type TPyObjPtr
PyObjectPtr to a PyObject.
#define PY_HEADER(t_parentClass)
Place as first line of your Pythonized class.
PyObject * fromSharedPtrToNakedCast(const util::SharedPtr< T, PyObjectStorage, PyObjectCounter > &object)
fromSharedPtrToNakedCast.
Comprehensive C++ to Python binding library.
Library for Assembled Shared Sources.