<commit_before>#pragma once

#include <exception>
#include <regex>
#include <iostream>

#include "acmacs-base/throw.hh"

// ----------------------------------------------------------------------

namespace virus_name
{
    namespace _internal
    {
#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
#endif

        const std::regex cdc{"^([A-Z][A-Z][A-Z]?) "};

        constexpr const char* re_international_name = "^(?:([AB][^/]*)/)?(?:([^/]+)/)?([^/]{2,})/0*([^/]+)/(19|20)?(\\d\\d)";
        constexpr const char* re_reassortant_passage = "(?:(?:\\s+|__)(.+))?";

          // [1] - type+subtype, [2] - host, [3] - location, [4] - isolation-number (omitting leading zeros), [5] - century, [6] - year (2 last digit), [7] - reassortant and passage
          // const std::regex international{"^([AB][^/]*)/(?:([^/]+)/)?([^/]+)/0*([^/]+)/(19|20)?(\\d\\d)(?:(?:\\s+|__)(.+))?$"};
        const std::regex international{std::string(re_international_name) + re_reassortant_passage + "$"};
        const std::regex international_name{re_international_name};

#pragma GCC diagnostic pop

        inline std::string make_year(const std::smatch& m)
        {
            std::string year;
            if (m[5].length())
                year = m[5].str() + m[6].str();
            else if (m[6].str()[0] > '2')
                year = "19" + m[6].str();
            else
                year = "20" + m[6].str();
            return year;
        }

        constexpr const size_t international_name_suffix_size = 9; // len(lo/isolation-number/year) >= 9

        inline std::string location_human(std::string name, size_t prefix_size)
        {
            const auto end = name.find('/', prefix_size);
            return name.substr(prefix_size, end - prefix_size);
        }
    }

// ----------------------------------------------------------------------

    class Unrecognized : public std::runtime_error { public: using std::runtime_error::runtime_error; };

// ----------------------------------------------------------------------

    std::string normalize(std::string name);

// ----------------------------------------------------------------------

    std::string normalize(std::string name);

    using location_func_t = std::string (*)(std::string);

      // returned cdc abbreviation starts with #
    inline std::string location(std::string name)
    {
        using namespace _internal;
        std::string location;
        std::smatch m;
        if (std::regex_match(name, m, international))
            location = m[3].str();
        else if (std::regex_search(name, m, cdc))
            location = "#" + m[1].str();
        else
            THROW(Unrecognized{"No location in " + name}, std::string{});
        return location;
    }

      // Faster version of location() for A(H3N2)/ and A(H1N1)/ names without host field
    inline std::string location_human_a(std::string name)
    {
        constexpr const size_t prefix_size = 8;
        return (name.size() > (prefix_size + _internal::international_name_suffix_size) && name[prefix_size - 1] == '/') ?  _internal::location_human(name, prefix_size) : location(name);
    }

      // Faster version of location() for B/ names without host field
    inline std::string location_human_b(std::string name)
    {
        constexpr const size_t prefix_size = 2;
        return (name.size() > (prefix_size + _internal::international_name_suffix_size) && name[prefix_size - 1] == '/') ?  _internal::location_human(name, prefix_size) : location(name);
    }

// ----------------------------------------------------------------------

    inline std::string virus_type(std::string name)
    {
        using namespace _internal;
        std::string virus_type;
        std::smatch m;
        if (std::regex_match(name, m, international))
            virus_type = m[1].str();
        else
            THROW(Unrecognized{"No virus_type in " + name}, std::string{});
        return virus_type;

    } // AntigenSerum::virus_type

// ----------------------------------------------------------------------

    inline std::string year(std::string name)
    {
        using namespace _internal;
        std::string year;
        std::smatch m;
        if (std::regex_match(name, m, international))
            year = make_year(m);
        else
            THROW(Unrecognized{"No year in " + name}, std::string{});
        return year;

    } // AntigenSerum::year

// ----------------------------------------------------------------------

    inline void split(std::string name, std::string& virus_type, std::string& host, std::string& location, std::string& isolation, std::string& year, std::string& passage)
    {
        std::smatch m;
        if (std::regex_match(name, m, _internal::international)) {
            virus_type = m[1].str();
            host = m[2].str();
            location = m[3].str();
            isolation = m[4].str();
            year = _internal::make_year(m);
            passage = m[7].str();
        }
        else
            THROW_OR_VOID(Unrecognized{"Cannot split " + name});
    }

// ----------------------------------------------------------------------

      // Extracts virus name without passage, reassortant, extra,
      // etc. and calculates match threshold (to use with
      // acmacs_chart::Antigens::find_by_name_matching), match threshold is a square
      // of virus name length.
    inline size_t match_threshold(std::string name)
    {
        size_t result = 0;
        std::smatch m;
        if (std::regex_search(name, m, _internal::international_name)) {
              // find end of year (m[6])
            const auto end_of_year_offset = static_cast<size_t>(m[6].second - name.begin());
            result = end_of_year_offset * end_of_year_offset;
              // std::cerr << "INFO: match_threshold: end_of_year_offset:" << end_of_year_offset << " name:" << name << std::endl;
        }
        return result;
    }

// ----------------------------------------------------------------------

}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>virus_name::name(full_name)<commit_after>#pragma once

#include <exception>
#include <regex>
#include <iostream>

#include "acmacs-base/throw.hh"

// ----------------------------------------------------------------------

namespace virus_name
{
    namespace _internal
    {
#pragma GCC diagnostic push
#ifdef __clang__
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
#endif

        const std::regex cdc{"^([A-Z][A-Z][A-Z]?) "};

        constexpr const char* re_international_name = "^(?:([AB][^/]*)/)?(?:([^/]+)/)?([^/]{2,})/0*([^/]+)/(19|20)?(\\d\\d)";
        constexpr const char* re_reassortant_passage = "(?:(?:\\s+|__)(.+))?";

          // [1] - type+subtype, [2] - host, [3] - location, [4] - isolation-number (omitting leading zeros), [5] - century, [6] - year (2 last digit), [7] - reassortant and passage
          // const std::regex international{"^([AB][^/]*)/(?:([^/]+)/)?([^/]+)/0*([^/]+)/(19|20)?(\\d\\d)(?:(?:\\s+|__)(.+))?$"};
        const std::regex international{std::string(re_international_name) + re_reassortant_passage + "$"};
        const std::regex international_name{re_international_name};

        const std::regex passage_after_name{" (MDCK|SIAT|MK|E|X)[X\\?\\d]"}; // to extract cdc name only! NOT to extract passage!

#pragma GCC diagnostic pop

        inline std::string make_year(const std::smatch& m)
        {
            std::string year;
            if (m[5].length())
                year = m[5].str() + m[6].str();
            else if (m[6].str()[0] > '2')
                year = "19" + m[6].str();
            else
                year = "20" + m[6].str();
            return year;
        }

        constexpr const size_t international_name_suffix_size = 9; // len(lo/isolation-number/year) >= 9

        inline std::string location_human(std::string name, size_t prefix_size)
        {
            const auto end = name.find('/', prefix_size);
            return name.substr(prefix_size, end - prefix_size);
        }
    }

// ----------------------------------------------------------------------

    class Unrecognized : public std::runtime_error { public: using std::runtime_error::runtime_error; };

// ----------------------------------------------------------------------

    std::string normalize(std::string name);

// ----------------------------------------------------------------------

      // Extracts virus name without passage, reassortant, extra, etc.
    inline std::string_view name(const std::string& aFullName) // pass by reference! because we return string_view to it
    {
        std::smatch m;
        if (std::regex_search(aFullName, m, _internal::international_name)) {
            return {aFullName.data(), static_cast<size_t>(m.length())};
        }
        else if (std::regex_search(aFullName, m, _internal::passage_after_name)) { // works for cdc name without extra and without reassortant (cdc names usually do not have reassortant)
            return {aFullName.data(), static_cast<size_t>(m.position())};
        }
        else {
            return aFullName;   // failed to split, perhaps cdc name without passage
        }
    }

// ----------------------------------------------------------------------

    using location_func_t = std::string (*)(std::string);

      // returned cdc abbreviation starts with #
    inline std::string location(std::string name)
    {
        using namespace _internal;
        std::string location;
        std::smatch m;
        if (std::regex_match(name, m, international))
            location = m[3].str();
        else if (std::regex_search(name, m, cdc))
            location = "#" + m[1].str();
        else
            THROW(Unrecognized{"No location in " + name}, std::string{});
        return location;
    }

      // Faster version of location() for A(H3N2)/ and A(H1N1)/ names without host field
    inline std::string location_human_a(std::string name)
    {
        constexpr const size_t prefix_size = 8;
        return (name.size() > (prefix_size + _internal::international_name_suffix_size) && name[prefix_size - 1] == '/') ?  _internal::location_human(name, prefix_size) : location(name);
    }

      // Faster version of location() for B/ names without host field
    inline std::string location_human_b(std::string name)
    {
        constexpr const size_t prefix_size = 2;
        return (name.size() > (prefix_size + _internal::international_name_suffix_size) && name[prefix_size - 1] == '/') ?  _internal::location_human(name, prefix_size) : location(name);
    }

// ----------------------------------------------------------------------

