<commit_before>// Copyright (c) 2014-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "base58.h"

#include "hash.h"
#include "script/script.h"
#include "uint256.h"

#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>

/** All alphanumeric characters except for "0", "I", "O", and "l" */
static const char *pszBase58 =
    "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

bool DecodeBase58(const char *psz, std::vector<uint8_t> &vch) {
    // Skip leading spaces.
    while (*psz && isspace(*psz)) {
        psz++;
    }
    // Skip and count leading '1's.
    int zeroes = 0;
    int length = 0;
    while (*psz == '1') {
        zeroes++;
        psz++;
    }
    // Allocate enough space in big-endian base256 representation.
    // log(58) / log(256), rounded up.
    int size = strlen(psz) * 733 / 1000 + 1;
    std::vector<uint8_t> b256(size);
    // Process the characters.
    while (*psz && !isspace(*psz)) {
        // Decode base58 character
        const char *ch = strchr(pszBase58, *psz);
        if (ch == nullptr) {
            return false;
        }
        // Apply "b256 = b256 * 58 + ch".
        int carry = ch - pszBase58;
        int i = 0;
        for (std::vector<uint8_t>::reverse_iterator it = b256.rbegin();
             (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
            carry += 58 * (*it);
            *it = carry % 256;
            carry /= 256;
        }
        assert(carry == 0);
        length = i;
        psz++;
    }
    // Skip trailing spaces.
    while (isspace(*psz)) {
        psz++;
    }
    if (*psz != 0) {
        return false;
    }
    // Skip leading zeroes in b256.
    std::vector<uint8_t>::iterator it = b256.begin() + (size - length);
    while (it != b256.end() && *it == 0)
        it++;
    // Copy result into output vector.
    vch.reserve(zeroes + (b256.end() - it));
    vch.assign(zeroes, 0x00);
    while (it != b256.end()) {
        vch.push_back(*(it++));
    }
    return true;
}

std::string EncodeBase58(const uint8_t *pbegin, const uint8_t *pend) {
    // Skip & count leading zeroes.
    int zeroes = 0;
    int length = 0;
    while (pbegin != pend && *pbegin == 0) {
        pbegin++;
        zeroes++;
    }
    // Allocate enough space in big-endian base58 representation.
    // log(256) / log(58), rounded up.
    int size = (pend - pbegin) * 138 / 100 + 1;
    std::vector<uint8_t> b58(size);
    // Process the bytes.
    while (pbegin != pend) {
        int carry = *pbegin;
        int i = 0;
        // Apply "b58 = b58 * 256 + ch".
        for (std::vector<uint8_t>::reverse_iterator it = b58.rbegin();
             (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
            carry += 256 * (*it);
            *it = carry % 58;
            carry /= 58;
        }

        assert(carry == 0);
        length = i;
        pbegin++;
    }
    // Skip leading zeroes in base58 result.
    std::vector<uint8_t>::iterator it = b58.begin() + (size - length);
    while (it != b58.end() && *it == 0) {
        it++;
    }
    // Translate the result into a string.
    std::string str;
    str.reserve(zeroes + (b58.end() - it));
    str.assign(zeroes, '1');
    while (it != b58.end()) {
        str += pszBase58[*(it++)];
    }
    return str;
}

std::string EncodeBase58(const std::vector<uint8_t> &vch) {
    return EncodeBase58(&vch[0], &vch[0] + vch.size());
}

bool DecodeBase58(const std::string &str, std::vector<uint8_t> &vchRet) {
    return DecodeBase58(str.c_str(), vchRet);
}

std::string EncodeBase58Check(const std::vector<uint8_t> &vchIn) {
    // add 4-byte hash check to the end
    std::vector<uint8_t> vch(vchIn);
    uint256 hash = Hash(vch.begin(), vch.end());
    vch.insert(vch.end(), (uint8_t *)&hash, (uint8_t *)&hash + 4);
    return EncodeBase58(vch);
}

bool DecodeBase58Check(const char *psz, std::vector<uint8_t> &vchRet) {
    if (!DecodeBase58(psz, vchRet) || (vchRet.size() < 4)) {
        vchRet.clear();
        return false;
    }
    // re-calculate the checksum, insure it matches the included 4-byte checksum
    uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
    if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) {
        vchRet.clear();
        return false;
    }
    vchRet.resize(vchRet.size() - 4);
    return true;
}

bool DecodeBase58Check(const std::string &str, std::vector<uint8_t> &vchRet) {
    return DecodeBase58Check(str.c_str(), vchRet);
}

CBase58Data::CBase58Data() {
    vchVersion.clear();
    vchData.clear();
}

void CBase58Data::SetData(const std::vector<uint8_t> &vchVersionIn,
                          const void *pdata, size_t nSize) {
    vchVersion = vchVersionIn;
    vchData.resize(nSize);
    if (!vchData.empty()) {
        memcpy(&vchData[0], pdata, nSize);
    }
}

void CBase58Data::SetData(const std::vector<uint8_t> &vchVersionIn,
                          const uint8_t *pbegin, const uint8_t *pend) {
    SetData(vchVersionIn, (void *)pbegin, pend - pbegin);
}

bool CBase58Data::SetString(const char *psz, unsigned int nVersionBytes) {
    std::vector<uint8_t> vchTemp;
    bool rc58 = DecodeBase58Check(psz, vchTemp);
    if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
        vchData.clear();
        vchVersion.clear();
        return false;
    }
    vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
    vchData.resize(vchTemp.size() - nVersionBytes);
    if (!vchData.empty()) {
        memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
    }
    memory_cleanse(&vchTemp[0], vchTemp.size());
    return true;
}

bool CBase58Data::SetString(const std::string &str) {
    return SetString(str.c_str());
}

std::string CBase58Data::ToString() const {
    std::vector<uint8_t> vch = vchVersion;
    vch.insert(vch.end(), vchData.begin(), vchData.end());
    return EncodeBase58Check(vch);
}

int CBase58Data::CompareTo(const CBase58Data &b58) const {
    if (vchVersion < b58.vchVersion) return -1;
    if (vchVersion > b58.vchVersion) return 1;
    if (vchData < b58.vchData) return -1;
    if (vchData > b58.vchData) return 1;
    return 0;
}

namespace {
class DestinationEncoder : public boost::static_visitor<std::string> {
private:
    const CChainParams &m_params;

public:
    DestinationEncoder(const CChainParams &params) : m_params(params) {}

    std::string operator()(const CKeyID &id) const {
        std::vector<uint8_t> data =
            m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
        data.insert(data.end(), id.begin(), id.end());
        return EncodeBase58Check(data);
    }

    std::string operator()(const CScriptID &id) const {
        std::vector<uint8_t> data =
            m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
        data.insert(data.end(), id.begin(), id.end());
        return EncodeBase58Check(data);
    }

    std::string operator()(const CNoDestination &no) const { return ""; }
};

CTxDestination DecodeDestination(const std::string &str,
                                 const CChainParams &params) {
    std::vector<uint8_t> data;
    uint160 hash;
    if (!DecodeBase58Check(str, data)) {
        return CNoDestination();
    }
    // Base58Check decoding
    const std::vector<uint8_t> &pubkey_prefix =
        params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
    if (data.size() == 20 + pubkey_prefix.size() &&
        std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
        memcpy(hash.begin(), &data[pubkey_prefix.size()], 20);
        return CKeyID(hash);
    }
    const std::vector<uint8_t> &script_prefix =
        params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
    if (data.size() == 20 + script_prefix.size() &&
        std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
        memcpy(hash.begin(), &data[script_prefix.size()], 20);
        return CScriptID(hash);
    }
    return CNoDestination();
}
} // namespace

} // namespace

void CBitcoinSecret::SetKey(const CKey &vchSecret) {
    assert(vchSecret.IsValid());
    SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(),
            vchSecret.size());
    if (vchSecret.IsCompressed()) vchData.push_back(1);
}

CKey CBitcoinSecret::GetKey() {
    CKey ret;
    assert(vchData.size() >= 32);
    ret.Set(vchData.begin(), vchData.begin() + 32,
            vchData.size() > 32 && vchData[32] == 1);
    return ret;
}

bool CBitcoinSecret::IsValid() const {
    bool fExpectedFormat =
        vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
    bool fCorrectVersion =
        vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
    return fExpectedFormat && fCorrectVersion;
}

bool CBitcoinSecret::SetString(const char *pszSecret) {
    return CBase58Data::SetString(pszSecret) && IsValid();
}

bool CBitcoinSecret::SetString(const std::string &strSecret) {
    return SetString(strSecret.c_str());
}

std::string EncodeLegacyAddr(const CTxDestination &dest,
                             const CChainParams &params) {
    return boost::apply_visitor(DestinationEncoder(params), dest);
}

CTxDestination DecodeLegacyAddr(const std::string &str,
                                const CChainParams &params) {
    return DecodeDestination(str, params);
}
<commit_msg>Remove the redundant namespace closing brace<commit_after>// Copyright (c) 2014-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "base58.h"

#include "hash.h"
#include "script/script.h"
#include "uint256.h"

#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>

