00001
00005 #ifndef CURRENCY_HPP_
00006 #define CURRENCY_HPP_
00007
00008 #include <iomanip>
00009 #include <istream>
00010 #include <locale>
00011 #include <ostream>
00012 #include <sstream>
00013 #include <string>
00014 #include <stdexcept>
00015
00016 #include "ioflags.hpp"
00017 #include "fixed.hpp"
00018 #include "rational.hpp"
00019
00021 template<class T=long, int N=2>
00022 class currency
00023 {
00024 public:
00025 typedef T int_type;
00026 typedef fixed<T,N> value_type;
00027
00029 currency() : value_() {}
00032 currency(T integer) : value_(integer) {}
00039 currency(T integer, T fraction) : value_(integer, fraction) {}
00042 currency(double value) : value_(value) {}
00043
00045 template<class U, int M>
00046 currency(currency<U, M> const& rhs): value_(rhs.value()) {}
00047
00049 template<class U, int M>
00050 currency& operator=(currency<U, M> rhs)
00051 {
00052 value_ = rhs.value();
00053 return *this;
00054 }
00055
00058 std::string as_string() const;
00065 template<class Char, class Traits>
00066 bool read(std::basic_istream<Char, Traits>& strm);
00067
00070 template<class U>
00072 U convert() const { return value().convert<U>(); }
00073
00075 int_type round() const { return value().round(); }
00076
00078 int_type integer() const { return value().integer(); }
00080 template<int M>
00081 int_type fraction() const { return value().fraction<M>(); }
00083 int_type fraction() const { return value().fraction(); }
00084
00088 currency& operator+=(currency c);
00092 currency& operator-=(currency c);
00096 currency& operator*=(value_type m);
00100 currency& operator*=(int_type m);
00104 currency& operator/=(value_type m);
00108 currency& operator/=(int_type m);
00109
00111 void negate();
00112
00114 currency& operator++();
00116 currency operator++(int);
00118 currency& operator--();
00120 currency operator--(int);
00121
00123 value_type value() const { return value_; }
00124
00125 private:
00126 value_type value_;
00127 };
00128
00129 template<class T, int N>
00130 std::string currency<T,N>::as_string()
00131 const
00132 {
00133 std::ostringstream digits;
00134 digits.imbue(std::locale::classic());
00135 digits << integer() << std::setw(value_type::places) << std::setfill('0') << fraction();
00136
00137 std::ostringstream out;
00138 std::money_put<char> const& put(std::use_facet<std::money_put<char> >(std::locale()));
00139 put.put(std::ostreambuf_iterator<char>(out), false, out, '0', digits.str());
00140 return out.str();
00141 }
00142
00143 template<class T, int N>
00144 currency<T,N>& currency<T,N>::operator+=(currency f)
00145 {
00146 value_ += f.value();
00147 return *this;
00148 }
00149
00150 template<class T, int N>
00151 currency<T,N>& currency<T,N>::operator-=(currency f)
00152 {
00153 value_ -= f.value();
00154 return *this;
00155 }
00156
00157 template<class T, int N>
00158 currency<T,N>& currency<T,N>::operator*=(value_type i)
00159 {
00160 value_ *= i;
00161 return *this;
00162 }
00163 template<class T, int N>
00164 currency<T,N>& currency<T,N>::operator*=(int_type i)
00165 {
00166 value_ *= i;
00167 return *this;
00168 }
00169
00170 template<class T, int N>
00171 currency<T,N>& currency<T,N>::operator/=(value_type i)
00172 {
00173 value_ /= i;
00174 return *this;
00175 }
00176 template<class T, int N>
00177 currency<T,N>& currency<T,N>::operator/=(int_type i)
00178 {
00179 value_ /= i;
00180 return *this;
00181 }
00182
00183 template<class T, int N>
00184 void currency<T,N>::negate()
00185 {
00186 value_ = -value_;
00187 }
00188
00189 template<class T, int N>
00190 currency<T,N>& currency<T,N>::operator++()
00191 {
00192 ++value_;
00193 return *this;
00194 }
00195
00196 template<class T, int N>
00197 currency<T,N> currency<T,N>::operator++(int)
00198 {
00199 currency result(*this);
00200 ++value_;
00201 return result;
00202 }
00203
00204 template<class T, int N>
00205 currency<T,N>& currency<T,N>::operator--()
00206 {
00207 --value_;
00208 return *this;
00209 }
00210
00211 template<class T, int N>
00212 currency<T,N> currency<T,N>::operator--(int)
00213 {
00214 currency result(*this);
00215 --value_;
00216 return result;
00217 }
00218
00219 template<class T, int N>
00220 template<class CharT, class Traits>
00221 bool currency<T,N>::read(std::basic_istream<CharT,Traits>& strm)
00222 {
00223 ioflags flags(strm);
00224 typename std::basic_istream<CharT, Traits>::sentry sentry(strm, false);
00225 if (not sentry)
00226 return false;
00227
00228 std::ios_base::iostate error(std::ios_base::goodbit);
00229 std::string digits;
00230 std::money_get<CharT> const& get(
00231 std::use_facet<std::money_get<CharT> >(strm.getloc()));
00232 get.get(std::istreambuf_iterator<CharT>(strm), std::istreambuf_iterator<CharT>(),
00233 false, strm, error, digits);
00234
00235 if ((error & std::ios_base::failbit) != 0)
00236 return false;
00237
00238 std::moneypunct<CharT> const& punct(
00239 std::use_facet<std::moneypunct<CharT> >(strm.getloc()));
00240
00241
00242 std::string fraction(digits.substr(digits.size() - punct.frac_digits(), punct.frac_digits()));
00243
00244 std::string integer(digits.substr(0, digits.size() - punct.frac_digits()));
00245
00246 std::istringstream fixed_stream(integer + "." + fraction);
00247 return value_.read(fixed_stream);
00248 }
00249
00253 template<class T, int N, class Char, class Traits>
00254 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& strm, currency<T,N>& c)
00255 {
00256 if (not c.read(strm))
00257 strm.setstate(strm.failbit);
00258 return strm;
00259 }
00260
00264 template<class T, int N, class Char, class Traits>
00265 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& strm, currency<T,N> c)
00266 {
00267 typename std::basic_ostream<Char, Traits>::sentry sentry(strm);
00268 strm << c.as_string();
00269 return strm;
00270 }
00271
00273 template<class T, int N>
00274 currency<T,N> operator-(currency<T,N> a)
00275 {
00276 a.negate();
00277 return a;
00278 }
00279
00283 template<class T, int N>
00284 currency<T,N> operator+(currency<T,N> a, currency<T,N> b)
00285 {
00286 a += b;
00287 return a;
00288 }
00289
00293 template<class T, int N>
00294 currency<T,N> operator-(currency<T,N> a, currency<T,N> b)
00295 {
00296 a -= b;
00297 return a;
00298 }
00299
00303 template<class T, int N>
00304 currency<T,N> operator*(currency<T,N> a, T b)
00305 {
00306 a *= b;
00307 return a;
00308 }
00309
00313 template<class T, int N>
00314 currency<T,N> operator*(T a, currency<T,N> b)
00315 {
00316 b *= a;
00317 return b;
00318 }
00319
00323 template<class T, int N>
00324 currency<T,N> operator/(currency<T,N> a, T b)
00325 {
00326 a /= b;
00327 return a;
00328 }
00329
00333 template<class T, int N>
00334 rational<T> operator/(currency<T,N> n, currency<T,N> d)
00335 {
00336
00337
00338
00339 return rational<T>(n.value().value(), d.value().value());
00340 }
00341
00345 template<class T, int N>
00346 bool operator==(currency<T,N> a, currency<T,N> b)
00347 {
00348 return a.value() == b.value();
00349 }
00353 template<class T, int N>
00354 bool operator==(currency<T,N> a, T b)
00355 {
00356 return a.value() == b;
00357 }
00361 template<class T, int N>
00362 bool operator==(T a, currency<T,N> b)
00363 {
00364 return a == b.value();
00365 }
00366
00370 template<class T, int N>
00371 inline bool operator!=(currency<T,N> a, currency<T,N> b)
00372 {
00373 return not (a == b);
00374 }
00378 template<class T, int N>
00379 inline bool operator!=(currency<T,N> a, T b)
00380 {
00381 return not (a == b);
00382 }
00386 template<class T, int N>
00387 inline bool operator!=(T a, currency<T,N> b)
00388 {
00389 return not (a == b);
00390 }
00391
00395 template<class T, int N>
00396 bool operator<(currency<T,N> a, currency<T,N> b)
00397 {
00398 return a.value() < b.value();
00399 }
00403 template<class T, int N>
00404 bool operator<(currency<T,N> a, T b)
00405 {
00406 return a.value() < b;
00407 }
00411 template<class T, int N>
00412 bool operator<(T a, currency<T,N> b)
00413 {
00414 return a < b.value();
00415 }
00416
00420 template<class T, int N>
00421 inline bool operator>(currency<T,N> a, currency<T,N> b)
00422 {
00423 return b < a;
00424 }
00428 template<class T, int N>
00429 inline bool operator>(currency<T,N> a, T b)
00430 {
00431 return b < a;
00432 }
00436 template<class T, int N>
00437 inline bool operator>(T a, currency<T,N> b)
00438 {
00439 return b < a;
00440 }
00441
00445 template<class T, int N>
00446 inline bool operator<=(currency<T,N> a, currency<T,N> b)
00447 {
00448 return not (b < a);
00449 }
00453 template<class T, int N>
00454 inline bool operator<=(currency<T,N> a, T b)
00455 {
00456 return not (b < a);
00457 }
00461 template<class T, int N>
00462 inline bool operator<=(T a, currency<T,N> b)
00463 {
00464 return not (b < a);
00465 }
00466
00470 template<class T, int N>
00471 inline bool operator>=(currency<T,N> a, currency<T,N> b)
00472 {
00473 return not (a < b);
00474 }
00478 template<class T, int N>
00479 inline bool operator>=(currency<T,N> a, T b)
00480 {
00481 return not (a < b);
00482 }
00486 template<class T, int N>
00487 inline bool operator>=(T a, currency<T,N> b)
00488 {
00489 return not (a < b);
00490 }
00491
00492 #endif