Promote 'amounts' to a new type. Codify storage format, both internal

and serialized. Define operators.
This commit is contained in:
JoelKatz
2012-04-09 19:36:51 -07:00
parent 3e91ddc6d7
commit fcdf42e799
5 changed files with 147 additions and 8 deletions

71
src/Amount.cpp Normal file
View File

@@ -0,0 +1,71 @@
#include <cmath>
#include <boost/lexical_cast.hpp>
#include "SerializedTypes.h"
void STAmount::canonicalize()
{
if(value==0)
{
offset=0;
value=0;
}
while(value<cMinValue)
{
value*=10;
offset-=1;
}
while(value>cMaxValue)
{ // Here we can make it throw on precision loss if we wish: ((value%10)!=0)
value/=10;
offset+=1;
}
assert( (value==0) || ( (value>=cMinValue) && (value<=cMaxValue) ) );
assert( (offset>=cMinOffset) && (offset<=cMaxOffset) );
}
STAmount* STAmount::construct(SerializerIterator& sit, const char *name)
{
uint64 value = sit.get64();
int offset = static_cast<int>(value>>(64-8));
offset-=142;
value&=~(255ull<<(64-8));
if(value==0)
{
if(offset!=0)
throw std::runtime_error("invalid currency value");
}
else
{
if( (value<cMinValue) || (value>cMaxValue) || (offset<cMinOffset) || (offset>cMaxOffset) )
throw std::runtime_error("invalid currency value");
}
return new STAmount(name, value, offset);
}
std::string STAmount::getText() const
{
return boost::lexical_cast<std::string>(static_cast<double>(*this));
}
void STAmount::add(Serializer& s) const
{
uint64 v=value;
v+=(static_cast<uint64>(offset+142) << (64-8));
s.add64(v);
}
bool STAmount::isEquivalent(const SerializedType& t) const
{
const STAmount* v=dynamic_cast<const STAmount*>(&t);
if(!v) return false;
return (value==v->value) && (offset==v->offset);
}
STAmount::operator double() const
{
if(!value) return 0.0;
return static_cast<double>(value) * pow(10.0, offset);
}