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