/** All alphanumeric characters except for "0", "I", "O", and "l" */
static const char *pszBase58 =
    "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

bool DecodeBase58(const char *psz, std::vector<uint8_t> &vch) {
    // Skip leading spaces.
    while (*psz && isspace(*psz)) {
        psz++;
    }
    // Skip and count leading '1's.
    int zeroes = 0;
    int length = 0;
    while (*psz == '1') {
        zeroes++;
        psz++;
    }
    // Allocate enough space in big-endian base256 representation.
    // log(58) / log(256), rounded up.
    int size = strlen(psz) * 733 / 1000 + 1;
    std::vector<uint8_t> b256(size);
    // Process the characters.
    while (*psz && !isspace(*psz)) {
        // Decode base58 character
        const char *ch = strchr(pszBase58, *psz);
        if (ch == nullptr) {
            return false;
        }
        // Apply "b256 = b256 * 58 + ch".
        int carry = ch - pszBase58;
        int i = 0;
        for (std::vector<uint8_t>::reverse_iterator it = b256.rbegin();
             (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
            carry += 58 * (*it);
            *it = carry % 256;
            carry /= 256;
        }
        assert(carry == 0);
        length = i;
        psz++;
    }
    // Skip trailing spaces.
    while (isspace(*psz)) {
        psz++;
    }
    if (*psz != 0) {
        return false;
    }
    // Skip leading zeroes in b256.
    std::vector<uint8_t>::iterator it = b256.begin() + (size - length);
    while (it != b256.end() && *it == 0)
        it++;
    // Copy result into output vector.
    vch.reserve(zeroes + (b256.end() - it));
    vch.assign(zeroes, 0x00);
    while (it != b256.end()) {
        vch.push_back(*(it++));
    }
    return true;
}

std::string EncodeBase58(const uint8_t *pbegin, const uint8_t *pend) {
    // Skip & count leading zeroes.
    int zeroes = 0;
    int length = 0;
    while (pbegin != pend && *pbegin == 0) {
        pbegin++;
        zeroes++;
    }
    // Allocate enough space in big-endian base58 representation.
    // log(256) / log(58), rounded up.
    int size = (pend - pbegin) * 138 / 100 + 1;
    std::vector<uint8_t> b58(size);
    // Process the bytes.
    while (pbegin != pend) {
        int carry = *pbegin;
        int i = 0;
        // Apply "b58 = b58 * 256 + ch".
        for (std::vector<uint8_t>::reverse_iterator it = b58.rbegin();
             (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
            carry += 256 * (*it);
            *it = carry % 58;
            carry /= 58;
        }

        assert(carry == 0);
        length = i;
        pbegin++;
    }
    // Skip leading zeroes in base58 result.
    std::vector<uint8_t>::iterator it = b58.begin() + (size - length);
    while (it != b58.end() && *it == 0) {
        it++;
    }
    // Translate the result into a string.
    std::string str;
    str.reserve(zeroes + (b58.end() - it));
    str.assign(zeroes, '1');
    while (it != b58.end()) {
        str += pszBase58[*(it++)];
    }
    return str;
}

std::string EncodeBase58(const std::vector<uint8_t> &vch) {
    return EncodeBase58(&vch[0], &vch[0] + vch.size());
}

bool DecodeBase58(const std::string &str, std::vector<uint8_t> &vchRet) {
    return DecodeBase58(str.c_str(), vchRet);
}

std::string EncodeBase58Check(const std::vector<uint8_t> &vchIn) {
    // add 4-byte hash check to the end
    std::vector<uint8_t> vch(vchIn);
    uint256 hash = Hash(vch.begin(), vch.end());
    vch.insert(vch.end(), (uint8_t *)&hash, (uint8_t *)&hash + 4);
    return EncodeBase58(vch);
}

bool DecodeBase58Check(const char *psz, std::vector<uint8_t> &vchRet) {
    if (!DecodeBase58(psz, vchRet) || (vchRet.size() < 4)) {
        vchRet.clear();
        return false;
    }
    // re-calculate the checksum, insure it matches the included 4-byte checksum
    uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
    if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) {
        vchRet.clear();
        return false;
    }
    vchRet.resize(vchRet.size() - 4);
    return true;
}

bool DecodeBase58Check(const std::string &str, std::vector<uint8_t> &vchRet) {
    return DecodeBase58Check(str.c_str(), vchRet);
}

CBase58Data::CBase58Data() {
    vchVersion.clear();
    vchData.clear();
}

void CBase58Data::SetData(const std::vector<uint8_t> &vchVersionIn,
                          const void *pdata, size_t nSize) {
    vchVersion = vchVersionIn;
    vchData.resize(nSize);
    if (!vchData.empty()) {
        memcpy(&vchData[0], pdata, nSize);
    }
}

void CBase58Data::SetData(const std::vector<uint8_t> &vchVersionIn,
                          const uint8_t *pbegin, const uint8_t *pend) {
    SetData(vchVersionIn, (void *)pbegin, pend - pbegin);
}

bool CBase58Data::SetString(const char *psz, unsigned int nVersionBytes) {
    std::vector<uint8_t> vchTemp;
    bool rc58 = DecodeBase58Check(psz, vchTemp);
    if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
        vchData.clear();
        vchVersion.clear();
        return false;
    }
    vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
    vchData.resize(vchTemp.size() - nVersionBytes);
    if (!vchData.empty()) {
        memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
    }
    memory_cleanse(&vchTemp[0], vchTemp.size());
    return true;
}

bool CBase58Data::SetString(const std::string &str) {
    return SetString(str.c_str());
}

std::string CBase58Data::ToString() const {
    std::vector<uint8_t> vch = vchVersion;
    vch.insert(vch.end(), vchData.begin(), vchData.end());
    return EncodeBase58Check(vch);
}

int CBase58Data::CompareTo(const CBase58Data &b58) const {
    if (vchVersion < b58.vchVersion) return -1;
    if (vchVersion > b58.vchVersion) return 1;
    if (vchData < b58.vchData) return -1;
    if (vchData > b58.vchData) return 1;
    return 0;
}

namespace {
class DestinationEncoder : public boost::static_visitor<std::string> {
private:
    const CChainParams &m_params;

public:
    DestinationEncoder(const CChainParams &params) : m_params(params) {}

    std::string operator()(const CKeyID &id) const {
        std::vector<uint8_t> data =
            m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
        data.insert(data.end(), id.begin(), id.end());
        return EncodeBase58Check(data);
    }

    std::string operator()(const CScriptID &id) const {
        std::vector<uint8_t> data =
            m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
        data.insert(data.end(), id.begin(), id.end());
        return EncodeBase58Check(data);
    }

    std::string operator()(const CNoDestination &no) const { return ""; }
};

CTxDestination DecodeDestination(const std::string &str,
                                 const CChainParams &params) {
    std::vector<uint8_t> data;
    uint160 hash;
    if (!DecodeBase58Check(str, data)) {
        return CNoDestination();
    }
    // Base58Check decoding
    const std::vector<uint8_t> &pubkey_prefix =
        params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
    if (data.size() == 20 + pubkey_prefix.size() &&
        std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
        memcpy(hash.begin(), &data[pubkey_prefix.size()], 20);
        return CKeyID(hash);
    }
    const std::vector<uint8_t> &script_prefix =
        params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
    if (data.size() == 20 + script_prefix.size() &&
        std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
        memcpy(hash.begin(), &data[script_prefix.size()], 20);
        return CScriptID(hash);
    }
    return CNoDestination();
}
} // namespace

void CBitcoinSecret::SetKey(const CKey &vchSecret) {
    assert(vchSecret.IsValid());
    SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(),
            vchSecret.size());
    if (vchSecret.IsCompressed()) vchData.push_back(1);
}

CKey CBitcoinSecret::GetKey() {
    CKey ret;
    assert(vchData.size() >= 32);
    ret.Set(vchData.begin(), vchData.begin() + 32,
            vchData.size() > 32 && vchData[32] == 1);
    return ret;
}

bool CBitcoinSecret::IsValid() const {
    bool fExpectedFormat =
        vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
    bool fCorrectVersion =
        vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
    return fExpectedFormat && fCorrectVersion;
}

bool CBitcoinSecret::SetString(const char *pszSecret) {
    return CBase58Data::SetString(pszSecret) && IsValid();
}

bool CBitcoinSecret::SetString(const std::string &strSecret) {
    return SetString(strSecret.c_str());
}

std::string EncodeLegacyAddr(const CTxDestination &dest,
                             const CChainParams &params) {
    return boost::apply_visitor(DestinationEncoder(params), dest);
}