    inline std::string_view virus_type(const std::string& name) // pass by reference! because we return string_view to it
    {
        std::smatch m;
        if (std::regex_match(name, m, _internal::international))
            return {name.data() + m.position(1), static_cast<size_t>(m.length(1))};
        THROW(Unrecognized("No virus_type in " + name), std::string_view(name.data(), 0U));

    } // AntigenSerum::virus_type

// ----------------------------------------------------------------------

    inline std::string year(std::string name)
    {
        std::smatch m;
        if (std::regex_match(name, m, _internal::international))
            return _internal::make_year(m);
        THROW(Unrecognized("No year in " + name), std::string{});

    } // AntigenSerum::year

// ----------------------------------------------------------------------

    inline void split(std::string name, std::string& virus_type, std::string& host, std::string& location, std::string& isolation, std::string& year, std::string& passage)
    {
        std::smatch m;
        if (std::regex_match(name, m, _internal::international)) {
            virus_type = m[1].str();
            host = m[2].str();
            location = m[3].str();
            isolation = m[4].str();
            year = _internal::make_year(m);
            passage = m[7].str();
        }
        else
            THROW_OR_VOID(Unrecognized{"Cannot split " + name});
    }

// ----------------------------------------------------------------------

      // Extracts virus name without passage, reassortant, extra,
      // etc. and calculates match threshold (to use with
      // acmacs_chart::Antigens::find_by_name_matching), match threshold is a square
      // of virus name length.
    inline size_t match_threshold(std::string name)
    {
        size_t result = 0;
        std::smatch m;
        if (std::regex_search(name, m, _internal::international_name)) {
              // find end of year (m[6])
            const auto end_of_year_offset = static_cast<size_t>(m[6].second - name.begin());
            result = end_of_year_offset * end_of_year_offset;
              // std::cerr << "INFO: match_threshold: end_of_year_offset:" << end_of_year_offset << " name:" << name << std::endl;
        }
        return result;
    }

// ----------------------------------------------------------------------

}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include <bits/stdc++.h>
using namespace std;
int iteration(vector<int> array, int n){
	int iter = array.size();
	int t_ele = array[0];
	array.erase(array.begin());
	array.push_back(n);
	int cnt = array.size();
	for(int i=0;i<t_ele-cnt;i++){
		int e;
		cin >> e;
		array.push_back(e);
	}

	vector<int> temp(array.size(),0);
	for(int i=0;i<iter;i++){
		adjacent_difference(array.begin(),array.end(),temp.begin());
		array = temp;
		if(array.size()>1)
			array.erase(array.begin());
	}
	return accumulate(array.begin(),array.end(),0);
}

int main(){
	int n;
	vector<int> vec;
	cin >> n;	//no of iterations
	for(int i=0;i<n;i++){	//first ele is number of elements
		int temp;
		cin >> temp;
		vec.push_back(temp);
	}

	cin >> n;	//iteration+1th number
	cout << iteration(vec, n);
}
<commit_msg>changed bat script to throw away unneeded output<commit_after>#include <bits/stdc++.h>
using namespace std;
nt iteration(vector<int> array, int n){
	int iter = array.size();
	int t_ele = array[0];
	array.erase(array.begin());
	array.push_back(n);
	int cnt = array.size();
	for(int i=0;i<t_ele-cnt;i++){
		int e;
		cin >> e;
		array.push_back(e);
	}

	vector<int> temp(array.size(),0);
	for(int i=0;i<iter;i++){
		adjacent_difference(array.begin(),array.end(),temp.begin());
		array = temp;
		if(array.size()>1)
			array.erase(array.begin());
	}
	return accumulate(array.begin(),array.end(),0);
}

int main(){
	int n;
	vector<int> vec;
	cin >> n;	//no of iterations
	for(int i=0;i<n;i++){	//first ele is number of elements
		int temp;
		cin >> temp;
		vec.push_back(temp);
	}

	cin >> n;	//iteration+1th number
	cout << iteration(vec, n);
}
<|endoftext|>


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

#include "bitcoinrpc.h"
#include "main.h"
#include <atomic>

#include <algorithm>

using namespace json_spirit;
using namespace std;

extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry);
extern enum Checkpoints::CPMode CheckpointsMode;

double GetDifficulty(const CBlockIndex* blockindex)
{
    // Floating point number that is a multiple of the minimum difficulty,
    // minimum difficulty = 1.0.
    if (blockindex == NULL) {
        if (pindexBest == NULL)
            return 1.0;
        else
            blockindex = GetLastBlockIndex(pindexBest.get(), false);
    }

    int nShift = (blockindex->nBits >> 24) & 0xff;

    double dDiff = (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);

    while (nShift < 29) {
        dDiff *= 256.0;
        nShift++;
    }
    while (nShift > 29) {
        dDiff /= 256.0;
        nShift--;
    }

    return dDiff;
}

double GetPoWMHashPS()
{
    if (boost::atomic_load(&pindexBest)->nHeight >= LAST_POW_BLOCK)
        return 0;

    int     nPoWInterval          = 72;
    int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30;

    CBlockIndexSmartPtr pindex         = boost::atomic_load(&pindexGenesisBlock);
    CBlockIndexSmartPtr pindexPrevWork = boost::atomic_load(&pindexGenesisBlock);

    while (pindex) {
        if (pindex->IsProofOfWork()) {
            int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime();
            nTargetSpacingWork =
                ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) /
                (nPoWInterval + 1);
            nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin);
            pindexPrevWork     = pindex;
        }

        pindex = atomic_load(&pindex->pnext);
    }

    return GetDifficulty() * 4294.967296 / nTargetSpacingWork;
}

double GetPoSKernelPS()
{
    int    nPoSInterval          = 72;
    double dStakeKernelsTriedAvg = 0;
    int    nStakesHandled = 0, nStakesTime = 0;

    CBlockIndexSmartPtr pindex = pindexBest;

    CBlockIndexSmartPtr pindexPrevStake = nullptr;

    while (pindex && nStakesHandled < nPoSInterval) {
        if (pindex->IsProofOfStake()) {
            dStakeKernelsTriedAvg += GetDifficulty(pindex.get()) * 4294967296.0;
            nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0;
            pindexPrevStake = pindex;
            nStakesHandled++;
        }

        pindex = pindex->pprev;
    }

    return nStakesTime ? dStakeKernelsTriedAvg / nStakesTime : 0;
}

Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail)
{
    Object result;
    result.push_back(Pair("hash", block.GetHash().GetHex()));
    CMerkleTx txGen(block.vtx[0]);
    txGen.SetMerkleBranch(&block);
    result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain()));
    result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
    result.push_back(Pair("height", blockindex->nHeight));
    result.push_back(Pair("version", block.nVersion));
    result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
    result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint)));
    result.push_back(Pair("time", (int64_t)block.GetBlockTime()));
    result.push_back(Pair("nonce", (uint64_t)block.nNonce));
    result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
    result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
    result.push_back(Pair("blocktrust", leftTrim(blockindex->GetBlockTrust().GetHex(), '0')));
    result.push_back(Pair("chaintrust", leftTrim(blockindex->nChainTrust.GetHex(), '0')));
    if (blockindex->pprev)
        result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
    if (blockindex->pnext)
        result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));

    result.push_back(Pair(
        "flags", strprintf("%s%s", blockindex->IsProofOfStake() ? "proof-of-stake" : "proof-of-work",
                           blockindex->GeneratedStakeModifier() ? " stake-modifier" : "")));
    result.push_back(Pair("proofhash", blockindex->hashProof.GetHex()));
    result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit()));
    result.push_back(Pair("modifier", strprintf("%016" PRIx64, blockindex->nStakeModifier)));
    result.push_back(Pair("modifierchecksum", strprintf("%08x", blockindex->nStakeModifierChecksum)));
    Array txinfo;
    BOOST_FOREACH (const CTransaction& tx, block.vtx) {
        if (fPrintTransactionDetail) {
            Object entry;

            TxToJSON(tx, 0, entry);

            txinfo.push_back(entry);
        } else
            txinfo.push_back(tx.GetHash().GetHex());
    }

    result.push_back(Pair("tx", txinfo));

    if (block.IsProofOfStake())
        result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end())));

    return result;
}

Value getbestblockhash(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error("getbestblockhash\n"
                            "Returns the hash of the best block in the longest block chain.");

    return hashBestChain.GetHex();
}

Value getblockcount(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error("getblockcount\n"
                            "Returns the number of blocks in the longest block chain.");

    return nBestHeight.load();
}

Value getdifficulty(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error("getdifficulty\n"
                            "Returns the difficulty as a multiple of the minimum difficulty.");

    Object obj;
    obj.push_back(Pair("proof-of-work", GetDifficulty()));
    obj.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest.get(), true))));
    obj.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval));
    return obj;
}

Value settxfee(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 1 || AmountFromValue(params[0]) < MIN_TX_FEE)
        throw runtime_error("settxfee <amount>\n"
                            "<amount> is a real and is rounded to the nearest 0.01");

    nTransactionFee = AmountFromValue(params[0]);
    nTransactionFee = (nTransactionFee / MIN_TX_FEE) * MIN_TX_FEE; // round to nearest 0.0001

    return true;
}

