Loading...
Searching...
No Matches
amount.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003-2023, John Wiegley. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of New Artisans LLC nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
53#pragma once
54
55#include "utils.h"
56#include "times.h"
57#include "flags.h"
58
59namespace ledger {
60
61class commodity_t;
62struct annotation_t;
63struct keep_details_t;
64
65DECLARE_EXCEPTION(amount_error, std::runtime_error);
66
78
80
92 : public ordered_field_operators<amount_t,
93 ordered_field_operators<amount_t, double,
94 ordered_field_operators<amount_t, unsigned long,
95 ordered_field_operators<amount_t, long> > > >
96{
97public:
100 static void initialize();
103 static void shutdown();
104
105 static bool is_initialized;
106
108 typedef uint_least16_t precision_t;
109
112 static const std::size_t extend_by_digits = 6U;
113
118
119protected:
120 void _copy(const amount_t& amt);
121 void _dup();
122 void _clear();
123 void _release();
124
125 struct bigint_t;
126
127 bigint_t * quantity;
129
130public:
137 amount_t() : quantity(NULL), commodity_(NULL) {
138 TRACE_CTOR(amount_t, "");
139 }
140
143 amount_t(const double val);
144
146 amount_t(const unsigned long val);
147
150 amount_t(const long val);
151
156 explicit amount_t(const string& val) : quantity(NULL) {
157 parse(val);
158 TRACE_CTOR(amount_t, "const string&");
159 }
164 explicit amount_t(const char * val) : quantity(NULL) {
165 assert(val);
166 parse(val);
167 TRACE_CTOR(amount_t, "const char *");
168 }
169
179 static amount_t exact(const string& value);
180
185 if (quantity)
186 _release();
187 }
188
196 amount_t(const amount_t& amt) : quantity(NULL) {
197 if (amt.quantity)
198 _copy(amt);
199 else
200 commodity_ = NULL;
201 TRACE_CTOR(amount_t, "copy");
202 }
207 amount_t(const amount_t& amt, const annotation_t& details) : quantity(NULL) {
208 assert(amt.quantity);
209 _copy(amt);
210 annotate(details);
211 TRACE_CTOR(amount_t, "const amount_t&, const annotation_t&");
212 }
217
218 amount_t& operator=(const double val) {
219 return *this = amount_t(val);
220 }
221 amount_t& operator=(const unsigned long val) {
222 return *this = amount_t(val);
223 }
224 amount_t& operator=(const long val) {
225 return *this = amount_t(val);
226 }
227
228 /* Assign a string to an amount. This causes the contents of the
229 string to be parsed, look for a commoditized or uncommoditized
230 amount specifier. */
231 amount_t& operator=(const string& str) {
232 return *this = amount_t(str);
233 }
234 amount_t& operator=(const char * str) {
235 assert(str);
236 return *this = amount_t(str);
237 }
238
248 int compare(const amount_t& amt) const;
249
253 bool operator==(const amount_t& amt) const;
254
255 template <typename T>
256 bool operator==(const T& val) const {
257 return compare(val) == 0;
258 }
259 template <typename T>
260 bool operator<(const T& amt) const {
261 return compare(amt) < 0;
262 }
263 template <typename T>
264 bool operator>(const T& amt) const {
265 return compare(amt) > 0;
266 }
267
273
277 return multiply(amt);
278 }
279 amount_t& multiply(const amount_t& amt, bool ignore_commodity = false);
280
287
300 bool keep_precision() const;
301 void set_keep_precision(const bool keep = true) const;
303
308 amount_t temp(*this);
309 temp.in_place_negate();
310 return temp;
311 }
313
315 return negated();
316 }
317
323 amount_t abs() const {
324 if (sign() < 0)
325 return negated();
326 return *this;
327 }
328
330 amount_t temp(*this);
331 temp.in_place_invert();
332 return temp;
333 }
335
342 amount_t temp(*this);
343 temp.in_place_round();
344 return temp;
345 }
347
348 amount_t roundto(int places) const {
349 amount_t temp(*this);
350 temp.in_place_roundto(places);
351 return temp;
352 }
353 void in_place_roundto(int places);
354
358 amount_t temp(*this);
359 temp.in_place_truncate();
360 return temp;
361 }
363
367 amount_t temp(*this);
368 temp.in_place_floor();
369 return temp;
370 }
372
376 amount_t temp(*this);
377 temp.in_place_ceiling();
378 return temp;
379 }
381
385 amount_t temp(*this);
386 temp.in_place_unround();
387 return temp;
388 }
390
396 amount_t temp(*this);
397 temp.in_place_reduce();
398 return temp;
399 }
401
407 amount_t temp(*this);
408 temp.in_place_unreduce();
409 return temp;
410 }
412
421 optional<amount_t>
422 value(const datetime_t& moment = datetime_t(),
423 const commodity_t * in_terms_of = NULL) const;
424
425 optional<amount_t> price() const;
426
432
456 int sign() const;
457
458 operator bool() const {
459 return is_nonzero();
460 }
461 bool is_nonzero() const {
462 return ! is_zero();
463 }
464
465 bool is_zero() const;
466 bool is_realzero() const {
467 return sign() == 0;
468 }
469
470 bool is_null() const {
471 if (! quantity) {
473 return true;
474 }
475 return false;
476 }
477
483
514 double to_double() const;
515 long to_long() const;
516 bool fits_in_long() const;
517
518 operator string() const {
519 return to_string();
520 }
521 string to_string() const;
522 string to_fullstring() const;
523 string quantity_string() const;
524
530
553 return *commodity_ptr();
554 }
555
556 bool has_commodity() const;
558 if (! quantity)
559 *this = 0L;
560 commodity_ = &comm;
561 }
563 if (commodity_ == &comm) {
564 return *this;
565 } else {
566 amount_t tmp(*this);
567 tmp.set_commodity(const_cast<commodity_t&>(comm));
568 return tmp;
569 }
570 }
572 commodity_ = NULL;
573 }
574
575 amount_t number() const {
576 if (! has_commodity())
577 return *this;
578
579 amount_t temp(*this);
580 temp.clear_commodity();
581 return temp;
582 }
583
589
609 void annotate(const annotation_t& details);
610 bool has_annotation() const;
611
613 const annotation_t& annotation() const {
614 return const_cast<amount_t&>(*this).annotation();
615 }
616
632 amount_t strip_annotations(const keep_details_t& what_to_keep) const;
633
639
680 bool parse(std::istream& in,
681 const parse_flags_t& flags = PARSE_DEFAULT);
682 bool parse(const string& str,
683 const parse_flags_t& flags = PARSE_DEFAULT) {
684 std::istringstream stream(str);
685 bool result = parse(stream, flags);
686 return result;
687 }
688
689 static void parse_conversion(const string& larger_str,
690 const string& smaller_str);
691
697
711#define AMOUNT_PRINT_NO_FLAGS 0x00
712#define AMOUNT_PRINT_RIGHT_JUSTIFY 0x01
713#define AMOUNT_PRINT_COLORIZE 0x02
714#define AMOUNT_PRINT_NO_COMPUTED_ANNOTATIONS 0x04
715#define AMOUNT_PRINT_ELIDE_COMMODITY_QUOTES 0x08
716
717 void print(std::ostream& out,
718 const uint_least8_t flags = AMOUNT_PRINT_NO_FLAGS) const;
719
725
737 void dump(std::ostream& out) const {
738 out << "AMOUNT(";
739 print(out);
740 out << ")";
741 }
742
743 bool valid() const;
744
746};
747
748inline amount_t amount_t::exact(const string& value) {
749 amount_t temp;
751 return temp;
752}
753
754inline string amount_t::to_string() const {
755 std::ostringstream bufstream;
756 print(bufstream);
757 return bufstream.str();
758}
759
760inline string amount_t::to_fullstring() const {
761 std::ostringstream bufstream;
762 unrounded().print(bufstream);
763 return bufstream.str();
764}
765
766inline string amount_t::quantity_string() const {
767 std::ostringstream bufstream;
768 number().print(bufstream);
769 return bufstream.str();
770}
771
772inline std::ostream& operator<<(std::ostream& out, const amount_t& amt) {
774 amt.unrounded().print(out);
775 else
776 amt.print(out);
777 return out;
778}
779inline std::istream& operator>>(std::istream& in, amount_t& amt) {
780 amt.parse(in);
781 return in;
782}
783
784void put_amount(property_tree::ptree& pt, const amount_t& amt,
785 bool commodity_details = false);
786
787} // namespace ledger
General utility facilities used by Ledger.
#define TRACE_DTOR(cls)
Definition utils.h:144
#define TRACE_CTOR(cls, args)
Definition utils.h:143
#define assert(x)
Definition utils.h:92
datetime_t and date_t objects
#define AMOUNT_PRINT_NO_FLAGS
An amount may be output to a stream using the ‘print’ method.
Definition amount.h:711
#define DECLARE_EXCEPTION(name, kind)
Definition error.h:88
flags::basic_t< parse_flags_enum_t, uint_least8_t > parse_flags_t
Definition amount.h:79
std::string string
Definition utils.h:59
std::ostream & operator<<(std::ostream &out, const account_t &account)
void put_amount(property_tree::ptree &pt, const amount_t &amt, bool commodity_details=false)
parse_flags_enum_t
Definition amount.h:67
@ PARSE_SINGLE
Definition amount.h:70
@ PARSE_SOFT_FAIL
Definition amount.h:76
@ PARSE_NO_MIGRATE
Definition amount.h:71
@ PARSE_NO_ASSIGN
Definition amount.h:73
@ PARSE_NO_REDUCE
Definition amount.h:72
@ PARSE_DEFAULT
Definition amount.h:68
@ PARSE_PARTIAL
Definition amount.h:69
@ PARSE_OP_CONTEXT
Definition amount.h:75
@ PARSE_NO_ANNOT
Definition amount.h:74
boost::posix_time::ptime datetime_t
Definition times.h:53
std::istream & operator>>(std::istream &in, amount_t &amt)
Definition amount.h:779
Encapsulate infinite-precision commoditized amounts.
Definition amount.h:96
void in_place_negate()
void in_place_reduce()
double to_double() const
Conversion methods.
annotation_t & annotation()
bool is_null() const
Definition amount.h:470
amount_t & operator=(const char *str)
Definition amount.h:234
amount_t(const char *val)
Parse a pointer to a C string as an (optionally commoditized) amount.
Definition amount.h:164
bool fits_in_long() const
void set_commodity(commodity_t &comm)
Definition amount.h:557
bool operator==(const T &val) const
Definition amount.h:256
void in_place_invert()
commodity_t * commodity_
Definition amount.h:128
void dump(std::ostream &out) const
There are two methods defined to help with debugging:
Definition amount.h:737
void in_place_unreduce()
bool has_annotation() const
amount_t unrounded() const
Yields an amount whose display precision is never truncated, even though its commodity normally displ...
Definition amount.h:384
void print(std::ostream &out, const uint_least8_t flags=0x00) const
static bool is_initialized
Definition amount.h:105
amount_t(const string &val)
Parse a string as an (optionally commoditized) amount.
Definition amount.h:156
string to_fullstring() const
Definition amount.h:760
void set_keep_precision(const bool keep=true) const
amount_t & operator*=(const amount_t &amt)
Definition amount.h:276
amount_t inverted() const
Definition amount.h:329
amount_t abs() const
Returns the absolute value of an amount.
Definition amount.h:323
amount_t(const unsigned long val)
Convert an unsigned long to an amount.
long to_long() const
amount_t negated() const
Returns the negated value of an amount.
Definition amount.h:307
bool operator<(const T &amt) const
Definition amount.h:260
amount_t(const amount_t &amt)
Copy an amount object.
Definition amount.h:196
int sign() const
Truth tests.
amount_t & operator-=(const amount_t &amt)
void in_place_ceiling()
static void initialize()
Ready the amount subsystem for use.
void annotate(const annotation_t &details)
An amount's commodity may be annotated with special details, such as the price it was purchased for,...
amount_t & operator/=(const amount_t &amt)
Divide two amounts while extending the precision to preserve the accuracy of the result.
bool operator==(const amount_t &amt) const
Test two amounts for equality.
optional< amount_t > price() const
amount_t(const long val)
Convert a long to an amount.
void _copy(const amount_t &amt)
amount_t operator-() const
Definition amount.h:314
optional< amount_t > value(const datetime_t &moment=datetime_t(), const commodity_t *in_terms_of=NULL) const
Returns the historical value for an amount – the default moment returns the most recently known price...
amount_t roundto(int places) const
Definition amount.h:348
void in_place_unround()
amount_t floored() const
Yields an amount which has lost all of its extra precision, beyond what the display precision of the ...
Definition amount.h:366
amount_t & operator=(const unsigned long val)
Definition amount.h:221
amount_t & operator=(const double val)
Definition amount.h:218
bool parse(const string &str, const parse_flags_t &flags=PARSE_DEFAULT)
Definition amount.h:682
string to_string() const
Definition amount.h:754
void clear_commodity()
Definition amount.h:571
bool keep_precision() const
amount_t()
Creates a value for which is_null() is true, and which has no value or commodity.
Definition amount.h:137
amount_t truncated() const
Yields an amount which has lost all of its extra precision, beyond what the display precision of the ...
Definition amount.h:357
void in_place_roundto(int places)
bool is_nonzero() const
Definition amount.h:461
amount_t reduced() const
reduces a value to its most basic commodity form, for amounts that utilize "scaling commodities".
Definition amount.h:395
string quantity_string() const
Definition amount.h:766
amount_t with_commodity(const commodity_t &comm) const
Definition amount.h:562
amount_t & multiply(const amount_t &amt, bool ignore_commodity=false)
bool valid() const
bigint_t * quantity
Definition amount.h:127
static const std::size_t extend_by_digits
Number of places of precision by which values are extended to avoid losing precision during division ...
Definition amount.h:112
amount_t strip_annotations(const keep_details_t &what_to_keep) const
If the lot price is considered whenever working with commoditized values.
amount_t ceilinged() const
Yields an amount which has lost all of its extra precision, beyond what the display precision of the ...
Definition amount.h:375
precision_t display_precision() const
precision_t precision() const
Return an amount's internal precision.
amount_t & operator+=(const amount_t &amt)
amount_t & operator=(const string &str)
Definition amount.h:231
static void shutdown()
Shutdown the amount subsystem and free all resources.
static amount_t exact(const string &value)
Create an amount whose display precision is never truncated, even if the amount uses a commodity (whi...
Definition amount.h:748
void in_place_truncate()
commodity_t & commodity() const
Definition amount.h:552
amount_t unreduced() const
unreduce(), if used with a "scaling commodity", yields the most compact form greater than one.
Definition amount.h:406
amount_t rounded() const
Yields an amount whose display precision when output is truncated to the display precision of its com...
Definition amount.h:341
bool is_realzero() const
Definition amount.h:466
bool parse(std::istream &in, const parse_flags_t &flags=PARSE_DEFAULT)
The ‘flags’ argument of both parsing may be one or more of the following:
amount_t & operator=(const long val)
Definition amount.h:224
const annotation_t & annotation() const
Definition amount.h:613
amount_t & operator=(const amount_t &amt)
Assign an amount object.
static void parse_conversion(const string &larger_str, const string &smaller_str)
amount_t number() const
Definition amount.h:575
commodity_t * commodity_ptr() const
The following methods relate to an amount's commodity:
amount_t(const double val)
Convert a double to an amount.
bool has_commodity() const
amount_t(const amount_t &amt, const annotation_t &details)
Copy an amount object, applying the given commodity annotation details afterward.
Definition amount.h:207
~amount_t()
Release the reference count held for the underlying amount_t::bigint_t object.
Definition amount.h:183
uint_least16_t precision_t
The amount's decimal precision.
Definition amount.h:108
bool operator>(const T &amt) const
Definition amount.h:264
int compare(const amount_t &amt) const
Compare two amounts, returning a number less than zero if amt is greater, exactly zero if they are eq...
static bool stream_fullstrings
If amounts should be streamed using to_fullstring() rather than to_string(), so that complete precisi...
Definition amount.h:117
bool is_zero() const