142 #include <irrxml/irrXML.hpp>
154 bool OTAssetContract::ParseFormatted(int64_t& lResult,
155 const std::string& str_input,
156 int32_t nFactor, int32_t nPower,
157 const char* szThousandSeparator,
158 const char* szDecimalPoint)
160 OT_ASSERT(
nullptr != szThousandSeparator);
165 char theSeparator = szThousandSeparator[0];
166 char theDecimalPoint = szDecimalPoint[0];
168 int64_t lDollars = 0;
173 bool bHasEnteredDollars =
false;
174 bool bHasEnteredCents =
false;
176 int32_t nDigitsCollectedBeforeDot = 0;
177 int32_t nDigitsCollectedAfterDot = 0;
183 std::deque<int64_t> deque_cents;
185 for (uint32_t uIndex = 0; uIndex < str_input.length(); ++uIndex) {
186 char theChar = str_input[uIndex];
188 if (iscntrl(theChar))
192 if (0 == isdigit(theChar))
194 if (theSeparator == theChar)
continue;
196 if (theDecimalPoint == theChar) {
197 if (bHasEnteredCents) {
208 bHasEnteredDollars =
true;
209 bHasEnteredCents =
true;
217 if (
'-' == theChar) {
233 if (bHasEnteredDollars || bHasEnteredCents)
245 if (bHasEnteredCents) {
246 ++nDigitsCollectedAfterDot;
250 if (nDigitsCollectedAfterDot > nPower)
break;
254 deque_cents.push_back(static_cast<int64_t>(theChar -
'0'));
262 if (!bHasEnteredDollars) bHasEnteredDollars =
true;
264 ++nDigitsCollectedBeforeDot;
270 lDollars +=
static_cast<int64_t
>(theChar -
'0');
276 lOutput *=
static_cast<int64_t
>(nFactor);
278 int32_t nTempPower = nPower;
280 while (nTempPower > 0) {
283 if (deque_cents.size() > 0) {
284 lCents += deque_cents.front();
285 deque_cents.pop_front();
295 lResult = (lOutput * lSign);
301 const char* szSeparator)
309 sss << szSeparator << std::setfill(
'0') << std::setw(3) << value % 1000;
312 std::string OTAssetContract::formatLongAmount(int64_t lValue, int32_t nFactor,
314 const char* szCurrencySymbol,
315 const char* szThousandSeparator,
316 const char* szDecimalPoint)
318 std::stringstream sss;
326 sss << szCurrencySymbol <<
" ";
336 sss << szDecimalPoint << std::setfill(
'0') << std::setw(nPower)
337 << (lValue % nFactor);
348 bool OTAssetContract::FormatAmount(int64_t amount,
349 std::string& str_output)
const
352 int32_t nFactor = atoi(
353 m_strCurrencyFactor.Get());
354 if (nFactor < 1) nFactor = 1;
357 int32_t nPower = atoi(m_strCurrencyDecimalPower.Get());
360 if (nPower < 0) nPower = 0;
383 str_output = OTAssetContract::formatLongAmount(
384 amount, nFactor, nPower, m_strCurrencySymbol.Get(), strSeparator.
Get(),
385 strDecimalPoint.
Get());
394 bool OTAssetContract::StringToAmount(
396 const std::string& str_input)
const
398 int32_t nFactor = atoi(
399 m_strCurrencyFactor.Get());
400 if (nFactor < 1) nFactor = 1;
403 int32_t nPower = atoi(m_strCurrencyDecimalPower.Get());
406 if (nPower < 0) nPower = 0;
424 static OTString strDecimalPoint(
".");
426 bool bSuccess = OTAssetContract::ParseFormatted(amount, str_input, nFactor,
427 nPower, strSeparator.
Get(),
428 strDecimalPoint.
Get());
433 OTAssetContract::OTAssetContract()
435 , m_bIsCurrency(true)
442 :
OTContract(name, foldername, filename, strID)
443 , m_bIsCurrency(true)
476 " assetTypeID=\"%s\" />\n\n",
500 OTString strAssetTypeID, strAcctRecordFile;
502 strAcctRecordFile.
Format(
"%s.a", strAssetTypeID.
Get());
506 strAcctRecordFile.
Get()));
514 if (
nullptr != pMap) {
517 "Assert: nullptr Server ID on functor. "
518 "(How did you even construct the "
528 for (
auto& it : theMap) {
529 const std::string& str_acct_id =
531 const std::string& str_asset_id =
535 if (!strAssetTypeID.
Compare(str_asset_id.c_str())) {
536 otErr <<
"OTAssetContract::VisitAccountRecords: Error: wrong "
537 "asset type ID (" << str_asset_id
538 <<
") when expecting: " << strAssetTypeID <<
"\n";
542 std::unique_ptr<OTAccount> theAcctAngel;
556 auto found_it = pLoadedAccounts->find(str_acct_id);
558 if (pLoadedAccounts->end() != found_it)
560 pAccount = found_it->second;
564 otErr <<
"Error: the actual account didn't have "
565 "the ID that the std::map SAID it had! "
566 "(Should never happen.)\n";
575 if (
nullptr == pAccount) {
578 theAcctAngel.reset(pAccount);
581 bool bSuccessLoadingAccount =
582 ((pAccount !=
nullptr) ?
true :
false);
583 if (bSuccessLoadingAccount) {
584 bool bTriggerSuccess = visitor.
Trigger(*pAccount);
585 if (!bTriggerSuccess)
586 otErr << __FUNCTION__ <<
": Error: Trigger Failed.";
589 otErr << __FUNCTION__ <<
": Error: Failed Loading Account!";
613 const char* szFunc =
"OTAssetContract::AddAccountRecord";
615 if (theAccount.GetAssetTypeID() != m_ID) {
616 otErr << szFunc <<
": Error: theAccount doesn't have the same asset "
617 "type ID as *this does.\n";
622 const OTString strAcctID(theAcctID);
624 OTString strAssetTypeID, strAcctRecordFile;
625 GetIdentifier(strAssetTypeID);
626 strAcctRecordFile.
Format(
"%s.a", strAssetTypeID.
Get());
629 std::unique_ptr<OTDB::Storable> theAngel;
633 strAcctRecordFile.
Get()))
637 strAcctRecordFile.
Get());
642 theAngel.reset(pStorable);
643 pMap = (
nullptr == pStorable) ?
nullptr
644 : dynamic_cast<OTDB::StringMap*>(pStorable);
648 if (
nullptr == pMap) {
650 <<
": Error: failed trying to load or create the account records "
651 "file for asset type: " << strAssetTypeID <<
"\n";
656 auto map_it = theMap.find(strAcctID.
Get());
658 if (theMap.end() != map_it)
666 const std::string& str2 =
673 strAssetTypeID.
Compare(str2.c_str()))
676 <<
": Error: wrong asset type found in account records "
677 "file...\n For asset type: " << strAssetTypeID
679 "For account: " << strAcctID
680 <<
"\n Found wrong asset type: " << str2 <<
"\n";
692 theMap[strAcctID.
Get()] = strAssetTypeID.
Get();
697 strAcctRecordFile.
Get())) {
699 <<
": Failed trying to StoreObject, while saving updated "
700 "account records file for asset type: " << strAssetTypeID
701 <<
"\n to contain account ID: " << strAcctID <<
"\n";
719 const char* szFunc =
"OTAssetContract::EraseAccountRecord";
721 const OTString strAcctID(theAcctID);
723 OTString strAssetTypeID, strAcctRecordFile;
724 GetIdentifier(strAssetTypeID);
725 strAcctRecordFile.
Format(
"%s.a", strAssetTypeID.
Get());
728 std::unique_ptr<OTDB::Storable> theAngel;
732 strAcctRecordFile.
Get()))
736 strAcctRecordFile.
Get());
741 theAngel.reset(pStorable);
742 pMap = (
nullptr == pStorable) ?
nullptr
743 : dynamic_cast<OTDB::StringMap*>(pStorable);
747 if (
nullptr == pMap) {
749 <<
": Error: failed trying to load or create the account records "
750 "file for asset type: " << strAssetTypeID <<
"\n";
757 auto map_it = theMap.find(strAcctID.
Get());
760 if (theMap.end() != map_it)
762 theMap.erase(map_it);
773 strAcctRecordFile.
Get())) {
775 <<
": Failed trying to StoreObject, while saving updated "
776 "account records file for asset type: " << strAssetTypeID
777 <<
"\n to erase account ID: " << strAcctID <<
"\n";
800 " email=\"%s\"/>\n\n",
808 " contractUrl=\"%s\"\n"
809 " type=\"%s\"/>\n\n",
817 "<currency name=\"%s\" tla=\"%s\" symbol=\"%s\" type=\"%s\" "
818 "factor=\"%s\" decimal_power=\"%s\" fraction=\"%s\" />\n\n",
825 "<shares name=\"%s\" symbol=\"%s\" type=\"%s\" "
826 "issuedate=\"%s\" />\n\n",
851 if (nReturnVal == 1 || nReturnVal == (-1))
return nReturnVal;
853 const OTString strNodeName(xml->getNodeName());
855 if (strNodeName.Compare(
"digitalAssetContract")) {
859 "===> Loading XML portion of asset contract into memory "
862 <<
"\nContract version: " <<
m_strVersion <<
"\n----------\n";
865 else if (strNodeName.Compare(
"issue")) {
878 else if (strNodeName.Compare(
"currency")) {
882 m_strName = xml->getAttributeValue(
"name");
912 else if (strNodeName.Compare(
"shares")) {
916 m_strName = xml->getAttributeValue(
"name");
virtual EXPORT bool DisplayStatistics(OTString &strContents) const
EXPORT Storable * CreateObject(StoredObjectType eType)
OTString m_strCurrencyName
EXPORT void CreateInnerContents()
OTString m_strCurrencyType
virtual EXPORT int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
OTString m_strCurrencyFraction
void separateThousands(std::stringstream &sss, int64_t value, const char *szSeparator)
EXPORT void Concatenate(const char *arg,...)
static EXPORT const OTString & Contract()
EXPORT Storable * QueryObject(StoredObjectType theObjectType, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
EXPORT bool Exists() const
EXPORT bool SetString(const OTString &theData, bool bLineBreaks=true)
EXPORT void Format(const char *fmt,...)
OTString m_strCurrencyDecimalPower
OTString m_strIssueCompany
EXPORT bool Compare(const char *compare) const
virtual EXPORT void CreateContents()
EXPORT bool AddAccountRecord(const OTAccount &theAccount) const
OTString m_strEntityShortName
OTString m_strCurrencyTLA
#define OT_ASSERT_MSG(x, s)
std::map< std::string, OTAccount * > mapOfAccounts
OTString m_strCurrencyFactor
OTLOG_IMPORT OTLogStream otInfo
virtual EXPORT void GetIdentifier(OTIdentifier &theIdentifier) const
OTString m_strCurrencySymbol
OTString m_strEntityLongName
OTStringXML m_xmlUnsigned
OTLOG_IMPORT OTLogStream otWarn
virtual EXPORT ~OTAssetContract()
EXPORT const char * Get() const
EXPORT bool VisitAccountRecords(AccountVisitor &visitor) const
OTLOG_IMPORT OTLogStream otErr
virtual EXPORT int32_t ProcessXMLNode(irr::io::IrrXMLReader *&xml)
const OTIdentifier & GetPurportedAccountID() const
std::map< std::string, std::string > the_map
OTString m_strIssueContractURL
EXPORT bool Exists(std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
OTString m_strEntityEmail
EXPORT bool EraseAccountRecord(const OTIdentifier &theAcctID) const
EXPORT bool StoreObject(Storable &theContents, std::string strFolder, std::string oneStr="", std::string twoStr="", std::string threeStr="")
EXPORT mapOfAccounts * GetLoadedAccts()
EXPORT OTIdentifier * GetServerID()
static EXPORT OTAccount * LoadExistingAccount(const OTIdentifier &accountId, const OTIdentifier &serverId)
virtual EXPORT void Release()
virtual EXPORT bool SaveContractWallet(OTString &strContents) const
virtual EXPORT bool Trigger(OTAccount &account)=0