CTxDestination DecodeLegacyAddr(const std::string &str,
                                const CChainParams &params) {
    return DecodeDestination(str, params);
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "base58.h"

#include "hash.h"
#include "uint256.h"

#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <vector>
#include <string>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>

/** All alphanumeric characters except for "0", "I", "O", and "l" */
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch)
{
    // Skip leading spaces.
    while (*psz && isspace(*psz))
        psz++;
    // Skip and count leading '1's.
    int zeroes = 0;
    while (*psz == '1') {
        zeroes++;
        psz++;
    }
    // Allocate enough space in big-endian base256 representation.
    std::vector<unsigned char> b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
    // Process the characters.
    while (*psz && !isspace(*psz)) {
        // Decode base58 character
        const char* ch = strchr(pszBase58, *psz);
        if (ch == NULL)
            return false;
        // Apply "b256 = b256 * 58 + ch".
        int carry = ch - pszBase58;
        for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) {
            carry += 58 * (*it);
            *it = carry % 256;
            carry /= 256;
        }
        assert(carry == 0);
        psz++;
    }
    // Skip trailing spaces.
    while (isspace(*psz))
        psz++;
    if (*psz != 0)
        return false;
    // Skip leading zeroes in b256.
    std::vector<unsigned char>::iterator it = b256.begin();
    while (it != b256.end() && *it == 0)
        it++;
    // Copy result into output vector.
    vch.reserve(zeroes + (b256.end() - it));
    vch.assign(zeroes, 0x00);
    while (it != b256.end())
        vch.push_back(*(it++));
    return true;
}

std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
{
    // Skip & count leading zeroes.
    int zeroes = 0;
    while (pbegin != pend && *pbegin == 0) {
        pbegin++;
        zeroes++;
    }
    // Allocate enough space in big-endian base58 representation.
    std::vector<unsigned char> b58((pend - pbegin) * 138 / 100 + 1); // log(256) / log(58), rounded up.
    // Process the bytes.
    while (pbegin != pend) {
        int carry = *pbegin;
        // Apply "b58 = b58 * 256 + ch".
        for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); it != b58.rend(); it++) {
            carry += 256 * (*it);
            *it = carry % 58;
            carry /= 58;
        }
        assert(carry == 0);
        pbegin++;
    }
    // Skip leading zeroes in base58 result.
    std::vector<unsigned char>::iterator it = b58.begin();
    while (it != b58.end() && *it == 0)
        it++;
    // Translate the result into a string.
    std::string str;
    str.reserve(zeroes + (b58.end() - it));
    str.assign(zeroes, '1');
    while (it != b58.end())
        str += pszBase58[*(it++)];
    return str;
}

std::string EncodeBase58(const std::vector<unsigned char>& vch)
{
    return EncodeBase58(&vch[0], &vch[0] + vch.size());
}

bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet)
{
    return DecodeBase58(str.c_str(), vchRet);
}

std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
{
    // add 4-byte hash check to the end
    std::vector<unsigned char> vch(vchIn);
    uint256 hash = Hash(vch.begin(), vch.end());
    vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
    return EncodeBase58(vch);
}

/*
bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet)
{
    if (!DecodeBase58(psz, vchRet) ||
        (vchRet.size() < 4)) {
        vchRet.clear();
        return false;
    }
    // re-calculate the checksum, insure it matches the included 4-byte checksum
    uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4);
    if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) {
        vchRet.clear();
        return false;
    }
    vchRet.resize(vchRet.size() - 4);
    return true;
}

bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet)
{
    return DecodeBase58Check(str.c_str(), vchRet);
}
*/

CBase58Data::CBase58Data()
{
    vchVersion.clear();
    vchData.clear();
}

void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
{
    vchVersion = vchVersionIn;
    vchData.resize(nSize);
    if (!vchData.empty())
        memcpy(&vchData[0], pdata, nSize);
}

void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
{
    SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
}

bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
{
    std::vector<unsigned char> vchTemp;
    bool rc58 = DecodeBase58Check(psz, vchTemp);
    if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
        vchData.clear();
        vchVersion.clear();
        return false;
    }
    vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
    vchData.resize(vchTemp.size() - nVersionBytes);
    if (!vchData.empty())
        memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
    OPENSSL_cleanse(&vchTemp[0], vchData.size());
    return true;
}

bool CBase58Data::SetString(const std::string& str)
{
    return SetString(str.c_str());
}

std::string CBase58Data::ToString() const
{
    std::vector<unsigned char> vch = vchVersion;
    vch.insert(vch.end(), vchData.begin(), vchData.end());
    return EncodeBase58Check(vch);
}

int CBase58Data::CompareTo(const CBase58Data& b58) const
{
    if (vchVersion < b58.vchVersion)
        return -1;
    if (vchVersion > b58.vchVersion)
        return 1;
    if (vchData < b58.vchData)
        return -1;
    if (vchData > b58.vchData)
        return 1;
    return 0;
}

namespace
{
class CBitcoinAddressVisitor : public boost::static_visitor<bool>
{
private:
    CBitcoinAddress* addr;

public:
    CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}

    bool operator()(const CKeyID& id) const { return addr->Set(id); }
    bool operator()(const CScriptID& id) const { return addr->Set(id); }
    bool operator()(const CNoDestination& no) const { return false; }
};

} // anon namespace

bool CBitcoinAddress::Set(const CKeyID& id)
{
    SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
    return true;
}

bool CBitcoinAddress::Set(const CScriptID& id)
{
    SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
    return true;
}

bool CBitcoinAddress::Set(const CTxDestination& dest)
{
    return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
}

bool CBitcoinAddress::IsValid() const
{
    return IsValid(Params());
}

bool CBitcoinAddress::IsValid(const CChainParams& params) const
{
    bool fCorrectSize = vchData.size() == 20;
    bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
                         vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
    return fCorrectSize && fKnownVersion;
}

CTxDestination CBitcoinAddress::Get() const
{
    if (!IsValid())
        return CNoDestination();
    uint160 id;
    memcpy(&id, &vchData[0], 20);
    if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
        return CKeyID(id);
    else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
        return CScriptID(id);
    else
        return CNoDestination();
}

bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
{
    if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
        return false;
    uint160 id;
    memcpy(&id, &vchData[0], 20);
    keyID = CKeyID(id);
    return true;
}

bool CBitcoinAddress::IsScript() const
{
    return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
}

void CBitcoinSecret::SetKey(const CKey& vchSecret)
{
    assert(vchSecret.IsValid());
    SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
    if (vchSecret.IsCompressed())
        vchData.push_back(1);
}

CKey CBitcoinSecret::GetKey()
{
    CKey ret;
    assert(vchData.size() >= 32);
    ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
    return ret;
}

bool CBitcoinSecret::IsValid() const
{
    bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
    bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
    return fExpectedFormat && fCorrectVersion;
}

bool CBitcoinSecret::SetString(const char* pszSecret)
{
    return CBase58Data::SetString(pszSecret) && IsValid();
}

bool CBitcoinSecret::SetString(const std::string& strSecret)
{
    return SetString(strSecret.c_str());
}
<commit_msg>Delete base58.cpp<commit_after><|endoftext|>


<commit_before>//===-- Instruction.cpp - Implement the Instruction class -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Instruction class for the VMCore library.
//
//===----------------------------------------------------------------------===//

#include "llvm/Type.h"
#include "llvm/Instructions.h"
#include "llvm/Function.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/LeakDetector.h"
using namespace llvm;

Instruction::Instruction(const Type *ty, unsigned it, Use *Ops, unsigned NumOps,
                         Instruction *InsertBefore)
  : User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(0) {
  // Make sure that we get added to a basicblock
  LeakDetector::addGarbageObject(this);

  // If requested, insert this instruction into a basic block...
  if (InsertBefore) {
    assert(InsertBefore->getParent() &&
           "Instruction to insert before is not in a basic block!");
    InsertBefore->getParent()->getInstList().insert(InsertBefore, this);
  }
}

Instruction::Instruction(const Type *ty, unsigned it, Use *Ops, unsigned NumOps,
                         BasicBlock *InsertAtEnd)
  : User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(0) {
  // Make sure that we get added to a basicblock
  LeakDetector::addGarbageObject(this);

  // append this instruction into the basic block
  assert(InsertAtEnd && "Basic block to append to may not be NULL!");
  InsertAtEnd->getInstList().push_back(this);
}

// Out of line virtual method, so the vtable, etc has a home.
Instruction::~Instruction() {
  assert(Parent == 0 && "Instruction still linked in the program!");
}

void Instruction::setParent(BasicBlock *P) {
  if (getParent()) {
    if (!P) LeakDetector::addGarbageObject(this);
  } else {
    if (P) LeakDetector::removeGarbageObject(this);
  }

  Parent = P;
}

void Instruction::removeFromParent() {
  getParent()->getInstList().remove(this);
}

void Instruction::eraseFromParent() {
  getParent()->getInstList().erase(this);
}

/// moveBefore - Unlink this instruction from its current basic block and
/// insert it into the basic block that MovePos lives in, right before
/// MovePos.
void Instruction::moveBefore(Instruction *MovePos) {
  MovePos->getParent()->getInstList().splice(MovePos,getParent()->getInstList(),
                                             this);
}

