44#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_PYITERATORRANGE_H
45#define LASS_GUARDIAN_OF_INCLUSION_UTIL_PYITERATORRANGE_H
53#if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
55# pragma warning(disable: 4244)
113 class LASS_PYTHON_DLL PyIteratorRangeImplBase
116 PyIteratorRangeImplBase() =
default;
117 virtual ~PyIteratorRangeImplBase() =
default;
118 virtual PyObject* iterNext() = 0;
124 template<
typename Iterator>
125 class PyIteratorRangeImpl :
public PyIteratorRangeImplBase
128 PyIteratorRangeImpl(Iterator first, Iterator last): first_(first), last_(last), current_(first) {}
129 ~PyIteratorRangeImpl() =
default;
130 PyObject* iterNext()
override
132 if (current_ != last_)
134 return pyBuildSimpleObject(*current_++);
149 template<
typename ValueType,
typename SizeType>
150 class PyIndexIteratorRangeImpl :
public PyIteratorRangeImplBase
153 using AtFunc = std::function<ValueType(SizeType)>;
154 PyIndexIteratorRangeImpl(AtFunc atFunc, SizeType size) : atFunc_(atFunc), size_(size), index_(0) {}
155 ~PyIndexIteratorRangeImpl() =
default;
156 PyObject* iterNext()
override
160 return pyBuildSimpleObject(atFunc_(index_++));
184 using TPimpl = std::unique_ptr<impl::PyIteratorRangeImplBase>;
191 PyIteratorRange(std::make_unique<impl::PyIteratorRangeImpl<Iterator>>(first, last))
215 static PyObject* iter( PyObject* iPo);
216 static PyObject* iterNext( PyObject* iPO);
240template <
typename SelfType,
typename ValueType>
244 using TSelf = SelfType;
245 using TValue = ValueType;
247 using TShadow =
typename ShadoweeTraits<TSelf>::TShadow;
248 using TShadowTraits = impl::ShadowTraits<TShadow>;
249 using TShadowPtr =
typename TShadowTraits::TPyClassPtr;
253 self_(std::move(self))
257 std::unique_ptr<PyIteratorRange> iter()
const
259 auto it = std::make_unique<PyIteratorRange>(self_->begin(), self_->end());
260 TShadowPtr owner = TShadowTraits::buildObject(self_);
261 [[maybe_unused]] TSelfPtr tmp;
262 LASS_ASSERT(TShadowTraits::getObject(owner.get(), tmp) == 0 && tmp == self_);
287 using TValue1 =
decltype(*std::declval<T>().begin());
288 using TValue2 =
decltype(*std::declval<T>().end());
289 static_assert(std::is_same_v<TValue1, TValue2>,
"Begin and end iterators must return the same value type");
314template <
typename SelfType,
typename ValueType,
typename GetIterator>
318 using TSelf = SelfType;
319 using TValue = ValueType;
320 using TGetIterator = GetIterator;
322 using TShadow =
typename ShadoweeTraits<TSelf>::TShadow;
323 using TShadowTraits = impl::ShadowTraits<TShadow>;
324 using TShadowPtr =
typename TShadowTraits::TPyClassPtr;
326 MemberRangeView(TSelfPtr self, TGetIterator begin, TGetIterator end):
327 self_(std::move(self)),
333 std::unique_ptr<PyIteratorRange> iter()
const
335 auto it = std::make_unique<PyIteratorRange>(((*self_).*begin_)(), ((*self_).*end_)());
336 TShadowPtr owner = TShadowTraits::buildObject(self_);
337 [[maybe_unused]] TSelfPtr tmp;
338 LASS_ASSERT(TShadowTraits::getObject(owner.get(), tmp) == 0 && tmp == self_);
355template <
typename T,
typename GetIterator>
358 using TGetIterator = std::decay_t<GetIterator>;
359 using TValue1 =
decltype(*(std::declval<T>().*begin)());
360 using TValue2 =
decltype(*(std::declval<T>().*end)());
361 static_assert(std::is_same_v<TValue1, TValue2>,
"Begin and end iterators must return the same value type");
362 return MemberRangeView<T, TValue1, TGetIterator>(self, begin, end);
377template <
typename T,
typename GetIterator>
381 using TGetIterator = std::decay_t<GetIterator>;
382 using TRangeView =
decltype(
makeMemberRangeView<T>(std::declval<TSelfPtr>(), std::declval<TGetIterator>(), std::declval<TGetIterator>()));
383 using TFactory = std::function<TRangeView(TSelfPtr)>;
385 TGetIterator start = begin;
386 TGetIterator stop = end;
387 TFactory makeRangeView = [start, stop](TSelfPtr self) {
390 return makeRangeView;
415template <
typename SelfType,
typename ValueType,
typename GetIterator>
419 using TSelf = SelfType;
420 using TValue = ValueType;
421 using TGetIterator = GetIterator;
423 using TShadow =
typename ShadoweeTraits<TSelf>::TShadow;
424 using TShadowTraits = impl::ShadowTraits<TShadow>;
425 using TShadowPtr =
typename TShadowTraits::TPyClassPtr;
427 FreeRangeView(TSelfPtr self, GetIterator begin, GetIterator end):
428 self_(std::move(self)),
434 std::unique_ptr<PyIteratorRange> iter()
const
436 auto it = std::make_unique<PyIteratorRange>(begin_(*self_), end_(*self_));
437 TShadowPtr owner = TShadowTraits::buildObject(self_);
438 [[maybe_unused]] TSelfPtr tmp;
439 LASS_ASSERT(TShadowTraits::getObject(owner.get(), tmp) == 0 && tmp == self_);
456template <
typename T,
typename GetIterator>
459 using TGetIterator = std::decay_t<GetIterator>;
460 using TValue1 =
decltype(*begin(std::declval<T&>()));
461 using TValue2 =
decltype(*end(std::declval<T&>()));
462 static_assert(std::is_same_v<TValue1, TValue2>,
"Begin and end iterators must return the same value type");
463 return FreeRangeView<T, TValue1, TGetIterator>(self, begin, end);
478template <
typename T,
typename GetIterator>
482 using TGetIterator = std::decay_t<GetIterator>;
483 using TRangeView =
decltype(
makeFreeRangeView<T>(std::declval<TSelfPtr>(), std::declval<TGetIterator>(), std::declval<TGetIterator>()));
484 using TFactory = std::function<TRangeView(TSelfPtr)>;
486 TGetIterator start = begin;
487 TGetIterator stop = end;
488 TFactory makeRangeView = [start, stop](TSelfPtr self) {
491 return makeRangeView;
518template <
typename SelfType,
typename ValueType,
typename SizeType,
typename AtMethod,
typename SizeMethod>
519class IndexedRangeView
522 using TSelf = SelfType;
523 using TShadowTraits = impl::ShadowTraits<typename ShadoweeTraits<TSelf>::TShadow>;
525 using TShadowPtr =
typename TShadowTraits::TPyClassPtr;
527 using TValue = ValueType;
528 using TSize = SizeType;
531 IndexedRangeView(TSelfPtr self, AtMethod atMethod, SizeMethod sizeMethod):
532 self_(std::move(self)),
534 sizeMethod_(sizeMethod)
538 std::unique_ptr<PyIteratorRange> iter()
const
540 TSelfPtr self = self_;
541 AtMethod at = atMethod_;
542 TSize size = ((*self).*sizeMethod_)();
543 auto pimpl = std::make_unique<TImpl>(
544 [self, at](TSize index) -> TValue {
return ((*self).*at)(index); },
547 auto it = std::make_unique<PyIteratorRange>(std::move(pimpl));
548 TShadowPtr owner = TShadowTraits::buildObject(self);
549 [[maybe_unused]] TSelfPtr tmp;
550 LASS_ASSERT(TShadowTraits::getObject(owner.get(), tmp) == 0 && tmp == self);
557 SizeMethod sizeMethod_;
566template <
typename T,
typename AtMethod,
typename SizeMethod>
569 using TAtMethod = std::decay_t<AtMethod>;
570 using TSizeMethod = std::decay_t<SizeMethod>;
571 using TSize =
decltype((std::declval<T>().*sizeMethod)());
572 using TValue =
decltype((std::declval<T>().*atMethod)(std::declval<TSize>()));
573 return IndexedRangeView<T, TValue, TSize, TAtMethod, TSizeMethod>(std::move(self), atMethod, sizeMethod);
587template <
typename T,
typename AtMethod,
typename SizeMethod>
591 using TAtMethod = std::decay_t<AtMethod>;
592 using TSizeMethod = std::decay_t<SizeMethod>;
593 using TRangeView =
decltype(
makeIndexedRangeView<T>(std::declval<TSelfPtr>(), std::declval<TAtMethod>(), std::declval<TSizeMethod>()));
594 using TFactory = std::function<TRangeView(TSelfPtr)>;
596 TAtMethod at = atMethod;
597 TSizeMethod size = sizeMethod;
598 TFactory makeRangeView = [at, size](TSelfPtr self) {
601 return makeRangeView;
628template <
typename SelfType,
typename ValueType,
typename SizeType,
typename AtFunc,
typename SizeFunc>
629class FreeIndexedRangeView
632 using TSelf = SelfType;
633 using TShadowTraits = impl::ShadowTraits<typename ShadoweeTraits<TSelf>::TShadow>;
635 using TShadowPtr =
typename TShadowTraits::TPyClassPtr;
637 using TValue = ValueType;
638 using TSize = SizeType;
641 FreeIndexedRangeView(TSelfPtr self, AtFunc atFunc, SizeFunc sizeFunc) :
642 self_(std::move(self)),
648 std::unique_ptr<PyIteratorRange> iter()
const
650 TSelfPtr self = self_;
652 TSize size = sizeFunc_(*self);
653 auto pimpl = std::make_unique<TImpl>(
654 [self, at](TSize index) -> TValue {
return at(*self, index); },
657 auto it = std::make_unique<PyIteratorRange>(std::move(pimpl));
658 TShadowPtr owner = TShadowTraits::buildObject(self);
659 [[maybe_unused]] TSelfPtr tmp;
660 LASS_ASSERT(TShadowTraits::getObject(owner.get(), tmp) == 0 && tmp == self);
676template <
typename T,
typename AtFunc,
typename SizeFunc>
679 using TSize =
decltype(sizeFunc(std::declval<T&>()));
680 using TValue =
decltype(atFunc(std::declval<T&>(), std::declval<TSize>()));
681 return FreeIndexedRangeView<T, TValue, TSize, AtFunc, SizeFunc>(std::move(self), atFunc, sizeFunc);
695template <
typename T,
typename AtFunc,
typename SizeFunc>
699 using TAtFunc = std::decay_t<AtFunc>;
700 using TSizeFunc = std::decay_t<SizeFunc>;
701 using TRangeView =
decltype(
makeFreeIndexedRangeView<T>(std::declval<TSelfPtr>(), std::declval<TAtFunc>(), std::declval<TSizeFunc>()));
702 using TFactory = std::function<TRangeView(TSelfPtr)>;
705 TSizeFunc size = sizeFunc;
706 TFactory makeRangeView = [at, size](TSelfPtr self) {
709 return makeRangeView;
724 constexpr static const char* py_typing =
"Iterator[Any]";
725 constexpr static const char* py_typing_preamble =
"from collections.abc import Iterator";
735template <
typename RangeViewType,
typename ValueType>
736struct PyExportTraitsRangeView
738 constexpr static const char* py_typing =
"Iterator[ValueType]";
739 constexpr static const char* py_typing_preamble =
"from collections.abc import Iterator";
741 static PyObject* build(
const RangeViewType& value)
743 return value.iter().release();
753template <
typename SelfType,
typename ValueType>
755 PyExportTraitsRangeView<ContainerRangeView<SelfType, ValueType>, ValueType>
765template <
typename SelfType,
typename ValueType,
typename GetIterator>
767 PyExportTraitsRangeView<MemberRangeView<SelfType, ValueType, GetIterator>, ValueType>
777template <
typename SelfType,
typename ValueType,
typename GetIterator>
779 PyExportTraitsRangeView<FreeRangeView<SelfType, ValueType, GetIterator>, ValueType>
789template <
typename SelfType,
typename ValueType,
typename SizeType,
typename AtMethod,
typename SizeMethod>
791 PyExportTraitsRangeView<IndexedRangeView<SelfType, ValueType, SizeType, AtMethod, SizeMethod>, ValueType>
801template <
typename SelfType,
typename ValueType,
typename SizeType,
typename AtFunc,
typename SizeFunc>
803 PyExportTraitsRangeView<FreeIndexedRangeView<SelfType, ValueType, SizeType, AtFunc, SizeFunc>, ValueType>
868#define PY_CLASS_ITERFUNC_EX( t_cppClass, i_cppBegin, i_cppEnd, s_doc, i_dispatcher )\
869 lass::python::PyIteratorRange* LASS_CONCATENATE_3( lassPyImpl_method_, i_dispatcher, itDispatch1 ) (const ::lass::python::impl::ShadowTraits< t_cppClass >::TCppClassPtr& iObj) { \
870 return new lass::python::PyIteratorRange(iObj->i_cppBegin (), iObj->i_cppEnd ()); } \
871 PY_CLASS_FREE_METHOD_NAME_DOC( t_cppClass, LASS_CONCATENATE_3( lassPyImpl_method_, i_dispatcher, itDispatch1 ), lass::python::methods::_iter_, s_doc)
876#define PY_CLASS_ITERFUNC_DOC( i_cppClass, i_cppBegin, icppEnd, s_doc )\
877 PY_CLASS_ITERFUNC_EX(\
878 i_cppClass, i_cppBegin, icppEnd, s_doc,\
879 LASS_UNIQUENAME(LASS_CONCATENATE(lassPyImpl_method_, i_cppClass)))
883#define PY_CLASS_ITERFUNC( i_cppClass, i_cppBegin, icppEnd )\
884 PY_CLASS_ITERFUNC_DOC( i_cppClass, i_cppBegin, icppEnd, 0 )
886#define PY_CLASS_FREE_ITERFUNC_EX( t_cppClass, i_cppBegin, i_cppEnd, s_doc, i_dispatcher )\
887lass::python::PyIteratorRange* LASS_CONCATENATE_3( lassPyImpl_method_, i_dispatcher, itDispatch2 ) (const ::lass::python::impl::ShadowTraits< t_cppClass >::TCppClassPtr& iObj) { \
888return new lass::python::PyIteratorRange(i_cppBegin(iObj), i_cppEnd(iObj)); } \
889 PY_CLASS_FREE_METHOD_NAME_DOC( t_cppClass, LASS_CONCATENATE_3( lassPyImpl_method_, i_dispatcher, itDispatch2 ), lass::python::methods::_iter_, s_doc)
894#define PY_CLASS_FREE_ITERFUNC_DOC( i_cppClass, i_cppBegin, icppEnd, s_doc )\
895 PY_CLASS_FREE_ITERFUNC_EX(\
896 i_cppClass, i_cppBegin, icppEnd, s_doc,\
897 LASS_UNIQUENAME(LASS_CONCATENATE(lassPyImpl_method_, i_cppClass)))
901#define PY_CLASS_FREE_ITERFUNC( i_cppClass, i_cppBegin, icppEnd )\
902 PY_CLASS_FREE_ITERFUNC_DOC( i_cppClass, i_cppBegin, icppEnd, 0 )
904#if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
View that adapts a C++ Range (begin()/end()) to a PyIteratorRange.
ContainerRangeView(TSelfPtr self)
Constructor creating a range view over a container.
View that adapts index-based element access to a PyIteratorRange.
View that adapts free iterator accessors to a PyIteratorRange.
View that adapts index-based element access to a PyIteratorRange.
View that adapts member iterator accessors to a PyIteratorRange.
PyIteratorRange(TPimpl pimpl)
Construct PyIteratorRange with custom implementation.
PyIteratorRange(Iterator first, Iterator last)
Construct PyIteratorRange with default implemenation iterating between two iterators.
Implementation of PyIteratorRangeImplBase to iterate over a sequence by index.
auto makeFreeRangeViewFactory(GetIterator begin, GetIterator end)
Returns a callable creating a FreeRangeView iterating over begin(*self) and end(*self)
auto makeIndexedRangeViewFactory(AtMethod atMethod, SizeMethod sizeMethod)
Returns callable that creates a IndexedRangeView iterating over (self->*atMethod)(index) for index in...
auto makeMemberRangeView(const ShadoweePtr< T > &self, GetIterator begin, GetIterator end)
Returns a MemberRangeView iterating over (self->*begin)() and (self->*end)()
auto makeFreeIndexedRangeViewFactory(AtFunc atFunc, SizeFunc sizeFunc)
Returns a callable that creates FreeIndexedRangeView iterating over atFunc(*self, index) for index in...
auto makeMemberRangeViewFactory(GetIterator begin, GetIterator end)
Returns a callable creating a MemberRangeView iterating over (self->*begin)() to (self->*end)()
auto makeIndexedRangeView(const ShadoweePtr< T > &self, AtMethod atMethod, SizeMethod sizeMethod)
Returns a IndexedRangeView iterating over (self->*atMethod)(index) for index in 0 to (self->*sizeMeth...
auto makeFreeIndexedRangeView(const ShadoweePtr< T > &self, AtFunc atFunc, SizeFunc sizeFunc)
Returns a FreeIndexedRangeView iterating over atFunc(*self, index) for index in 0 to sizeFunc(*self) ...
auto makeFreeRangeView(const ShadoweePtr< T > &self, GetIterator begin, GetIterator end)
Returns a FreeRangeView iterating over begin(*self) and end(*self)
auto makeContainerRangeView(const ShadoweePtr< T > &self)
Returns a ContainerRangeView iterating over self->begin() to self->end()
PyObjectPtr< PyObject >::Type TPyObjPtr
PyObjectPtr to a PyObject.
#define PY_HEADER(t_parentClass)
Place as first line of your Pythonized class.
std::conditional_t< std::is_const_v< ShadoweeType >, typename impl::ShadowTraits< typename ShadoweeTraits< ShadoweeType >::TShadow >::TConstCppClassPtr, typename impl::ShadowTraits< typename ShadoweeTraits< ShadoweeType >::TShadow >::TCppClassPtr > ShadoweePtr
Helper to get the pointer type holding the shadowee in a shadow object.
Comprehensive C++ to Python binding library.
Library for Assembled Shared Sources.
static PyObject * build(PyIteratorRange *iV)
we take ownership!
by copy, general case assumes shadow type or PyObjectPlus based type.