00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_PYSEQUENCE_H
00048 #define LASS_GUARDIAN_OF_INCLUSION_UTIL_PYSEQUENCE_H
00049
00050 #include "util_common.h"
00051 #include "pyobject_plus.h"
00052 #include "pyobject_util.h"
00053 #include "string_cast.h"
00054 #include "../stde/extended_algorithm.h"
00055
00056 #include <vector>
00057 #include <list>
00058 #include <deque>
00059 #include "../stde/static_vector.h"
00060
00061 namespace lass
00062 {
00063 namespace python
00064 {
00065
00066 namespace impl
00067 {
00068
00069 template<typename C>
00070 struct ContainerTraits
00071 {
00072 static const typename C::value_type& element_at(const C& iC, Py_ssize_t i) { return iC[i]; };
00073 static typename C::value_type& element_at(C& iC, Py_ssize_t i) { return iC[i]; };
00074 static typename C::const_iterator const_iterator_at(const C& iC, Py_ssize_t i) { return iC.begin()+i; };
00075 static typename C::iterator iterator_at(C& iC, Py_ssize_t i) { return iC.begin()+i; };
00076 static void reserve(C& , int ) {};
00077 };
00078
00079 template<typename C, typename A>
00080 struct ContainerTraits<std::vector<C, A> >
00081 {
00082 static const typename std::vector<C, A>::value_type& element_at(const std::vector<C, A>& iC, Py_ssize_t i) { return iC[i]; };
00083 static typename std::vector<C, A>::value_type& element_at(std::vector<C, A>& iC, Py_ssize_t i) { return iC[i]; };
00084 static typename std::vector<C, A>::const_iterator const_iterator_at(const std::vector<C, A>& iC, Py_ssize_t i) { return iC.begin()+i; };
00085 static typename std::vector<C, A>::iterator iterator_at(std::vector<C, A>& iC, Py_ssize_t i) { return iC.begin()+i; };
00086 static void reserve(std::vector<C, A>& iC, int iAmount) {iC.reserve(iAmount);};
00087 };
00088
00089
00090 template<typename C, typename A>
00091 struct ContainerTraits<std::list<C, A> >
00092 {
00093 static const C& element_at(const std::list<C,A>& iC, Py_ssize_t i) { return *const_iterator_at(iC,i); };
00094 static C& element_at(std::list<C,A>& iC, Py_ssize_t i) { return *iterator_at(iC,i); };
00095 static typename std::list<C, A>::const_iterator const_iterator_at(const std::list<C,A>& iC, Py_ssize_t i)
00096 {
00097 typename std::list<C,A>::const_iterator it = iC.begin();
00098 for (Py_ssize_t j=0;j<i;++j)
00099 ++it;
00100 return it;
00101 };
00102 static typename std::list<C, A>::iterator iterator_at(std::list<C,A>& iC, Py_ssize_t i)
00103 {
00104 typename std::list<C,A>::iterator it = iC.begin();
00105 for (Py_ssize_t j=0;j<i;++j)
00106 ++it;
00107 return it;
00108 };
00109 static void reserve(std::list<C, A>& , int ) {};
00110 };
00111
00112
00113
00114 class LASS_DLL PySequenceImplBase
00115 {
00116 public:
00117 PySequenceImplBase() {};
00118 virtual ~PySequenceImplBase() {};
00119 virtual void clear() = 0;
00120 virtual void reserve(int iAmount) = 0;
00121
00122
00123 virtual Py_ssize_t PySequence_Length() = 0;
00124 virtual PyObject* PySequence_Concat(PyObject *bb) = 0;
00125 virtual PyObject* PySequence_Repeat(Py_ssize_t n) = 0;
00126 virtual PyObject* PySequence_Item(Py_ssize_t i) = 0;
00127 virtual PyObject* PySequence_Slice(Py_ssize_t ilow, Py_ssize_t ihigh) = 0;
00128 virtual int PySequence_AssItem(Py_ssize_t i, PyObject *v) = 0;
00129 virtual int PySequence_AssSlice(Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v) = 0;
00130 virtual int PySequence_Contains(PyObject *el) = 0;
00131 virtual int PySequence_InplaceConcat(PyObject *other) = 0;
00132 virtual int PySequence_InplaceRepeat(Py_ssize_t n) = 0;
00133 virtual void append(PyObject* i) = 0;
00134 virtual TPyObjPtr pop(int i) = 0;
00135 virtual bool pointsToSameContainer(void* iO) = 0;
00136 virtual std::string pyStr(void) = 0;
00137 virtual std::string pyRepr(void) = 0;
00138 };
00139
00140 template<typename Container>
00141 struct ContainerNotOwned
00142 {
00143 typedef Container* ContainerPtr;
00144 static void dispose(ContainerPtr ) {};
00145 };
00146 template<typename Container>
00147 struct ContainerOwned
00148 {
00149 typedef Container* ContainerPtr;
00150 static void dispose(ContainerPtr ioC) {delete ioC;};
00151 };
00152
00153 template<typename Container, typename ContainerOwnerShipPolicy = ContainerNotOwned<Container> >
00154 class PySequenceContainer : public PySequenceImplBase
00155 {
00156 public:
00157 PySequenceContainer(typename ContainerOwnerShipPolicy::ContainerPtr iC, bool iReadOnly = false) : cont_(iC), readOnly_(iReadOnly) {}
00158 virtual ~PySequenceContainer() { ContainerOwnerShipPolicy::dispose(cont_); }
00159 virtual void clear();
00160 virtual void reserve(int iAmount);
00161
00162 virtual Py_ssize_t PySequence_Length();
00163 virtual PyObject* PySequence_Concat(PyObject *bb);
00164 virtual PyObject* PySequence_Repeat(Py_ssize_t n);
00165 virtual PyObject* PySequence_Item(Py_ssize_t i);
00166 virtual PyObject* PySequence_Slice(Py_ssize_t ilow, Py_ssize_t ihigh);
00167 virtual int PySequence_AssItem(Py_ssize_t i, PyObject *v);
00168 virtual int PySequence_AssSlice(Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v);
00169 virtual int PySequence_Contains(PyObject *el);
00170 virtual int PySequence_InplaceConcat(PyObject *other);
00171 virtual int PySequence_InplaceRepeat(Py_ssize_t n);
00172 virtual void append(PyObject* i);
00173 virtual TPyObjPtr pop(int i);
00174 virtual bool pointsToSameContainer(void* iO)
00175 {
00176 return (iO == (void*)cont_);
00177 }
00178 virtual std::string pyStr(void);
00179 virtual std::string pyRepr(void);
00180 private:
00181 typename ContainerOwnerShipPolicy::ContainerPtr cont_;
00182 bool readOnly_;
00183 };
00184
00185
00186
00187 class LASS_DLL PySequence : public PyObjectPlus
00188 {
00189 PY_HEADER(PyObjectPlus);
00190 static PySequenceMethods pySequenceMethods;
00191 static bool isInitialized;
00192
00193 public:
00194 template<typename Container> PySequence( Container& iCont )
00195 {
00196 initialize();
00197 impl::fixObjectType(this);
00198 pimpl_ = new PySequenceContainer<Container>(&iCont);
00199 }
00200 template<typename Container> PySequence( const Container& iCont )
00201 {
00202 initialize();
00203 impl::fixObjectType(this);
00204 pimpl_ = new PySequenceContainer<Container>(const_cast<Container*>(&iCont),true);
00205 }
00206
00207 virtual ~PySequence();
00208 virtual std::string doPyStr(void) { return pimpl_->pyStr(); }
00209 virtual std::string doPyRepr(void) { return pimpl_->pyRepr(); }
00210 virtual void append(PyObject* i) { pimpl_->append(i); }
00211 virtual void clear() { pimpl_->clear(); }
00212 virtual void reserve(int iAmount) { pimpl_->reserve(iAmount); }
00213 virtual TPyObjPtr pop(int i) { return pimpl_->pop(i); }
00214
00215
00216
00217 static Py_ssize_t PySequence_Length( PyObject* iPO);
00218 static PyObject* PySequence_Concat(PyObject *a, PyObject *bb);
00219 static PyObject* PySequence_Repeat(PyObject *a, Py_ssize_t n);
00220 static PyObject* PySequence_Item(PyObject*a, Py_ssize_t i);
00221 static PyObject* PySequence_Slice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh);
00222 static int PySequence_AssItem(PyObject *a, Py_ssize_t i, PyObject *v);
00223 static int PySequence_AssSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v);
00224 static int PySequence_Contains(PyObject *a, PyObject *el);
00225 static PyObject * PySequence_InplaceConcat(PyObject *self, PyObject *other);
00226 static PyObject * PySequence_InplaceRepeat(PyObject *self, Py_ssize_t n);
00227
00228 template<typename Container> bool pointsToSameContainer(Container& iO)
00229 {
00230 return pimpl_->pointsToSameContainer(&iO);
00231 }
00232 private:
00233 PySequence();
00234 PySequenceImplBase* pimpl_;
00235 static void initialize();
00236 };
00237
00238 template <typename Sequence>
00239 int pyGetSequenceObject( PyObject* iValue, Sequence& oV )
00240 {
00241 if (!PySequence_Check(iValue))
00242 {
00243 PyErr_SetString(PyExc_TypeError, "not a python sequence");
00244 return 1;
00245 }
00246
00247 if (isOfType(iValue, &PySequence::_lassPyType) && ((PySequence*)iValue)->pointsToSameContainer(oV))
00248 {
00249 return 0;
00250 }
00251 else
00252 {
00253 Sequence result;
00254 const Py_ssize_t size = PySequence_Length(iValue);
00255 for (Py_ssize_t i = 0; i < size; ++i)
00256 {
00257 typename Sequence::value_type temp;
00258 if (PyExportTraits<typename Sequence::value_type>::get( PySequence_ITEM(iValue, i) , temp ) != 0)
00259 {
00260 impl::addMessageHeader(
00261 std::string("sequence element ") + util::stringCast<std::string>(i));
00262 return 1;
00263 }
00264 result.push_back( temp );
00265 }
00266 oV.swap(result);
00267 }
00268 return 0;
00269 }
00270
00271
00272 template<typename Container, typename ContainerOwnerShipPolicy>
00273 void PySequenceContainer<Container, ContainerOwnerShipPolicy>::clear()
00274 {
00275 cont_->clear();
00276 }
00277 template<typename Container, typename ContainerOwnerShipPolicy>
00278 void PySequenceContainer<Container, ContainerOwnerShipPolicy>::reserve(int iAmount)
00279 {
00280 ContainerTraits<Container>::reserve(*cont_,iAmount);
00281 }
00282 template<typename Container, typename ContainerOwnerShipPolicy>
00283 Py_ssize_t PySequenceContainer<Container,ContainerOwnerShipPolicy>::PySequence_Length()
00284 {
00285 const Py_ssize_t size = static_cast<Py_ssize_t>(cont_->size());
00286 LASS_ASSERT(size >= 0);
00287 return size;
00288 }
00289 template<typename Container, typename ContainerOwnerShipPolicy>
00290 PyObject* PySequenceContainer<Container,ContainerOwnerShipPolicy>::PySequence_Concat(PyObject *bb)
00291 {
00292 Container toConcat;
00293 int r = pyGetSequenceObject(bb,toConcat);
00294 if (r)
00295 {
00296 PyErr_SetString(PyExc_TypeError, "Cannot convert to concatenation type");
00297 return NULL;
00298 }
00299 Container result(*cont_);
00300 result.insert(result.end(), toConcat.begin(), toConcat.end());
00301 return fromSharedPtrToNakedCast(pyBuildList(result.begin(),result.end()));
00302 }
00303 template<typename Container, typename ContainerOwnerShipPolicy>
00304 PyObject* PySequenceContainer<Container,ContainerOwnerShipPolicy>::PySequence_Repeat(Py_ssize_t n)
00305 {
00306 Container result = stde::repeat_c(*cont_,n);
00307 return fromSharedPtrToNakedCast(pyBuildList(result.begin(),result.end()));
00308 }
00309 template<typename Container, typename ContainerOwnerShipPolicy>
00310 PyObject* PySequenceContainer<Container,ContainerOwnerShipPolicy>::PySequence_Item(Py_ssize_t i)
00311 {
00312 const Py_ssize_t size = static_cast<Py_ssize_t>(cont_->size());
00313 LASS_ASSERT(size >= 0);
00314
00315 if (i<0 || i>=size)
00316 {
00317 PyErr_SetString(PyExc_IndexError, "Index out of bounds");
00318 return NULL;
00319 }
00320 return lass::python::PyExportTraits< typename Container::value_type >::build( ContainerTraits<Container>::element_at(*cont_,i));
00321 }
00322 template<typename Container, typename ContainerOwnerShipPolicy>
00323 PyObject* PySequenceContainer<Container,ContainerOwnerShipPolicy>::PySequence_Slice(Py_ssize_t ilow, Py_ssize_t ihigh)
00324 {
00325 const Py_ssize_t size = static_cast<Py_ssize_t>(cont_->size());
00326 LASS_ASSERT(size >= 0);
00327
00328 Py_ssize_t len;
00329 if (ilow < 0)
00330 ilow = 0;
00331 else if (ilow > size)
00332 ilow = size;
00333 if (ihigh < ilow)
00334 ihigh = ilow;
00335 else if (ihigh > size)
00336 ihigh = size;
00337 len = ihigh - ilow;
00338 return fromSharedPtrToNakedCast(pyBuildList(
00339 ContainerTraits<Container>::const_iterator_at(*cont_,ilow),
00340 ContainerTraits<Container>::const_iterator_at(*cont_,ilow+len) ));
00341 }
00342 template<typename Container, typename ContainerOwnerShipPolicy>
00343 int PySequenceContainer<Container,ContainerOwnerShipPolicy>::PySequence_AssItem(Py_ssize_t i, PyObject *v)
00344 {
00345 if (readOnly_)
00346 {
00347 PyErr_SetString(PyExc_TypeError, "Sequence is read-only");
00348 return -1;
00349 }
00350 if (i < 0 || i >= PySequence_Length())
00351 {
00352 PyErr_SetString(PyExc_IndexError,"list assignment index out of range");
00353 return -1;
00354 }
00355 if (v == NULL)
00356 return PySequence_AssSlice(i, i+1, v);
00357 return PyExportTraits<typename Container::value_type>::get(v,ContainerTraits<Container>::element_at(*cont_,i));
00358 }
00359 template<typename Container, typename ContainerOwnerShipPolicy>
00360 int PySequenceContainer<Container,ContainerOwnerShipPolicy>::PySequence_AssSlice(Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
00361 {
00362 if (readOnly_)
00363 {
00364 PyErr_SetString(PyExc_TypeError, "Sequence is read-only");
00365 return -1;
00366 }
00367 Container temp;
00368 int r = pyGetSequenceObject(v,temp);
00369 if (r)
00370 {
00371 PyErr_SetString(PyExc_TypeError, "Cannot convert to type for slice assignment");
00372 return -1;
00373 }
00374 cont_->erase( ContainerTraits<Container>::iterator_at(*cont_,ilow),
00375 ContainerTraits<Container>::iterator_at(*cont_,ihigh) );
00376 cont_->insert( ContainerTraits<Container>::iterator_at(*cont_,ilow+1),
00377 temp.begin(),temp.end());
00378 return 0;
00379 }
00380 template<typename Container, typename ContainerOwnerShipPolicy>
00381 int PySequenceContainer<Container,ContainerOwnerShipPolicy>::PySequence_Contains(PyObject *el)
00382 {
00383 typename Container::value_type temp;
00384 int r = PyExportTraits<typename Container::value_type>::get(el,temp);
00385 if (r)
00386 {
00387
00388
00389 return 0;
00390 }
00391 if (std::find(cont_->begin(),cont_->end(),temp)!=cont_->end())
00392 return 1;
00393 return 0;
00394 }
00395 template<typename Container, typename ContainerOwnerShipPolicy>
00396 int PySequenceContainer<Container,ContainerOwnerShipPolicy>::PySequence_InplaceConcat(PyObject *other)
00397 {
00398 if (readOnly_)
00399 {
00400 PyErr_SetString(PyExc_TypeError, "Sequence is read-only");
00401 return -1;
00402 }
00403 Container toConcat;
00404
00405 int r = pyGetSequenceObject(other,toConcat);
00406 if (r)
00407 {
00408 PyErr_SetString(PyExc_TypeError, "Cannot convert to concatenation type");
00409 return 1;
00410 }
00411 cont_->insert(cont_->end(), toConcat.begin(), toConcat.end());
00412 return 0;
00413 }
00414 template<typename Container, typename ContainerOwnerShipPolicy>
00415 int PySequenceContainer<Container,ContainerOwnerShipPolicy>::PySequence_InplaceRepeat(Py_ssize_t n)
00416 {
00417 if (readOnly_)
00418 {
00419 PyErr_SetString(PyExc_TypeError, "Sequence is read-only");
00420 return -1;
00421 }
00422 stde::inplace_repeat_c(*cont_,n);
00423 return 0;
00424 }
00425 template<typename Container, typename ContainerOwnerShipPolicy>
00426 void PySequenceContainer<Container,ContainerOwnerShipPolicy>::append(PyObject* i)
00427 {
00428 if (readOnly_)
00429 {
00430 PyErr_SetString(PyExc_TypeError, "Sequence is read-only");
00431 return;
00432 }
00433 typename Container::value_type temp;
00434 int r = PyExportTraits<typename Container::value_type>::get(i,temp);
00435 if (r)
00436 {
00437 PyErr_SetString(PyExc_TypeError, "Cannot convert to append type");
00438 return;
00439 }
00440 cont_->push_back( temp );
00441 }
00442 template<typename Container, typename ContainerOwnerShipPolicy>
00443 TPyObjPtr PySequenceContainer<Container,ContainerOwnerShipPolicy>::pop(int i)
00444 {
00445 if (readOnly_)
00446 {
00447 PyErr_SetString(PyExc_TypeError, "Sequence is read-only");
00448 return TPyObjPtr();
00449 }
00450 typename Container::value_type temp = ContainerTraits<Container>::element_at(*cont_,i);
00451 cont_->erase(ContainerTraits<Container>::iterator_at(*cont_,i));
00452 return fromNakedToSharedPtrCast<PyObject>(lass::python::PyExportTraits<typename Container::value_type>::build(temp));
00453 }
00454
00455 template<typename Container, typename ContainerOwnerShipPolicy>
00456 std::string PySequenceContainer<Container,ContainerOwnerShipPolicy>::pyStr( void)
00457 {
00458 return pyRepr();
00459 }
00460
00461 template<typename Container, typename ContainerOwnerShipPolicy>
00462 std::string PySequenceContainer<Container,ContainerOwnerShipPolicy>::pyRepr( void)
00463 {
00464 return util::stringCast<std::string>(*cont_);
00465 }
00466 }
00467
00468
00469
00470
00471
00472
00473 template <typename ContainerType>
00474 struct PyExportTraitsSequence
00475 {
00476 typedef ContainerType TContainer;
00477
00478
00479
00480
00481 static PyObject* build( const TContainer& iV)
00482 {
00483 return fromSharedPtrToNakedCast(impl::pyBuildTuple(iV.begin(),iV.end()));
00484 }
00485
00486
00487
00488
00489
00490 static PyObject* build(TContainer& iV)
00491 {
00492 return new impl::PySequence(iV);
00493 }
00494
00495
00496
00497
00498 static int get( PyObject* iV, TContainer& oV)
00499 {
00500 return impl::pyGetSequenceObject(iV, oV);
00501 }
00502 };
00503
00504
00505
00506
00507 template< typename C, typename A>
00508 struct PyExportTraits< std::vector< C, A > >:
00509 public PyExportTraitsSequence< std::vector< C, A > >
00510 {
00511 };
00512
00513
00514
00515
00516 template< typename C, typename A>
00517 struct PyExportTraits< std::list< C, A > >:
00518 public PyExportTraitsSequence< std::list< C, A > >
00519 {
00520 };
00521
00522
00523
00524
00525 template< typename C, typename A>
00526 struct PyExportTraits< std::deque< C, A > >:
00527 public PyExportTraitsSequence< std::deque< C, A > >
00528 {
00529 };
00530
00531
00532
00533
00534 template< typename C, size_t maxsize>
00535 struct PyExportTraits< stde::static_vector< C, maxsize > >:
00536 public PyExportTraitsSequence< stde::static_vector< C, maxsize > >
00537 {
00538 };
00539
00540
00541 }
00542
00543 }
00544
00545 #endif