diff --git a/src/Amount.cpp b/src/Amount.cpp index 3095bace10..a36ec50943 100644 --- a/src/Amount.cpp +++ b/src/Amount.cpp @@ -1,11 +1,156 @@ #include #include +#include #include #include +#include "Config.h" #include "SerializedTypes.h" +#include "utils.h" + +bool STAmount::currencyFromString(uint160& uDstCurrency, const std::string& sCurrency) +{ + bool bSuccess = true; + + if (sCurrency.empty() || !sCurrency.compare(SYSTEM_CURRENCY_CODE)) + { + uDstCurrency = 0; + } + else if (3 == sCurrency.size()) + { + std::vector vucIso(3); + + std::transform(sCurrency.begin(), sCurrency.end(), vucIso.begin(), ::toupper); + + // std::string sIso; + // sIso.assign(vucIso.begin(), vucIso.end()); + // std::cerr << "currency: " << sIso << std::endl; + + Serializer s; + + s.addZeros(98/8); + s.addRaw(vucIso); + s.addZeros(16/8); + s.addZeros(25/8); + + SerializerIterator sit(s); + + uDstCurrency = sit.get160(); + } + else + { + bSuccess = false; + } + + return bSuccess; +} + +std::string STAmount::getCurrencyHuman() +{ + std::string sCurrency; + + if (mIsNative) + { + return SYSTEM_CURRENCY_CODE; + } + else + { + uint160 uReserved = mCurrency; + Serializer s(160/20); + + s.add160(mCurrency); + + SerializerIterator sit(s); + + std::vector vucZeros = sit.getRaw(96/8); + std::vector vucIso = sit.getRaw(24/8); + std::vector vucVersion = sit.getRaw(16/8); + std::vector vucReserved = sit.getRaw(24/8); + + if (!::isZero(vucZeros.begin(), vucZeros.size())) + { + throw std::runtime_error("bad currency: zeros"); + } + else if (!::isZero(vucVersion.begin(), vucVersion.size())) + { + throw std::runtime_error("bad currency: version"); + } + else if (!::isZero(vucReserved.begin(), vucReserved.size())) + { + throw std::runtime_error("bad currency: reserved"); + } + else + { + sCurrency.assign(vucIso.begin(), vucIso.end()); + } + } + + return sCurrency; +} + +// Not meant to be the ultimate parser. For use by RPC which is supposed to be sane and trusted. +bool STAmount::setValue(const std::string& sAmount, const std::string& sCurrency) +{ + if (!currencyFromString(mCurrency, sCurrency)) + return false; + + uint64 uValue; + int iOffset; + size_t uDecimal = sAmount.find_first_of(".,"); + bool bInteger = uDecimal == std::string::npos; + + if (bInteger) + { + uValue = sAmount.empty() ? 0 : boost::lexical_cast(sAmount); + iOffset = 0; + } + else + { + // Example size decimal size-decimal offset + // .1 2 0 2 -1 + // 123. 4 3 1 0 + // 1.23 4 1 3 -2 + iOffset = -(sAmount.size()-uDecimal-1); + + uint64 uInteger = uDecimal ? boost::lexical_cast(sAmount.substr(0, uDecimal)) : 0; + uint64 uFraction = iOffset ? boost::lexical_cast(sAmount.substr(uDecimal+1)) : 0; + + uValue = uInteger; + for (int i=-iOffset; i--;) + uValue *= 10; + + uValue += uFraction; + } + + mIsNative = !mCurrency; + if (mIsNative) + { + if (bInteger) + iOffset = -SYSTEM_CURRENCY_PRECISION; + + while (iOffset > -SYSTEM_CURRENCY_PRECISION) { + uValue *= 10; + --iOffset; + } + + while (iOffset < -SYSTEM_CURRENCY_PRECISION) { + uValue /= 10; + ++iOffset; + } + + mValue = uValue; + } + else + { + mValue = uValue; + mOffset = iOffset; + canonicalize(); + } + + return true; +} // amount = value * [10 ^ offset] // representation range is 10^80 - 10^(-80) diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 9622d55dd1..5d48415140 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -228,10 +228,12 @@ public: int getOffset() const { return mOffset; } uint64 getValue() const { return mValue; } void setValue(const STAmount& v) { mValue=v; } + std::string getCurrencyHuman(); bool isNative() const { return mIsNative; } const uint160& getCurrency() const { return mCurrency; } void zero() { mOffset = mIsNative ? -100 : 0; mValue = 0; } bool isZero() const { return mValue == 0; } + bool setValue(const std::string& sAmount, const std::string& sCurrency); virtual bool isEquivalent(const SerializedType& t) const; @@ -275,6 +277,7 @@ public: const char *name = NULL); static STAmount deSerialize(SerializerIterator&); + static bool currencyFromString(uint160& uDstCurrency, const std::string& sCurrency); }; class STHash128 : public SerializedType