43#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_PYSEQUENCE_H
44#define LASS_GUARDIAN_OF_INCLUSION_UTIL_PYSEQUENCE_H
65 class LASS_PYTHON_DLL PySequenceImplBase:
public ContainerImplBase
68 typedef std::unique_ptr<PySequenceImplBase> TPimpl;
69 virtual TPimpl copy()
const = 0;
70 virtual bool reserve(Py_ssize_t n) = 0;
71 virtual bool append(
const TPyObjPtr& i) = 0;
72 virtual bool pop(Py_ssize_t i) = 0;
73 virtual PyObject* item(Py_ssize_t i)
const = 0;
74 virtual PyObject* slice(Py_ssize_t low, Py_ssize_t high, Py_ssize_t step)
const = 0;
75 virtual int assItem(Py_ssize_t i, PyObject* obj) = 0;
76 virtual int assSlice(Py_ssize_t low, Py_ssize_t high, Py_ssize_t step, PyObject* obj) = 0;
77 virtual int contains(PyObject* obj)
const = 0;
78 virtual bool inplaceConcat(PyObject* obj) = 0;
79 virtual bool inplaceRepeat(Py_ssize_t n) = 0;
82 template<
typename Container>
83 class PySequenceContainer:
public ContainerImpl<Container, PySequenceImplBase>
86 typedef ContainerImpl<Container, PySequenceImplBase> TBase;
87 typedef typename TBase::TContainerPtr TContainerPtr;
88 typedef typename TBase::TConstContainerPtr TConstContainerPtr;
89 typedef typename TBase::TContainerTraits TContainerTraits;
90 typedef typename TContainerTraits::iterator TIterator;
91 typedef typename TContainerTraits::const_iterator TConstIterator;
92 typedef ArgumentTraits<typename TContainerTraits::value_type> TArgTraits;
93 typedef PySequenceImplBase::TPimpl TPimpl;
95 PySequenceContainer(
const TContainerPtr& container,
bool readOnly =
false):
96 TBase(container, readOnly)
99 ~PySequenceContainer()
102 const TPyObjPtr asNative()
const override
104 return pyBuildList(this->begin(), this->next(this->begin(), this->length()));
106 TPimpl copy()
const override
108 TContainerPtr copy = TContainerTraits::copy(this->container());
109 return TPimpl(
new PySequenceContainer(copy));
111 bool reserve(Py_ssize_t n)
override
113 if (!this->checkWritable())
117 TContainerTraits::reserve(this->container(), n);
120 bool append(
const TPyObjPtr& obj)
override
122 if (!this->checkWritable())
126 typename TArgTraits::TStorage value;
127 if (pyGetSimpleObject(obj.get(), value) != 0)
131 TIterator end = this->next(this->begin(), this->length());
132 TContainerTraits::insert(this->container(), end, TArgTraits::arg(value));
135 bool pop(Py_ssize_t i)
override
137 if (!this->checkWritable())
141 if (!this->checkIndex(i))
145 TContainerTraits::erase(this->container(), this->next(this->begin(), i), this->next(this->begin(), i + 1));
148 PyObject* item(Py_ssize_t i)
const override
150 if (!this->checkIndex(i))
154 return pyBuildSimpleObject(*this->next(this->begin(), i));
156 PyObject* slice(Py_ssize_t low, Py_ssize_t high, Py_ssize_t step)
const override
158 const Py_ssize_t size = this->length();
161 step = std::max(step, Py_ssize_t(1));
162 const Py_ssize_t n = (high - low + step - 1) / step;
164 TConstIterator first = this->next(this->begin(), low);
165 for (Py_ssize_t i = 0; i < n; ++i)
170 std::advance(first, step);
172 PyList_SET_ITEM(s.get(), i, pyBuildSimpleObject(*first));
176 int assItem(Py_ssize_t i, PyObject* obj)
override
178 if (!this->checkWritable() || !this->checkIndex(i))
184 return assSlice(i, i + 1, 1, 0);
186 if (pyGetSimpleObject(obj, *this->next(this->begin(), i)) != 0)
192 int assSlice(Py_ssize_t low, Py_ssize_t high, Py_ssize_t step, PyObject* other)
override
194 if (!this->checkWritable())
198 const Py_ssize_t size = this->length();
201 step = std::max(step, Py_ssize_t(1));
202 TConstContainerPtr b;
205 if (pyGetSimpleObject(other, b) != 0)
209 if (&this->container() == b.get())
211 b = TContainerTraits::copy(*b);
216 const TIterator first = this->next(this->begin(), low);
217 const TIterator last = this->next(first, high - low);
218 TContainerTraits::erase(this->container(), first, last);
221 const TConstIterator bFirst = TContainerTraits::begin(*b);
222 const TConstIterator bLast = this->next(bFirst, TContainerTraits::size(*b));
223 TContainerTraits::insert(this->container(), this->next(this->begin(), low), bFirst, bLast);
230 const Py_ssize_t sliceLength = (high - low + step - 1) / step;
231 const Py_ssize_t bLength = TContainerTraits::size(*b);
232 if (sliceLength != bLength)
234 std::ostringstream buffer;
235 buffer <<
"cannot assign sequence of length " << bLength <<
" to an extended slice of length " << sliceLength;
236 PyErr_SetString(PyExc_ValueError, buffer.str().c_str());
239 TIterator left = this->next(this->begin(), low);
240 TConstIterator right = TContainerTraits::begin(*b);
247 left = this->next(left, step);
255 TContainerTraits::erase(this->container(), this->next(this->begin(), low));
263 int contains(PyObject* obj)
const override
265 typename TArgTraits::TStorage value;
266 if (pyGetSimpleObject(obj, value) != 0)
268 if (PyErr_ExceptionMatches(PyExc_TypeError))
277 TConstIterator end = this->next(this->begin(), this->length());
278 if (std::find(this->begin(), end, TArgTraits::arg(value)) != end)
284 bool inplaceConcat(PyObject* other)
override
286 if (!this->checkWritable())
290 TConstContainerPtr b;
291 if (pyGetSimpleObject(other, b) != 0)
295 if (&this->container() == b.get())
297 b = TContainerTraits::copy(*b);
299 const TIterator end = this->next(this->begin(), this->length());
300 const TConstIterator first = TContainerTraits::begin(*b);
301 const TConstIterator last = this->next(first, TContainerTraits::size(*b));
302 TContainerTraits::insert(this->container(), end, first, last);
305 bool inplaceRepeat(Py_ssize_t n)
override
307 if (!this->checkWritable())
311 TContainerTraits::inplace_repeat(this->container(),n);
315 bool checkIndex(Py_ssize_t& i)
const
317 const Py_ssize_t size = this->length();
318 if (i < 0 || i >= size)
320 PyErr_SetString(PyExc_IndexError,
"list assignment index out of range");
328 typedef PyObjectPtr<Sequence>::Type TSequencePtr;
337 template<
typename Container> Sequence(
const util::SharedPtr<Container>& container )
339 TPimpl pimpl(
new PySequenceContainer<Container>(
340 LASS_ENFORCE_POINTER(container)));
341 init(std::move(pimpl));
343 template<
typename Container> Sequence(
const util::SharedPtr<const Container>& container )
345 TPimpl pimpl(
new PySequenceContainer<Container>(
346 LASS_ENFORCE_POINTER(container).
template constCast<Container>(),
true));
347 init(std::move(pimpl));
349 template<
typename Container> Sequence(
const Container& container )
351 util::SharedPtr<Container> p(ContainerTraits<Container>::copy(container));
352 TPimpl pimpl(
new PySequenceContainer<Container>(p,
true));
353 init(std::move(pimpl));
356 const TSequencePtr copy()
const;
358 void reserve(Py_ssize_t n);
364 std::string repr()
const;
366 const std::type_info& type()
const;
367 void* raw(
bool writable)
const;
369 static Py_ssize_t length(PyObject* self);
370 static PyObject* concat(PyObject* self, PyObject* other);
371 static PyObject* repeat(PyObject* self, Py_ssize_t n);
372 static PyObject* item(PyObject* self, Py_ssize_t i);
373 static int assItem(PyObject* self, Py_ssize_t i, PyObject* obj);
374 static int contains(PyObject* a, PyObject* obj);
375 static PyObject* inplaceConcat(PyObject* self, PyObject* other);
376 static PyObject* inplaceRepeat(PyObject* self, Py_ssize_t n);
377 static PyObject* subscript(PyObject* self, PyObject* key);
378 static int assSubscript(PyObject* self, PyObject* key, PyObject* value);
381 typedef PySequenceImplBase::TPimpl TPimpl;
383 Sequence(TPimpl&& pimpl);
384 void init(TPimpl&& pimpl);
390 struct ShadowTraits<
Sequence>:
public ShadowTraitsContainer< Sequence, ShadowTraits<Sequence> >
392 template <
typename Container>
static int getObjectImpl(PyObject* obj, util::SharedPtr<Container>& value,
bool writable)
394 if (!PySequence_Check(obj))
396 PyErr_SetString(PyExc_TypeError,
"not a sequence");
401 if (obj->ob_type == Sequence::_lassPyClassDef.type())
403 const Sequence*
const sequence =
static_cast<Sequence*
>(obj);
404 void*
const raw = sequence->raw(writable);
405 if (raw &&
typeid(value) == sequence->type())
407 value = *
static_cast< util::SharedPtr<Container>*
>(raw);
412 const util::SharedPtr<Container> result(
new Container);
413 const Py_ssize_t size = PySequence_Length(obj);
414 ContainerTraits<Container>::reserve(*result, size);
415 typedef ArgumentTraits<typename Container::value_type> TArgTraits;
416 for (Py_ssize_t i = 0; i < size; ++i)
418 typename TArgTraits::TStorage temp;
419 TPyObjPtr item( PySequence_ITEM(obj, i) );
420 if (pyGetSimpleObject( item.get() , temp ) != 0)
422 std::ostringstream buffer;
423 buffer <<
"sequence element " << i;
427 result->emplace_back(TArgTraits::arg(temp));
429 value = std::move(result);
435template <
typename ContainerType>
436struct ShadoweeTraitsSequence: meta::True
438 typedef impl::Sequence TShadow;
439 typedef impl::ShadowTraits<impl::Sequence> TShadowTraits;
440 typedef SharedPointerTraits<ContainerType> TPointerTraits;
446template<
typename C,
typename A>
447struct ShadoweeTraits< std::vector< C, A > >:
448 public ShadoweeTraitsSequence< std::vector< C, A > >
455template<
typename C,
typename A>
456struct ShadoweeTraits< std::list< C, A > >:
457 public ShadoweeTraitsSequence< std::list< C, A > >
464template<
typename C,
typename A>
465struct ShadoweeTraits< std::deque< C, A > >:
466 public ShadoweeTraitsSequence< std::deque< C, A > >
475#ifdef LASS_GUARDIAN_OF_INCLUSION_STDE_STATIC_VECTOR_H
484template<
typename C,
size_t maxsize>
485struct ShadoweeTraits< stde::static_vector< C, maxsize > >:
486 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
const T & clamp(const T &x, const T &min, const T &max)
if x < min return min, else if x > max return max, else return x.
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.