const char *Instruction::getOpcodeName(unsigned OpCode) {
  switch (OpCode) {
  // Terminators
  case Ret:    return "ret";
  case Br:     return "br";
  case Switch: return "switch";
  case Invoke: return "invoke";
  case Unwind: return "unwind";
  case Unreachable: return "unreachable";

  // Standard binary operators...
  case Add: return "add";
  case Sub: return "sub";
  case Mul: return "mul";
  case UDiv: return "udiv";
  case SDiv: return "sdiv";
  case FDiv: return "fdiv";
  case URem: return "urem";
  case SRem: return "srem";
  case FRem: return "frem";

  // Logical operators...
  case And: return "and";
  case Or : return "or";
  case Xor: return "xor";

  // Memory instructions...
  case Malloc:        return "malloc";
  case Free:          return "free";
  case Alloca:        return "alloca";
  case Load:          return "load";
  case Store:         return "store";
  case GetElementPtr: return "getelementptr";

  // Convert instructions...
  case Trunc:     return "trunc";
  case ZExt:      return "zext";
  case SExt:      return "sext";
  case FPTrunc:   return "fptrunc";
  case FPExt:     return "fpext";
  case FPToUI:    return "fptoui";
  case FPToSI:    return "fptosi";
  case UIToFP:    return "uitofp";
  case SIToFP:    return "sitofp";
  case IntToPtr:  return "inttoptr";
  case PtrToInt:  return "ptrtoint";
  case BitCast:   return "bitcast";

  // Other instructions...
  case ICmp:           return "icmp";
  case FCmp:           return "fcmp";
  case PHI:            return "phi";
  case Select:         return "select";
  case Call:           return "call";
  case Shl:            return "shl";
  case LShr:           return "lshr";
  case AShr:           return "ashr";
  case VAArg:          return "va_arg";
  case ExtractElement: return "extractelement";
  case InsertElement:  return "insertelement";
  case ShuffleVector:  return "shufflevector";

  default: return "<Invalid operator> ";
  }

  return 0;
}

/// isIdenticalTo - Return true if the specified instruction is exactly
/// identical to the current one.  This means that all operands match and any
/// extra information (e.g. load is volatile) agree.
bool Instruction::isIdenticalTo(Instruction *I) const {
  if (getOpcode() != I->getOpcode() ||
      getNumOperands() != I->getNumOperands() ||
      getType() != I->getType())
    return false;

  // We have two instructions of identical opcode and #operands.  Check to see
  // if all operands are the same.
  for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
    if (getOperand(i) != I->getOperand(i))
      return false;

  // Check special state that is a part of some instructions.
  if (const LoadInst *LI = dyn_cast<LoadInst>(this))
    return LI->isVolatile() == cast<LoadInst>(I)->isVolatile();
  if (const StoreInst *SI = dyn_cast<StoreInst>(this))
    return SI->isVolatile() == cast<StoreInst>(I)->isVolatile();
  if (const CmpInst *CI = dyn_cast<CmpInst>(this))
    return CI->getPredicate() == cast<CmpInst>(I)->getPredicate();
  if (const CallInst *CI = dyn_cast<CallInst>(this))
    return CI->isTailCall() == cast<CallInst>(I)->isTailCall();
  return true;
}

// isSameOperationAs
bool Instruction::isSameOperationAs(Instruction *I) const {
  if (getOpcode() != I->getOpcode() || getType() != I->getType() ||
      getNumOperands() != I->getNumOperands())
    return false;

  // We have two instructions of identical opcode and #operands.  Check to see
  // if all operands are the same type
  for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
    if (getOperand(i)->getType() != I->getOperand(i)->getType())
      return false;

  // Check special state that is a part of some instructions.
  if (const LoadInst *LI = dyn_cast<LoadInst>(this))
    return LI->isVolatile() == cast<LoadInst>(I)->isVolatile();
  if (const StoreInst *SI = dyn_cast<StoreInst>(this))
    return SI->isVolatile() == cast<StoreInst>(I)->isVolatile();
  if (const CmpInst *CI = dyn_cast<CmpInst>(this))
    return CI->getPredicate() == cast<CmpInst>(I)->getPredicate();
  if (const CallInst *CI = dyn_cast<CallInst>(this))
    return CI->isTailCall() == cast<CallInst>(I)->isTailCall();

  return true;
}

/// mayWriteToMemory - Return true if this instruction may modify memory.
///
bool Instruction::mayWriteToMemory() const {
  switch (getOpcode()) {
  default: return false;
  case Instruction::Free:
  case Instruction::Invoke:
  case Instruction::Store:
  case Instruction::VAArg:
    return true;
  case Instruction::Call:
    return !cast<CallInst>(this)->onlyReadsMemory();
  case Instruction::Load:
    return cast<LoadInst>(this)->isVolatile();
  }
}

/// isAssociative - Return true if the instruction is associative:
///
///   Associative operators satisfy:  x op (y op z) === (x op y) op z)
///
/// In LLVM, the Add, Mul, And, Or, and Xor operators are associative, when not
/// applied to floating point types.
///
bool Instruction::isAssociative(unsigned Opcode, const Type *Ty) {
  if (Opcode == And || Opcode == Or || Opcode == Xor)
    return true;

  // Add/Mul reassociate unless they are FP or FP vectors.
  if (Opcode == Add || Opcode == Mul)
    return !Ty->isFPOrFPVector();
  return 0;
}

/// isCommutative - Return true if the instruction is commutative:
///
///   Commutative operators satisfy: (x op y) === (y op x)
///
/// In LLVM, these are the associative operators, plus SetEQ and SetNE, when
/// applied to any type.
///
bool Instruction::isCommutative(unsigned op) {
  switch (op) {
  case Add:
  case Mul:
  case And:
  case Or:
  case Xor:
    return true;
  default:
    return false;
  }
}

/// isTrappingInstruction - Return true if the instruction may trap.
///
bool Instruction::isTrapping(unsigned op) {
  switch(op) {
  case UDiv:
  case SDiv:
  case FDiv:
  case URem:
  case SRem:
  case FRem:
  case Load:
  case Store:
  case Call:
  case Invoke:
    return true;
  default:
    return false;
  }
}
<commit_msg>print getresult instruction.<commit_after>//===-- Instruction.cpp - Implement the Instruction class -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Instruction class for the VMCore library.
//
//===----------------------------------------------------------------------===//

#include "llvm/Type.h"
#include "llvm/Instructions.h"
#include "llvm/Function.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/LeakDetector.h"
using namespace llvm;

Instruction::Instruction(const Type *ty, unsigned it, Use *Ops, unsigned NumOps,
                         Instruction *InsertBefore)
  : User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(0) {
  // Make sure that we get added to a basicblock
  LeakDetector::addGarbageObject(this);

  // If requested, insert this instruction into a basic block...
  if (InsertBefore) {
    assert(InsertBefore->getParent() &&
           "Instruction to insert before is not in a basic block!");
    InsertBefore->getParent()->getInstList().insert(InsertBefore, this);
  }
}

Instruction::Instruction(const Type *ty, unsigned it, Use *Ops, unsigned NumOps,
                         BasicBlock *InsertAtEnd)
  : User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(0) {
  // Make sure that we get added to a basicblock
  LeakDetector::addGarbageObject(this);

  // append this instruction into the basic block
  assert(InsertAtEnd && "Basic block to append to may not be NULL!");
  InsertAtEnd->getInstList().push_back(this);
}

// Out of line virtual method, so the vtable, etc has a home.
Instruction::~Instruction() {
  assert(Parent == 0 && "Instruction still linked in the program!");
}

void Instruction::setParent(BasicBlock *P) {
  if (getParent()) {
    if (!P) LeakDetector::addGarbageObject(this);
  } else {
    if (P) LeakDetector::removeGarbageObject(this);
  }

  Parent = P;
}

void Instruction::removeFromParent() {
  getParent()->getInstList().remove(this);
}

void Instruction::eraseFromParent() {
  getParent()->getInstList().erase(this);
}

/// moveBefore - Unlink this instruction from its current basic block and
/// insert it into the basic block that MovePos lives in, right before
/// MovePos.
void Instruction::moveBefore(Instruction *MovePos) {
  MovePos->getParent()->getInstList().splice(MovePos,getParent()->getInstList(),
                                             this);
}

const char *Instruction::getOpcodeName(unsigned OpCode) {
  switch (OpCode) {
  // Terminators
  case Ret:    return "ret";
  case Br:     return "br";
  case Switch: return "switch";
  case Invoke: return "invoke";
  case Unwind: return "unwind";
  case Unreachable: return "unreachable";

  // Standard binary operators...
  case Add: return "add";
  case Sub: return "sub";
  case Mul: return "mul";
  case UDiv: return "udiv";
  case SDiv: return "sdiv";
  case FDiv: return "fdiv";
  case URem: return "urem";
  case SRem: return "srem";
  case FRem: return "frem";

  // Logical operators...
  case And: return "and";
  case Or : return "or";
  case Xor: return "xor";

  // Memory instructions...
  case Malloc:        return "malloc";
  case Free:          return "free";
  case Alloca:        return "alloca";
  case Load:          return "load";
  case Store:         return "store";
  case GetElementPtr: return "getelementptr";

  // Convert instructions...
  case Trunc:     return "trunc";
  case ZExt:      return "zext";
  case SExt:      return "sext";
  case FPTrunc:   return "fptrunc";
  case FPExt:     return "fpext";
  case FPToUI:    return "fptoui";
  case FPToSI:    return "fptosi";
  case UIToFP:    return "uitofp";
  case SIToFP:    return "sitofp";
  case IntToPtr:  return "inttoptr";
  case PtrToInt:  return "ptrtoint";
  case BitCast:   return "bitcast";

  // Other instructions...
  case ICmp:           return "icmp";
  case FCmp:           return "fcmp";
  case PHI:            return "phi";
  case Select:         return "select";
  case Call:           return "call";
  case Shl:            return "shl";
  case LShr:           return "lshr";
  case AShr:           return "ashr";
  case VAArg:          return "va_arg";
  case ExtractElement: return "extractelement";
  case InsertElement:  return "insertelement";
  case ShuffleVector:  return "shufflevector";
  case GetResult:      return "getresult";

  default: return "<Invalid operator> ";
  }

  return 0;
}

