1 /*
2  * Copyright (c) 2003-2019, 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 
32 #include <system.hh>
33 
34 #include "value.h"
35 #include "commodity.h"
36 #include "annotate.h"
37 #include "pool.h"
38 #include "unistring.h"          // for justify()
39 #include "op.h"
40 
41 namespace ledger {
42 
43 intrusive_ptr<value_t::storage_t> value_t::true_value;
44 intrusive_ptr<value_t::storage_t> value_t::false_value;
45 
operator =(const value_t::storage_t & rhs)46 value_t::storage_t& value_t::storage_t::operator=(const value_t::storage_t& rhs)
47 {
48   type = rhs.type;
49 
50   switch (type) {
51   case BALANCE:
52     data = new balance_t(*boost::get<balance_t *>(rhs.data));
53     break;
54   case SEQUENCE:
55     data = new sequence_t(*boost::get<sequence_t *>(rhs.data));
56     break;
57 
58   default:
59     data = rhs.data;
60     break;
61   }
62 
63   return *this;
64 }
65 
initialize()66 void value_t::initialize()
67 {
68   true_value        = new storage_t;
69   true_value->type  = BOOLEAN;
70   true_value->data  = true;
71 
72   false_value       = new storage_t;
73   false_value->type = BOOLEAN;
74   false_value->data = false;
75 }
76 
shutdown()77 void value_t::shutdown()
78 {
79   true_value  = intrusive_ptr<storage_t>();
80   false_value = intrusive_ptr<storage_t>();
81 }
82 
operator bool() const83 value_t::operator bool() const
84 {
85   switch (type()) {
86   case VOID:
87     return false;
88   case BOOLEAN:
89     return as_boolean();
90   case DATETIME:
91     return is_valid(as_datetime());
92   case DATE:
93     return is_valid(as_date());
94   case INTEGER:
95     return as_long();
96   case AMOUNT:
97     return as_amount();
98   case BALANCE:
99     return as_balance();
100   case STRING:
101     return ! as_string().empty();
102   case MASK: {
103     std::ostringstream out;
104     out << *this;
105     throw_(value_error,
106            _f("Cannot determine truth of %1% (did you mean 'account =~ %2%'?)")
107            % label() % out.str());
108   }
109   case SEQUENCE:
110     if (! as_sequence().empty()) {
111       foreach (const value_t& value, as_sequence()) {
112         if (value)
113           return true;
114       }
115     }
116     return false;
117   case SCOPE:
118     return as_scope() != NULL;
119   case ANY:
120     return ! as_any().empty();
121   }
122 
123   add_error_context(_f("While taking boolean value of %1%:") % *this);
124   throw_(value_error, _f("Cannot determine truth of %1%") % label());
125 
126   return false;
127 }
128 
set_type(type_t new_type)129 void value_t::set_type(type_t new_type)
130 {
131   if (new_type == VOID) {
132     storage.reset();
133   } else {
134     if (! storage || storage->refc > 1)
135       storage = new storage_t;
136     else
137       storage->destroy();
138     storage->type = new_type;
139   }
140 }
141 
to_boolean() const142 bool value_t::to_boolean() const
143 {
144   if (is_boolean()) {
145     return as_boolean();
146   } else {
147     value_t temp(*this);
148     temp.in_place_cast(BOOLEAN);
149     return temp.as_boolean();
150   }
151 }
152 
to_datetime() const153 datetime_t value_t::to_datetime() const
154 {
155   if (is_datetime()) {
156     return as_datetime();
157   } else {
158     value_t temp(*this);
159     temp.in_place_cast(DATETIME);
160     return temp.as_datetime();
161   }
162 }
163 
to_date() const164 date_t value_t::to_date() const
165 {
166   if (is_date()) {
167     return as_date();
168   } else {
169     value_t temp(*this);
170     temp.in_place_cast(DATE);
171     return temp.as_date();
172   }
173 }
174 
to_int() const175 int value_t::to_int() const
176 {
177   if (is_long()) {
178     return static_cast<int>(as_long());
179   } else {
180     value_t temp(*this);
181     temp.in_place_cast(INTEGER);
182     return static_cast<int>(temp.as_long());
183   }
184 }
185 
to_long() const186 long value_t::to_long() const
187 {
188   if (is_long()) {
189     return as_long();
190   } else {
191     value_t temp(*this);
192     temp.in_place_cast(INTEGER);
193     return temp.as_long();
194   }
195 }
196 
to_amount() const197 amount_t value_t::to_amount() const
198 {
199   if (is_amount()) {
200     return as_amount();
201   } else {
202     value_t temp(*this);
203     temp.in_place_cast(AMOUNT);
204     return temp.as_amount();
205   }
206 }
207 
to_balance() const208 balance_t value_t::to_balance() const
209 {
210   if (is_balance()) {
211     return as_balance();
212   } else {
213     value_t temp(*this);
214     temp.in_place_cast(BALANCE);
215     return temp.as_balance();
216   }
217 }
218 
to_string() const219 string value_t::to_string() const
220 {
221   if (is_string()) {
222     return as_string();
223   } else {
224     value_t temp(*this);
225     temp.in_place_cast(STRING);
226     return temp.as_string();
227   }
228 }
229 
to_mask() const230 mask_t value_t::to_mask() const
231 {
232   if (is_mask()) {
233     return as_mask();
234   } else {
235     value_t temp(*this);
236     temp.in_place_cast(MASK);
237     return temp.as_mask();
238   }
239 }
240 
to_sequence() const241 value_t::sequence_t value_t::to_sequence() const
242 {
243   if (is_sequence()) {
244     return as_sequence();
245   } else {
246     value_t temp(*this);
247     temp.in_place_cast(SEQUENCE);
248     return temp.as_sequence();
249   }
250 }
251 
252 
in_place_simplify()253 void value_t::in_place_simplify()
254 {
255 #if DEBUG_ON
256   LOGGER("value.simplify");
257 #endif
258 
259   if (is_realzero()) {
260     DEBUG_("Zeroing type " << static_cast<int>(type()));
261     set_long(0L);
262     return;
263   }
264 
265   if (is_balance() && as_balance().single_amount()) {
266     DEBUG_("Reducing balance to amount");
267     DEBUG_("as a balance it looks like: " << *this);
268     in_place_cast(AMOUNT);
269     DEBUG_("as an amount it looks like: " << *this);
270   }
271 
272 #if REDUCE_TO_INTEGER        // this is off by default
273   if (is_amount() && ! as_amount().has_commodity() &&
274       as_amount().fits_in_long()) {
275     DEBUG_("Reducing amount to integer");
276     in_place_cast(INTEGER);
277   }
278 #endif
279 }
280 
number() const281 value_t value_t::number() const
282 {
283   switch (type()) {
284   case VOID:
285     return 0L;
286   case BOOLEAN:
287     return as_boolean() ? 1L : 0L;
288   case INTEGER:
289     return as_long();
290   case AMOUNT:
291     return as_amount().number();
292   case BALANCE:
293     return as_balance().number();
294   case SEQUENCE:
295     if (! as_sequence().empty()) {
296       value_t temp;
297       foreach (const value_t& value, as_sequence())
298         temp += value.number();
299       return temp;
300     }
301     break;
302   default:
303     break;
304   }
305 
306   add_error_context(_f("While calling number() on %1%:") % *this);
307   throw_(value_error, _f("Cannot determine numeric value of %1%") % label());
308 
309   return false;
310 }
311 
operator +=(const value_t & val)312 value_t& value_t::operator+=(const value_t& val)
313 {
314   if (is_string()) {
315     if (val.is_string())
316       as_string_lval() += val.as_string();
317     else
318       as_string_lval() += val.to_string();
319     return *this;
320   }
321   else if (is_sequence()) {
322     if (val.is_sequence()) {
323       if (size() == val.size()) {
324         sequence_t::iterator       i = begin();
325         sequence_t::const_iterator j = val.begin();
326 
327         for (; i != end(); i++, j++)
328           *i += *j;
329       } else {
330         add_error_context(_f("While adding %1% to %2%:") % val % *this);
331         throw_(value_error, _("Cannot add sequences of different lengths"));
332       }
333     } else {
334       as_sequence_lval().push_back(new value_t(val));
335     }
336     return *this;
337   }
338 
339   switch (type()) {
340   case VOID:
341     *this = value_t(val);
342     return *this;
343 
344   case DATETIME:
345     switch (val.type()) {
346     case INTEGER:
347       as_datetime_lval() +=
348         time_duration_t(0, 0, static_cast<time_duration_t::sec_type>(val.as_long()));
349       return *this;
350     case AMOUNT:
351       as_datetime_lval() +=
352         time_duration_t(0, 0, static_cast<time_duration_t::sec_type>
353                         (val.as_amount().to_long()));
354       return *this;
355     default:
356       break;
357     }
358     break;
359 
360   case DATE:
361     switch (val.type()) {
362     case INTEGER:
363       as_date_lval() += gregorian::date_duration(val.as_long());
364       return *this;
365     case AMOUNT:
366       as_date_lval() += gregorian::date_duration(val.as_amount().to_long());
367       return *this;
368     default:
369       break;
370     }
371     break;
372 
373   case INTEGER:
374     switch (val.type()) {
375     case INTEGER:
376       as_long_lval() += val.as_long();
377       return *this;
378     case AMOUNT:
379       if (val.as_amount().has_commodity()) {
380         in_place_cast(BALANCE);
381         return *this += val;
382       }
383       in_place_cast(AMOUNT);
384       as_amount_lval() += val.as_amount();
385       return *this;
386     case BALANCE:
387       in_place_cast(BALANCE);
388       as_balance_lval() += val.as_balance();
389       return *this;
390     default:
391       break;
392     }
393     break;
394 
395   case AMOUNT:
396     switch (val.type()) {
397     case INTEGER:
398       if (as_amount().has_commodity()) {
399         in_place_cast(BALANCE);
400         return *this += val;
401       } else {
402         as_amount_lval() += val.as_long();
403         return *this;
404       }
405 
406     case AMOUNT:
407       if (as_amount().commodity() != val.as_amount().commodity()) {
408         in_place_cast(BALANCE);
409         return *this += val;
410       } else {
411         as_amount_lval() += val.as_amount();
412         return *this;
413       }
414 
415     case BALANCE:
416       in_place_cast(BALANCE);
417       as_balance_lval() += val.as_balance();
418       return *this;
419 
420     default:
421       break;
422     }
423     break;
424 
425   case BALANCE:
426     switch (val.type()) {
427     case INTEGER:
428       as_balance_lval() += val.to_amount();
429       return *this;
430     case AMOUNT:
431       as_balance_lval() += val.as_amount();
432       return *this;
433     case BALANCE:
434       as_balance_lval() += val.as_balance();
435       return *this;
436     default:
437       break;
438     }
439     break;
440 
441   default:
442     break;
443   }
444 
445   add_error_context(_f("While adding %1% to %2%:") % val % *this);
446   throw_(value_error, _f("Cannot add %1% to %2%") % val.label() % label());
447 
448   return *this;
449 }
450 
operator -=(const value_t & val)451 value_t& value_t::operator-=(const value_t& val)
452 {
453   if (is_sequence()) {
454     sequence_t& seq(as_sequence_lval());
455 
456     if (val.is_sequence()) {
457       if (size() == val.size()) {
458         sequence_t::iterator       i = begin();
459         sequence_t::const_iterator j = val.begin();
460 
461         for (; i != end(); i++, j++)
462           *i -= *j;
463       } else {
464         add_error_context(_f("While subtracting %1% from %2%:") % val % *this);
465         throw_(value_error, _("Cannot subtract sequences of different lengths"));
466       }
467     } else {
468       sequence_t::iterator i = std::find(seq.begin(), seq.end(), val);
469       if (i != seq.end())
470         seq.erase(i);
471     }
472     return *this;
473   }
474 
475   switch (type()) {
476   case DATETIME:
477     switch (val.type()) {
478     case INTEGER:
479       as_datetime_lval() -=
480         time_duration_t(0, 0, static_cast<time_duration_t::sec_type>(val.as_long()));
481       return *this;
482     case AMOUNT:
483       as_datetime_lval() -=
484         time_duration_t(0, 0, static_cast<time_duration_t::sec_type>
485                         (val.as_amount().to_long()));
486       return *this;
487     default:
488       break;
489     }
490     break;
491 
492   case DATE:
493     switch (val.type()) {
494     case INTEGER:
495       as_date_lval() -= gregorian::date_duration(val.as_long());
496       return *this;
497     case AMOUNT:
498       as_date_lval() -= gregorian::date_duration(val.as_amount().to_long());
499       return *this;
500     default:
501       break;
502     }
503     break;
504 
505   case INTEGER:
506     switch (val.type()) {
507     case INTEGER:
508       as_long_lval() -= val.as_long();
509       return *this;
510     case AMOUNT:
511       in_place_cast(AMOUNT);
512       as_amount_lval() -= val.as_amount();
513       in_place_simplify();
514       return *this;
515     case BALANCE:
516       in_place_cast(BALANCE);
517       as_balance_lval() -= val.as_balance();
518       in_place_simplify();
519       return *this;
520     default:
521       break;
522     }
523     break;
524 
525   case AMOUNT:
526     switch (val.type()) {
527     case INTEGER:
528       if (as_amount().has_commodity()) {
529         in_place_cast(BALANCE);
530         *this -= val;
531         in_place_simplify();
532         return *this;
533       } else {
534         as_amount_lval() -= val.as_long();
535         in_place_simplify();
536         return *this;
537       }
538 
539     case AMOUNT:
540       if (as_amount().commodity() != val.as_amount().commodity()) {
541         in_place_cast(BALANCE);
542         *this -= val;
543         in_place_simplify();
544         return *this;
545       } else {
546         as_amount_lval() -= val.as_amount();
547         in_place_simplify();
548         return *this;
549       }
550 
551     case BALANCE:
552       in_place_cast(BALANCE);
553       as_balance_lval() -= val.as_balance();
554       in_place_simplify();
555       return *this;
556 
557     default:
558       break;
559     }
560     break;
561 
562   case BALANCE:
563     switch (val.type()) {
564     case INTEGER:
565       as_balance_lval() -= val.to_amount();
566       in_place_simplify();
567       return *this;
568     case AMOUNT:
569       as_balance_lval() -= val.as_amount();
570       in_place_simplify();
571       return *this;
572     case BALANCE:
573       as_balance_lval() -= val.as_balance();
574       in_place_simplify();
575       return *this;
576     default:
577       break;
578     }
579     break;
580 
581   default:
582     break;
583   }
584 
585   add_error_context(_f("While subtracting %1% from %2%:") % val % *this);
586   throw_(value_error, _f("Cannot subtract %1% from %2%") % val.label() % label());
587 
588   return *this;
589 }
590 
operator *=(const value_t & val)591 value_t& value_t::operator*=(const value_t& val)
592 {
593   if (is_string()) {
594     string temp;
595     long count = val.to_long();
596     for (long i = 0; i < count; i++)
597       temp += as_string();
598     set_string(temp);
599     return *this;
600   }
601   else if (is_sequence()) {
602     value_t temp;
603     long count = val.to_long();
604     for (long i = 0; i < count; i++)
605       temp += as_sequence();
606     return *this = temp;
607   }
608 
609   switch (type()) {
610   case INTEGER:
611     switch (val.type()) {
612     case INTEGER:
613       as_long_lval() *= val.as_long();
614       return *this;
615     case AMOUNT:
616       set_amount(val.as_amount() * as_long());
617       return *this;
618     default:
619       break;
620     }
621     break;
622 
623   case AMOUNT:
624     switch (val.type()) {
625     case INTEGER:
626       as_amount_lval() *= val.as_long();
627       return *this;
628     case AMOUNT:
629       as_amount_lval() *= val.as_amount();
630       return *this;
631     case BALANCE:
632       if (val.as_balance().single_amount()) {
633         as_amount_lval() *= val.simplified().as_amount();
634         return *this;
635       }
636       break;
637     default:
638       break;
639     }
640     break;
641 
642   case BALANCE:
643     switch (val.type()) {
644     case INTEGER:
645       as_balance_lval() *= val.as_long();
646       return *this;
647     case AMOUNT:
648       if (as_balance().single_amount()) {
649         in_place_simplify();
650         as_amount_lval() *= val.as_amount();
651         return *this;
652       }
653       else if (! val.as_amount().has_commodity()) {
654         as_balance_lval() *= val.as_amount();
655         return *this;
656       }
657       break;
658     default:
659       break;
660     }
661     break;
662 
663   default:
664     break;
665   }
666 
667   add_error_context(_f("While multiplying %1% with %2%:") % val % *this);
668   throw_(value_error, _f("Cannot multiply %1% with %2%") % label() % val.label());
669 
670   return *this;
671 }
672 
operator /=(const value_t & val)673 value_t& value_t::operator/=(const value_t& val)
674 {
675   switch (type()) {
676   case INTEGER:
677     switch (val.type()) {
678     case INTEGER:
679       as_long_lval() /= val.as_long();
680       return *this;
681     case AMOUNT:
682       set_amount(val.as_amount() / as_long());
683       return *this;
684     default:
685       break;
686     }
687     break;
688 
689   case AMOUNT:
690     switch (val.type()) {
691     case INTEGER:
692       as_amount_lval() /= val.as_long();
693       return *this;
694 
695     case AMOUNT:
696       as_amount_lval() /= val.as_amount();
697       return *this;
698     case BALANCE:
699       if (val.as_balance().single_amount()) {
700         value_t simpler(val.simplified());
701         switch (simpler.type()) {
702         case INTEGER:
703           as_amount_lval() /= simpler.as_long();
704           break;
705         case AMOUNT:
706           as_amount_lval() /= simpler.as_amount();
707           break;
708         default:
709           assert(false);
710           break;
711         }
712         return *this;
713       }
714       break;
715     default:
716       break;
717     }
718     break;
719 
720   case BALANCE:
721     switch (val.type()) {
722     case INTEGER:
723       as_balance_lval() /= val.as_long();
724       return *this;
725     case AMOUNT:
726       if (as_balance().single_amount()) {
727         in_place_cast(AMOUNT);
728         as_amount_lval() /= val.as_amount();
729         return *this;
730       }
731       else if (! val.as_amount().has_commodity()) {
732         as_balance_lval() /= val.as_amount();
733         return *this;
734       }
735       break;
736     default:
737       break;
738     }
739     break;
740 
741   default:
742     break;
743   }
744 
745   add_error_context(_f("While dividing %1% by %2%:") % *this % val);
746   throw_(value_error, _f("Cannot divide %1% by %2%") % label() % val.label());
747 
748   return *this;
749 }
750 
751 
is_equal_to(const value_t & val) const752 bool value_t::is_equal_to(const value_t& val) const
753 {
754   switch (type()) {
755   case VOID:
756     return val.type() == VOID;
757 
758   case BOOLEAN:
759     if (val.is_boolean())
760       return as_boolean() == val.as_boolean();
761     break;
762 
763   case DATETIME:
764     if (val.is_datetime())
765       return as_datetime() == val.as_datetime();
766     break;
767 
768   case DATE:
769     if (val.is_date())
770       return as_date() == val.as_date();
771     break;
772 
773   case INTEGER:
774     switch (val.type()) {
775     case INTEGER:
776       return as_long() == val.as_long();
777     case AMOUNT:
778       return val.as_amount() == to_amount();
779     case BALANCE:
780       return val.as_balance() == to_amount();
781     default:
782       break;
783     }
784     break;
785 
786   case AMOUNT:
787     switch (val.type()) {
788     case INTEGER:
789       return as_amount() == val.as_long();
790     case AMOUNT:
791       return as_amount() == val.as_amount();
792     case BALANCE:
793       return val.as_balance() == as_amount();
794     default:
795       break;
796     }
797     break;
798 
799   case BALANCE:
800     switch (val.type()) {
801     case INTEGER:
802       return as_balance() == val.to_amount();
803     case AMOUNT:
804       return as_balance() == val.as_amount();
805     case BALANCE:
806       return as_balance() == val.as_balance();
807     default:
808       break;
809     }
810     break;
811 
812   case STRING:
813     if (val.is_string())
814       return as_string() == val.as_string();
815     break;
816 
817   case MASK:
818     if (val.is_mask())
819       return as_mask() == val.as_mask();
820     break;
821 
822   case SEQUENCE:
823     if (val.is_sequence())
824       return as_sequence() == val.as_sequence();
825     break;
826 
827   default:
828     break;
829   }
830 
831   add_error_context(_f("While comparing equality of %1% and %2%:") % *this % val);
832   throw_(value_error, _f("Cannot compare %1% to %2%") % label() % val.label());
833 
834   return *this;
835 }
836 
is_less_than(const value_t & val) const837 bool value_t::is_less_than(const value_t& val) const
838 {
839   switch (type()) {
840   case BOOLEAN:
841     if (val.is_boolean()) {
842       if (as_boolean()) {
843         if (! val.as_boolean())
844           return false;
845         else
846           return false;
847       }
848       else if (! as_boolean()) {
849         if (! val.as_boolean())
850           return false;
851         else
852           return true;
853       }
854     }
855     break;
856 
857   case DATETIME:
858     if (val.is_datetime())
859       return as_datetime() < val.as_datetime();
860     break;
861 
862   case DATE:
863     if (val.is_date())
864       return as_date() < val.as_date();
865     break;
866 
867   case INTEGER:
868     switch (val.type()) {
869     case INTEGER:
870       return as_long() < val.as_long();
871     case AMOUNT:
872       return val.as_amount() > as_long();
873     case BALANCE:
874       return val.to_amount() > as_long();
875     default:
876       break;
877     }
878     break;
879 
880   case AMOUNT:
881     switch (val.type()) {
882     case INTEGER:
883       return as_amount() < val.as_long();
884     case AMOUNT:
885       if (as_amount().commodity() == val.as_amount().commodity() ||
886           ! as_amount().has_commodity() ||
887           ! val.as_amount().has_commodity())
888         return as_amount() < val.as_amount();
889       else
890         return commodity_t::compare_by_commodity()(&as_amount(), &val.as_amount()) < 0;
891     case BALANCE:
892       return val.to_amount() > as_amount();
893     default:
894       break;
895     }
896     break;
897 
898   case BALANCE:
899     switch (val.type()) {
900     case INTEGER:
901     case AMOUNT: {
902       bool no_amounts = true;
903       foreach (const balance_t::amounts_map::value_type& pair,
904                as_balance().amounts) {
905         if (pair.second >= val)
906           return false;
907         no_amounts = false;
908       }
909       return ! no_amounts;
910     }
911     case BALANCE:
912       return val.to_amount() > to_amount();
913     default:
914       break;
915     }
916     break;
917 
918   case STRING:
919     if (val.is_string())
920       return as_string() < val.as_string();
921     break;
922 
923   case SEQUENCE:
924     switch (val.type()) {
925     case INTEGER:
926     case AMOUNT: {
927       bool no_amounts = true;
928       foreach (const value_t& value, as_sequence()) {
929         if (value >= val)
930           return false;
931         no_amounts = false;
932       }
933       return ! no_amounts;
934     }
935     case SEQUENCE: {
936       sequence_t::const_iterator i = as_sequence().begin();
937       sequence_t::const_iterator j = val.as_sequence().begin();
938       for (; (i != as_sequence().end() &&
939               j != val.as_sequence().end()); i++, j++) {
940         if (! ((*i) < (*j)))
941           return false;
942       }
943       if (i == as_sequence().end())
944         return true;
945       else
946         return false;
947     }
948     default:
949       break;
950     }
951     break;
952 
953   default:
954     break;
955   }
956 
957   add_error_context(_f("While comparing if %1% is less than %2%:") % *this % val);
958   throw_(value_error, _f("Cannot compare %1% to %2%") % label() % val.label());
959 
960   return *this;
961 }
962 
is_greater_than(const value_t & val) const963 bool value_t::is_greater_than(const value_t& val) const
964 {
965   switch (type()) {
966   case BOOLEAN:
967     if (val.is_boolean()) {
968       if (as_boolean()) {
969         if (! val.as_boolean())
970           return true;
971         else
972           return false;
973       }
974       else if (! as_boolean()) {
975         if (! val.as_boolean())
976           return false;
977         else
978           return false;
979       }
980     }
981     break;
982 
983   case DATETIME:
984     if (val.is_datetime())
985       return as_datetime() > val.as_datetime();
986     break;
987 
988   case DATE:
989     if (val.is_date())
990       return as_date() > val.as_date();
991     break;
992 
993   case INTEGER:
994     switch (val.type()) {
995     case INTEGER:
996       return as_long() > val.as_long();
997     case AMOUNT:
998       return val.as_amount() < as_long();
999     case BALANCE:
1000       return val.to_amount() < as_long();
1001     default:
1002       break;
1003     }
1004     break;
1005 
1006   case AMOUNT:
1007     switch (val.type()) {
1008     case INTEGER:
1009       return as_amount() > val.as_long();
1010     case AMOUNT:
1011       return as_amount() > val.as_amount();
1012     case BALANCE:
1013       return val.to_amount() < as_amount();
1014     default:
1015       break;
1016     }
1017     break;
1018 
1019   case BALANCE:
1020     switch (val.type()) {
1021     case INTEGER:
1022     case AMOUNT: {
1023       bool no_amounts = true;
1024       foreach (const balance_t::amounts_map::value_type& pair,
1025                as_balance().amounts) {
1026         if (pair.second <= val)
1027           return false;
1028         no_amounts = false;
1029       }
1030       return ! no_amounts;
1031     }
1032     case BALANCE:
1033       return val.to_amount() < to_amount();
1034     default:
1035       break;
1036     }
1037     break;
1038 
1039   case STRING:
1040     if (val.is_string())
1041       return as_string() > val.as_string();
1042     break;
1043 
1044   case SEQUENCE:
1045     switch (val.type()) {
1046     case INTEGER:
1047     case AMOUNT: {
1048       bool no_amounts = true;
1049       foreach (const value_t& value, as_sequence()) {
1050         if (value <= val)
1051           return false;
1052         no_amounts = false;
1053       }
1054       return ! no_amounts;
1055     }
1056     case SEQUENCE: {
1057       sequence_t::const_iterator i = as_sequence().begin();
1058       sequence_t::const_iterator j = val.as_sequence().begin();
1059       for (; (i != as_sequence().end() &&
1060               j != val.as_sequence().end()); i++, j++) {
1061         if (! ((*i) > (*j)))
1062           return false;
1063       }
1064       if (i == as_sequence().end())
1065         return false;
1066       else
1067         return true;
1068     }
1069     default:
1070       break;
1071     }
1072     break;
1073 
1074   default:
1075     break;
1076   }
1077 
1078   add_error_context(_f("While comparing if %1% is greater than %2%:") % *this % val);
1079   throw_(value_error, _f("Cannot compare %1% to %2%") % label() % val.label());
1080 
1081   return *this;
1082 }
1083 
in_place_cast(type_t cast_type)1084 void value_t::in_place_cast(type_t cast_type)
1085 {
1086   if (type() == cast_type)
1087     return;
1088 
1089   _dup();
1090 
1091   if (cast_type == BOOLEAN) {
1092     set_boolean(bool(*this));
1093     return;
1094   }
1095   else if (cast_type == SEQUENCE) {
1096     sequence_t temp;
1097     if (! is_null())
1098       temp.push_back(new value_t(*this));
1099     set_sequence(temp);
1100     return;
1101   }
1102 
1103   switch (type()) {
1104   case VOID:
1105     switch (cast_type) {
1106     case INTEGER:
1107       set_long(0L);
1108       return;
1109     case AMOUNT:
1110       set_amount(0L);
1111       return;
1112     case STRING:
1113       set_string("");
1114       return;
1115     default:
1116       break;
1117     }
1118     break;
1119 
1120   case BOOLEAN:
1121     switch (cast_type) {
1122     case INTEGER:
1123       set_long(as_boolean() ? 1L : 0L);
1124       return;
1125     case AMOUNT:
1126       set_amount(as_boolean() ? 1L : 0L);
1127       return;
1128     case STRING:
1129       set_string(as_boolean() ? "true" : "false");
1130       return;
1131     default:
1132       break;
1133     }
1134     break;
1135 
1136   case DATE:
1137     switch (cast_type) {
1138     case DATETIME:
1139       set_datetime(datetime_t(as_date(), time_duration(0, 0, 0, 0)));
1140       return;
1141     case STRING:
1142       set_string(format_date(as_date(), FMT_WRITTEN));
1143       return;
1144     default:
1145       break;
1146     }
1147     break;
1148   case DATETIME:
1149     switch (cast_type) {
1150     case DATE:
1151       set_date(as_datetime().date());
1152       return;
1153     case STRING:
1154       set_string(format_datetime(as_datetime(), FMT_WRITTEN));
1155       return;
1156     default:
1157       break;
1158     }
1159     break;
1160 
1161   case INTEGER:
1162     switch (cast_type) {
1163     case AMOUNT:
1164       set_amount(as_long());
1165       return;
1166     case BALANCE:
1167       set_balance(to_amount());
1168       return;
1169     case STRING:
1170       set_string(lexical_cast<string>(as_long()));
1171       return;
1172     default:
1173       break;
1174     }
1175     break;
1176 
1177   case AMOUNT: {
1178     const amount_t& amt(as_amount());
1179     switch (cast_type) {
1180     case INTEGER:
1181       if (amt.is_null())
1182         set_long(0L);
1183       else
1184         set_long(as_amount().to_long());
1185       return;
1186     case BALANCE:
1187       if (amt.is_null())
1188         set_balance(balance_t());
1189       else
1190         set_balance(as_amount());
1191       return;
1192     case STRING:
1193       if (amt.is_null())
1194         set_string("");
1195       else
1196         set_string(as_amount().to_string());
1197       return;
1198     default:
1199       break;
1200     }
1201     break;
1202   }
1203 
1204   case BALANCE: {
1205     const balance_t& bal(as_balance());
1206     switch (cast_type) {
1207     case AMOUNT: {
1208       if (bal.amounts.size() == 1) {
1209         // Because we are changing the current balance value to an amount
1210         // value, and because set_amount takes a reference (and that memory is
1211         // about to be repurposed), we must pass in a copy.
1212         set_amount(amount_t((*bal.amounts.begin()).second));
1213         return;
1214       }
1215       else if (bal.amounts.size() == 0) {
1216         set_amount(0L);
1217         return;
1218       }
1219       else {
1220         add_error_context(_f("While converting %1% to an amount:") % *this);
1221         throw_(value_error, _f("Cannot convert %1% with multiple commodities to %2%")
1222                % label() % label(cast_type));
1223       }
1224       break;
1225     }
1226     case STRING:
1227       if (bal.is_empty())
1228         set_string("");
1229       else
1230         set_string(as_balance().to_string());
1231       return;
1232     default:
1233       break;
1234     }
1235     break;
1236   }
1237 
1238   case STRING:
1239     switch (cast_type) {
1240     case INTEGER: {
1241       if (all(as_string(), is_any_of("-0123456789"))) {
1242         set_long(lexical_cast<long>(as_string()));
1243         return;
1244       }
1245       break;
1246     }
1247     case AMOUNT:
1248       set_amount(amount_t(as_string()));
1249       return;
1250     case DATE:
1251       set_date(parse_date(as_string()));
1252       return;
1253     case DATETIME:
1254       set_datetime(parse_datetime(as_string()));
1255       return;
1256     case MASK:
1257       set_mask(as_string());
1258       return;
1259     default:
1260       break;
1261     }
1262     break;
1263 
1264   case MASK:
1265     switch (cast_type) {
1266     case STRING:
1267       set_string(as_mask().str());
1268       return;
1269     default:
1270       break;
1271     }
1272     break;
1273 
1274   default:
1275     break;
1276   }
1277 
1278   add_error_context(_f("While converting %1%:") % *this);
1279   throw_(value_error,
1280          _f("Cannot convert %1% to %2%") % label() % label(cast_type));
1281 }
1282 
in_place_negate()1283 void value_t::in_place_negate()
1284 {
1285   switch (type()) {
1286   case BOOLEAN:
1287     set_boolean(! as_boolean());
1288     return;
1289   case INTEGER:
1290   case DATETIME:
1291     set_long(- as_long());
1292     return;
1293   case DATE:
1294     set_long(- as_long());
1295     return;
1296   case AMOUNT:
1297     as_amount_lval().in_place_negate();
1298     return;
1299   case BALANCE:
1300     as_balance_lval().in_place_negate();
1301     return;
1302   case SEQUENCE:
1303     foreach (value_t& value, as_sequence_lval())
1304       value.in_place_negate();
1305     return;
1306   default:
1307     break;
1308   }
1309 
1310   add_error_context(_f("While negating %1%:") % *this);
1311   throw_(value_error, _f("Cannot negate %1%") % label());
1312 }
1313 
in_place_not()1314 void value_t::in_place_not()
1315 {
1316   switch (type()) {
1317   case BOOLEAN:
1318     set_boolean(! as_boolean());
1319     return;
1320   case INTEGER:
1321   case DATETIME:
1322     set_boolean(! as_long());
1323     return;
1324   case DATE:
1325     set_boolean(! as_long());
1326     return;
1327   case AMOUNT:
1328     set_boolean(! as_amount());
1329     return;
1330   case BALANCE:
1331     set_boolean(! as_balance());
1332     return;
1333   case STRING:
1334     set_boolean(as_string().empty());
1335     return;
1336   case SEQUENCE:
1337     foreach (value_t& value, as_sequence_lval())
1338       value.in_place_not();
1339     return;
1340   default:
1341     break;
1342   }
1343 
1344   add_error_context(_f("While applying not to %1%:") % *this);
1345   throw_(value_error, _f("Cannot 'not' %1%") % label());
1346 }
1347 
is_realzero() const1348 bool value_t::is_realzero() const
1349 {
1350   switch (type()) {
1351   case BOOLEAN:
1352     return ! as_boolean();
1353   case INTEGER:
1354     return as_long() == 0;
1355   case DATETIME:
1356     return ! is_valid(as_datetime());
1357   case DATE:
1358     return ! is_valid(as_date());
1359   case AMOUNT:
1360     return as_amount().is_realzero();
1361   case BALANCE:
1362     return as_balance().is_realzero();
1363   case STRING:
1364     return as_string().empty();
1365   case SEQUENCE:
1366     return as_sequence().empty();
1367 
1368   case SCOPE:
1369     return as_scope() == NULL;
1370   case ANY:
1371     return as_any().empty();
1372 
1373   default:
1374     add_error_context(_f("While applying is_realzero to %1%:") % *this);
1375     throw_(value_error, _f("Cannot determine if %1% is really zero") % label());
1376   }
1377   return false;
1378 }
1379 
is_zero() const1380 bool value_t::is_zero() const
1381 {
1382   switch (type()) {
1383   case BOOLEAN:
1384     return ! as_boolean();
1385   case INTEGER:
1386     return as_long() == 0;
1387   case DATETIME:
1388     return ! is_valid(as_datetime());
1389   case DATE:
1390     return ! is_valid(as_date());
1391   case AMOUNT:
1392     return as_amount().is_zero();
1393   case BALANCE:
1394     return as_balance().is_zero();
1395   case STRING:
1396     return as_string().empty();
1397   case SEQUENCE:
1398     return as_sequence().empty();
1399 
1400   case SCOPE:
1401     return as_scope() == NULL;
1402   case ANY:
1403     return as_any().empty();
1404 
1405   default:
1406     add_error_context(_f("While applying is_zero to %1%:") % *this);
1407     throw_(value_error, _f("Cannot determine if %1% is zero") % label());
1408   }
1409   return false;
1410 }
1411 
value(const datetime_t & moment,const commodity_t * in_terms_of) const1412 value_t value_t::value(const datetime_t&   moment,
1413                        const commodity_t * in_terms_of) const
1414 {
1415   switch (type()) {
1416   case INTEGER:
1417     return NULL_VALUE;
1418 
1419   case AMOUNT:
1420     if (optional<amount_t> val = as_amount().value(moment, in_terms_of))
1421       return *val;
1422     return NULL_VALUE;
1423 
1424   case BALANCE:
1425     if (optional<balance_t> bal = as_balance().value(moment, in_terms_of))
1426       return *bal;
1427     return NULL_VALUE;
1428 
1429   case SEQUENCE: {
1430     value_t temp;
1431     foreach (const value_t& value, as_sequence())
1432       temp.push_back(value.value(moment, in_terms_of));
1433     return temp;
1434   }
1435 
1436   default:
1437     break;
1438   }
1439 
1440   add_error_context(_f("While finding valuation of %1%:") % *this);
1441   throw_(value_error, _f("Cannot find the value of %1%") % label());
1442   return NULL_VALUE;
1443 }
1444 
exchange_commodities(const std::string & commodities,const bool add_prices,const datetime_t & moment)1445 value_t value_t::exchange_commodities(const std::string& commodities,
1446                                       const bool         add_prices,
1447                                       const datetime_t&  moment)
1448 {
1449   if (type() == SEQUENCE) {
1450     value_t temp;
1451     foreach (value_t& value, as_sequence_lval())
1452       temp.push_back(value.exchange_commodities(commodities, add_prices, moment));
1453     return temp;
1454   }
1455 
1456   // If we are repricing to just a single commodity, with no price
1457   // expression, skip the expensive logic below.
1458   if (commodities.find(',') == string::npos &&
1459       commodities.find('=') == string::npos)
1460     return value(moment, commodity_pool_t::current_pool->find_or_create(commodities));
1461 
1462   std::vector<commodity_t *> comms;
1463   std::vector<bool>          force;
1464 
1465   typedef tokenizer<char_separator<char> > tokenizer;
1466   tokenizer tokens(commodities, char_separator<char>(","));
1467 
1468   foreach (const string& name, tokens) {
1469     string::size_type name_len = name.length();
1470 
1471     if (commodity_t * commodity = commodity_pool_t::current_pool
1472         ->parse_price_expression(name[name_len - 1] == '!' ?
1473                                  string(name, 0, name_len - 1) :
1474                                  name, add_prices, moment)) {
1475       DEBUG("commodity.exchange", "Pricing for commodity: " << commodity->symbol());
1476       comms.push_back(&commodity->referent());
1477       force.push_back(name[name_len - 1] == '!');
1478     }
1479   }
1480 
1481   std::size_t index = 0;
1482   foreach (commodity_t * comm, comms) {
1483     switch (type()) {
1484     case AMOUNT:
1485       DEBUG("commodity.exchange", "We have an amount: " << as_amount_lval());
1486       if (! force[index] &&
1487           std::find(comms.begin(), comms.end(),
1488                     &as_amount_lval().commodity().referent()) != comms.end())
1489         break;
1490 
1491       DEBUG("commodity.exchange", "Referent doesn't match, pricing...");
1492       if (optional<amount_t> val = as_amount_lval().value(moment, comm)) {
1493         DEBUG("commodity.exchange", "Re-priced amount is: " << *val);
1494         return *val;
1495       }
1496       DEBUG("commodity.exchange", "Was unable to find a price");
1497       break;
1498 
1499     case BALANCE: {
1500       balance_t temp;
1501       bool repriced = false;
1502 
1503       DEBUG("commodity.exchange", "We have a balance: " << as_balance_lval());
1504       foreach (const balance_t::amounts_map::value_type& pair,
1505                as_balance_lval().amounts) {
1506         DEBUG("commodity.exchange", "We have a balance amount of commodity: "
1507               << pair.first->symbol() << " == "
1508               << pair.second.commodity().symbol());
1509         if (! force[index] &&
1510             std::find(comms.begin(), comms.end(),
1511                       &pair.first->referent()) != comms.end()) {
1512           temp += pair.second;
1513         } else {
1514           DEBUG("commodity.exchange", "Referent doesn't match, pricing...");
1515           if (optional<amount_t> val = pair.second.value(moment, comm)) {
1516             DEBUG("commodity.exchange", "Re-priced member amount is: " << *val);
1517             temp += *val;
1518             repriced = true;
1519           } else {
1520             DEBUG("commodity.exchange", "Was unable to find price");
1521             temp += pair.second;
1522           }
1523         }
1524       }
1525 
1526       if (repriced) {
1527         DEBUG("commodity.exchange", "Re-priced balance is: " << temp);
1528         return temp;
1529       }
1530     }
1531 
1532     default:
1533       break;
1534     }
1535 
1536     ++index;
1537   }
1538 
1539   return *this;
1540 }
1541 
in_place_reduce()1542 void value_t::in_place_reduce()
1543 {
1544   switch (type()) {
1545   case AMOUNT:
1546     as_amount_lval().in_place_reduce();
1547     return;
1548   case BALANCE:
1549     as_balance_lval().in_place_reduce();
1550     return;
1551   case SEQUENCE:
1552     foreach (value_t& value, as_sequence_lval())
1553       value.in_place_reduce();
1554     return;
1555   default:
1556     return;
1557   }
1558 
1559   //throw_(value_error, _f("Cannot reduce %1%") % label());
1560 }
1561 
in_place_unreduce()1562 void value_t::in_place_unreduce()
1563 {
1564   switch (type()) {
1565   case AMOUNT:
1566     as_amount_lval().in_place_unreduce();
1567     return;
1568   case BALANCE:
1569     as_balance_lval().in_place_unreduce();
1570     return;
1571   case SEQUENCE:
1572     foreach (value_t& value, as_sequence_lval())
1573       value.in_place_unreduce();
1574     return;
1575   default:
1576     return;
1577   }
1578 
1579   //throw_(value_error, _f("Cannot reduce %1%") % label());
1580 }
1581 
abs() const1582 value_t value_t::abs() const
1583 {
1584   switch (type()) {
1585   case INTEGER: {
1586     long val = as_long();
1587     if (val < 0)
1588       return - val;
1589     return val;
1590   }
1591   case AMOUNT:
1592     return as_amount().abs();
1593   case BALANCE:
1594     return as_balance().abs();
1595   default:
1596     break;
1597   }
1598 
1599   add_error_context(_f("While taking abs of %1%:") % *this);
1600   throw_(value_error, _f("Cannot abs %1%") % label());
1601   return NULL_VALUE;
1602 }
1603 
in_place_round()1604 void value_t::in_place_round()
1605 {
1606   switch (type()) {
1607   case INTEGER:
1608     return;
1609   case AMOUNT:
1610     as_amount_lval().in_place_round();
1611     return;
1612   case BALANCE:
1613     as_balance_lval().in_place_round();
1614     return;
1615   case SEQUENCE:
1616     foreach (value_t& value, as_sequence_lval())
1617       value.in_place_round();
1618     return;
1619   default:
1620     break;
1621   }
1622 
1623   add_error_context(_f("While rounding %1%:") % *this);
1624   throw_(value_error, _f("Cannot set rounding for %1%") % label());
1625 }
1626 
in_place_roundto(int places)1627 void value_t::in_place_roundto(int places)
1628 {
1629   DEBUG("amount.roundto", "=====> roundto places " << places);
1630   switch (type()) {
1631   case INTEGER:
1632     return;
1633   case AMOUNT:
1634     as_amount_lval().in_place_roundto(places);
1635     return;
1636   case BALANCE:
1637     as_balance_lval().in_place_roundto(places);
1638     return;
1639   case SEQUENCE:
1640     foreach (value_t& value, as_sequence_lval())
1641       value.in_place_roundto(places);
1642     return;
1643   default:
1644     break;
1645   }
1646 }
1647 
in_place_truncate()1648 void value_t::in_place_truncate()
1649 {
1650   switch (type()) {
1651   case INTEGER:
1652     return;
1653   case AMOUNT:
1654     as_amount_lval().in_place_truncate();
1655     return;
1656   case BALANCE:
1657     as_balance_lval().in_place_truncate();
1658     return;
1659   case SEQUENCE:
1660     foreach (value_t& value, as_sequence_lval())
1661       value.in_place_truncate();
1662     return;
1663   default:
1664     break;
1665   }
1666 
1667   add_error_context(_f("While truncating %1%:") % *this);
1668   throw_(value_error, _f("Cannot truncate %1%") % label());
1669 }
1670 
in_place_floor()1671 void value_t::in_place_floor()
1672 {
1673   switch (type()) {
1674   case INTEGER:
1675     return;
1676   case AMOUNT:
1677     as_amount_lval().in_place_floor();
1678     return;
1679   case BALANCE:
1680     as_balance_lval().in_place_floor();
1681     return;
1682   case SEQUENCE:
1683     foreach (value_t& value, as_sequence_lval())
1684       value.in_place_floor();
1685     return;
1686   default:
1687     break;
1688   }
1689 
1690   add_error_context(_f("While flooring %1%:") % *this);
1691   throw_(value_error, _f("Cannot floor %1%") % label());
1692 }
1693 
in_place_ceiling()1694 void value_t::in_place_ceiling()
1695 {
1696   switch (type()) {
1697   case INTEGER:
1698     return;
1699   case AMOUNT:
1700     as_amount_lval().in_place_ceiling();
1701     return;
1702   case BALANCE:
1703     as_balance_lval().in_place_ceiling();
1704     return;
1705   case SEQUENCE:
1706     foreach (value_t& value, as_sequence_lval())
1707       value.in_place_ceiling();
1708     return;
1709   default:
1710     break;
1711   }
1712 
1713   add_error_context(_f("While ceiling %1%:") % *this);
1714   throw_(value_error, _f("Cannot ceiling %1%") % label());
1715 }
1716 
in_place_unround()1717 void value_t::in_place_unround()
1718 {
1719   switch (type()) {
1720   case INTEGER:
1721     return;
1722   case AMOUNT:
1723     as_amount_lval().in_place_unround();
1724     return;
1725   case BALANCE:
1726     as_balance_lval().in_place_unround();
1727     return;
1728   case SEQUENCE:
1729     foreach (value_t& value, as_sequence_lval())
1730       value.in_place_unround();
1731     return;
1732   default:
1733     break;
1734   }
1735 
1736   add_error_context(_f("While unrounding %1%:") % *this);
1737   throw_(value_error, _f("Cannot unround %1%") % label());
1738 }
1739 
annotate(const annotation_t & details)1740 void value_t::annotate(const annotation_t& details)
1741 {
1742   if (is_amount()) {
1743     as_amount_lval().annotate(details);
1744   } else {
1745     add_error_context(_f("While attempting to annotate %1%:") % *this);
1746     throw_(value_error, _f("Cannot annotate %1%") % label());
1747   }
1748 }
1749 
has_annotation() const1750 bool value_t::has_annotation() const
1751 {
1752   if (is_amount()) {
1753     return as_amount().has_annotation();
1754   } else {
1755     add_error_context(_f("While checking if %1% has annotations:") % *this);
1756     throw_(value_error,
1757            _f("Cannot determine whether %1% is annotated") % label());
1758   }
1759   return false;
1760 }
1761 
annotation()1762 annotation_t& value_t::annotation()
1763 {
1764   if (is_amount()) {
1765     return as_amount_lval().annotation();
1766   } else {
1767     add_error_context(_f("While requesting the annotations of %1%:") % *this);
1768     throw_(value_error, _f("Cannot request annotation of %1%") % label());
1769     return as_amount_lval().annotation(); // quiet g++ warning
1770   }
1771 }
1772 
strip_annotations(const keep_details_t & what_to_keep) const1773 value_t value_t::strip_annotations(const keep_details_t& what_to_keep) const
1774 {
1775   if (what_to_keep.keep_all())
1776     return *this;
1777 
1778   switch (type()) {
1779   case VOID:
1780   case BOOLEAN:
1781   case INTEGER:
1782   case DATETIME:
1783   case DATE:
1784   case STRING:
1785   case MASK:
1786   case SCOPE:
1787   case ANY:
1788     return *this;
1789 
1790   case SEQUENCE: {
1791     sequence_t temp;
1792     foreach (const value_t& value, as_sequence())
1793       temp.push_back(new value_t(value.strip_annotations(what_to_keep)));
1794     return temp;
1795   }
1796 
1797   case AMOUNT:
1798     return as_amount().strip_annotations(what_to_keep);
1799   case BALANCE:
1800     return as_balance().strip_annotations(what_to_keep);
1801   }
1802 
1803   assert(false);
1804   return NULL_VALUE;
1805 }
1806 
label(optional<type_t> the_type) const1807 string value_t::label(optional<type_t> the_type) const
1808 {
1809   switch (the_type ? *the_type : type()) {
1810   case VOID:
1811     return _("an uninitialized value");
1812   case BOOLEAN:
1813     return _("a boolean");
1814   case DATETIME:
1815     return _("a date/time");
1816   case DATE:
1817     return _("a date");
1818   case INTEGER:
1819     return _("an integer");
1820   case AMOUNT:
1821     return _("an amount");
1822   case BALANCE:
1823     return _("a balance");
1824   case STRING:
1825     return _("a string");
1826   case MASK:
1827     return _("a regexp");
1828   case SEQUENCE:
1829     return _("a sequence");
1830   case SCOPE:
1831     return _("a scope");
1832   case ANY:
1833     if (as_any().type() == typeid(expr_t::ptr_op_t))
1834       return _("an expr");
1835     else
1836       return _("an object");
1837   }
1838   assert(false);
1839   return _("<invalid>");
1840 }
1841 
print(std::ostream & _out,const int first_width,const int latter_width,const uint_least8_t flags) const1842 void value_t::print(std::ostream&       _out,
1843                     const int           first_width,
1844                     const int           latter_width,
1845                     const uint_least8_t flags) const
1846 {
1847   std::ostringstream out;
1848 
1849   if (first_width > 0 &&
1850       (! is_amount() || as_amount().is_zero()) &&
1851       ! is_balance() && ! is_string()) {
1852     out.width(first_width);
1853 
1854     if (flags & AMOUNT_PRINT_RIGHT_JUSTIFY)
1855       out << std::right;
1856     else
1857       out << std::left;
1858   }
1859 
1860   switch (type()) {
1861   case VOID:
1862     out << "";
1863     break;
1864 
1865   case BOOLEAN:
1866     out << (as_boolean() ? "1" : "0");
1867     break;
1868 
1869   case DATETIME:
1870     out << format_datetime(as_datetime(), FMT_WRITTEN);
1871     break;
1872 
1873   case DATE:
1874     out << format_date(as_date(), FMT_WRITTEN);
1875     break;
1876 
1877   case INTEGER:
1878     if (flags & AMOUNT_PRINT_COLORIZE && as_long() < 0)
1879       justify(out, to_string(), first_width,
1880               flags & AMOUNT_PRINT_RIGHT_JUSTIFY, true);
1881     else
1882       out << as_long();
1883     break;
1884 
1885   case AMOUNT: {
1886     if (as_amount().is_zero()) {
1887       out << 0;
1888     } else {
1889       std::ostringstream buf;
1890       as_amount().print(buf, flags);
1891       justify(out, buf.str(), first_width, flags & AMOUNT_PRINT_RIGHT_JUSTIFY,
1892               flags & AMOUNT_PRINT_COLORIZE && as_amount().sign() < 0);
1893     }
1894     break;
1895   }
1896 
1897   case BALANCE:
1898     as_balance().print(out, first_width, latter_width, flags);
1899     break;
1900 
1901   case STRING:
1902     if (first_width > 0)
1903       justify(out, as_string(), first_width, flags & AMOUNT_PRINT_RIGHT_JUSTIFY);
1904     else
1905       out << as_string();
1906     break;
1907 
1908   case MASK:
1909     out << '/' << as_mask() << '/';
1910     break;
1911 
1912   case SEQUENCE: {
1913     out << '(';
1914     bool first = true;
1915     foreach (const value_t& value, as_sequence()) {
1916       if (first)
1917         first = false;
1918       else
1919         out << ", ";
1920 
1921       value.print(out, first_width, latter_width, flags);
1922     }
1923     out << ')';
1924     break;
1925   }
1926 
1927   case SCOPE:
1928     out << "<#SCOPE>";
1929     break;
1930   case ANY:
1931     if (as_any().type() == typeid(expr_t::ptr_op_t)) {
1932       out << "<#EXPR ";
1933       as_any<expr_t::ptr_op_t>()->print(out);
1934       out << ">";
1935     } else {
1936       out << "<#OBJECT>";
1937     }
1938     break;
1939   }
1940 
1941   _out << out.str();
1942 }
1943 
dump(std::ostream & out,const bool relaxed) const1944 void value_t::dump(std::ostream& out, const bool relaxed) const
1945 {
1946   switch (type()) {
1947   case VOID:
1948     out << "null";
1949     break;
1950 
1951   case BOOLEAN:
1952     if (as_boolean())
1953       out << "true";
1954     else
1955       out << "false";
1956     break;
1957 
1958   case DATETIME:
1959     out << '[' << format_datetime(as_datetime(), FMT_WRITTEN) << ']';
1960     break;
1961   case DATE:
1962     out << '[' << format_date(as_date(), FMT_WRITTEN) << ']';
1963     break;
1964 
1965   case INTEGER:
1966     out << as_long();
1967     break;
1968 
1969   case AMOUNT:
1970     if (! relaxed)
1971       out << '{';
1972     out << as_amount();
1973     if (! relaxed)
1974       out << '}';
1975     break;
1976 
1977   case BALANCE:
1978     out << as_balance();
1979     break;
1980 
1981   case STRING:
1982     out << '"';
1983     foreach (const char& ch, as_string()) {
1984       switch (ch) {
1985       case '"':
1986         out << "\\\"";
1987         break;
1988       case '\\':
1989         out << "\\\\";
1990         break;
1991       default:
1992         out << ch;
1993         break;
1994       }
1995     }
1996     out << '"';
1997     break;
1998 
1999   case MASK:
2000     out << '/' << as_mask() << '/';
2001     break;
2002 
2003   case SCOPE:
2004     out << as_scope();
2005     break;
2006   case ANY:
2007     if (as_any().type() == typeid(expr_t::ptr_op_t))
2008       as_any<expr_t::ptr_op_t>()->dump(out);
2009     else
2010       out << boost::unsafe_any_cast<const void *>(&as_any());
2011     break;
2012 
2013   case SEQUENCE: {
2014     out << '(';
2015     bool first = true;
2016     foreach (const value_t& value, as_sequence()) {
2017       if (first)
2018         first = false;
2019       else
2020         out << ", ";
2021 
2022       value.dump(out, relaxed);
2023     }
2024     out << ')';
2025     break;
2026   }
2027   }
2028 }
2029 
valid() const2030 bool value_t::valid() const
2031 {
2032   switch (type()) {
2033   case AMOUNT:
2034     return as_amount().valid();
2035   case BALANCE:
2036     return as_balance().valid();
2037   default:
2038     break;
2039   }
2040   return true;
2041 }
2042 
sort_value_is_less_than(const std::list<sort_value_t> & left_values,const std::list<sort_value_t> & right_values)2043 bool sort_value_is_less_than(const std::list<sort_value_t>& left_values,
2044                              const std::list<sort_value_t>& right_values)
2045 {
2046   std::list<sort_value_t>::const_iterator left_iter  = left_values.begin();
2047   std::list<sort_value_t>::const_iterator right_iter = right_values.begin();
2048 
2049   while (left_iter != left_values.end() && right_iter != right_values.end()) {
2050     // Don't even try to sort balance values
2051     if (! (*left_iter).value.is_balance() &&
2052         ! (*right_iter).value.is_balance()) {
2053       DEBUG("value.sort",
2054             " Comparing " << (*left_iter).value << " < " << (*right_iter).value);
2055       if ((*left_iter).value < (*right_iter).value) {
2056         DEBUG("value.sort", "  is less");
2057         return ! (*left_iter).inverted;
2058       }
2059       else if ((*left_iter).value > (*right_iter).value) {
2060         DEBUG("value.sort", "  is greater");
2061         return (*left_iter).inverted;
2062       }
2063     }
2064     left_iter++; right_iter++;
2065   }
2066 
2067   assert(left_iter == left_values.end());
2068   assert(right_iter == right_values.end());
2069 
2070   return false;
2071 }
2072 
put_value(property_tree::ptree & pt,const value_t & value)2073 void put_value(property_tree::ptree& pt, const value_t& value)
2074 {
2075   switch (value.type()) {
2076   case value_t::VOID:
2077     pt.add("void", "");
2078     break;
2079   case value_t::BOOLEAN:
2080     pt.add("bool", value.as_boolean() ? "true" : "false");
2081     break;
2082   case value_t::INTEGER:
2083     pt.add("int", value.to_string());
2084     break;
2085   case value_t::AMOUNT:
2086     put_amount(pt.add("amount", ""), value.as_amount());
2087     break;
2088   case value_t::BALANCE:
2089     put_balance(pt.add("balance", ""), value.as_balance());
2090     break;
2091   case value_t::DATETIME:
2092     put_datetime(pt.add("datetime", ""), value.as_datetime());
2093     break;
2094   case value_t::DATE:
2095     put_date(pt.add("date", ""), value.as_date());
2096     break;
2097   case value_t::STRING:
2098     pt.add("string", value.as_string());
2099     break;
2100   case value_t::MASK:
2101     put_mask(pt.add("mask", ""), value.as_mask());
2102     break;
2103 
2104   case value_t::SEQUENCE: {
2105     property_tree::ptree& st(pt.add("sequence", ""));
2106     foreach (const value_t& member, value.as_sequence())
2107       put_value(st, member);
2108     break;
2109   }
2110 
2111   case value_t::SCOPE:
2112   case value_t::ANY:
2113     assert(false);
2114     break;
2115   }
2116 }
2117 
2118 } // namespace ledger
2119