Value getrawmempool(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error("getrawmempool\n"
                            "Returns all transaction ids in memory pool.");

    vector<uint256> vtxid;
    mempool.queryHashes(vtxid);

    Array a;
    BOOST_FOREACH (const uint256& hash, vtxid)
        a.push_back(hash.ToString());

    return a;
}

Value getblockhash(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 1)
        throw runtime_error("getblockhash <index>\n"
                            "Returns hash of block in best-block-chain at <index>.");

    int nHeight = params[0].get_int();
    if (nHeight < 0 || nHeight > nBestHeight)
        throw runtime_error("Block number out of range.");

    CBlockIndexSmartPtr pblockindex = FindBlockByHeight(nHeight);
    return pblockindex->phashBlock->GetHex();
}

// Experimentally deprecated in an effort to support the getblock() call electrum requires
// Value getblock(const Array& params, bool fHelp)
// {
//     if (fHelp || params.size() < 1 || params.size() > 2)
//         throw runtime_error(
//             "getblock <hash> [txinfo]\n"
//             "txinfo optional to print more detailed tx info\n"
//             "Returns details of a block with given block-hash.");

//     std::string strHash = params[0].get_str();
//     uint256 hash(strHash);

//     if (mapBlockIndex.count(hash) == 0)
//         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");

//     CBlock block;
//     CBlockIndex* pblockindex = mapBlockIndex[hash];
//     block.ReadFromDisk(pblockindex, true);

//     return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
// }

Value getblock(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 3)
        throw runtime_error(
            "getblock <hash> [verbose=true] [showtxns=false]\n"
            "If verbose is false, returns a string that is serialized, hex-encoded data for block "
            "<hash>.\n"
            "If verbose is true, returns an Object with information about block <hash> .\n"
            "If verbose is true and showtxns is true, also returns Object about each transaction.");

    std::string strHash = params[0].get_str();
    uint256     hash(strHash);

    bool fVerbose = true;
    if (params.size() > 1)
        fVerbose = params[1].get_bool();

    bool fShowTxns = false;
    if (params.size() > 2)
        fShowTxns = params[2].get_bool();

    if (mapBlockIndex.count(hash) == 0)
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");

    CBlock       block;
    CBlockIndex* pblockindex = boost::atomic_load(&mapBlockIndex[hash]).get();
    block.ReadFromDisk(pblockindex, true);

    if (!fVerbose) {
        CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
        ssBlock << block;
        std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
        return strHex;
    }

    return blockToJSON(block, pblockindex, fShowTxns);
}

Value getblockbynumber(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 2)
        throw runtime_error("getblockbynumber <number> [txinfo]\n"
                            "txinfo optional to print more detailed tx info\n"
                            "Returns details of a block with given block-number.");

    int nHeight = params[0].get_int();
    if (nHeight < 0 || nHeight > nBestHeight)
        throw runtime_error("Block number out of range.");

    CBlock              block;
    CBlockIndexSmartPtr pblockindex = boost::atomic_load(&mapBlockIndex[hashBestChain]);
    while (pblockindex->nHeight > nHeight)
        pblockindex = pblockindex->pprev;

    uint256 hash = *pblockindex->phashBlock;

    pblockindex = boost::atomic_load(&mapBlockIndex[hash]);
    block.ReadFromDisk(pblockindex.get(), true);

    return blockToJSON(block, pblockindex.get(), params.size() > 1 ? params[1].get_bool() : false);
}

// ppcoin: get information of sync-checkpoint
Value getcheckpoint(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error("getcheckpoint\n"
                            "Show info of synchronized checkpoint.\n");

    Object       result;
    CBlockIndex* pindexCheckpoint;

    result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str()));
    pindexCheckpoint = boost::atomic_load(&mapBlockIndex[Checkpoints::hashSyncCheckpoint]).get();
    result.push_back(Pair("height", pindexCheckpoint->nHeight));
    result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str()));

    // Check that the block satisfies synchronized checkpoint
    if (CheckpointsMode == Checkpoints::STRICT)
        result.push_back(Pair("policy", "strict"));

    if (CheckpointsMode == Checkpoints::ADVISORY)
        result.push_back(Pair("policy", "advisory"));

    if (CheckpointsMode == Checkpoints::PERMISSIVE)
        result.push_back(Pair("policy", "permissive"));

    if (mapArgs.exists("-checkpointkey"))
        result.push_back(Pair("checkpointmaster", true));

    return result;
}

Value exportblockchain(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 1)
        throw runtime_error("exportblockchain <path-dir>\n"
                            "Exports the blockchain bootstrap.dat file to <path-dir>.\n"
                            "<path-dir> must be a directory that exists.");

    boost::filesystem::path bdir(params[0].get_str());
    if (!boost::filesystem::exists(bdir))
        throw runtime_error("Directory " + bdir.string() + " does not exist.");

    boost::filesystem::path filename = bdir / "bootstrap.dat";

    boost::promise<void>       finished;
    boost::unique_future<void> finished_future = finished.get_future();
    std::atomic<bool>          stopped{false};
    std::atomic<double>        progress{false};
    boost::thread              exporterThread(boost::bind(&ExportBootstrapBlockchain, filename.string(),
                                             boost::ref(stopped), boost::ref(progress),
                                             boost::ref(finished)));
    exporterThread.detach();

    printf("Export blockchain to path started in another thread. Writing to path: %s\n",
           filename.string().c_str());

    int progVal            = 0;
    int lastPrintedProgVal = -1;
    while (!finished_future.is_ready()) {
        progVal = static_cast<int>(progress.load() * 100);
        if (progVal > lastPrintedProgVal) {
            printf("Export blockchain progress: %i%%\n", progVal);
            lastPrintedProgVal = progVal;
        }
        boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
        if (fShutdown) {
            stopped.store(true);
        }
    }

    finished_future.get(); // throws, but that's compatible with exception handle in this function

    printf("Export blockchain to path %s is done.\n", filename.string().c_str());

    return Value();
}
<commit_msg>Added RPC options for exporting the blockchain with orphans<commit_after>// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bitcoinrpc.h"
#include "main.h"
#include <atomic>

#include <algorithm>

using namespace json_spirit;
using namespace std;

extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry);
extern enum Checkpoints::CPMode CheckpointsMode;

double GetDifficulty(const CBlockIndex* blockindex)
{
    // Floating point number that is a multiple of the minimum difficulty,
    // minimum difficulty = 1.0.
    if (blockindex == NULL) {
        if (pindexBest == NULL)
            return 1.0;
        else
            blockindex = GetLastBlockIndex(pindexBest.get(), false);
    }

    int nShift = (blockindex->nBits >> 24) & 0xff;

    double dDiff = (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);

    while (nShift < 29) {
        dDiff *= 256.0;
        nShift++;
    }
    while (nShift > 29) {
        dDiff /= 256.0;
        nShift--;
    }

    return dDiff;
}

double GetPoWMHashPS()
{
    if (boost::atomic_load(&pindexBest)->nHeight >= LAST_POW_BLOCK)
        return 0;

    int     nPoWInterval          = 72;
    int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30;

    CBlockIndexSmartPtr pindex         = boost::atomic_load(&pindexGenesisBlock);
    CBlockIndexSmartPtr pindexPrevWork = boost::atomic_load(&pindexGenesisBlock);

    while (pindex) {
        if (pindex->IsProofOfWork()) {
            int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime();
            nTargetSpacingWork =
                ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) /
                (nPoWInterval + 1);
            nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin);
            pindexPrevWork     = pindex;
        }

        pindex = atomic_load(&pindex->pnext);
    }

    return GetDifficulty() * 4294.967296 / nTargetSpacingWork;
}

double GetPoSKernelPS()
{
    int    nPoSInterval          = 72;
    double dStakeKernelsTriedAvg = 0;
    int    nStakesHandled = 0, nStakesTime = 0;

    CBlockIndexSmartPtr pindex = pindexBest;

    CBlockIndexSmartPtr pindexPrevStake = nullptr;

    while (pindex && nStakesHandled < nPoSInterval) {
        if (pindex->IsProofOfStake()) {
            dStakeKernelsTriedAvg += GetDifficulty(pindex.get()) * 4294967296.0;
            nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0;
            pindexPrevStake = pindex;
            nStakesHandled++;
        }

        pindex = pindex->pprev;
    }

    return nStakesTime ? dStakeKernelsTriedAvg / nStakesTime : 0;
}

Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail)
{
    Object result;
    result.push_back(Pair("hash", block.GetHash().GetHex()));
    CMerkleTx txGen(block.vtx[0]);
    txGen.SetMerkleBranch(&block);
    result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain()));
    result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
    result.push_back(Pair("height", blockindex->nHeight));
    result.push_back(Pair("version", block.nVersion));
    result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
    result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint)));
    result.push_back(Pair("time", (int64_t)block.GetBlockTime()));
    result.push_back(Pair("nonce", (uint64_t)block.nNonce));
    result.push_back(Pair("bits", strprintf("%08x", block.nBits)));
    result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
    result.push_back(Pair("blocktrust", leftTrim(blockindex->GetBlockTrust().GetHex(), '0')));
    result.push_back(Pair("chaintrust", leftTrim(blockindex->nChainTrust.GetHex(), '0')));
    if (blockindex->pprev)
        result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
    if (blockindex->pnext)
        result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex()));

    result.push_back(Pair(
        "flags", strprintf("%s%s", blockindex->IsProofOfStake() ? "proof-of-stake" : "proof-of-work",
                           blockindex->GeneratedStakeModifier() ? " stake-modifier" : "")));
    result.push_back(Pair("proofhash", blockindex->hashProof.GetHex()));
    result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit()));
    result.push_back(Pair("modifier", strprintf("%016" PRIx64, blockindex->nStakeModifier)));
    result.push_back(Pair("modifierchecksum", strprintf("%08x", blockindex->nStakeModifierChecksum)));
    Array txinfo;
    BOOST_FOREACH (const CTransaction& tx, block.vtx) {
        if (fPrintTransactionDetail) {
            Object entry;

            TxToJSON(tx, 0, entry);

            txinfo.push_back(entry);
        } else
            txinfo.push_back(tx.GetHash().GetHex());
    }

    result.push_back(Pair("tx", txinfo));

    if (block.IsProofOfStake())
        result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end())));

    return result;
}

Value getbestblockhash(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error("getbestblockhash\n"
                            "Returns the hash of the best block in the longest block chain.");

    return hashBestChain.GetHex();
}

Value getblockcount(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error("getblockcount\n"
                            "Returns the number of blocks in the longest block chain.");

    return nBestHeight.load();
}

Value getdifficulty(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error("getdifficulty\n"
                            "Returns the difficulty as a multiple of the minimum difficulty.");

    Object obj;
    obj.push_back(Pair("proof-of-work", GetDifficulty()));
    obj.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest.get(), true))));
    obj.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval));
    return obj;
}

Value settxfee(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 1 || AmountFromValue(params[0]) < MIN_TX_FEE)
        throw runtime_error("settxfee <amount>\n"
                            "<amount> is a real and is rounded to the nearest 0.01");

    nTransactionFee = AmountFromValue(params[0]);
    nTransactionFee = (nTransactionFee / MIN_TX_FEE) * MIN_TX_FEE; // round to nearest 0.0001

    return true;
}

Value getrawmempool(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error("getrawmempool\n"
                            "Returns all transaction ids in memory pool.");

    vector<uint256> vtxid;
    mempool.queryHashes(vtxid);

    Array a;
    BOOST_FOREACH (const uint256& hash, vtxid)
        a.push_back(hash.ToString());

    return a;
}

Value getblockhash(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 1)
        throw runtime_error("getblockhash <index>\n"
                            "Returns hash of block in best-block-chain at <index>.");

    int nHeight = params[0].get_int();
    if (nHeight < 0 || nHeight > nBestHeight)
        throw runtime_error("Block number out of range.");

    CBlockIndexSmartPtr pblockindex = FindBlockByHeight(nHeight);
    return pblockindex->phashBlock->GetHex();
}

// Experimentally deprecated in an effort to support the getblock() call electrum requires
// Value getblock(const Array& params, bool fHelp)
// {
//     if (fHelp || params.size() < 1 || params.size() > 2)
//         throw runtime_error(
//             "getblock <hash> [txinfo]\n"
//             "txinfo optional to print more detailed tx info\n"
//             "Returns details of a block with given block-hash.");

//     std::string strHash = params[0].get_str();
//     uint256 hash(strHash);

//     if (mapBlockIndex.count(hash) == 0)
//         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");

//     CBlock block;
//     CBlockIndex* pblockindex = mapBlockIndex[hash];
//     block.ReadFromDisk(pblockindex, true);

//     return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false);
// }

Value getblock(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 3)
        throw runtime_error(
            "getblock <hash> [verbose=true] [showtxns=false]\n"
            "If verbose is false, returns a string that is serialized, hex-encoded data for block "
            "<hash>.\n"
            "If verbose is true, returns an Object with information about block <hash> .\n"
            "If verbose is true and showtxns is true, also returns Object about each transaction.");

    std::string strHash = params[0].get_str();
    uint256     hash(strHash);

    bool fVerbose = true;
    if (params.size() > 1)
        fVerbose = params[1].get_bool();

    bool fShowTxns = false;
    if (params.size() > 2)
        fShowTxns = params[2].get_bool();

    if (mapBlockIndex.count(hash) == 0)
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");

    CBlock       block;
    CBlockIndex* pblockindex = boost::atomic_load(&mapBlockIndex[hash]).get();
    block.ReadFromDisk(pblockindex, true);

    if (!fVerbose) {
        CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
        ssBlock << block;
        std::string strHex = HexStr(ssBlock.begin(), ssBlock.end());
        return strHex;
    }

    return blockToJSON(block, pblockindex, fShowTxns);
}

Value getblockbynumber(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 2)
        throw runtime_error("getblockbynumber <number> [txinfo]\n"
                            "txinfo optional to print more detailed tx info\n"
                            "Returns details of a block with given block-number.");

    int nHeight = params[0].get_int();
    if (nHeight < 0 || nHeight > nBestHeight)
        throw runtime_error("Block number out of range.");

    CBlock              block;
    CBlockIndexSmartPtr pblockindex = boost::atomic_load(&mapBlockIndex[hashBestChain]);
    while (pblockindex->nHeight > nHeight)
        pblockindex = pblockindex->pprev;

    uint256 hash = *pblockindex->phashBlock;

    pblockindex = boost::atomic_load(&mapBlockIndex[hash]);
    block.ReadFromDisk(pblockindex.get(), true);

    return blockToJSON(block, pblockindex.get(), params.size() > 1 ? params[1].get_bool() : false);
}

// ppcoin: get information of sync-checkpoint
Value getcheckpoint(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error("getcheckpoint\n"
                            "Show info of synchronized checkpoint.\n");

    Object       result;
    CBlockIndex* pindexCheckpoint;

    result.push_back(Pair("synccheckpoint", Checkpoints::hashSyncCheckpoint.ToString().c_str()));
    pindexCheckpoint = boost::atomic_load(&mapBlockIndex[Checkpoints::hashSyncCheckpoint]).get();
    result.push_back(Pair("height", pindexCheckpoint->nHeight));
    result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str()));

    // Check that the block satisfies synchronized checkpoint
    if (CheckpointsMode == Checkpoints::STRICT)
        result.push_back(Pair("policy", "strict"));

    if (CheckpointsMode == Checkpoints::ADVISORY)
        result.push_back(Pair("policy", "advisory"));

    if (CheckpointsMode == Checkpoints::PERMISSIVE)
        result.push_back(Pair("policy", "permissive"));

    if (mapArgs.exists("-checkpointkey"))
        result.push_back(Pair("checkpointmaster", true));

    return result;
}

Value exportblockchain(const Array& params, bool fHelp)
{
    if (fHelp || params.size() < 1 || params.size() > 2) {
        throw runtime_error(
            "exportblockchain <path-dir> [breadth or depth]\n"
            "Exports the blockchain bootstrap.dat file to <path-dir>.\n"
            "<path-dir> must be a directory that exists. Ignoring the last parameter "
            "will export a linear version of the blockchain. If you need orphan chains, "
            "you can choose whether traversal is going to be breadth-firsth or depth-first.");
    }
    if (params.size() == 2 && params[1].get_str() != "breadth" && params[1].get_str() != "depth") {
        throw runtime_error("The second parameter can only be depth or breadth");
    }

    boost::optional<GraphTraverseType> graphTraverseType;
    if (params.size() == 2) {
        if (params[1].get_str() == "breadth") {
            graphTraverseType = GraphTraverseType::BreadthFirst;
        } else if (params[1].get_str() == "depth") {
            graphTraverseType = GraphTraverseType::DepthFirst;
        } else {
            graphTraverseType.reset();
        }
    }

    boost::filesystem::path bdir(params[0].get_str());
    if (!boost::filesystem::exists(bdir))
        throw runtime_error("Directory " + bdir.string() + " does not exist.");

    boost::filesystem::path filename = bdir / "bootstrap.dat";

    boost::promise<void>       finished;
    boost::unique_future<void> finished_future = finished.get_future();
    std::atomic<bool>          stopped{false};
    std::atomic<double>        progress{false};

    if (graphTraverseType != boost::none) {
        // with orphans
        boost::thread exporterThread(
            boost::bind(&ExportBootstrapBlockchainWithOrphans, filename.string(), boost::ref(stopped),
                        boost::ref(progress), boost::ref(finished), graphTraverseType.value()));
        exporterThread.detach();
    } else {
        // without orphans
        boost::thread exporterThread(boost::bind(&ExportBootstrapBlockchain, filename.string(),
                                                 boost::ref(stopped), boost::ref(progress),
                                                 boost::ref(finished)));
        exporterThread.detach();
    }

    printf("Export blockchain to path started in another thread. Writing to path: %s\n",
           filename.string().c_str());

    int progVal            = 0;
    int lastPrintedProgVal = -1;
    while (!finished_future.is_ready()) {
        progVal = static_cast<int>(progress.load() * 100);
        if (progVal > lastPrintedProgVal) {
            printf("Export blockchain progress: %i%%\n", progVal);
            lastPrintedProgVal = progVal;
        }
        boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
        if (fShutdown) {
            stopped.store(true);
        }
    }

    finished_future.get(); // throws, but that's compatible with exception handle in this function

    printf("Export blockchain to path %s is done.\n", filename.string().c_str());

    return Value();
}
<|endoftext|>


