Chris@16: #ifndef _DATE_TIME_WRAPPING_INT_HPP__ Chris@16: #define _DATE_TIME_WRAPPING_INT_HPP__ Chris@16: Chris@16: /* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. Chris@16: * Use, modification and distribution is subject to the Chris@16: * Boost Software License, Version 1.0. (See accompanying Chris@16: * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) Chris@16: * Author: Jeff Garland, Bart Garst Chris@101: * $Date$ Chris@16: */ Chris@16: Chris@16: Chris@16: namespace boost { Chris@16: namespace date_time { Chris@16: Chris@16: //! A wrapping integer used to support time durations (WARNING: only instantiate with a signed type) Chris@16: /*! In composite date and time types this type is used to Chris@16: * wrap at the day boundary. Chris@16: * Ex: Chris@16: * A wrapping_int will roll over after nine, and Chris@16: * roll under below zero. This gives a range of [0,9] Chris@16: * Chris@16: * NOTE: it is strongly recommended that wrapping_int2 be used Chris@16: * instead of wrapping_int as wrapping_int is to be depricated Chris@16: * at some point soon. Chris@16: * Chris@16: * Also Note that warnings will occur if instantiated with an Chris@16: * unsigned type. Only a signed type should be used! Chris@16: */ Chris@16: template Chris@16: class wrapping_int { Chris@16: public: Chris@16: typedef int_type_ int_type; Chris@16: //typedef overflow_type_ overflow_type; Chris@16: static int_type wrap_value() {return wrap_val;} Chris@16: //!Add, return true if wrapped Chris@16: wrapping_int(int_type v) : value_(v) {} Chris@16: //! Explicit converion method Chris@16: int_type as_int() const {return value_;} Chris@16: operator int_type() const {return value_;} Chris@16: //!Add, return number of wraps performed Chris@16: /*! The sign of the returned value will indicate which direction the Chris@16: * wraps went. Ex: add a negative number and wrapping under could occur, Chris@16: * this would be indicated by a negative return value. If wrapping over Chris@16: * took place, a positive value would be returned */ Chris@16: template< typename IntT > Chris@16: IntT add(IntT v) Chris@16: { Chris@16: int_type remainder = static_cast(v % (wrap_val)); Chris@16: IntT overflow = static_cast(v / (wrap_val)); Chris@16: value_ = static_cast(value_ + remainder); Chris@16: return calculate_wrap(overflow); Chris@16: } Chris@16: //! Subtract will return '+d' if wrapping under took place ('d' is the number of wraps) Chris@16: /*! The sign of the returned value will indicate which direction the Chris@16: * wraps went (positive indicates wrap under, negative indicates wrap over). Chris@16: * Ex: subtract a negative number and wrapping over could Chris@16: * occur, this would be indicated by a negative return value. If Chris@16: * wrapping under took place, a positive value would be returned. */ Chris@16: template< typename IntT > Chris@16: IntT subtract(IntT v) Chris@16: { Chris@16: int_type remainder = static_cast(v % (wrap_val)); Chris@16: IntT underflow = static_cast(-(v / (wrap_val))); Chris@16: value_ = static_cast(value_ - remainder); Chris@16: return calculate_wrap(underflow) * -1; Chris@16: } Chris@16: private: Chris@16: int_type value_; Chris@16: Chris@16: template< typename IntT > Chris@16: IntT calculate_wrap(IntT wrap) Chris@16: { Chris@16: if ((value_) >= wrap_val) Chris@16: { Chris@16: ++wrap; Chris@16: value_ -= (wrap_val); Chris@16: } Chris@16: else if(value_ < 0) Chris@16: { Chris@16: --wrap; Chris@16: value_ += (wrap_val); Chris@16: } Chris@16: return wrap; Chris@16: } Chris@16: Chris@16: }; Chris@16: Chris@16: Chris@16: //! A wrapping integer used to wrap around at the top (WARNING: only instantiate with a signed type) Chris@16: /*! Bad name, quick impl to fix a bug -- fix later!! Chris@16: * This allows the wrap to restart at a value other than 0. Chris@16: */ Chris@16: template Chris@16: class wrapping_int2 { Chris@16: public: Chris@16: typedef int_type_ int_type; Chris@16: static int_type wrap_value() {return wrap_max;} Chris@16: static int_type min_value() {return wrap_min;} Chris@16: /*! If initializing value is out of range of [wrap_min, wrap_max], Chris@16: * value will be initialized to closest of min or max */ Chris@16: wrapping_int2(int_type v) : value_(v) { Chris@16: if(value_ < wrap_min) Chris@16: { Chris@16: value_ = wrap_min; Chris@16: } Chris@16: if(value_ > wrap_max) Chris@16: { Chris@16: value_ = wrap_max; Chris@16: } Chris@16: } Chris@16: //! Explicit converion method Chris@16: int_type as_int() const {return value_;} Chris@16: operator int_type() const {return value_;} Chris@16: //!Add, return number of wraps performed Chris@16: /*! The sign of the returned value will indicate which direction the Chris@16: * wraps went. Ex: add a negative number and wrapping under could occur, Chris@16: * this would be indicated by a negative return value. If wrapping over Chris@16: * took place, a positive value would be returned */ Chris@16: template< typename IntT > Chris@16: IntT add(IntT v) Chris@16: { Chris@16: int_type remainder = static_cast(v % (wrap_max - wrap_min + 1)); Chris@16: IntT overflow = static_cast(v / (wrap_max - wrap_min + 1)); Chris@16: value_ = static_cast(value_ + remainder); Chris@16: return calculate_wrap(overflow); Chris@16: } Chris@16: //! Subtract will return '-d' if wrapping under took place ('d' is the number of wraps) Chris@16: /*! The sign of the returned value will indicate which direction the Chris@16: * wraps went. Ex: subtract a negative number and wrapping over could Chris@16: * occur, this would be indicated by a positive return value. If Chris@16: * wrapping under took place, a negative value would be returned */ Chris@16: template< typename IntT > Chris@16: IntT subtract(IntT v) Chris@16: { Chris@16: int_type remainder = static_cast(v % (wrap_max - wrap_min + 1)); Chris@16: IntT underflow = static_cast(-(v / (wrap_max - wrap_min + 1))); Chris@16: value_ = static_cast(value_ - remainder); Chris@16: return calculate_wrap(underflow); Chris@16: } Chris@16: Chris@16: private: Chris@16: int_type value_; Chris@16: Chris@16: template< typename IntT > Chris@16: IntT calculate_wrap(IntT wrap) Chris@16: { Chris@16: if ((value_) > wrap_max) Chris@16: { Chris@16: ++wrap; Chris@16: value_ -= (wrap_max - wrap_min + 1); Chris@16: } Chris@16: else if((value_) < wrap_min) Chris@16: { Chris@16: --wrap; Chris@16: value_ += (wrap_max - wrap_min + 1); Chris@16: } Chris@16: return wrap; Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: } } //namespace date_time Chris@16: Chris@16: Chris@16: Chris@16: #endif Chris@16: