File indexing completed on 2025-01-30 09:35:23
0001 #ifndef _DATE_TIME_INT_ADAPTER_HPP__
0002 #define _DATE_TIME_INT_ADAPTER_HPP__
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include "boost/config.hpp"
0014 #include "boost/limits.hpp" //work around compilers without limits
0015 #include "boost/date_time/special_defs.hpp"
0016 #include "boost/date_time/locale_config.hpp"
0017 #ifndef BOOST_DATE_TIME_NO_LOCALE
0018 # include <ostream>
0019 #endif
0020
0021 #if defined(BOOST_MSVC)
0022 #pragma warning(push)
0023
0024 #pragma warning(disable: 4127)
0025 #endif
0026
0027 namespace boost {
0028 namespace date_time {
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 template<typename int_type_>
0046 class int_adapter {
0047 public:
0048 typedef int_type_ int_type;
0049 BOOST_CXX14_CONSTEXPR int_adapter(int_type v) :
0050 value_(v)
0051 {}
0052 static BOOST_CONSTEXPR bool has_infinity()
0053 {
0054 return true;
0055 }
0056 static BOOST_CONSTEXPR int_adapter pos_infinity()
0057 {
0058 return (::std::numeric_limits<int_type>::max)();
0059 }
0060 static BOOST_CONSTEXPR int_adapter neg_infinity()
0061 {
0062 return (::std::numeric_limits<int_type>::min)();
0063 }
0064 static BOOST_CONSTEXPR int_adapter not_a_number()
0065 {
0066 return (::std::numeric_limits<int_type>::max)()-1;
0067 }
0068 static BOOST_CONSTEXPR int_adapter max BOOST_PREVENT_MACRO_SUBSTITUTION ()
0069 {
0070 return (::std::numeric_limits<int_type>::max)()-2;
0071 }
0072 static BOOST_CONSTEXPR int_adapter min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0073 {
0074 return (::std::numeric_limits<int_type>::min)()+1;
0075 }
0076 static BOOST_CXX14_CONSTEXPR int_adapter from_special(special_values sv)
0077 {
0078 switch (sv) {
0079 case not_a_date_time: return not_a_number();
0080 case neg_infin: return neg_infinity();
0081 case pos_infin: return pos_infinity();
0082 case max_date_time: return (max)();
0083 case min_date_time: return (min)();
0084 default: return not_a_number();
0085 }
0086 }
0087 static BOOST_CONSTEXPR bool is_inf(int_type v)
0088 {
0089 return (v == neg_infinity().as_number() ||
0090 v == pos_infinity().as_number());
0091 }
0092 static BOOST_CXX14_CONSTEXPR bool is_neg_inf(int_type v)
0093 {
0094 return (v == neg_infinity().as_number());
0095 }
0096 static BOOST_CXX14_CONSTEXPR bool is_pos_inf(int_type v)
0097 {
0098 return (v == pos_infinity().as_number());
0099 }
0100 static BOOST_CXX14_CONSTEXPR bool is_not_a_number(int_type v)
0101 {
0102 return (v == not_a_number().as_number());
0103 }
0104
0105 static BOOST_CXX14_CONSTEXPR special_values to_special(int_type v)
0106 {
0107 if (is_not_a_number(v)) return not_a_date_time;
0108 if (is_neg_inf(v)) return neg_infin;
0109 if (is_pos_inf(v)) return pos_infin;
0110 return not_special;
0111 }
0112
0113
0114 static BOOST_CONSTEXPR int_type maxcount()
0115 {
0116 return (::std::numeric_limits<int_type>::max)()-3;
0117 }
0118 BOOST_CONSTEXPR bool is_infinity() const
0119 {
0120 return (value_ == neg_infinity().as_number() ||
0121 value_ == pos_infinity().as_number());
0122 }
0123 BOOST_CONSTEXPR bool is_pos_infinity()const
0124 {
0125 return(value_ == pos_infinity().as_number());
0126 }
0127 BOOST_CONSTEXPR bool is_neg_infinity()const
0128 {
0129 return(value_ == neg_infinity().as_number());
0130 }
0131 BOOST_CONSTEXPR bool is_nan() const
0132 {
0133 return (value_ == not_a_number().as_number());
0134 }
0135 BOOST_CONSTEXPR bool is_special() const
0136 {
0137 return(is_infinity() || is_nan());
0138 }
0139 BOOST_CONSTEXPR bool operator==(const int_adapter& rhs) const
0140 {
0141 return (compare(rhs) == 0);
0142 }
0143 BOOST_CXX14_CONSTEXPR bool operator==(const int& rhs) const
0144 {
0145 if(!std::numeric_limits<int_type>::is_signed)
0146 {
0147 if(is_neg_inf(value_) && rhs == 0)
0148 {
0149 return false;
0150 }
0151 }
0152 return (compare(rhs) == 0);
0153 }
0154 BOOST_CONSTEXPR bool operator!=(const int_adapter& rhs) const
0155 {
0156 return (compare(rhs) != 0);
0157 }
0158 BOOST_CXX14_CONSTEXPR bool operator!=(const int& rhs) const
0159 {
0160 if(!std::numeric_limits<int_type>::is_signed)
0161 {
0162 if(is_neg_inf(value_) && rhs == 0)
0163 {
0164 return true;
0165 }
0166 }
0167 return (compare(rhs) != 0);
0168 }
0169 BOOST_CONSTEXPR bool operator<(const int_adapter& rhs) const
0170 {
0171 return (compare(rhs) == -1);
0172 }
0173 BOOST_CXX14_CONSTEXPR bool operator<(const int& rhs) const
0174 {
0175
0176 if(!std::numeric_limits<int_type>::is_signed)
0177 {
0178 if(is_neg_inf(value_) && rhs == 0)
0179 {
0180 return true;
0181 }
0182 }
0183 return (compare(rhs) == -1);
0184 }
0185 BOOST_CONSTEXPR bool operator>(const int_adapter& rhs) const
0186 {
0187 return (compare(rhs) == 1);
0188 }
0189 BOOST_CONSTEXPR int_type as_number() const
0190 {
0191 return value_;
0192 }
0193
0194 BOOST_CONSTEXPR special_values as_special() const
0195 {
0196 return int_adapter::to_special(value_);
0197 }
0198
0199
0200
0201
0202
0203
0204
0205
0206 template<class rhs_type>
0207 BOOST_CXX14_CONSTEXPR
0208 int_adapter operator+(const int_adapter<rhs_type>& rhs) const
0209 {
0210 if(is_special() || rhs.is_special())
0211 {
0212 if (is_nan() || rhs.is_nan())
0213 {
0214 return int_adapter::not_a_number();
0215 }
0216 if((is_pos_inf(value_) && rhs.is_neg_inf(rhs.as_number())) ||
0217 (is_neg_inf(value_) && rhs.is_pos_inf(rhs.as_number())) )
0218 {
0219 return int_adapter::not_a_number();
0220 }
0221 if (is_infinity())
0222 {
0223 return *this;
0224 }
0225 if (rhs.is_pos_inf(rhs.as_number()))
0226 {
0227 return int_adapter::pos_infinity();
0228 }
0229 if (rhs.is_neg_inf(rhs.as_number()))
0230 {
0231 return int_adapter::neg_infinity();
0232 }
0233 }
0234 return int_adapter<int_type>(value_ + static_cast<int_type>(rhs.as_number()));
0235 }
0236
0237 BOOST_CXX14_CONSTEXPR
0238 int_adapter operator+(const int_type rhs) const
0239 {
0240 if(is_special())
0241 {
0242 if (is_nan())
0243 {
0244 return int_adapter<int_type>(not_a_number());
0245 }
0246 if (is_infinity())
0247 {
0248 return *this;
0249 }
0250 }
0251 return int_adapter<int_type>(value_ + rhs);
0252 }
0253
0254
0255
0256 template<class rhs_type>
0257 BOOST_CXX14_CONSTEXPR
0258 int_adapter operator-(const int_adapter<rhs_type>& rhs)const
0259 {
0260 if(is_special() || rhs.is_special())
0261 {
0262 if (is_nan() || rhs.is_nan())
0263 {
0264 return int_adapter::not_a_number();
0265 }
0266 if((is_pos_inf(value_) && rhs.is_pos_inf(rhs.as_number())) ||
0267 (is_neg_inf(value_) && rhs.is_neg_inf(rhs.as_number())) )
0268 {
0269 return int_adapter::not_a_number();
0270 }
0271 if (is_infinity())
0272 {
0273 return *this;
0274 }
0275 if (rhs.is_pos_inf(rhs.as_number()))
0276 {
0277 return int_adapter::neg_infinity();
0278 }
0279 if (rhs.is_neg_inf(rhs.as_number()))
0280 {
0281 return int_adapter::pos_infinity();
0282 }
0283 }
0284 return int_adapter<int_type>(value_ - static_cast<int_type>(rhs.as_number()));
0285 }
0286
0287 BOOST_CXX14_CONSTEXPR
0288 int_adapter operator-(const int_type rhs) const
0289 {
0290 if(is_special())
0291 {
0292 if (is_nan())
0293 {
0294 return int_adapter<int_type>(not_a_number());
0295 }
0296 if (is_infinity())
0297 {
0298 return *this;
0299 }
0300 }
0301 return int_adapter<int_type>(value_ - rhs);
0302 }
0303
0304
0305 BOOST_CXX14_CONSTEXPR
0306 int_adapter operator*(const int_adapter& rhs)const
0307 {
0308 if(this->is_special() || rhs.is_special())
0309 {
0310 return mult_div_specials(rhs);
0311 }
0312 return int_adapter<int_type>(value_ * rhs.value_);
0313 }
0314
0315
0316
0317 BOOST_CXX14_CONSTEXPR
0318 int_adapter operator*(const int rhs) const
0319 {
0320 if(is_special())
0321 {
0322 return mult_div_specials(rhs);
0323 }
0324 return int_adapter<int_type>(value_ * rhs);
0325 }
0326
0327
0328 BOOST_CXX14_CONSTEXPR
0329 int_adapter operator/(const int_adapter& rhs)const
0330 {
0331 if(this->is_special() || rhs.is_special())
0332 {
0333 if(is_infinity() && rhs.is_infinity())
0334 {
0335 return int_adapter<int_type>(not_a_number());
0336 }
0337 if(rhs != 0)
0338 {
0339 return mult_div_specials(rhs);
0340 }
0341 else {
0342 return int_adapter<int_type>(value_ / rhs.value_);
0343 }
0344 }
0345 return int_adapter<int_type>(value_ / rhs.value_);
0346 }
0347
0348
0349
0350 BOOST_CXX14_CONSTEXPR
0351 int_adapter operator/(const int rhs) const
0352 {
0353 if(is_special() && rhs != 0)
0354 {
0355 return mult_div_specials(rhs);
0356 }
0357
0358 return int_adapter<int_type>(value_ / rhs);
0359 }
0360
0361
0362 BOOST_CXX14_CONSTEXPR
0363 int_adapter operator%(const int_adapter& rhs)const
0364 {
0365 if(this->is_special() || rhs.is_special())
0366 {
0367 if(is_infinity() && rhs.is_infinity())
0368 {
0369 return int_adapter<int_type>(not_a_number());
0370 }
0371 if(rhs != 0)
0372 {
0373 return mult_div_specials(rhs);
0374 }
0375 else {
0376 return int_adapter<int_type>(value_ % rhs.value_);
0377 }
0378 }
0379 return int_adapter<int_type>(value_ % rhs.value_);
0380 }
0381
0382
0383
0384 BOOST_CXX14_CONSTEXPR
0385 int_adapter operator%(const int rhs) const
0386 {
0387 if(is_special() && rhs != 0)
0388 {
0389 return mult_div_specials(rhs);
0390 }
0391
0392 return int_adapter<int_type>(value_ % rhs);
0393 }
0394
0395 private:
0396 int_type value_;
0397
0398
0399 BOOST_CXX14_CONSTEXPR
0400 int compare( const int_adapter& rhs ) const
0401 {
0402 if(this->is_special() || rhs.is_special())
0403 {
0404 if(this->is_nan() || rhs.is_nan()) {
0405 if(this->is_nan() && rhs.is_nan()) {
0406 return 0;
0407 }
0408 else {
0409 return 2;
0410 }
0411 }
0412 if((is_neg_inf(value_) && !is_neg_inf(rhs.value_)) ||
0413 (is_pos_inf(rhs.value_) && !is_pos_inf(value_)) )
0414 {
0415 return -1;
0416 }
0417 if((is_pos_inf(value_) && !is_pos_inf(rhs.value_)) ||
0418 (is_neg_inf(rhs.value_) && !is_neg_inf(value_)) ) {
0419 return 1;
0420 }
0421 }
0422 if(value_ < rhs.value_) return -1;
0423 if(value_ > rhs.value_) return 1;
0424
0425 return 0;
0426 }
0427
0428
0429
0430
0431
0432
0433 BOOST_CXX14_CONSTEXPR
0434 int_adapter mult_div_specials(const int_adapter& rhs) const
0435 {
0436 if(this->is_nan() || rhs.is_nan()) {
0437 return int_adapter<int_type>(not_a_number());
0438 }
0439 BOOST_CONSTEXPR_OR_CONST int min_value = std::numeric_limits<int_type>::is_signed ? 0 : 1;
0440 if((*this > 0 && rhs > 0) || (*this < min_value && rhs < min_value)) {
0441 return int_adapter<int_type>(pos_infinity());
0442 }
0443 if((*this > 0 && rhs < min_value) || (*this < min_value && rhs > 0)) {
0444 return int_adapter<int_type>(neg_infinity());
0445 }
0446
0447 return int_adapter<int_type>(not_a_number());
0448 }
0449
0450
0451
0452
0453
0454
0455
0456 BOOST_CXX14_CONSTEXPR
0457 int_adapter mult_div_specials(const int& rhs) const
0458 {
0459 if(this->is_nan()) {
0460 return int_adapter<int_type>(not_a_number());
0461 }
0462 BOOST_CONSTEXPR_OR_CONST int min_value = std::numeric_limits<int_type>::is_signed ? 0 : 1;
0463 if((*this > 0 && rhs > 0) || (*this < min_value && rhs < 0)) {
0464 return int_adapter<int_type>(pos_infinity());
0465 }
0466 if((*this > 0 && rhs < 0) || (*this < min_value && rhs > 0)) {
0467 return int_adapter<int_type>(neg_infinity());
0468 }
0469
0470 return int_adapter<int_type>(not_a_number());
0471 }
0472
0473 };
0474
0475 #ifndef BOOST_DATE_TIME_NO_LOCALE
0476
0477
0478
0479
0480 template<class charT, class traits, typename int_type>
0481 inline
0482 std::basic_ostream<charT, traits>&
0483 operator<<(std::basic_ostream<charT, traits>& os, const int_adapter<int_type>& ia)
0484 {
0485 if(ia.is_special()) {
0486
0487 switch(ia.as_special())
0488 {
0489 case not_a_date_time:
0490 os << "not-a-number";
0491 break;
0492 case pos_infin:
0493 os << "+infinity";
0494 break;
0495 case neg_infin:
0496 os << "-infinity";
0497 break;
0498 default:
0499 os << "";
0500 }
0501 }
0502 else {
0503 os << ia.as_number();
0504 }
0505 return os;
0506 }
0507 #endif
0508
0509
0510 } }
0511
0512 #if defined(BOOST_MSVC)
0513 #pragma warning(pop)
0514 #endif
0515
0516 #endif