<commit_before>//
//  ex10_07.cpp
//  Exercise 10.7
//
//  Created by pezy on 12/9/14.
//
//  @Brief  Determine if there are any errors in the following programs and, if so, correct the error(s)

#include <iostream>
#include <vector>
#include <list>
#include <algorithm>

using std::vector; using std::cout; using std::endl; using std::list; using std::cin; using std::fill_n;

template<typename Sequence>
void print(Sequence const& seq)
{
    for (const auto& i : seq)
        cout << i << " ";
    cout << endl;
}

int main()
{
    // (a)
    vector<int> vec;
    list<int> lst;
    int i;
    while (cin >> i)
        lst.push_back(i);
    vec.resize(lst.size());
    // ^ Fixed: added this statement
    // Cause Algorithms that write to a destination iterator assume
    // the destination is large enough to hold the number of elements being written.
    copy(lst.cbegin(), lst.cend(), vec.begin());

    // (b)
    vector<int> v;
    v.reserve(10);
    fill_n(v.begin(), 10, 0);
    // ^ (b)No error, but not any sense. v.size() still equal zero.
    // Fixed: 1. use `v.resize(10);`
    //    or  2. use `fill_n(std::back_inserter(v), 10, 0)`

    print(v);
    print(vec);
}
<commit_msg>Update ex10_07.cpp<commit_after>//
//  ex10_07.cpp
//  Exercise 10.7
//
//  Created by pezy on 12/9/14.
//
//  @Brief  Determine if there are any errors in the following programs and, if so, correct the error(s)

#include <iostream>
#include <vector>
#include <list>
#include <algorithm>

using std::vector; using std::cout; using std::endl; using std::list; using std::cin; using std::fill_n;

template<typename Sequence>
void print(Sequence const& seq)
{
    for (const auto& i : seq)
        cout << i << " ";
    cout << endl;
}

int main()
{
    // (a)
    vector<int> vec;
    list<int> lst;
    int i;
    while (cin >> i)
        lst.push_back(i);

    copy(lst.cbegin(), lst.cend(), back_inserter(vec));
    // Fixed: the vec.begin() was replaced by a back_inserter iterator, capable of
    // insert new elements automatically at the end of the container.

    // (b)
    vector<int> v;
    v.reserve(10);
    fill_n(v.begin(), 10, 0);
    // ^ (b)No error, but not any sense. v.size() still equal zero.
    // Fixed: 1. use `v.resize(10);`
    //    or  2. use `fill_n(std::back_inserter(v), 10, 0)`

    print(v);
    print(vec);
}
<|endoftext|>


<commit_before>//! @Alan
//! Exercise 10.11:
//! Write a program that uses stable_sort and isShorter to sort a vector passed
//! to your version of elimDups.
//! Print the vector to verify that your program is correct.
//!

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <list>

//! print a container like vector,deque, list,etc.
template <typename Sequence> inline std::ostream& println(Sequence const& seq)
{
    for (auto const& elem : seq) std::cout << elem << " ";
    std::cout << std::endl;

    return std::cout;
}

inline bool is_shorter(std::string const& lhs, std::string const& rhs)
{
    return lhs.size() < rhs.size();
}

void elimdups(std::vector<std::string>& vs)
{
    std::sort(vs.begin(), vs.end());
    auto new_end = std::unique(vs.begin(), vs.end());
    vs.erase(new_end, vs.end());
}

int main()
{
    std::vector<std::string> v{"1234", "1234", "1234", "Hi", "alan", "wang"};
    elimdups(v);
    std::stable_sort(v.begin(), v.end(), is_shorter);
    std::cout << "ex10.11 :\n";
    println(v);

    return 0;
}
//! output
// ex10.11 :
// Hi 1234 alan
<commit_msg>Update ex10_11.cpp<commit_after>//! @Alan
//! Exercise 10.11:
//! Write a program that uses stable_sort and isShorter to sort a vector passed
//! to your version of elimDups.
//! Print the vector to verify that your program is correct.
//!

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

//! print a container like vector, deque, list, etc.
template <typename Sequence>
inline void println(const Sequence &seq)
{
    for(const auto &elem : seq)
        cout<<elem<<" ";
    cout<<endl;
}

inline bool is_shorter(const string &lhs, const string &rhs)
{
    return lhs.size()<rhs.size();
}

void elimdups(vector<string> &svec)
{
    sort(svec.begin(), svec.end());
    auto new_end=unique(svec.begin(), svec.end());
    svec.erase(new_end, svec.end());
}

int main()
{
    vector<string> svec{"1234", "1234", "1234", "Hi", "alan", "wang"};
    elimdups(svec);
    stable_sort(svec.begin(), svec.end(), is_shorter);
    cout<<"ex10.11 :\n";
    println(svec);
}

//! output
// ex10.11 :
// Hi 1234 alan
<|endoftext|>


<commit_before>#pragma once

// (Possibly augmented) matrix implementation, represented as a vector of sparse rows.

#include <algorithm>
#include <utility>
#include <initializer_list>
#include <iterator>
#include <stdexcept>
#include <vector>

namespace msparse {

struct msparse_error: std::runtime_error {
    msparse_error(const std::string &what): std::runtime_error(what) {}
};

constexpr unsigned row_npos = unsigned(-1);

// `msparse::row` represents one sparse matrix row as a vector of
// (column, value) pairs, ordered by (unsigned) column. `row_npos`
// is used to represent an invalid column number.

template <typename X>
class row {
public:
    struct entry {
        unsigned col;
        X value;
    };
    static constexpr unsigned npos = row_npos;

private:
    std::vector<entry> data_;

    // Entries must have strictly monotonically increasing column numbers.
    bool check_invariant() const {
        for (unsigned i = 1; i<data_.size(); ++i) {
            if (data_[i].col<=data_[i-1].col) return false;
        }
        return true;
    }

public:
    row() = default;
    row(const row&) = default;

    row(std::initializer_list<entry> il): data_(il) {
        if (!check_invariant())
            throw msparse_error("improper row element list");
    }

    template <typename InIter>
    row(InIter b, InIter e): data_(b, e) {
        if (!check_invariant())
            throw msparse_error("improper row element list");
    }

    unsigned size() const { return data_.size(); }
    bool empty() const { return size()==0; }

    // Iterators present row as sequence of `entry` objects.
    auto begin() -> decltype(data_.begin()) { return data_.begin(); }
    auto begin() const -> decltype(data_.cbegin()) { return data_.cbegin(); }
    auto end() -> decltype(data_.end()) { return data_.end(); }
    auto end() const -> decltype(data_.cend()) { return data_.cend(); }

    // Return column of first (left-most) entry.
    unsigned mincol() const {
        return empty()? npos: data_.front().col;
    }

    // Return column of first entry with column greater than `c`.
    unsigned mincol_after(unsigned c) const {
        auto i = std::upper_bound(data_.begin(), data_.end(), c,
            [](unsigned a, const entry& b) { return a<b.col; });

        return i==data_.end()? npos: i->col;
    }

    // Return column of last (right-most) entry.
    unsigned maxcol() const {
        return empty()? npos: data_.back().col;
    }

    // As opposed to [] indexing (see below), retrieve `i'th entry from
    // the list of entries.
    const entry& get(unsigned i) const {
        return data_[i];
    }

    void push_back(const entry& e) {
        if (!empty() && e.col <= data_.back().col)
            throw msparse_error("cannot push_back row elements out of order");
        data_.push_back(e);
    }

    // Return index into entry list which has column `c`.
    unsigned index(unsigned c) const {
        auto i = std::lower_bound(data_.begin(), data_.end(), c,
            [](const entry& a, unsigned b) { return a.col<b; });

        return (i==data_.end() || i->col!=c)? npos: std::distance(data_.begin(), i);
    }

    // Remove all entries from column `c` onwards.
    void truncate(unsigned c) {
        auto i = std::lower_bound(data_.begin(), data_.end(), c,
            [](const entry& a, unsigned b) { return a.col<b; });
        data_.erase(i, data_.end());
    }

    // Return value at column `c`; if no entry in row, return default-constructed `X`,
    // i.e. 0 for numeric types.
    X operator[](unsigned c) const {
        auto i = index(c);
        return i==npos? X{}: data_[i].value;
    }

    // Proxy object to allow assigning elements with the syntax `row[c] = value`.
    struct assign_proxy {
        row<X>& row_;
        unsigned c;

        assign_proxy(row<X>& r, unsigned c): row_(r), c(c) {}

        operator X() const { return const_cast<const row<X>&>(row_)[c]; }
        assign_proxy& operator=(const X& x) {
            auto i = std::lower_bound(row_.data_.begin(), row_.data_.end(), c,
                [](const entry& a, unsigned b) { return a.col<b; });

            if (i==row_.data_.end() || i->col!=c) {
                row_.data_.insert(i, {c, x});
            }
            else if (x == X{}) {
                row_.data_.erase(i);
            }
            else {
                i->value = x;
            }

            return *this;
        }
    };

    assign_proxy operator[](unsigned c) {
        return assign_proxy{*this, c};
    }
};

// `msparse::matrix` represents a matrix by a size (number of rows,
// columns) and vector of sparse `mspase::row` rows.
//
// The matrix may also be 'augmented', with columns corresponding to a second
// matrix appended on the right.

template <typename X>
class matrix {
private:
    std::vector<row<X>> rows;
    unsigned cols = 0;
    unsigned aug = row_npos;

public:
    static constexpr unsigned npos = row_npos;

    matrix() = default;
    matrix(unsigned n, unsigned c): rows(n), cols(c) {}

    row<X>& operator[](unsigned i) { return rows[i]; }
    const row<X>& operator[](unsigned i) const { return rows[i]; }

    unsigned size() const { return rows.size(); }
    unsigned nrow() const { return size(); }
    unsigned ncol() const { return cols; }

    // First column corresponding to the augmented submatrix.
    unsigned augcol() const { return aug; }

    bool empty() const { return size()==0; }
    bool augmented() const { return aug!=npos; }

    // Add a column on the right as part of the augmented submatrix.
    // The new entries are provided by a (full, dense representation)
    // sequence of values.
    template <typename Seq>
    void augment(const Seq& col_dense) {
        unsigned r = 0;
        for (const auto& v: col_dense) {
            if (r>=rows.size()) throw msparse_error("augmented column size mismatch");
            rows[r++].push_back({cols, v});
        }
        if (aug==npos) aug=cols;
        ++cols;
    }

    // Remove all augmented columns.
    void diminish() {
        if (aug==npos) return;
        for (auto& row: rows) row.truncate(aug);
        cols = aug;
        aug = npos;
    }
};

} // namespace msparse
<commit_msg>Fix compilation with Clang 3.9 (#172)<commit_after>#pragma once

// (Possibly augmented) matrix implementation, represented as a vector of sparse rows.

#include <algorithm>
#include <utility>
#include <initializer_list>
#include <iterator>
#include <stdexcept>
#include <string>
#include <vector>

namespace msparse {

struct msparse_error: std::runtime_error {
    msparse_error(const std::string &what): std::runtime_error(what) {}
};

constexpr unsigned row_npos = unsigned(-1);

// `msparse::row` represents one sparse matrix row as a vector of
// (column, value) pairs, ordered by (unsigned) column. `row_npos`
// is used to represent an invalid column number.

template <typename X>
class row {
public:
    struct entry {
        unsigned col;
        X value;
    };
    static constexpr unsigned npos = row_npos;

private:
    std::vector<entry> data_;

    // Entries must have strictly monotonically increasing column numbers.
    bool check_invariant() const {
        for (unsigned i = 1; i<data_.size(); ++i) {
            if (data_[i].col<=data_[i-1].col) return false;
        }
        return true;
    }

public:
    row() = default;
    row(const row&) = default;

    row(std::initializer_list<entry> il): data_(il) {
        if (!check_invariant())
            throw msparse_error("improper row element list");
    }

    template <typename InIter>
    row(InIter b, InIter e): data_(b, e) {
        if (!check_invariant())
            throw msparse_error("improper row element list");
    }

    unsigned size() const { return data_.size(); }
    bool empty() const { return size()==0; }

    // Iterators present row as sequence of `entry` objects.
    auto begin() -> decltype(data_.begin()) { return data_.begin(); }
    auto begin() const -> decltype(data_.cbegin()) { return data_.cbegin(); }
    auto end() -> decltype(data_.end()) { return data_.end(); }
    auto end() const -> decltype(data_.cend()) { return data_.cend(); }

    // Return column of first (left-most) entry.
    unsigned mincol() const {
        return empty()? npos: data_.front().col;
    }

    // Return column of first entry with column greater than `c`.
    unsigned mincol_after(unsigned c) const {
        auto i = std::upper_bound(data_.begin(), data_.end(), c,
            [](unsigned a, const entry& b) { return a<b.col; });

        return i==data_.end()? npos: i->col;
    }

    // Return column of last (right-most) entry.
    unsigned maxcol() const {
        return empty()? npos: data_.back().col;
    }

    // As opposed to [] indexing (see below), retrieve `i'th entry from
    // the list of entries.
    const entry& get(unsigned i) const {
        return data_[i];
    }

    void push_back(const entry& e) {
        if (!empty() && e.col <= data_.back().col)
            throw msparse_error("cannot push_back row elements out of order");
        data_.push_back(e);
    }

    // Return index into entry list which has column `c`.
    unsigned index(unsigned c) const {
        auto i = std::lower_bound(data_.begin(), data_.end(), c,
            [](const entry& a, unsigned b) { return a.col<b; });

        return (i==data_.end() || i->col!=c)? npos: std::distance(data_.begin(), i);
    }

    // Remove all entries from column `c` onwards.
    void truncate(unsigned c) {
        auto i = std::lower_bound(data_.begin(), data_.end(), c,
            [](const entry& a, unsigned b) { return a.col<b; });
        data_.erase(i, data_.end());
    }

    // Return value at column `c`; if no entry in row, return default-constructed `X`,
    // i.e. 0 for numeric types.
    X operator[](unsigned c) const {
        auto i = index(c);
        return i==npos? X{}: data_[i].value;
    }

    // Proxy object to allow assigning elements with the syntax `row[c] = value`.
    struct assign_proxy {
        row<X>& row_;
        unsigned c;

        assign_proxy(row<X>& r, unsigned c): row_(r), c(c) {}

        operator X() const { return const_cast<const row<X>&>(row_)[c]; }
        assign_proxy& operator=(const X& x) {
            auto i = std::lower_bound(row_.data_.begin(), row_.data_.end(), c,
                [](const entry& a, unsigned b) { return a.col<b; });

            if (i==row_.data_.end() || i->col!=c) {
                row_.data_.insert(i, {c, x});
            }
            else if (x == X{}) {
                row_.data_.erase(i);
            }
            else {
                i->value = x;
            }

            return *this;
        }
    };

    assign_proxy operator[](unsigned c) {
        return assign_proxy{*this, c};
    }
};

// `msparse::matrix` represents a matrix by a size (number of rows,
// columns) and vector of sparse `mspase::row` rows.
//
// The matrix may also be 'augmented', with columns corresponding to a second
// matrix appended on the right.

template <typename X>
class matrix {
private:
    std::vector<row<X>> rows;
    unsigned cols = 0;
    unsigned aug = row_npos;

public:
    static constexpr unsigned npos = row_npos;

    matrix() = default;
    matrix(unsigned n, unsigned c): rows(n), cols(c) {}

    row<X>& operator[](unsigned i) { return rows[i]; }
    const row<X>& operator[](unsigned i) const { return rows[i]; }

    unsigned size() const { return rows.size(); }
    unsigned nrow() const { return size(); }
    unsigned ncol() const { return cols; }

    // First column corresponding to the augmented submatrix.
    unsigned augcol() const { return aug; }

    bool empty() const { return size()==0; }
    bool augmented() const { return aug!=npos; }

    // Add a column on the right as part of the augmented submatrix.
    // The new entries are provided by a (full, dense representation)
    // sequence of values.
    template <typename Seq>
    void augment(const Seq& col_dense) {
        unsigned r = 0;
        for (const auto& v: col_dense) {
            if (r>=rows.size()) throw msparse_error("augmented column size mismatch");
            rows[r++].push_back({cols, v});
        }
        if (aug==npos) aug=cols;
        ++cols;
    }

    // Remove all augmented columns.
    void diminish() {
        if (aug==npos) return;
        for (auto& row: rows) row.truncate(aug);
        cols = aug;
        aug = npos;
    }
};

} // namespace msparse
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of QMime
**
** Based on Qt Creator source code
**
** Qt Creator Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
**************************************************************************/

#include "qmimetype.h"
#include "qmimetype_p.h"
#include "qmimedatabase_p.h"
#include "qmimeprovider_p.h"

#include "qmimeglobpattern_p.h"

#include <QtCore/QDebug>
#include <QtCore/QLocale>

QT_BEGIN_NAMESPACE

QMimeTypePrivate::QMimeTypePrivate()
{}

QMimeTypePrivate::QMimeTypePrivate(const QMimeType &other)
        : name(other.d->name)
        //, comment(other.d->comment)
        , localeComments(other.d->localeComments)
        , genericIconName(other.d->genericIconName)
        , iconName(other.d->iconName)
        , globPatterns(other.d->globPatterns)
{}

void QMimeTypePrivate::clear()
{
    name.clear();
    //comment.clear();
    localeComments.clear();
    genericIconName.clear();
    iconName.clear();
    globPatterns.clear();
}

bool QMimeTypePrivate::operator==(const QMimeTypePrivate &other) const
{
    return name == other.name &&
            //comment == other.comment &&
            localeComments == other.localeComments &&
            genericIconName == other.genericIconName &&
            iconName == other.iconName &&
            globPatterns == other.globPatterns;
}

void QMimeTypePrivate::addGlobPattern(const QString &pattern)
{
    globPatterns.append(pattern);
}

// TODO rewrite this docu!
/*!
    \class QMimeType

    \brief MIME type data used in Qt Creator

    Contains most information from standard MIME type XML database files.

    In addition, the class provides a list of suffixes and a concept of the
    'preferred suffix' (derived from glob patterns). This is used for example
    to be able to configure the suffix used for C++-files in Qt Creator.

    MIME XML looks like:
    \code
    <?xml version="1.0" encoding="UTF-8"?>
    <mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
    <!-- MIME types must match the desktop file associations -->
      <mime-type type="application/vnd.nokia.qt.qmakeprofile">
        <comment xml:lang="en">Qt qmake Profile</comment>
        <glob pattern="*.pro" weight="50"/>
      </mime-type>
    </mime-info>
    \endcode

    \sa QMimeDatabase
 */

/*!
    \fn QMimeType::QMimeType();
    \brief Initializes the attributes with default values that indicate an invalid MIME type.
 */
QMimeType::QMimeType() :
        d(new QMimeTypePrivate())
{}

/*!
    \fn QMimeType::QMimeType(const QMimeType &other);
    \brief Initializes the attributes with the data of another MIME type.
    \a other The other MIME type the data of which is copied
 */
QMimeType::QMimeType(const QMimeType &other) :
        d(other.d)
{}

#if !defined(Q_COMPILER_RVALUE_REFS) || TEST_COMPILER_RVALUE_REFS == 0
/*!
    \fn QMimeType &QMimeType::operator=(const QMimeType &other);
    \brief Assigns the data of another MIME type.
    \a other The other MIME type the data of which is assigned
 */
QMimeType &QMimeType::operator=(const QMimeType &other)
{
    if (d != other.d)
        d = other.d;
    return *this;
}
#endif

#ifdef Q_COMPILER_RVALUE_REFS
/*!
    \fn QMimeType::QMimeType(QMimeType &&other);
    \brief Moves the data of another rvalue MIME type into the attributes.
    \a other The other rvalue MIME type the data of which is moved
 */
QMimeType::QMimeType(QMimeType &&other) :
        d(std::move(other.d))
{}
#endif

QMimeType::QMimeType(const QMimeTypePrivate &dd) :
        d(new QMimeTypePrivate(dd))
{}

/*!
    \fn QMimeType::~QMimeType();
    \brief Releases the d.
 */
QMimeType::~QMimeType()
{}

/*!
    \fn bool QMimeType::operator==(const QMimeType &other) const;
    \brief Tests for equality with another MIME type.
    \a other The other MIME type that is to be compared with
    Returns if the other MIME type is equal.
 */
bool QMimeType::operator==(const QMimeType &other) const
{
    return d == other.d || *d == *other.d;
}

/*!
    \fn bool QMimeType::operator!=(const QMimeType &other) const;
    \brief Tests for non-equality with another MIME type.
    \a other The other MIME type that is to be compared with
    Returns if the other MIME type is not equal.
 */

/*!
    \fn bool QMimeType::isValid() const;
    \brief Returns true if the MIME type is valid, otherwise returns false.
    A valid MIME type has a non-empty name().
    The invalid MIME type is the default-constructed QMimeType.
 */
bool QMimeType::isValid() const
{
    return !d->name.isEmpty();
}

/*!
    Returns true if this MIME type is the default MIME type which
    applies to all files: application/octet-stream.
 */
bool QMimeType::isDefault() const
{
    return d->name == QMimeDatabasePrivate::instance()->defaultMimeType();
}

/*!
    \fn QString QMimeType::name() const;
    \brief Returns the name of the MIME type.
 */
QString QMimeType::name() const
{
    return d->name;
}

#if 0
/*!
    \fn QStringList QMimeType::aliases() const;
    \brief Returns the aliases of the MIME type.
 */
// What is the use case for this? [apart from mimetypeviewer.cpp ...]
QStringList QMimeType::aliases() const
{
    return d->aliases;
}
#endif

/*!
    \fn QString QMimeType::comment() const;
    \brief Returns the description of the MIME type to be displayed on user interfaces.

    The system language (QLocale::system().name()) is used to select the appropriate translation.
    Another language can be specified by setting the \a localName argument.
 */
QString QMimeType::comment(const QString& localeName) const
{
    QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);

    QStringList languageList;
    if (!localeName.isEmpty())
        languageList << localeName;
    languageList << QLocale::system().name();
    languageList << QLocale::system().uiLanguages();
    Q_FOREACH(const QString& lang, languageList) {
        const QString comm = d->localeComments.value(lang);
        if (!comm.isEmpty())
            return comm;
        const int pos = lang.indexOf(QLatin1Char('_'));
        if (pos != -1) {
            // "pt_BR" not found? try just "pt"
            const QString shortLang = lang.left(pos);
            const QString commShort = d->localeComments.value(shortLang);
            if (!commShort.isEmpty())
                return commShort;
        }
    }

    // Use d->name as fallback, but this is only used by filterString()
    return d->name;
}

/*!
    \fn QString QMimeType::genericIconName() const;
    \brief Returns the file name of an icon image that represents the MIME type.
 */
QString QMimeType::genericIconName() const
{
    QMimeDatabasePrivate::instance()->provider()->loadGenericIcon(*d);
    return d->genericIconName;
}

/*!
    \fn QString QMimeType::iconName() const;
    \brief Returns the file name of an icon image that represents the MIME type.
 */
QString QMimeType::iconName() const
{
    QMimeDatabasePrivate::instance()->provider()->loadIcon(*d);
    if (d->iconName.isEmpty()) {
        // Make default icon name from the mimetype name
        d->iconName = name();
        const int slashindex = d->iconName.indexOf(QLatin1Char('/'));
        if (slashindex != -1)
            d->iconName[slashindex] = QLatin1Char('-');
    }
    return d->iconName;
}

QStringList QMimeType::globPatterns() const
{
    QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);
    return d->globPatterns;
}

QStringList QMimeType::parentMimeTypes() const
{
    return QMimeDatabasePrivate::instance()->provider()->parents(d->name);
}

static void collectParentMimeTypes(const QString& mime, QStringList& allParents)
{
    QStringList parents = QMimeDatabasePrivate::instance()->provider()->parents(mime);
    foreach(const QString& parent, parents) {
        // I would use QSet, but since order matters I better not
        if (!allParents.contains(parent))
            allParents.append(parent);
    }
    // We want a breadth-first search, so that the least-specific parent (octet-stream) is last
    // This means iterating twice, unfortunately.
    foreach(const QString& parent, parents) {
        collectParentMimeTypes(parent, allParents);
    }
}

QStringList QMimeType::allParentMimeTypes() const
{
    QStringList allParents;
    const QString canonical = d->name;
    if (!canonical.isEmpty())
        allParents.append(canonical);
    collectParentMimeTypes(d->name, allParents);

    return allParents;
}

/*!
    \fn QStringList QMimeType::suffixes() const;
    \brief Returns the known suffixes for the MIME type.
 */
QStringList QMimeType::suffixes() const
{
    QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);

    QStringList result;
    foreach (const QString& pattern, d->globPatterns) {
        // Not a simple suffix if if looks like: README or *. or *.* or *.JP*G or *.JP?
        if (pattern.startsWith(QLatin1String("*.")) &&
            pattern.length() > 2 &&
            pattern.indexOf(QLatin1Char('*'), 2) < 0 && pattern.indexOf(QLatin1Char('?'), 2) < 0) {
            const QString suffix = pattern.mid(2);
            result.append(suffix);
        }
    }

    return result;
}

/*!
    \fn QString QMimeType::preferredSuffix() const;
    \brief Returns the preferred suffix for the MIME type.
 */
QString QMimeType::preferredSuffix() const
{
    const QStringList suffixList = suffixes();
    return suffixList.isEmpty() ? QString() : suffixList.at(0);
}

/*!
    Returns a filter string usable for a file dialog.
*/
QString QMimeType::filterString() const
{
    QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);
    QString filter;

    if (!d->globPatterns.empty()) { // !Binary files
        filter += comment() + QLatin1String(" (");
        for (int i = 0; i < d->globPatterns.size(); ++i) {
            if (i != 0)
                filter += QLatin1Char(' ');
            filter += d->globPatterns.at(i);
        }
        filter +=  QLatin1Char(')');
    }

    return filter;
}

/*!
    Returns true if this mimetype is \a mimeTypeName, or inherits \a mimeTypeName,
    or \a mimeTypeName is an alias for this mimetype.
 */
bool QMimeType::inherits(const QString &mimeTypeName) const
{
    if (d->name == mimeTypeName)
        return true;
    return QMimeDatabasePrivate::instance()->inherits(d->name, mimeTypeName);
}

QT_END_NAMESPACE
<commit_msg>Adjust comment<commit_after>/**************************************************************************
**
** This file is part of QMime
**
** Based on Qt Creator source code
**
** Qt Creator Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
**************************************************************************/

#include "qmimetype.h"
#include "qmimetype_p.h"
#include "qmimedatabase_p.h"
#include "qmimeprovider_p.h"

#include "qmimeglobpattern_p.h"

#include <QtCore/QDebug>
#include <QtCore/QLocale>

QT_BEGIN_NAMESPACE

QMimeTypePrivate::QMimeTypePrivate()
{}

QMimeTypePrivate::QMimeTypePrivate(const QMimeType &other)
        : name(other.d->name)
        //, comment(other.d->comment)
        , localeComments(other.d->localeComments)
        , genericIconName(other.d->genericIconName)
        , iconName(other.d->iconName)
        , globPatterns(other.d->globPatterns)
{}

void QMimeTypePrivate::clear()
{
    name.clear();
    //comment.clear();
    localeComments.clear();
    genericIconName.clear();
    iconName.clear();
    globPatterns.clear();
}

