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
14namespace boost {
15namespace 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 */
31template<typename int_type_, int_type_ wrap_val>
32class wrapping_int {
33public:
34 typedef int_type_ int_type;
35 //typedef overflow_type_ overflow_type;
36 static BOOST_CONSTEXPR int_type wrap_value() {return wrap_val;}
37 //!Add, return true if wrapped
38 BOOST_CXX14_CONSTEXPR wrapping_int(int_type v) : value_(v) {}
39 //! Explicit converion method
40 BOOST_CONSTEXPR int_type as_int() const {return value_;}
41 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 >
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 >
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 }
69private:
70 int_type value_;
71
72 template< typename IntT >
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 */
95template<typename int_type_, int_type_ wrap_min, int_type_ wrap_max>
96class wrapping_int2 {
97public:
98 typedef int_type_ int_type;
99 static BOOST_CONSTEXPR int_type wrap_value() {return wrap_max;}
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 */
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
114 BOOST_CONSTEXPR int_type as_int() const {return value_;}
115 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 >
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 >
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
143private:
144 int_type value_;
145
146 template< typename IntT >
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

source code of include/boost/date_time/wrapping_int.hpp