/// isIdenticalTo - Return true if the specified instruction is exactly
/// identical to the current one.  This means that all operands match and any
/// extra information (e.g. load is volatile) agree.
bool Instruction::isIdenticalTo(Instruction *I) const {
  if (getOpcode() != I->getOpcode() ||
      getNumOperands() != I->getNumOperands() ||
      getType() != I->getType())
    return false;

  // We have two instructions of identical opcode and #operands.  Check to see
  // if all operands are the same.
  for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
    if (getOperand(i) != I->getOperand(i))
      return false;

  // Check special state that is a part of some instructions.
  if (const LoadInst *LI = dyn_cast<LoadInst>(this))
    return LI->isVolatile() == cast<LoadInst>(I)->isVolatile();
  if (const StoreInst *SI = dyn_cast<StoreInst>(this))
    return SI->isVolatile() == cast<StoreInst>(I)->isVolatile();
  if (const CmpInst *CI = dyn_cast<CmpInst>(this))
    return CI->getPredicate() == cast<CmpInst>(I)->getPredicate();
  if (const CallInst *CI = dyn_cast<CallInst>(this))
    return CI->isTailCall() == cast<CallInst>(I)->isTailCall();
  return true;
}

// isSameOperationAs
bool Instruction::isSameOperationAs(Instruction *I) const {
  if (getOpcode() != I->getOpcode() || getType() != I->getType() ||
      getNumOperands() != I->getNumOperands())
    return false;

  // We have two instructions of identical opcode and #operands.  Check to see
  // if all operands are the same type
  for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
    if (getOperand(i)->getType() != I->getOperand(i)->getType())
      return false;

  // Check special state that is a part of some instructions.
  if (const LoadInst *LI = dyn_cast<LoadInst>(this))
    return LI->isVolatile() == cast<LoadInst>(I)->isVolatile();
  if (const StoreInst *SI = dyn_cast<StoreInst>(this))
    return SI->isVolatile() == cast<StoreInst>(I)->isVolatile();
  if (const CmpInst *CI = dyn_cast<CmpInst>(this))
    return CI->getPredicate() == cast<CmpInst>(I)->getPredicate();
  if (const CallInst *CI = dyn_cast<CallInst>(this))
    return CI->isTailCall() == cast<CallInst>(I)->isTailCall();

  return true;
}

/// mayWriteToMemory - Return true if this instruction may modify memory.
///
bool Instruction::mayWriteToMemory() const {
  switch (getOpcode()) {
  default: return false;
  case Instruction::Free:
  case Instruction::Invoke:
  case Instruction::Store:
  case Instruction::VAArg:
    return true;
  case Instruction::Call:
    return !cast<CallInst>(this)->onlyReadsMemory();
  case Instruction::Load:
    return cast<LoadInst>(this)->isVolatile();
  }
}

/// isAssociative - Return true if the instruction is associative:
///
///   Associative operators satisfy:  x op (y op z) === (x op y) op z)
///
/// In LLVM, the Add, Mul, And, Or, and Xor operators are associative, when not
/// applied to floating point types.
///
bool Instruction::isAssociative(unsigned Opcode, const Type *Ty) {
  if (Opcode == And || Opcode == Or || Opcode == Xor)
    return true;

  // Add/Mul reassociate unless they are FP or FP vectors.
  if (Opcode == Add || Opcode == Mul)
    return !Ty->isFPOrFPVector();
  return 0;
}

/// isCommutative - Return true if the instruction is commutative:
///
///   Commutative operators satisfy: (x op y) === (y op x)
///
/// In LLVM, these are the associative operators, plus SetEQ and SetNE, when
/// applied to any type.
///
bool Instruction::isCommutative(unsigned op) {
  switch (op) {
  case Add:
  case Mul:
  case And:
  case Or:
  case Xor:
    return true;
  default:
    return false;
  }
}

/// isTrappingInstruction - Return true if the instruction may trap.
///
bool Instruction::isTrapping(unsigned op) {
  switch(op) {
  case UDiv:
  case SDiv:
  case FDiv:
  case URem:
  case SRem:
  case FRem:
  case Load:
  case Store:
  case Call:
  case Invoke:
    return true;
  default:
    return false;
  }
}
<|endoftext|>


<commit_before>// $Id: nucleotide.C,v 1.3 2000/05/10 18:54:30 amoll Exp $

#include <BALL/KERNEL/nucleotide.h>

#include <BALL/KERNEL/nucleicAcid.h>

using namespace std;

namespace BALL
{

	Nucleotide::Nucleotide()
		:	Fragment(),
			id_(BALL_NUCLEOTIDE_DEFAULT_ID),
			insertion_code_(BALL_NUCLEOTIDE_DEFAULT_INSERTION_CODE)
	{
	}

	Nucleotide::Nucleotide(const Nucleotide& nucleotide, bool deep)
		:	Fragment(nucleotide, deep),
			id_(nucleotide.id_),
			insertion_code_(nucleotide.insertion_code_)
	{
	}

	Nucleotide::Nucleotide(const String& name, const String& id, char insertion_code)
		:	Fragment(name),
			id_(id),
			insertion_code_(insertion_code)
	{
	}

	Nucleotide::~Nucleotide()
	{
		destroy();
	}

	void Nucleotide::clear()
	{
		Fragment::clear();

		clear_();
	}

	void Nucleotide::destroy()
	{
		Fragment::destroy();

		clear_();
	}

	void Nucleotide::persistentWrite(PersistenceManager& pm, const char* name) const
	{
		pm.writeObjectHeader(this, name);
			Fragment::persistentWrite(pm);
			pm.writePrimitive(id_, "id_");
			pm.writePrimitive(insertion_code_, "insertion_code_");
		pm.writeObjectTrailer(name);
	}

	void Nucleotide::persistentRead(PersistenceManager& pm)
	{
		pm.checkObjectHeader(RTTI::getStreamName<Fragment>());
			Fragment::persistentRead(pm);
		pm.checkObjectTrailer(0);

		pm.readPrimitive(id_, "id_");
		pm.readPrimitive(insertion_code_, "insertion_code_");
	}

	void Nucleotide::set(const Nucleotide& nucleotide, bool deep)
	{
		Fragment::set(nucleotide, deep);

		id_ = nucleotide.id_;
		insertion_code_ = nucleotide.insertion_code_;
	}

	Nucleotide& Nucleotide::operator =(const Nucleotide& nucleotide)
	{
		set(nucleotide);

		return *this;
	}

	void Nucleotide::get(Nucleotide& nucleotide, bool deep) const
	{
		nucleotide.set(*this, deep);
	}

	void Nucleotide::swap(Nucleotide& nucleotide)
	{
		Fragment::swap(nucleotide);

		id_.swap(nucleotide.id_);

		char temp_insertion_code = insertion_code_;
		insertion_code_ = nucleotide.insertion_code_;
		nucleotide.insertion_code_ = temp_insertion_code;
	}

	NucleicAcid* Nucleotide::getNucleicAcid()
	{
		for (Composite::AncestorIterator ancestor_it = beginAncestor(); !ancestor_it.isEnd(); ++ancestor_it)
		{
			if (RTTI::isKindOf<NucleicAcid>(*ancestor_it))
			{
				return (NucleicAcid*)&*ancestor_it;
			}
		}

		return 0;
	}

	const NucleicAcid* Nucleotide::getNucleicAcid() const
	{
		return (const_cast<const Nucleotide*>(this)->getNucleicAcid());
	}

	void Nucleotide::setID(const String &id)
	{
		id_ = id;
	}

	const String &Nucleotide::getID() const
	{
		return id_;
	}

	void Nucleotide::setInsertionCode(char insertion_code)
	{
		insertion_code_ = insertion_code;
	}

	char Nucleotide::getInsertionCode() const
	{
		return insertion_code_;
	}

	void Nucleotide::prepend(Atom& atom)
	{
		Composite::prependChild(atom);
	}

	void Nucleotide::append(Atom &atom)
	{
		Composite::appendChild(atom);
	}

	void Nucleotide::insert(Atom &atom)
	{
		append(atom);
	}

	void Nucleotide::insertBefore(Atom &atom, Composite& before)
	{
		before.Composite::insertBefore(atom);
	}

	void Nucleotide::insertAfter(Atom& atom, Composite &after)
	{
		after.Composite::insertAfter(atom);
	}

	bool Nucleotide::remove(Atom& atom)
	{
		return Composite::removeChild(atom);
	}

