From f587a1b684a72f27a1cee482db1aa6d3851f838a Mon Sep 17 00:00:00 2001 From: Raoul Gough Date: Wed, 10 Sep 2003 15:37:45 +0000 Subject: [PATCH] TypeWrapper for Python slice objects [SVN r1525] --- include/boost/python/suite/indexing/slice.cpp | 93 +++++++++++++++++++ include/boost/python/suite/indexing/slice.hpp | 71 ++++++++++++++ 2 files changed, 164 insertions(+) create mode 100755 include/boost/python/suite/indexing/slice.cpp create mode 100755 include/boost/python/suite/indexing/slice.hpp diff --git a/include/boost/python/suite/indexing/slice.cpp b/include/boost/python/suite/indexing/slice.cpp new file mode 100755 index 00000000..3247860b --- /dev/null +++ b/include/boost/python/suite/indexing/slice.cpp @@ -0,0 +1,93 @@ +// -*- mode:c++ -*- +// +// Module slice.cpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// This material is provided "as is", with absolutely no warranty expressed +// or implied. Any use is at your own risk. +// +// Permission to use or copy this material for any purpose is hereby +// granted without fee, provided the above notices are retained on all +// copies. Permission to modify the material and to distribute modified +// versions is granted, provided the above notices are retained, and a +// notice that the material was modified is included with the above +// copyright notice. +// +// History +// ======= +// 2003/ 9/10 rmg File creation +// +// $Id$ +// + +#include "slice.hpp" + +///////////////////////////////////////////////////////////////////////////// +// Check that setLength has been called, and throw otherwise +///////////////////////////////////////////////////////////////////////////// + +void indexing::slice::validate () const +{ + if (mDirection == 0) + { + PyErr_SetString (PyExc_RuntimeError + , "slice access attempted before setLength called"); + boost::python::throw_error_already_set(); + } +} + +///////////////////////////////////////////////////////////////////////////// +// Slice constructor +///////////////////////////////////////////////////////////////////////////// + +indexing::slice::slice (boost::python::detail::borrowed_reference ref) + : boost::python::object (ref) + , mStart (0) + , mStep (0) + , mStop (0) + , mDirection (0) +{ + if (!PySlice_Check (this->ptr())) + { + PyErr_SetString (PyExc_TypeError + , "slice constructor: passed a non-slice object"); + + boost::python::throw_error_already_set(); + } + + // This slice object is useless until setLength is called +} + +///////////////////////////////////////////////////////////////////////////// +// Set up our member variables for a sequence of a given length +///////////////////////////////////////////////////////////////////////////// + +void indexing::slice::setLength (int sequenceLength) +{ + PySlice_GetIndices ((PySliceObject *) this->ptr() + , sequenceLength + , &mStart + , &mStop + , &mStep); + + if (mStep == 0) + { + // Can happen with Python prior to 2.3 + PyErr_SetString (PyExc_ValueError, "slice step cannot be zero"); + boost::python::throw_error_already_set (); + } + + mStart = std::max (0, std::min (sequenceLength, mStart)); + mStop = std::max (0, std::min (sequenceLength, mStop)); + mDirection = (mStep > 0) ? 1 : -1; +} + +///////////////////////////////////////////////////////////////////////////// +// Check if an index is within the range of this slice +///////////////////////////////////////////////////////////////////////////// + +bool indexing::slice::inRange (int index) +{ + return ((mStop - index) * mDirection) > 0; +} diff --git a/include/boost/python/suite/indexing/slice.hpp b/include/boost/python/suite/indexing/slice.hpp new file mode 100755 index 00000000..3c626a01 --- /dev/null +++ b/include/boost/python/suite/indexing/slice.hpp @@ -0,0 +1,71 @@ +// -*- mode:c++ -*- +// +// Header file slice.hpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// This material is provided "as is", with absolutely no warranty expressed +// or implied. Any use is at your own risk. +// +// Permission to use or copy this material for any purpose is hereby +// granted without fee, provided the above notices are retained on all +// copies. Permission to modify the material and to distribute modified +// versions is granted, provided the above notices are retained, and a +// notice that the material was modified is included with the above +// copyright notice. +// +// History +// ======= +// 2003/ 9/10 rmg File creation +// +// $Id$ +// + +#ifndef slice_rmg_20030910_included +#define slice_rmg_20030910_included + +#include +#include +#include + +namespace indexing +{ + struct slice : public boost::python::object + { + // + // *** WARNING *** + // + // A newly constructed slice object is useless until setLength is called + // + + slice (boost::python::detail::borrowed_reference ref); + void setLength (int sequenceLength); + + int start() const { validate(); return mStart; } + int step() const { validate(); return mStep; } + int stop() const { validate(); return mStop; } + + int size() const { validate(); return (mStop - mStart) / mStep; } + + bool inRange (int index); + + private: + void validate () const; // throws unless setLength has been called + + int mStart; + int mStep; + int mStop; + int mDirection; + }; +} + +namespace boost { namespace python { namespace converter { + // Specialized converter to handle PySlice_Type objects + template<> + struct object_manager_traits + : pytype_object_manager_traits<&PySlice_Type, ::indexing::slice> + { + }; +}}} + +#endif // slice_rmg_20030910_included