<commit_before>/* currency.cc
   <NAME>, 5 November 2012
   Copyright (c) 2012 Datacratic Inc.  All rights reserved.

*/

#include "rtbkit/common/currency.h"

using namespace std;
using namespace ML;
using namespace Datacratic;


namespace RTBKIT {


/*****************************************************************************/
/* CURRENCY CODE                                                             */
/*****************************************************************************/

std::string toString(CurrencyCode code)
{
    if (code == CurrencyCode::CC_NONE)
        return "NONE";
    else if (code == CurrencyCode::CC_USD)
        return "USD";
    else throw ML::Exception("unknown currency code");
}

CurrencyCode parseCurrencyCode(const std::string & code)
{
    if (code == "USD")
        return CurrencyCode::CC_USD;
    else if (code == "NONE")
        return CurrencyCode::CC_NONE;
    else throw ML::Exception("unknown currency code");
}

CurrencyCode jsonDecode(const Json::Value & j, CurrencyCode *)
{
    if (j.isNull())
        return CurrencyCode::CC_NONE;
    string s = j.asString();
    if (s.size() > 4)
        throw ML::Exception("unknown currency code " + s);
    if (s == "USD")
        return CurrencyCode::CC_USD;
    
    throw ML::Exception("not done: decoding other currency " + s);
}

Json::Value jsonEncode(CurrencyCode code)
{
    switch (code) {
    case CurrencyCode::CC_NONE:
        return Json::Value();
    case CurrencyCode::CC_USD:
        return Json::Value("USD");
    default:
        throw ML::Exception("not done: encoding other currencies");
    }
}

/*****************************************************************************/
/* AMOUNT                                                                    */
/*****************************************************************************/


Json::Value
Amount::
toJson() const
{
    if (isZero())
        return 0;

    Json::Value result(Json::arrayValue);
    result[0] = value;
    result[1] = getCurrencyStr();

    //cerr << "Amount toJson() gave " << result.toString() << endl;

    return result;
}

std::string
Amount::
getCurrencyStr(CurrencyCode currencyCode)
{
    switch (currencyCode) {
    case CurrencyCode::CC_NONE: return "NONE";
    case CurrencyCode::CC_USD:  return "USD/1M";
    case CurrencyCode::CC_IMP:  return "IMP";
    default:
        throw ML::Exception("unknown currency code %d", (uint32_t)currencyCode);
    }
}

std::string
Amount::
getCurrencyStr() const
{
    return getCurrencyStr(currencyCode);
}

std::string
Amount::
toString() const
{
    if (!*this)
        return "0";
    return to_string(value) + getCurrencyStr();
}

Amount
Amount::
fromJson(const Json::Value & val)
{
    //cerr << "Amount fromJson " << val.toString() << endl;

    if (val.isArray()) {
        if (val.size() != 2)
            throw ML::Exception("invalid amount size");
        return Amount(val[1].asString(), val[0].asInt());
    }
    else if (val.isString())
        return parse(val.asString());
    else if (val.isNumeric() && val.asDouble() == 0.0)
        return Amount();
    else if (val.isNull())
        return Amount();
    else if (val.isObject()) {
        string currencyCode = "NONE";
        int64_t value = 0;
        for (auto it = val.begin(), end = val.end();  it != end;  ++it) {
            if (it.memberName() == "value")
                value = it->asInt();
            else if (it.memberName() == "currencyCode")
                currencyCode = it->asString();
            else throw ML::Exception("unknown Amount field " + it.memberName());
        }
        return Amount(currencyCode, value);
    }
    else throw ML::Exception("unknown amount " + val.toString());
}

Amount
Amount::
parse(const std::string & value)
{
    if (value == "0")
        return Amount();

    const char * p = value.c_str();
    char * ep = 0;
    errno = 0;
    long long val = strtoll(p, &ep, 10);
    if (errno != 0)
        throw ML::Exception("invalid amount parsed");
    string currency(ep);

    if (currency == "") {
        throw ML::Exception("no currency on Amount " + value);
    }

    return Amount(currency, val);
}

CurrencyCode
Amount::
parseCurrency(const std::string & currency)
{
    if (currency == "NONE")
        return CurrencyCode::CC_NONE;
    else if (currency == "USD/1M")
        return CurrencyCode::CC_USD;
    else if (currency == "IMP")
        return CurrencyCode::CC_IMP;
    else throw ML::Exception("unknown currency code " + currency);
}

std::ostream &
operator << (std::ostream & stream, Amount amount)
{
    return stream << amount.toString();
}

void
Amount::
assertCurrencyIsCompatible(const Amount & other) const
{
    if (!currencyIsCompatible(other))
        throw ML::Exception("currencies are not compatible: "
                            + toString() + " vs " + other.toString());
}


bool
Amount::
operator < (const Amount & other) const<commit_msg>minor refactoring of duplicated currency code<commit_after>/* currency.cc
   <NAME>, 5 November 2012
   Copyright (c) 2012 Datacratic Inc.  All rights reserved.

*/

#include "rtbkit/common/currency.h"

using namespace std;
using namespace ML;
using namespace Datacratic;


namespace RTBKIT {


/*****************************************************************************/
/* CURRENCY CODE                                                             */
/*****************************************************************************/

std::string toString(CurrencyCode code)
{
    if (code == CurrencyCode::CC_NONE)
        return "NONE";
    if (code == CurrencyCode::CC_USD)
        return "USD";
    if (code == CurrencyCode::CC_IMP)
        return "IMP";
    throw ML::Exception("unknown currency code");
}

CurrencyCode parseCurrencyCode(const std::string & code)
{
    if (code == "NONE")
        return CurrencyCode::CC_NONE;
    if (code == "USD")
        return CurrencyCode::CC_USD;
    if (code == "IMP")
        return CurrencyCode::CC_IMP;
    throw ML::Exception("unknown currency code");
}

CurrencyCode jsonDecode(const Json::Value & j, CurrencyCode *)
{
    if (j.isNull())
        return CurrencyCode::CC_NONE;
    string s = j.asString();
    if (s.size() > 4)
        throw ML::Exception("unknown currency code " + s);
    return parseCurrencyCode(s);
}

Json::Value jsonEncode(CurrencyCode code)
{
    return Json::Value(toString(code));
}

/*****************************************************************************/
/* AMOUNT                                                                    */
/*****************************************************************************/


Json::Value
Amount::
toJson() const
{
    if (isZero())
        return 0;

    Json::Value result(Json::arrayValue);
    result[0] = value;
    result[1] = getCurrencyStr();

    //cerr << "Amount toJson() gave " << result.toString() << endl;

    return result;
}

std::string
Amount::
getCurrencyStr(CurrencyCode currencyCode)
{
    switch (currencyCode) {
    case CurrencyCode::CC_NONE:
        return "NONE";
    case CurrencyCode::CC_USD:
        return "USD/1M";
    case CurrencyCode::CC_IMP:
        return "IMP";
    default:
        throw ML::Exception("unknown currency code %d", (uint32_t)currencyCode);
    }
}

std::string
Amount::
getCurrencyStr() const
{
    return getCurrencyStr(currencyCode);
}

std::string
Amount::
toString() const
{
    if (!*this)
        return "0";
    return to_string(value) + getCurrencyStr();
}

Amount
Amount::
fromJson(const Json::Value & val)
{
    //cerr << "Amount fromJson " << val.toString() << endl;

    if (val.isArray()) {
        if (val.size() != 2)
            throw ML::Exception("invalid amount size");
        return Amount(val[1].asString(), val[0].asInt());
    }
    else if (val.isString())
        return parse(val.asString());
    else if (val.isNumeric() && val.asDouble() == 0.0)
        return Amount();
    else if (val.isNull())
        return Amount();
    else if (val.isObject()) {
        string currencyCode = "NONE";
        int64_t value = 0;
        for (auto it = val.begin(), end = val.end();  it != end;  ++it) {
            if (it.memberName() == "value")
                value = it->asInt();
            else if (it.memberName() == "currencyCode")
                currencyCode = it->asString();
            else throw ML::Exception("unknown Amount field " + it.memberName());
        }
        return Amount(currencyCode, value);
    }
    else throw ML::Exception("unknown amount " + val.toString());
}

Amount
Amount::
parse(const std::string & value)
{
    if (value == "0")
        return Amount();

    const char * p = value.c_str();
    char * ep = 0;
    errno = 0;
    long long val = strtoll(p, &ep, 10);
    if (errno != 0)
        throw ML::Exception("invalid amount parsed");
    string currency(ep);

    if (currency == "") {
        throw ML::Exception("no currency on Amount " + value);
    }

    return Amount(currency, val);
}

CurrencyCode
Amount::
parseCurrency(const std::string & currency)
{
    if (currency == "NONE")
        return CurrencyCode::CC_NONE;
    if (currency == "USD/1M")
        return CurrencyCode::CC_USD;
    if (currency == "IMP")
        return CurrencyCode::CC_IMP;
    throw ML::Exception("unknown currency code " + currency);
}

std::ostream &
operator << (std::ostream & stream, Amount amount)
{
    return stream << amount.toString();
}

void
Amount::
assertCurrencyIsCompatible(const Amount & other) const
{
    if (!currencyIsCompatible(other))
        throw ML::Exception("currencies are not compatible: "
                            + toString() + " vs " + other.toString());
}


bool
Amount::
operator < (const Amount & other) const
{'fraction_non_alphanumeric': 0.19878525838995265, 'fraction_numerical': 0.006588429071443277, 'mean_word_length': 2.8038371182458888, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5271876', 'n_tokens_mistral': 2877, 'n_tokens_neox': 2774, 'n_words': 726}