	void Nucleotide::spliceBefore(Nucleotide& nucleotide)
	{
		Composite::spliceBefore(nucleotide);
	}

	void Nucleotide::spliceAfter(Nucleotide& nucleotide)
	{
		Composite::spliceAfter(nucleotide);
	}

	void Nucleotide::splice(Nucleotide& nucleotide)
	{
		Composite::splice(nucleotide);
	}

	bool Nucleotide::isTerminal() const
	{
		// BAUSTELLE
		return false;
	}

	bool Nucleotide::is5Prime() const
	{
		// BAUSTELLE
		return false;
	}

	bool Nucleotide::is3Prime() const
	{
		return false;
	}

	bool Nucleotide::isValid() const
	{
		if (Fragment::isValid() == false
				|| id_.isValid() == false)
		{
			return false;
		}

		return true;
	}

	void Nucleotide::dump(ostream& s, Size depth) const
	{
		BALL_DUMP_STREAM_PREFIX(s);

		Fragment::dump(s, depth);

		BALL_DUMP_DEPTH(s, depth);
		s << "  id: " << id_ << endl;

		BALL_DUMP_DEPTH(s, depth);
		s << "  insertion code: " << insertion_code_ << endl;

		BALL_DUMP_STREAM_SUFFIX(s);
	}

	void Nucleotide::read(istream&  /* s */)
	{
		throw Exception::NotImplemented(__FILE__, __LINE__);
	}

	void Nucleotide::write(ostream&  /*s */) const
	{
		throw Exception::NotImplemented(__FILE__, __LINE__);
	}

	void Nucleotide::clear_()
	{
		id_ = BALL_NUCLEOTIDE_DEFAULT_ID;
		insertion_code_ = BALL_NUCLEOTIDE_DEFAULT_INSERTION_CODE;
	}

} // namespace BALL
<commit_msg>*** empty log message ***<commit_after>// $Id: nucleotide.C,v 1.4 2000/05/15 16:01:01 amoll Exp $

#include <BALL/KERNEL/nucleotide.h>

#include <BALL/KERNEL/nucleicAcid.h>

using namespace std;

namespace BALL
{

	Nucleotide::Nucleotide()
		:	Fragment(),
			id_(BALL_NUCLEOTIDE_DEFAULT_ID),
			insertion_code_(BALL_NUCLEOTIDE_DEFAULT_INSERTION_CODE)
	{
	}

	Nucleotide::Nucleotide(const Nucleotide& nucleotide, bool deep)
		:	Fragment(nucleotide, deep),
			id_(nucleotide.id_),
			insertion_code_(nucleotide.insertion_code_)
	{
	}

	Nucleotide::Nucleotide(const String& name, const String& id, char insertion_code)
		:	Fragment(name),
			id_(id),
			insertion_code_(insertion_code)
	{
	}

	Nucleotide::~Nucleotide()
	{
		destroy();
	}

	void Nucleotide::clear()
	{
		Fragment::clear();

		clear_();
	}

	void Nucleotide::destroy()
	{
		Fragment::destroy();

		clear_();
	}

	void Nucleotide::persistentWrite(PersistenceManager& pm, const char* name) const
	{
		pm.writeObjectHeader(this, name);
			Fragment::persistentWrite(pm);
			pm.writePrimitive(id_, "id_");
			pm.writePrimitive(insertion_code_, "insertion_code_");
		pm.writeObjectTrailer(name);
	}

	void Nucleotide::persistentRead(PersistenceManager& pm)
	{
		pm.checkObjectHeader(RTTI::getStreamName<Fragment>());
			Fragment::persistentRead(pm);
		pm.checkObjectTrailer(0);

		pm.readPrimitive(id_, "id_");
		pm.readPrimitive(insertion_code_, "insertion_code_");
	}

	void Nucleotide::set(const Nucleotide& nucleotide, bool deep)
	{
		Fragment::set(nucleotide, deep);

		id_ = nucleotide.id_;
		insertion_code_ = nucleotide.insertion_code_;
	}

	Nucleotide& Nucleotide::operator =(const Nucleotide& nucleotide)
	{
		set(nucleotide);

		return *this;
	}

	void Nucleotide::get(Nucleotide& nucleotide, bool deep) const
	{
		nucleotide.set(*this, deep);
	}

	void Nucleotide::swap(Nucleotide& nucleotide)
	{
		Fragment::swap(nucleotide);

		id_.swap(nucleotide.id_);

		char temp_insertion_code = insertion_code_;
		insertion_code_ = nucleotide.insertion_code_;
		nucleotide.insertion_code_ = temp_insertion_code;
	}

	NucleicAcid* Nucleotide::getNucleicAcid()
	{
		for (Composite::AncestorIterator ancestor_it = beginAncestor(); !ancestor_it.isEnd(); ++ancestor_it)
		{
			if (RTTI::isKindOf<NucleicAcid>(*ancestor_it))
			{
				return (NucleicAcid*)&*ancestor_it;
			}
		}

		return 0;
	}

	const NucleicAcid* Nucleotide::getNucleicAcid() const
	{
		return (const_cast<const Nucleotide*>(this)->getNucleicAcid());
	}

	void Nucleotide::setID(const String &id)
	{
		id_ = id;
	}

	const String &Nucleotide::getID() const
	{
		return id_;
	}

	void Nucleotide::setInsertionCode(char insertion_code)
	{
		insertion_code_ = insertion_code;
	}

	char Nucleotide::getInsertionCode() const
	{
		return insertion_code_;
	}

	void Nucleotide::prepend(Atom& atom)
	{
		Composite::prependChild(atom);
	}

	void Nucleotide::append(Atom &atom)
	{
		Composite::appendChild(atom);
	}

	void Nucleotide::insert(Atom &atom)
	{
		append(atom);
	}

	void Nucleotide::insertBefore(Atom &atom, Composite& before)
	{
		before.Composite::insertBefore(atom);
	}

	void Nucleotide::insertAfter(Atom& atom, Composite &after)
	{
		after.Composite::insertAfter(atom);
	}

	bool Nucleotide::remove(Atom& atom)
	{
		return Composite::removeChild(atom);
	}

	void Nucleotide::spliceBefore(Nucleotide& nucleotide)
	{
		Composite::spliceBefore(nucleotide);
	}

	void Nucleotide::spliceAfter(Nucleotide& nucleotide)
	{
		Composite::spliceAfter(nucleotide);
	}

	void Nucleotide::splice(Nucleotide& nucleotide)
	{
		Composite::splice(nucleotide);
	}

	bool Nucleotide::isTerminal() const
	{
		const NucleicAcid* parent = (*this).getNucleicAcid();
		/*if (parent != 0)
		{
			if (parent->get3Prime() == this ||
					parent->get5Prime() == this)
			{
				return true;
			}
		}*/
		return false;
	}

	bool Nucleotide::is5Prime() const
	{
		const NucleicAcid* parent = getNucleicAcid();
		if (parent != 0)
		{
			if (parent->get5Prime() == this)
			{
				return true;
			}
		}
		return false;
	}

	bool Nucleotide::is3Prime() const
	{
		const NucleicAcid* parent = getNucleicAcid();
		if (parent != 0)
		{
			if (parent->get3Prime() == this)
			{
				return true;
			}
		}
		return false;
	}

	bool Nucleotide::isValid() const
	{
		if (Fragment::isValid() == false
				|| id_.isValid() == false)
		{
			return false;
		}

		return true;
	}

	void Nucleotide::dump(ostream& s, Size depth) const
	{
		BALL_DUMP_STREAM_PREFIX(s);

		Fragment::dump(s, depth);

		BALL_DUMP_DEPTH(s, depth);
		s << "  id: " << id_ << endl;

		BALL_DUMP_DEPTH(s, depth);
		s << "  insertion code: " << insertion_code_ << endl;

		BALL_DUMP_STREAM_SUFFIX(s);
	}

	void Nucleotide::read(istream&  /* s */)
	{
		throw Exception::NotImplemented(__FILE__, __LINE__);
	}

	void Nucleotide::write(ostream&  /*s */) const
	{
		throw Exception::NotImplemented(__FILE__, __LINE__);
	}

	void Nucleotide::clear_()
	{
		id_ = BALL_NUCLEOTIDE_DEFAULT_ID;
		insertion_code_ = BALL_NUCLEOTIDE_DEFAULT_INSERTION_CODE;
	}

} // namespace BALL
<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2013, Stuart W Baker and Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file Executor.hxx
 *
 * Class to control execution of tasks that get pulled of an input queue.  This
 * is based off of work started by Balazs on 5 August 2013.
 *
 * @author Stuart W Baker and Balazs Racz
 * @date 26 October 2013
 */

#ifndef _EXECUTOR_EXECUTOR_HXX_
#define _EXECUTOR_EXECUTOR_HXX_

#include <functional>

#include "executor/Executable.hxx"
#include "executor/Notifiable.hxx"
#include "executor/Selectable.hxx"
#include "executor/Timer.hxx"
#include "utils/Queue.hxx"
#include "utils/SimpleQueue.hxx"
#include "utils/logging.h"
#include "os/OSSelectWakeup.hxx"