bool QMimeTypePrivate::operator==(const QMimeTypePrivate &other) const
{
    return name == other.name &&
            //comment == other.comment &&
            localeComments == other.localeComments &&
            genericIconName == other.genericIconName &&
            iconName == other.iconName &&
            globPatterns == other.globPatterns;
}

void QMimeTypePrivate::addGlobPattern(const QString &pattern)
{
    globPatterns.append(pattern);
}

// TODO rewrite this docu!
/*!
    \class QMimeType

    \brief MIME type data used in Qt Creator

    Contains most information from standard MIME type XML database files.

    In addition, the class provides a list of suffixes and a concept of the
    'preferred suffix' (derived from glob patterns). This is used for example
    to be able to configure the suffix used for C++-files in Qt Creator.

    MIME XML looks like:
    \code
    <?xml version="1.0" encoding="UTF-8"?>
    <mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
    <!-- MIME types must match the desktop file associations -->
      <mime-type type="application/vnd.nokia.qt.qmakeprofile">
        <comment xml:lang="en">Qt qmake Profile</comment>
        <glob pattern="*.pro" weight="50"/>
      </mime-type>
    </mime-info>
    \endcode

    \sa QMimeDatabase
 */

/*!
    \fn QMimeType::QMimeType();
    \brief Initializes the attributes with default values that indicate an invalid MIME type.
 */
QMimeType::QMimeType() :
        d(new QMimeTypePrivate())
{}

/*!
    \fn QMimeType::QMimeType(const QMimeType &other);
    \brief Initializes the attributes with the data of another MIME type.
    \a other The other MIME type the data of which is copied
 */
QMimeType::QMimeType(const QMimeType &other) :
        d(other.d)
{}

#if !defined(Q_COMPILER_RVALUE_REFS) || TEST_COMPILER_RVALUE_REFS == 0
/*!
    \fn QMimeType &QMimeType::operator=(const QMimeType &other);
    \brief Assigns the data of another MIME type.
    \a other The other MIME type the data of which is assigned
 */
QMimeType &QMimeType::operator=(const QMimeType &other)
{
    if (d != other.d)
        d = other.d;
    return *this;
}
#endif

#ifdef Q_COMPILER_RVALUE_REFS
/*!
    \fn QMimeType::QMimeType(QMimeType &&other);
    \brief Moves the data of another rvalue MIME type into the attributes.
    \a other The other rvalue MIME type the data of which is moved
 */
QMimeType::QMimeType(QMimeType &&other) :
        d(std::move(other.d))
{}
#endif

QMimeType::QMimeType(const QMimeTypePrivate &dd) :
        d(new QMimeTypePrivate(dd))
{}

/*!
    \fn QMimeType::~QMimeType();
    \brief Releases the d.
 */
QMimeType::~QMimeType()
{}

/*!
    \fn bool QMimeType::operator==(const QMimeType &other) const;
    \brief Tests for equality with another MIME type.
    \a other The other MIME type that is to be compared with
    Returns if the other MIME type is equal.
 */
bool QMimeType::operator==(const QMimeType &other) const
{
    return d == other.d || *d == *other.d;
}

/*!
    \fn bool QMimeType::operator!=(const QMimeType &other) const;
    \brief Tests for non-equality with another MIME type.
    \a other The other MIME type that is to be compared with
    Returns if the other MIME type is not equal.
 */

/*!
    \fn bool QMimeType::isValid() const;
    \brief Returns true if the MIME type is valid, otherwise returns false.
    A valid MIME type has a non-empty name().
    The invalid MIME type is the default-constructed QMimeType.
 */
bool QMimeType::isValid() const
{
    return !d->name.isEmpty();
}

/*!
    Returns true if this MIME type is the default MIME type which
    applies to all files: application/octet-stream.
 */
bool QMimeType::isDefault() const
{
    return d->name == QMimeDatabasePrivate::instance()->defaultMimeType();
}

/*!
    \fn QString QMimeType::name() const;
    \brief Returns the name of the MIME type.
 */
QString QMimeType::name() const
{
    return d->name;
}

#if 0
/*!
    \fn QStringList QMimeType::aliases() const;
    \brief Returns the aliases of the MIME type.
 */
// What is the use case for this? [apart from mimetypeviewer.cpp ...]
QStringList QMimeType::aliases() const
{
    return d->aliases;
}
#endif

/*!
    \fn QString QMimeType::comment() const;
    \brief Returns the description of the MIME type to be displayed on user interfaces.

    The system language (QLocale::system().name()) is used to select the appropriate translation.
    Another language can be specified by setting the \a localName argument.
 */
QString QMimeType::comment(const QString& localeName) const
{
    QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);

    QStringList languageList;
    if (!localeName.isEmpty())
        languageList << localeName;
    languageList << QLocale::system().name();
    languageList << QLocale::system().uiLanguages();
    Q_FOREACH(const QString& lang, languageList) {
        const QString comm = d->localeComments.value(lang);
        if (!comm.isEmpty())
            return comm;
        const int pos = lang.indexOf(QLatin1Char('_'));
        if (pos != -1) {
            // "pt_BR" not found? try just "pt"
            const QString shortLang = lang.left(pos);
            const QString commShort = d->localeComments.value(shortLang);
            if (!commShort.isEmpty())
                return commShort;
        }
    }

    // Use the mimetype name as fallback
    return d->name;
}

/*!
    \fn QString QMimeType::genericIconName() const;
    \brief Returns the file name of an icon image that represents the MIME type.
 */
QString QMimeType::genericIconName() const
{
    QMimeDatabasePrivate::instance()->provider()->loadGenericIcon(*d);
    return d->genericIconName;
}

/*!
    \fn QString QMimeType::iconName() const;
    \brief Returns the file name of an icon image that represents the MIME type.
 */
QString QMimeType::iconName() const
{
    QMimeDatabasePrivate::instance()->provider()->loadIcon(*d);
    if (d->iconName.isEmpty()) {
        // Make default icon name from the mimetype name
        d->iconName = name();
        const int slashindex = d->iconName.indexOf(QLatin1Char('/'));
        if (slashindex != -1)
            d->iconName[slashindex] = QLatin1Char('-');
    }
    return d->iconName;
}

QStringList QMimeType::globPatterns() const
{
    QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);
    return d->globPatterns;
}

QStringList QMimeType::parentMimeTypes() const
{
    return QMimeDatabasePrivate::instance()->provider()->parents(d->name);
}

static void collectParentMimeTypes(const QString& mime, QStringList& allParents)
{
    QStringList parents = QMimeDatabasePrivate::instance()->provider()->parents(mime);
    foreach(const QString& parent, parents) {
        // I would use QSet, but since order matters I better not
        if (!allParents.contains(parent))
            allParents.append(parent);
    }
    // We want a breadth-first search, so that the least-specific parent (octet-stream) is last
    // This means iterating twice, unfortunately.
    foreach(const QString& parent, parents) {
        collectParentMimeTypes(parent, allParents);
    }
}

QStringList QMimeType::allParentMimeTypes() const
{
    QStringList allParents;
    const QString canonical = d->name;
    if (!canonical.isEmpty())
        allParents.append(canonical);
    collectParentMimeTypes(d->name, allParents);

    return allParents;
}

/*!
    \fn QStringList QMimeType::suffixes() const;
    \brief Returns the known suffixes for the MIME type.
 */
QStringList QMimeType::suffixes() const
{
    QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);

    QStringList result;
    foreach (const QString& pattern, d->globPatterns) {
        // Not a simple suffix if if looks like: README or *. or *.* or *.JP*G or *.JP?
        if (pattern.startsWith(QLatin1String("*.")) &&
            pattern.length() > 2 &&
            pattern.indexOf(QLatin1Char('*'), 2) < 0 && pattern.indexOf(QLatin1Char('?'), 2) < 0) {
            const QString suffix = pattern.mid(2);
            result.append(suffix);
        }
    }

    return result;
}

/*!
    \fn QString QMimeType::preferredSuffix() const;
    \brief Returns the preferred suffix for the MIME type.
 */
QString QMimeType::preferredSuffix() const
{
    const QStringList suffixList = suffixes();
    return suffixList.isEmpty() ? QString() : suffixList.at(0);
}

/*!
    Returns a filter string usable for a file dialog.
*/
QString QMimeType::filterString() const
{
    QMimeDatabasePrivate::instance()->provider()->loadMimeTypePrivate(*d);
    QString filter;

    if (!d->globPatterns.empty()) { // !Binary files
        filter += comment() + QLatin1String(" (");
        for (int i = 0; i < d->globPatterns.size(); ++i) {
            if (i != 0)
                filter += QLatin1Char(' ');
            filter += d->globPatterns.at(i);
        }
        filter +=  QLatin1Char(')');
    }

    return filter;
}

/*!
    Returns true if this mimetype is \a mimeTypeName, or inherits \a mimeTypeName,
    or \a mimeTypeName is an alias for this mimetype.
 */
bool QMimeType::inherits(const QString &mimeTypeName) const
{
    if (d->name == mimeTypeName)
        return true;
    return QMimeDatabasePrivate::instance()->inherits(d->name, mimeTypeName);
}

QT_END_NAMESPACE
<|endoftext|>