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