class ActiveTimers;

/** This class implements an execution of tasks pulled off an input queue.
 */
class ExecutorBase : protected OSThread, protected Executable
{
public:
    /** Constructor.
     */
    ExecutorBase();

    /** Destructor.
     */
    ~ExecutorBase();

    /** Lookup an executor by its name.
     * @param name name of executor to lookup
     * @param wait wait forever for an executor to show up
     * @return pointer to executor upon success, else NULL if not found
     */
    static ExecutorBase *by_name(const char *name, bool wait);

    /** Send a message to this Executor's queue.
     * @param action Executable instance to insert into the input queue
     * @param priority priority of execution
     */
    virtual void add(Executable *action, unsigned priority = UINT_MAX) = 0;

    /** Synchronously runs a closure on this executor. Does not return until
     * the execution is completed. */
    void sync_run(std::function<void()> fn);

#ifdef __FreeRTOS__
    /** Send a message to this Executor's queue. Callable from interrupt
     * context.
     * @param action Executable instance to insert into the input queue
     * @param priority priority of execution
     */
    virtual void add_from_isr(Executable *action,
                              unsigned priority = UINT_MAX) = 0;
#endif

    /** Adds a file descriptor to be watched to the select loop.
     * @param job Selectable structure that describes the descriptor to watch.
     * The pointer must stay alive until it is activated, or is unselected.
     *
     * Must be called on the executor thread.
     *
     * @param job is a Selectable pointer that is not currently watched.
     */
    void select(Selectable* job);
    /** Removes a job from the select loop.
     *
     * This stops watching the given file descriptor. The job must have been
     * previously inserted into the Executor and must be not yet activated.
     *
     * Must be called on the executor thread.
     *
     * @param job is a Selectable pointer that was previously inserted.
     */
    void unselect(Selectable* job);

    /** Performs one loop of the execution on the calling thread. Returns true
     * if there is more scheduled work to do. Returns false if the executor
     * loop would block right now. */
    bool loop_once();

    /** @returns the list of active timers. */
    ActiveTimers* active_timers() { return &activeTimers_; }

    /** Terminates the executor thread. Waits until it is safe to delete the
     * executor. */
    void shutdown();

    virtual bool empty() = 0;

protected:
    /** Thread entry point.
     * @return Should never return
     */
    virtual void *entry();

    virtual void run() {}

    /** Helper object for interruptible select calls. */
    OSSelectWakeup selectHelper_;

private:
    /** Wait for an item from the front of the queue.
     * @param timeout time to wait in nanoseconds
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL with errno set:
     *         ETIMEDOUT - timeout occured, EINTR - woken up asynchronously
     */
    virtual Executable *timedwait(long long timeout, unsigned *priority) = 0;

    /** Wait for an item from the front of the queue.
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL with errno set:
     *         EINTR - woken up asynchronously
     */
    virtual Executable *wait(unsigned *priority) = 0;

    /** Retrieve an item from the front of the queue.
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL if queue is empty.
     */
    virtual Executable *next(unsigned *priority) = 0;

    /** Executes a select call, and schedules any necessary executables based
     * on the return. Will not sleep at all if not empty, otherwise sleeps at
     * most next_timer_nsec nanoseconds (from now).
     *
     * @param next_timer is the maximum time to sleep in nanoseconds. */
    void wait_with_select(long long next_timer_nsec);

    fd_set* get_select_set(Selectable::SelectType type) {
        switch(type) {
        case Selectable::READ: return &selectRead_;
        case Selectable::WRITE: return &selectWrite_;
        case Selectable::EXCEPT: return &selectExcept_;
        }
        LOG(FATAL, "Unexpected select type %d", type);
        return nullptr;
    }

    /** name of this Executor */
    const char *name_;

    /** next executor in the lookup list */
    ExecutorBase *next_;

    /** executor list for lookup purposes */
    static ExecutorBase *list;

    /** Currently executing closure. USeful for debugging crashes. */
    Executable* current_;

    /** List of active timers. */
    ActiveTimers activeTimers_;

    /** fd to select for read. */
    fd_set selectRead_;
    /** fd to select for write. */
    fd_set selectWrite_;
    /** fd to select for except. */
    fd_set selectExcept_;
    /** maximum fd to select for + 1 */
    int selectNFds_;
    /** Head of the linked list for the select calls. */
    TypedQueue<Selectable> selectables_;

    /** Set to 1 when the executor thread has exited and it is safe to delete
     * *this. */
    unsigned done_ : 1;
    unsigned started_ : 1;
    unsigned selectPrescaler_ : 5;

    /** provide access to Executor::send method. */
    friend class Service;

    DISALLOW_COPY_AND_ASSIGN(ExecutorBase);
};

/** This is an empty struct. If you give it as an argument to the executor
 * constructor, the executor will be created without a thread. The owner is
 * responsible for "donating" a thread (typically the main thread) to that
 * executor. See @ref Executor::thread_body() */
class NO_THREAD {
public:
    NO_THREAD() {}
};

template <unsigned NUM_PRIO>
class Executor : public ExecutorBase
{
public:

    /** Constructor.
     * @param name name of executor
     * @param priority thread priority
     * @param stack_size thread stack size
     */
    Executor(const char *name, int priority, size_t stack_size)
    {
        start_thread(name, priority, stack_size);
    }

    explicit Executor(const NO_THREAD& unused) {}

    void start_thread(const char *name, int priority, size_t stack_size)
    {
        OSThread::start(name, priority, stack_size);
    }

    /** Destructor.
     */
    ~Executor();

    /** Send a message to this Executor's queue.
     * @param msg Executable instance to insert into the input queue
     * @param priority priority of message
     */
    void add(Executable *msg, unsigned priority = UINT_MAX)
    {
        queue_.insert(
            msg, priority >= NUM_PRIO ? NUM_PRIO - 1 : priority);
        selectHelper_.wakeup();
    }

#ifdef __FreeRTOS__
    /** Send a message to this Executor's queue. Callable from interrupt
     * context.
     * @param msg Executable instance to insert into the input queue
     * @param priority priority of message
     */
    void add_from_isr(Executable *msg, unsigned priority = UINT_MAX)
    {
        queue_.insert_from_isr(
            msg, priority >= NUM_PRIO ? NUM_PRIO - 1 : priority);
        selectHelper_.wakeup_from_isr();
    }
#endif

    /** If the executor was created with NO_THREAD, then this function needs to
     * be called to run the executor loop. It will exit when the execut gets
     * shut down. Useful for having an executor loop run in the main thread. */
    void thread_body() {
        HASSERT(!is_created());
        entry();
    }

    bool empty() OVERRIDE
    {
        return queue_.empty();
    }

private:
    /** Wait for an item from the front of the queue.
     * @param timeout time to wait in nanoseconds
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL with errno set:
     *         ETIMEDOUT - timeout occured, EINTR - woken up asynchronously
     */
    Executable *timedwait(long long timeout, unsigned *priority) OVERRIDE
    {
        auto result = queue_.timedwait(timeout);
        *priority = result.index;
        return static_cast<Executable*>(result.item);
    }

    /** Wait for an item from the front of the queue.
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL with errno set:
     *         EINTR - woken up asynchronously
     */
    Executable *wait(unsigned *priority) OVERRIDE
    {
        auto result = queue_.wait();
        *priority = result.index;
        return static_cast<Executable*>(result.item);
    }

    /** Retrieve an item from the front of the queue.
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL if none waiting.
     */
    Executable *next(unsigned *priority) OVERRIDE
    {
        auto result = queue_.next();
        *priority = result.index;
        return static_cast<Executable*>(result.item);
    }

    /** Default Constructor.
     */
    Executor();

    DISALLOW_COPY_AND_ASSIGN(Executor);

    QListProtectedWait<NUM_PRIO> queue_;
};

/** This class can be given an executor, and will notify itself when that
 *   executor is out of work. Callers can pend on the sync notifiable to wait
 *   for that. */
class ExecutorGuard : private Executable, public SyncNotifiable
{
public:
    ExecutorGuard(ExecutorBase* e)
        : executor_(e) {
        executor_->add(this);  // lowest priority
    }

    virtual void run() {
        if (executor_->empty()) {
            SyncNotifiable::notify();
        } else {
            executor_->add(this);  // wait more on the lowest priority
        }
    }
private:
    ExecutorBase* executor_;
};

template <unsigned NUM_PRIO>
/** Destructs the executor. Waits for the executor to run out of work first. */
Executor<NUM_PRIO>::~Executor()
{
    shutdown();
}

#endif /* _EXECUTOR_EXECUTOR_HXX_ */
<commit_msg>Adds accessor to executor thread handle.<commit_after>/** \copyright
 * Copyright (c) 2013, Stuart W Baker and Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file Executor.hxx
 *
 * Class to control execution of tasks that get pulled of an input queue.  This
 * is based off of work started by Balazs on 5 August 2013.
 *
 * @author Stuart W Baker and Balazs Racz
 * @date 26 October 2013
 */

#ifndef _EXECUTOR_EXECUTOR_HXX_
#define _EXECUTOR_EXECUTOR_HXX_

