1 #ifndef _DATE_TIME_WRAPPING_INT_HPP__ 2 #define _DATE_TIME_WRAPPING_INT_HPP__ 3 4 /* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. 5 * Use, modification and distribution is subject to the 6 * Boost Software License, Version 1.0. (See accompanying 7 * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) 8 * Author: Jeff Garland, Bart Garst 9 * $Date$ 10 */ 11 12 #include "boost/config.hpp" 13 14 namespace boost { 15 namespace date_time { 16 17 //! A wrapping integer used to support time durations (WARNING: only instantiate with a signed type) 18 /*! In composite date and time types this type is used to 19 * wrap at the day boundary. 20 * Ex: 21 * A wrapping_int<short, 10> will roll over after nine, and 22 * roll under below zero. This gives a range of [0,9] 23 * 24 * NOTE: it is strongly recommended that wrapping_int2 be used 25 * instead of wrapping_int as wrapping_int is to be depricated 26 * at some point soon. 27 * 28 * Also Note that warnings will occur if instantiated with an 29 * unsigned type. Only a signed type should be used! 30 */ 31 template<typename int_type_, int_type_ wrap_val> 32 class wrapping_int { 33 public: 34 typedef int_type_ int_type; 35 //typedef overflow_type_ overflow_type; wrap_value()36 static BOOST_CONSTEXPR int_type wrap_value() {return wrap_val;} 37 //!Add, return true if wrapped wrapping_int(int_type v)38 BOOST_CXX14_CONSTEXPR wrapping_int(int_type v) : value_(v) {} 39 //! Explicit converion method as_int() const40 BOOST_CONSTEXPR int_type as_int() const {return value_;} operator int_type() const41 BOOST_CONSTEXPR operator int_type() const {return value_;} 42 //!Add, return number of wraps performed 43 /*! The sign of the returned value will indicate which direction the 44 * wraps went. Ex: add a negative number and wrapping under could occur, 45 * this would be indicated by a negative return value. If wrapping over 46 * took place, a positive value would be returned */ 47 template< typename IntT > add(IntT v)48 BOOST_CXX14_CONSTEXPR IntT add(IntT v) 49 { 50 int_type remainder = static_cast<int_type>(v % (wrap_val)); 51 IntT overflow = static_cast<IntT>(v / (wrap_val)); 52 value_ = static_cast<int_type>(value_ + remainder); 53 return calculate_wrap(overflow); 54 } 55 //! Subtract will return '+d' if wrapping under took place ('d' is the number of wraps) 56 /*! The sign of the returned value will indicate which direction the 57 * wraps went (positive indicates wrap under, negative indicates wrap over). 58 * Ex: subtract a negative number and wrapping over could 59 * occur, this would be indicated by a negative return value. If 60 * wrapping under took place, a positive value would be returned. */ 61 template< typename IntT > subtract(IntT v)62 BOOST_CXX14_CONSTEXPR IntT subtract(IntT v) 63 { 64 int_type remainder = static_cast<int_type>(v % (wrap_val)); 65 IntT underflow = static_cast<IntT>(-(v / (wrap_val))); 66 value_ = static_cast<int_type>(value_ - remainder); 67 return calculate_wrap(underflow) * -1; 68 } 69 private: 70 int_type value_; 71 72 template< typename IntT > calculate_wrap(IntT wrap)73 BOOST_CXX14_CONSTEXPR IntT calculate_wrap(IntT wrap) 74 { 75 if ((value_) >= wrap_val) 76 { 77 ++wrap; 78 value_ -= (wrap_val); 79 } 80 else if(value_ < 0) 81 { 82 --wrap; 83 value_ += (wrap_val); 84 } 85 return wrap; 86 } 87 88 }; 89 90 91 //! A wrapping integer used to wrap around at the top (WARNING: only instantiate with a signed type) 92 /*! Bad name, quick impl to fix a bug -- fix later!! 93 * This allows the wrap to restart at a value other than 0. 94 */ 95 template<typename int_type_, int_type_ wrap_min, int_type_ wrap_max> 96 class wrapping_int2 { 97 public: 98 typedef int_type_ int_type; wrap_value()99 static BOOST_CONSTEXPR int_type wrap_value() {return wrap_max;} min_value()100 static BOOST_CONSTEXPR int_type min_value() {return wrap_min;} 101 /*! If initializing value is out of range of [wrap_min, wrap_max], 102 * value will be initialized to closest of min or max */ wrapping_int2(int_type v)103 BOOST_CXX14_CONSTEXPR wrapping_int2(int_type v) : value_(v) { 104 if(value_ < wrap_min) 105 { 106 value_ = wrap_min; 107 } 108 if(value_ > wrap_max) 109 { 110 value_ = wrap_max; 111 } 112 } 113 //! Explicit converion method as_int() const114 BOOST_CONSTEXPR int_type as_int() const {return value_;} operator int_type() const115 BOOST_CONSTEXPR operator int_type() const {return value_;} 116 //!Add, return number of wraps performed 117 /*! The sign of the returned value will indicate which direction the 118 * wraps went. Ex: add a negative number and wrapping under could occur, 119 * this would be indicated by a negative return value. If wrapping over 120 * took place, a positive value would be returned */ 121 template< typename IntT > add(IntT v)122 BOOST_CXX14_CONSTEXPR IntT add(IntT v) 123 { 124 int_type remainder = static_cast<int_type>(v % (wrap_max - wrap_min + 1)); 125 IntT overflow = static_cast<IntT>(v / (wrap_max - wrap_min + 1)); 126 value_ = static_cast<int_type>(value_ + remainder); 127 return calculate_wrap(overflow); 128 } 129 //! Subtract will return '-d' if wrapping under took place ('d' is the number of wraps) 130 /*! The sign of the returned value will indicate which direction the 131 * wraps went. Ex: subtract a negative number and wrapping over could 132 * occur, this would be indicated by a positive return value. If 133 * wrapping under took place, a negative value would be returned */ 134 template< typename IntT > subtract(IntT v)135 BOOST_CXX14_CONSTEXPR IntT subtract(IntT v) 136 { 137 int_type remainder = static_cast<int_type>(v % (wrap_max - wrap_min + 1)); 138 IntT underflow = static_cast<IntT>(-(v / (wrap_max - wrap_min + 1))); 139 value_ = static_cast<int_type>(value_ - remainder); 140 return calculate_wrap(underflow); 141 } 142 143 private: 144 int_type value_; 145 146 template< typename IntT > calculate_wrap(IntT wrap)147 BOOST_CXX14_CONSTEXPR IntT calculate_wrap(IntT wrap) 148 { 149 if ((value_) > wrap_max) 150 { 151 ++wrap; 152 value_ -= (wrap_max - wrap_min + 1); 153 } 154 else if((value_) < wrap_min) 155 { 156 --wrap; 157 value_ += (wrap_max - wrap_min + 1); 158 } 159 return wrap; 160 } 161 }; 162 163 164 165 } } //namespace date_time 166 167 168 169 #endif 170 171