#include <functional>

#include "executor/Executable.hxx"
#include "executor/Notifiable.hxx"
#include "executor/Selectable.hxx"
#include "executor/Timer.hxx"
#include "utils/Queue.hxx"
#include "utils/SimpleQueue.hxx"
#include "utils/logging.h"
#include "os/OSSelectWakeup.hxx"

class ActiveTimers;

/** This class implements an execution of tasks pulled off an input queue.
 */
class ExecutorBase : protected OSThread, protected Executable
{
public:
    /** Constructor.
     */
    ExecutorBase();

    /** Destructor.
     */
    ~ExecutorBase();

    /** Lookup an executor by its name.
     * @param name name of executor to lookup
     * @param wait wait forever for an executor to show up
     * @return pointer to executor upon success, else NULL if not found
     */
    static ExecutorBase *by_name(const char *name, bool wait);

    /** Send a message to this Executor's queue.
     * @param action Executable instance to insert into the input queue
     * @param priority priority of execution
     */
    virtual void add(Executable *action, unsigned priority = UINT_MAX) = 0;

    /** Synchronously runs a closure on this executor. Does not return until
     * the execution is completed. */
    void sync_run(std::function<void()> fn);

#ifdef __FreeRTOS__
    /** Send a message to this Executor's queue. Callable from interrupt
     * context.
     * @param action Executable instance to insert into the input queue
     * @param priority priority of execution
     */
    virtual void add_from_isr(Executable *action,
                              unsigned priority = UINT_MAX) = 0;
#endif

    /** Adds a file descriptor to be watched to the select loop.
     * @param job Selectable structure that describes the descriptor to watch.
     * The pointer must stay alive until it is activated, or is unselected.
     *
     * Must be called on the executor thread.
     *
     * @param job is a Selectable pointer that is not currently watched.
     */
    void select(Selectable* job);
    /** Removes a job from the select loop.
     *
     * This stops watching the given file descriptor. The job must have been
     * previously inserted into the Executor and must be not yet activated.
     *
     * Must be called on the executor thread.
     *
     * @param job is a Selectable pointer that was previously inserted.
     */
    void unselect(Selectable* job);

    /** Performs one loop of the execution on the calling thread. Returns true
     * if there is more scheduled work to do. Returns false if the executor
     * loop would block right now. */
    bool loop_once();

    /** @returns the list of active timers. */
    ActiveTimers* active_timers() { return &activeTimers_; }

    /** Terminates the executor thread. Waits until it is safe to delete the
     * executor. */
    void shutdown();

    virtual bool empty() = 0;

    os_thread_t thread_handle() { return OSThread::get_handle(); }

protected:
    /** Thread entry point.
     * @return Should never return
     */
    virtual void *entry();

    virtual void run() {}

    /** Helper object for interruptible select calls. */
    OSSelectWakeup selectHelper_;

private:
    /** Wait for an item from the front of the queue.
     * @param timeout time to wait in nanoseconds
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL with errno set:
     *         ETIMEDOUT - timeout occured, EINTR - woken up asynchronously
     */
    virtual Executable *timedwait(long long timeout, unsigned *priority) = 0;

    /** Wait for an item from the front of the queue.
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL with errno set:
     *         EINTR - woken up asynchronously
     */
    virtual Executable *wait(unsigned *priority) = 0;

    /** Retrieve an item from the front of the queue.
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL if queue is empty.
     */
    virtual Executable *next(unsigned *priority) = 0;

    /** Executes a select call, and schedules any necessary executables based
     * on the return. Will not sleep at all if not empty, otherwise sleeps at
     * most next_timer_nsec nanoseconds (from now).
     *
     * @param next_timer is the maximum time to sleep in nanoseconds. */
    void wait_with_select(long long next_timer_nsec);

    fd_set* get_select_set(Selectable::SelectType type) {
        switch(type) {
        case Selectable::READ: return &selectRead_;
        case Selectable::WRITE: return &selectWrite_;
        case Selectable::EXCEPT: return &selectExcept_;
        }
        LOG(FATAL, "Unexpected select type %d", type);
        return nullptr;
    }

    /** name of this Executor */
    const char *name_;

    /** next executor in the lookup list */
    ExecutorBase *next_;

    /** executor list for lookup purposes */
    static ExecutorBase *list;

    /** Currently executing closure. USeful for debugging crashes. */
    Executable* current_;

    /** List of active timers. */
    ActiveTimers activeTimers_;

    /** fd to select for read. */
    fd_set selectRead_;
    /** fd to select for write. */
    fd_set selectWrite_;
    /** fd to select for except. */
    fd_set selectExcept_;
    /** maximum fd to select for + 1 */
    int selectNFds_;
    /** Head of the linked list for the select calls. */
    TypedQueue<Selectable> selectables_;

    /** Set to 1 when the executor thread has exited and it is safe to delete
     * *this. */
    unsigned done_ : 1;
    unsigned started_ : 1;
    unsigned selectPrescaler_ : 5;

    /** provide access to Executor::send method. */
    friend class Service;

    DISALLOW_COPY_AND_ASSIGN(ExecutorBase);
};

/** This is an empty struct. If you give it as an argument to the executor
 * constructor, the executor will be created without a thread. The owner is
 * responsible for "donating" a thread (typically the main thread) to that
 * executor. See @ref Executor::thread_body() */
class NO_THREAD {
public:
    NO_THREAD() {}
};

template <unsigned NUM_PRIO>
class Executor : public ExecutorBase
{
public:

    /** Constructor.
     * @param name name of executor
     * @param priority thread priority
     * @param stack_size thread stack size
     */
    Executor(const char *name, int priority, size_t stack_size)
    {
        start_thread(name, priority, stack_size);
    }

    explicit Executor(const NO_THREAD& unused) {}

    void start_thread(const char *name, int priority, size_t stack_size)
    {
        OSThread::start(name, priority, stack_size);
    }

    /** Destructor.
     */
    ~Executor();

    /** Send a message to this Executor's queue.
     * @param msg Executable instance to insert into the input queue
     * @param priority priority of message
     */
    void add(Executable *msg, unsigned priority = UINT_MAX)
    {
        queue_.insert(
            msg, priority >= NUM_PRIO ? NUM_PRIO - 1 : priority);
        selectHelper_.wakeup();
    }

#ifdef __FreeRTOS__
    /** Send a message to this Executor's queue. Callable from interrupt
     * context.
     * @param msg Executable instance to insert into the input queue
     * @param priority priority of message
     */
    void add_from_isr(Executable *msg, unsigned priority = UINT_MAX)
    {
        queue_.insert_from_isr(
            msg, priority >= NUM_PRIO ? NUM_PRIO - 1 : priority);
        selectHelper_.wakeup_from_isr();
    }
#endif

    /** If the executor was created with NO_THREAD, then this function needs to
     * be called to run the executor loop. It will exit when the execut gets
     * shut down. Useful for having an executor loop run in the main thread. */
    void thread_body() {
        HASSERT(!is_created());
        entry();
    }

    bool empty() OVERRIDE
    {
        return queue_.empty();
    }

private:
    /** Wait for an item from the front of the queue.
     * @param timeout time to wait in nanoseconds
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL with errno set:
     *         ETIMEDOUT - timeout occured, EINTR - woken up asynchronously
     */
    Executable *timedwait(long long timeout, unsigned *priority) OVERRIDE
    {
        auto result = queue_.timedwait(timeout);
        *priority = result.index;
        return static_cast<Executable*>(result.item);
    }

    /** Wait for an item from the front of the queue.
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL with errno set:
     *         EINTR - woken up asynchronously
     */
    Executable *wait(unsigned *priority) OVERRIDE
    {
        auto result = queue_.wait();
        *priority = result.index;
        return static_cast<Executable*>(result.item);
    }

    /** Retrieve an item from the front of the queue.
     * @param priority pass back the priority of the queue pulled from
     * @return item retrieved from queue, else NULL if none waiting.
     */
    Executable *next(unsigned *priority) OVERRIDE
    {
        auto result = queue_.next();
        *priority = result.index;
        return static_cast<Executable*>(result.item);
    }

    /** Default Constructor.
     */
    Executor();

    DISALLOW_COPY_AND_ASSIGN(Executor);

    QListProtectedWait<NUM_PRIO> queue_;
};

/** This class can be given an executor, and will notify itself when that
 *   executor is out of work. Callers can pend on the sync notifiable to wait
 *   for that. */
class ExecutorGuard : private Executable, public SyncNotifiable
{
public:
    ExecutorGuard(ExecutorBase* e)
        : executor_(e) {
        executor_->add(this);  // lowest priority
    }

    virtual void run() {
        if (executor_->empty()) {
            SyncNotifiable::notify();
        } else {
            executor_->add(this);  // wait more on the lowest priority
        }
    }
private:
    ExecutorBase* executor_;
};

template <unsigned NUM_PRIO>
/** Destructs the executor. Waits for the executor to run out of work first. */
Executor<NUM_PRIO>::~Executor()
{
    shutdown();
}

#endif /* _EXECUTOR_EXECUTOR_HXX_ */
<|endoftext|>