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

#include "txdb.h"

#include "chain.h"
#include "chainparams.h"
#include "hash.h"
#include "main.h"
#include "pow.h"
#include "uint256.h"
#include "ui_interface.h"

#include <stdint.h>

using namespace std;

static const char DB_COIN = 'C';
static const char DB_COINS = 'c';
static const char DB_BLOCK_FILES = 'f';
static const char DB_TXINDEX = 't';
static const char DB_BLOCK_INDEX = 'b';

static const char DB_BEST_BLOCK = 'B';
static const char DB_FLAG = 'F';
static const char DB_REINDEX_FLAG = 'R';
static const char DB_LAST_BLOCK = 'l';

namespace {

struct CoinEntry {
    COutPoint* outpoint;
    char key;
    CoinEntry(const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)), key(DB_COIN)  {}

    template<typename Stream>
    void Serialize(Stream &s) const {
        s << key;
        s << outpoint->hash;
        s << VARINT(outpoint->n);
    }

    template<typename Stream>
    void Unserialize(Stream& s) {
        s >> key;
        s >> outpoint->hash;
        s >> VARINT(outpoint->n);
    }
};

}

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true)
{
}

bool CCoinsViewDB::GetCoin(const COutPoint &outpoint, Coin &coin) const {
    return db.Read(CoinEntry(&outpoint), coin);
}

bool CCoinsViewDB::HaveCoin(const COutPoint &outpoint) const {
    return db.Exists(CoinEntry(&outpoint));
}

uint256 CCoinsViewDB::GetBestBlock() const {
    LOCK(cs_utxo);
    uint256 hashBestChain;
    if (!db.Read(DB_BEST_BLOCK, hashBestChain))
        return uint256();
    return hashBestChain;
}

bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, size_t &nChildCachedCoinsUsage)
{
    LOCK(cs_utxo);
    CDBBatch batch(db);
    size_t count = 0;
    size_t changed = 0;
    size_t nBatchSize = 0;
    size_t nBatchWrites = 0;
    for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();)
    {
        if (it->second.flags & CCoinsCacheEntry::DIRTY)
        {
            CoinEntry entry(&it->first);
            size_t nUsage = it->second.coin.DynamicMemoryUsage();
            if (it->second.coin.IsSpent())
            {
                batch.Erase(entry);

                // Update the usage of the child cache before deleting the entry in the child cache
                nChildCachedCoinsUsage -= nUsage;
                it = mapCoins.erase(it);
            }
            else
            {
                batch.Write(entry, it->second.coin);

                // Only delete valid coins from the cache when we're nearly syncd.  During IBD, and also
                // if BlockOnly mode is turned on, these coins will be used, whereas, once the chain is
                // syncd we only need the coins that have come from accepting txns into the memory pool.
                bool fBlocksOnly = GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
                if (IsChainNearlySyncd() && !fImporting && !fReindex && !fBlocksOnly)
                {
                    // Update the usage of the child cache before deleting the entry in the child cache
                    nChildCachedCoinsUsage -= nUsage;
                    it = mapCoins.erase(it);
                }
                else
                {
                    it->second.flags = 0;
                    it++;
                }
            }
            changed++;

            // In order to prevent the spikes in memory usage that used to happen when we prepared large as
            // was possible, we instead break up the batches such that the performance gains for writing to
            // leveldb are still realized but the memory spikes are not seen.
            nBatchSize += nUsage;
            if (nBatchSize > nCoinCacheUsage * 0.01)
            {
                 db.WriteBatch(batch);
                 batch.Clear();
                 nBatchSize = 0;
                 nBatchWrites++;
            }
        }
        else
            it++;
        count++;
    }
    if (!hashBlock.IsNull())
        batch.Write(DB_BEST_BLOCK, hashBlock);

    bool ret = db.WriteBatch(batch);
    LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database with %u batch writes...\n", (unsigned int)changed, (unsigned int)count, (unsigned int)nBatchWrites);
    return ret;
}

size_t CCoinsViewDB::EstimateSize() const
{
    return db.EstimateSize(DB_COIN, (char)(DB_COIN+1));
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair(DB_BLOCK_FILES, nFile), info);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write(DB_REINDEX_FLAG, '1');
    else
        return Erase(DB_REINDEX_FLAG);
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists(DB_REINDEX_FLAG);
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read(DB_LAST_BLOCK, nFile);
}

CCoinsViewCursor *CCoinsViewDB::Cursor() const
{
    CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast<CDBWrapper*>(&db)->NewIterator(), GetBestBlock());
    /* It seems that there are no "const iterators" for LevelDB.  Since we
       only need read operations on it, use a const-cast to get around
       that restriction.  */
    i->pcursor->Seek(DB_COIN);
    // Cache key of first record
    if (i->pcursor->Valid()) {
        CoinEntry entry(&i->keyTmp.second);
        i->pcursor->GetKey(entry);
        i->keyTmp.first = entry.key;
    } else {
        i->keyTmp.first = 0; // Make sure Valid() and GetKey() return false
    }
    return i;
}

bool CCoinsViewDBCursor::GetKey(COutPoint &key) const
{
    // Return cached key
    if (keyTmp.first == DB_COIN) {
        key = keyTmp.second;
        return true;
    }
    return false;
}

bool CCoinsViewDBCursor::GetValue(Coin &coin) const
{
    return pcursor->GetValue(coin);
}

unsigned int CCoinsViewDBCursor::GetValueSize() const
{
    return pcursor->GetValueSize();
}

bool CCoinsViewDBCursor::Valid() const
{
    return keyTmp.first == DB_COIN;
}

void CCoinsViewDBCursor::Next()
{
    pcursor->Next();
    CoinEntry entry(&keyTmp.second);
    if (!pcursor->Valid() || !pcursor->GetKey(entry)) {
        keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
    } else {
        keyTmp.first = entry.key;
    }
}

bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
    CDBBatch batch(*this);
    for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
    }
    batch.Write(DB_LAST_BLOCK, nLastFile);
    for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
    }
    return WriteBatch(batch, true);
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(make_pair(DB_TXINDEX, txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CDBBatch batch(*this);
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(make_pair(DB_TXINDEX, it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair(DB_FLAG, name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    boost::scoped_ptr<CDBIterator> pcursor(NewIterator());

    pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256()));

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
            CDiskBlockIndex diskindex;
            if (pcursor->GetValue(diskindex)) {
                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;

                if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
                    return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());

                pcursor->Next();
            } else {
                return error("LoadBlockIndex() : failed to read value");
            }
        } else {
            break;
        }
    }

    return true;
}

namespace {

//! Legacy class to deserialize pre-pertxout database entries without reindex.
class CCoins
{
public:
    //! whether transaction is a coinbase
    bool fCoinBase;

    //! unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped
    std::vector<CTxOut> vout;

    //! at which height this transaction was included in the active block chain
    int nHeight;

    //! empty constructor
    CCoins() : fCoinBase(false), vout(0), nHeight(0) { }

    template<typename Stream>
    void Unserialize(Stream &s) {
        unsigned int nCode = 0;
        // version
        int nVersionDummy;
        ::Unserialize(s, VARINT(nVersionDummy));
        // header code
        ::Unserialize(s, VARINT(nCode));
        fCoinBase = nCode & 1;
        std::vector<bool> vAvail(2, false);
        vAvail[0] = (nCode & 2) != 0;
        vAvail[1] = (nCode & 4) != 0;
        unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
        // spentness bitmask
        while (nMaskCode > 0) {
            unsigned char chAvail = 0;
            ::Unserialize(s, chAvail);
            for (unsigned int p = 0; p < 8; p++) {
                bool f = (chAvail & (1 << p)) != 0;
                vAvail.push_back(f);
            }
            if (chAvail != 0)
                nMaskCode--;
        }
        // txouts themself
        vout.assign(vAvail.size(), CTxOut());
        for (unsigned int i = 0; i < vAvail.size(); i++) {
            if (vAvail[i])
                ::Unserialize(s, REF(CTxOutCompressor(vout[i])));
        }
        // coinbase height
        ::Unserialize(s, VARINT(nHeight));
    }
};

}

/** Upgrade the database from older formats.
 *
 * Currently implemented: from the per-tx utxo model (0.8..0.14.x) to per-txout.
 */
bool CCoinsViewDB::Upgrade() {
    std::unique_ptr<CDBIterator> pcursor(db.NewIterator());
    pcursor->Seek(std::make_pair(DB_COINS, uint256()));
    if (!pcursor->Valid()) {
        return true;
    }

    LogPrintf("Upgrading database...\n");
    uiInterface.InitMessage(_("Upgrading database...this may take a while"));
    size_t batch_size = 1 << 24;
    CDBBatch batch(db);
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<unsigned char, uint256> key;
        if (pcursor->GetKey(key) && key.first == DB_COINS) {
            CCoins old_coins;
            if (!pcursor->GetValue(old_coins)) {
                return error("%s: cannot parse CCoins record", __func__);
            }
            COutPoint outpoint(key.second, 0);
            for (size_t i = 0; i < old_coins.vout.size(); ++i) {
                if (!old_coins.vout[i].IsNull() && !old_coins.vout[i].scriptPubKey.IsUnspendable()) {
                    Coin newcoin(std::move(old_coins.vout[i]), old_coins.nHeight, old_coins.fCoinBase);
                    outpoint.n = i;
                    CoinEntry entry(&outpoint);
                    batch.Write(entry, newcoin);
                }
            }
            batch.Erase(key);
            if (batch.SizeEstimate() > batch_size) {
                db.WriteBatch(batch);
                batch.Clear();
            }
            pcursor->Next();
        } else {
            break;
        }
    }
    db.WriteBatch(batch);
    return true;
}
<commit_msg>Force on-the-fly compaction during pertxout upgrade<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2015-2017 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txdb.h"

#include "chain.h"
#include "chainparams.h"
#include "hash.h"
#include "main.h"
#include "pow.h"
#include "uint256.h"
#include "ui_interface.h"

#include <stdint.h>

using namespace std;

static const char DB_COIN = 'C';
static const char DB_COINS = 'c';
static const char DB_BLOCK_FILES = 'f';
static const char DB_TXINDEX = 't';
static const char DB_BLOCK_INDEX = 'b';

static const char DB_BEST_BLOCK = 'B';
static const char DB_FLAG = 'F';
static const char DB_REINDEX_FLAG = 'R';
static const char DB_LAST_BLOCK = 'l';

namespace {

struct CoinEntry {
    COutPoint* outpoint;
    char key;
    CoinEntry(const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)), key(DB_COIN)  {}

    template<typename Stream>
    void Serialize(Stream &s) const {
        s << key;
        s << outpoint->hash;
        s << VARINT(outpoint->n);
    }

    template<typename Stream>
    void Unserialize(Stream& s) {
        s >> key;
        s >> outpoint->hash;
        s >> VARINT(outpoint->n);
    }
};

}

CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true)
{
}

bool CCoinsViewDB::GetCoin(const COutPoint &outpoint, Coin &coin) const {
    return db.Read(CoinEntry(&outpoint), coin);
}

bool CCoinsViewDB::HaveCoin(const COutPoint &outpoint) const {
    return db.Exists(CoinEntry(&outpoint));
}

uint256 CCoinsViewDB::GetBestBlock() const {
    LOCK(cs_utxo);
    uint256 hashBestChain;
    if (!db.Read(DB_BEST_BLOCK, hashBestChain))
        return uint256();
    return hashBestChain;
}

bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, size_t &nChildCachedCoinsUsage)
{
    LOCK(cs_utxo);
    CDBBatch batch(db);
    size_t count = 0;
    size_t changed = 0;
    size_t nBatchSize = 0;
    size_t nBatchWrites = 0;
    for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();)
    {
        if (it->second.flags & CCoinsCacheEntry::DIRTY)
        {
            CoinEntry entry(&it->first);
            size_t nUsage = it->second.coin.DynamicMemoryUsage();
            if (it->second.coin.IsSpent())
            {
                batch.Erase(entry);

                // Update the usage of the child cache before deleting the entry in the child cache
                nChildCachedCoinsUsage -= nUsage;
                it = mapCoins.erase(it);
            }
            else
            {
                batch.Write(entry, it->second.coin);

                // Only delete valid coins from the cache when we're nearly syncd.  During IBD, and also
                // if BlockOnly mode is turned on, these coins will be used, whereas, once the chain is
                // syncd we only need the coins that have come from accepting txns into the memory pool.
                bool fBlocksOnly = GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
                if (IsChainNearlySyncd() && !fImporting && !fReindex && !fBlocksOnly)
                {
                    // Update the usage of the child cache before deleting the entry in the child cache
                    nChildCachedCoinsUsage -= nUsage;
                    it = mapCoins.erase(it);
                }
                else
                {
                    it->second.flags = 0;
                    it++;
                }
            }
            changed++;

            // In order to prevent the spikes in memory usage that used to happen when we prepared large as
            // was possible, we instead break up the batches such that the performance gains for writing to
            // leveldb are still realized but the memory spikes are not seen.
            nBatchSize += nUsage;
            if (nBatchSize > nCoinCacheUsage * 0.01)
            {
                 db.WriteBatch(batch);
                 batch.Clear();
                 nBatchSize = 0;
                 nBatchWrites++;
            }
        }
        else
            it++;
        count++;
    }
    if (!hashBlock.IsNull())
        batch.Write(DB_BEST_BLOCK, hashBlock);

    bool ret = db.WriteBatch(batch);
    LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database with %u batch writes...\n", (unsigned int)changed, (unsigned int)count, (unsigned int)nBatchWrites);
    return ret;
}

size_t CCoinsViewDB::EstimateSize() const
{
    return db.EstimateSize(DB_COIN, (char)(DB_COIN+1));
}

CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}

bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
    return Read(make_pair(DB_BLOCK_FILES, nFile), info);
}

bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
    if (fReindexing)
        return Write(DB_REINDEX_FLAG, '1');
    else
        return Erase(DB_REINDEX_FLAG);
}

bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
    fReindexing = Exists(DB_REINDEX_FLAG);
    return true;
}

bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
    return Read(DB_LAST_BLOCK, nFile);
}

CCoinsViewCursor *CCoinsViewDB::Cursor() const
{
    CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast<CDBWrapper*>(&db)->NewIterator(), GetBestBlock());
    /* It seems that there are no "const iterators" for LevelDB.  Since we
       only need read operations on it, use a const-cast to get around
       that restriction.  */
    i->pcursor->Seek(DB_COIN);
    // Cache key of first record
    if (i->pcursor->Valid()) {
        CoinEntry entry(&i->keyTmp.second);
        i->pcursor->GetKey(entry);
        i->keyTmp.first = entry.key;
    } else {
        i->keyTmp.first = 0; // Make sure Valid() and GetKey() return false
    }
    return i;
}

bool CCoinsViewDBCursor::GetKey(COutPoint &key) const
{
    // Return cached key
    if (keyTmp.first == DB_COIN) {
        key = keyTmp.second;
        return true;
    }
    return false;
}

bool CCoinsViewDBCursor::GetValue(Coin &coin) const
{
    return pcursor->GetValue(coin);
}

unsigned int CCoinsViewDBCursor::GetValueSize() const
{
    return pcursor->GetValueSize();
}

bool CCoinsViewDBCursor::Valid() const
{
    return keyTmp.first == DB_COIN;
}

void CCoinsViewDBCursor::Next()
{
    pcursor->Next();
    CoinEntry entry(&keyTmp.second);
    if (!pcursor->Valid() || !pcursor->GetKey(entry)) {
        keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
    } else {
        keyTmp.first = entry.key;
    }
}

bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
    CDBBatch batch(*this);
    for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
    }
    batch.Write(DB_LAST_BLOCK, nLastFile);
    for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
        batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
    }
    return WriteBatch(batch, true);
}

bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
    return Read(make_pair(DB_TXINDEX, txid), pos);
}

bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
    CDBBatch batch(*this);
    for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
        batch.Write(make_pair(DB_TXINDEX, it->first), it->second);
    return WriteBatch(batch);
}

bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
    return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
}

bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
    char ch;
    if (!Read(std::make_pair(DB_FLAG, name), ch))
        return false;
    fValue = ch == '1';
    return true;
}

bool CBlockTreeDB::LoadBlockIndexGuts()
{
    boost::scoped_ptr<CDBIterator> pcursor(NewIterator());

    pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256()));

    // Load mapBlockIndex
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();
        std::pair<char, uint256> key;
        if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
            CDiskBlockIndex diskindex;
            if (pcursor->GetValue(diskindex)) {
                // Construct block index object
                CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
                pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
                pindexNew->nHeight        = diskindex.nHeight;
                pindexNew->nFile          = diskindex.nFile;
                pindexNew->nDataPos       = diskindex.nDataPos;
                pindexNew->nUndoPos       = diskindex.nUndoPos;
                pindexNew->nVersion       = diskindex.nVersion;
                pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
                pindexNew->nTime          = diskindex.nTime;
                pindexNew->nBits          = diskindex.nBits;
                pindexNew->nNonce         = diskindex.nNonce;
                pindexNew->nStatus        = diskindex.nStatus;
                pindexNew->nTx            = diskindex.nTx;

                if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus()))
                    return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString());

                pcursor->Next();
            } else {
                return error("LoadBlockIndex() : failed to read value");
            }
        } else {
            break;
        }
    }

    return true;
}

namespace {

//! Legacy class to deserialize pre-pertxout database entries without reindex.
class CCoins
{
public:
    //! whether transaction is a coinbase
    bool fCoinBase;

    //! unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are dropped
    std::vector<CTxOut> vout;

    //! at which height this transaction was included in the active block chain
    int nHeight;

    //! empty constructor
    CCoins() : fCoinBase(false), vout(0), nHeight(0) { }

    template<typename Stream>
    void Unserialize(Stream &s) {
        unsigned int nCode = 0;
        // version
        int nVersionDummy;
        ::Unserialize(s, VARINT(nVersionDummy));
        // header code
        ::Unserialize(s, VARINT(nCode));
        fCoinBase = nCode & 1;
        std::vector<bool> vAvail(2, false);
        vAvail[0] = (nCode & 2) != 0;
        vAvail[1] = (nCode & 4) != 0;
        unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
        // spentness bitmask
        while (nMaskCode > 0) {
            unsigned char chAvail = 0;
            ::Unserialize(s, chAvail);
            for (unsigned int p = 0; p < 8; p++) {
                bool f = (chAvail & (1 << p)) != 0;
                vAvail.push_back(f);
            }
            if (chAvail != 0)
                nMaskCode--;
        }
        // txouts themself
        vout.assign(vAvail.size(), CTxOut());
        for (unsigned int i = 0; i < vAvail.size(); i++) {
            if (vAvail[i])
                ::Unserialize(s, REF(CTxOutCompressor(vout[i])));
        }
        // coinbase height
        ::Unserialize(s, VARINT(nHeight));
    }
};

}

/** Upgrade the database from older formats.
 *
 * Currently implemented: from the per-tx utxo model (0.8..0.14.x) to per-txout.
 */
bool CCoinsViewDB::Upgrade() {
    std::unique_ptr<CDBIterator> pcursor(db.NewIterator());
    pcursor->Seek(std::make_pair(DB_COINS, uint256()));
    if (!pcursor->Valid()) {
        return true;
    }

    LogPrintf("Upgrading database...\n");
    uiInterface.InitMessage(_("Upgrading database...this may take a while"));
    size_t batch_size = 1 << 24;
    CDBBatch batch(db);

    int reportDone = 0;
    std::pair<unsigned char, uint256> key;
    std::pair<unsigned char, uint256> prev_key = {DB_COINS, uint256()};
    while (pcursor->Valid()) {
        boost::this_thread::interruption_point();

        if (pcursor->GetKey(key) && key.first == DB_COINS) {
            CCoins old_coins;
            if (!pcursor->GetValue(old_coins)) {
                return error("%s: cannot parse CCoins record", __func__);
            }
            COutPoint outpoint(key.second, 0);
            for (size_t i = 0; i < old_coins.vout.size(); ++i) {
                if (!old_coins.vout[i].IsNull() && !old_coins.vout[i].scriptPubKey.IsUnspendable()) {
                    Coin newcoin(std::move(old_coins.vout[i]), old_coins.nHeight, old_coins.fCoinBase);
                    outpoint.n = i;
                    CoinEntry entry(&outpoint);
                    batch.Write(entry, newcoin);
                }
            }
            batch.Erase(key);
            if (batch.SizeEstimate() > batch_size) {
                db.WriteBatch(batch);
                batch.Clear();
                db.CompactRange(prev_key, key);
                prev_key = key;
            }
            pcursor->Next();
        } else {
            break;
        }
    }
    db.WriteBatch(batch);

    db.CompactRange({DB_COINS, uint256()}, key);

    return true;
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, squirreldb. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

// db
int CONF_db_file_size = 1; // file size in MB

// sdk
int CONF_sdk_thread_num = 4;
int CONF_sdk_put_pending = 1;

// server
std::string CONF_server_addr = "st01-spi-session1.st01.baidu.com";
//std::string CONF_server_addr = "yq01-tera-dev1.yq01.baidu.com";
std::string CONF_server_port = "8221";
<commit_msg>localhost<commit_after>// Copyright (c) 2015, squirreldb. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

// db
int CONF_db_file_size = 1; // file size in MB

// sdk
int CONF_sdk_thread_num = 4;
int CONF_sdk_put_pending = 1;

// server
std::string CONF_server_addr = "localhost";
std::string CONF_server_port = "8221";
<|endoftext|>


<commit_before>#pragma once

namespace nano
{
enum class timer_state
{
	started,
	stopped
};

/** Timer utility with nesting support */
template <typename UNIT = std::chrono::milliseconds>
class timer
{
public:
	timer () = default;

	timer (nano::timer_state state_a, std::string description_a = "timer") :
	desc (description_a)
	{
		if (state_a == nano::timer_state::started)
		{
			start ();
		}
	}

	timer (std::string description_a) :
	desc (description_a)
	{
	}

	timer (std::string description_a, timer * parent_a) :
	desc (description_a), parent (parent_a)
	{
	}

	/** Do not output if measured time is below the time units threshold in \p minimum_a */
	timer & set_minimum (UNIT minimum_a)
	{
		minimum = minimum_a;
		return *this;
	}

	/**
	 * Create a child timer without starting it.
	 * Since the timing API needs to have low overhead, this function
	 * does not check if a timer with the same name already exists.
	 */
	timer & child (std::string description_a = "child timer")
	{
		children.emplace_back (description_a, this);
		return children.back ();
	}

	/** Create and start a child timer */
	timer & start_child (std::string description_a = "child timer")
	{
		auto & child_timer = child (description_a);
		child_timer.start ();
		return child_timer;
	}

	/** Start the timer. This will assert if the timer is already started. */
	void start ()
	{
		assert (state == nano::timer_state::stopped);
		state = nano::timer_state::started;
		begin = std::chrono::high_resolution_clock::now ();
	}

	/** Restarts the timer */
	void restart ()
	{
		state = nano::timer_state::started;
		begin = std::chrono::high_resolution_clock::now ();
		ticks = UNIT::zero ();
		measurements = 0;
	}

	/**
	 * Stops the timer and increases the measurement count. A timer can be started and paused
	 * multiple times (e.g. in a loop).
	 * @return duration
	 */
	UNIT pause ()
	{
		++measurements;
		return stop ();
	}

	/**
	 * Stop timer
	 * @return duration
	 */
	UNIT stop ()
	{
		assert (state == nano::timer_state::started);
		state = nano::timer_state::stopped;

		auto end = std::chrono::high_resolution_clock::now ();
		ticks += std::chrono::duration_cast<UNIT> (end - begin);
		return ticks;
	}

	/**
	 * Return current units.
	 */
	UNIT value ()
	{
		return ticks;
	}

	/** Returns the duration in UNIT since the timer was last started. */
	UNIT since_start ()
	{
		auto end = std::chrono::high_resolution_clock::now ();
		return std::chrono::duration_cast<UNIT> (end - begin);
	}

	/** Returns true if the timer was last started longer than \p duration_a units ago*/
	bool after_deadline (UNIT duration_a)
	{
		auto end = std::chrono::high_resolution_clock::now ();
		return std::chrono::duration_cast<UNIT> (end - begin) > duration_a;
	}

	/** Returns true if the timer was last started shorter than \p duration_a units ago*/
	bool before_deadline (UNIT duration_a)
	{
		auto end = std::chrono::high_resolution_clock::now ();
		return std::chrono::duration_cast<UNIT> (end - begin) < duration_a;
	}

	/** Stop timer and write measurements to \p output_a */
	void stop (std::string & output_a)
	{
		std::ostringstream stream;
		stop (stream);
		output_a = stream.str ();
	}

	/** Stop timer and write measurements to \p stream_a */
	void stop (std::ostream & stream_a)
	{
		stop ();
		print (stream_a);
	}

	/** Print measurements to the \p stream_a */
	void print (std::ostream & stream_a)
	{
		if (ticks >= minimum)
		{
			// Print cumulative children first. Non-cumulative children prints directly.
			for (auto & child : children)
			{
				if (child.measurements > 0)
				{
					child.print (stream_a);
				}
			}

			auto current_parent = parent;
			while (current_parent)
			{
				stream_a << parent->desc << ".";
				current_parent = current_parent->parent;
			}

			stream_a << desc << ": " << ticks.count () << ' ' << unit ();
			if (measurements > 0)
			{
				stream_a << " (" << measurements << " measurements, " << std::setprecision (2) << std::fixed << static_cast<double> (ticks.count ()) / static_cast<double> (measurements) << ' ' << unit () << " avg)";
			}
			stream_a << std::endl;
		}
	}

	/** Returns the SI unit string */
	std::string unit () const
	{
		return typed_unit<UNIT> ();
	}

	nano::timer_state current_state () const
	{
		return state;
	}

private:
	timer * parent{ nullptr };
	std::vector<timer> children;
	nano::timer_state state{ nano::timer_state::stopped };
	std::string desc;
	std::chrono::time_point<std::chrono::high_resolution_clock> begin;
	UNIT ticks{ 0 };
	UNIT minimum{ UNIT::zero () };
	unsigned measurements{ 0 };

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::nanoseconds>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "nanoseconds";
	}

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::microseconds>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "microseconds";
	}

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::milliseconds>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "milliseconds";
	}

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::seconds>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "seconds";
	}

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::minutes>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "minutes";
	}

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::hours>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "hours";
	}
};

/**
 * The autotimer starts on construction, and stops and prints on destruction.
 */
template <typename UNIT = std::chrono::milliseconds>
class autotimer : public nano::timer<UNIT>
{
public:
	autotimer (std::string description_a, std::ostream & stream_a = std::cout) :
	nano::timer<UNIT> (description_a), stream (stream_a)
	{
		nano::timer<UNIT>::start ();
	}
	~autotimer ()
	{
		nano::timer<UNIT>::stop (stream);
	}

private:
	std::ostream & stream;
};
}
<commit_msg>Add missing headers in timer (#1673)<commit_after>#pragma once

#include <chrono>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

namespace nano
{
enum class timer_state
{
	started,
	stopped
};

/** Timer utility with nesting support */
template <typename UNIT = std::chrono::milliseconds>
class timer
{
public:
	timer () = default;

	timer (nano::timer_state state_a, std::string description_a = "timer") :
	desc (description_a)
	{
		if (state_a == nano::timer_state::started)
		{
			start ();
		}
	}

	timer (std::string description_a) :
	desc (description_a)
	{
	}

	timer (std::string description_a, timer * parent_a) :
	desc (description_a), parent (parent_a)
	{
	}

	/** Do not output if measured time is below the time units threshold in \p minimum_a */
	timer & set_minimum (UNIT minimum_a)
	{
		minimum = minimum_a;
		return *this;
	}

	/**
	 * Create a child timer without starting it.
	 * Since the timing API needs to have low overhead, this function
	 * does not check if a timer with the same name already exists.
	 */
	timer & child (std::string description_a = "child timer")
	{
		children.emplace_back (description_a, this);
		return children.back ();
	}

	/** Create and start a child timer */
	timer & start_child (std::string description_a = "child timer")
	{
		auto & child_timer = child (description_a);
		child_timer.start ();
		return child_timer;
	}

	/** Start the timer. This will assert if the timer is already started. */
	void start ()
	{
		assert (state == nano::timer_state::stopped);
		state = nano::timer_state::started;
		begin = std::chrono::high_resolution_clock::now ();
	}

	/** Restarts the timer */
	void restart ()
	{
		state = nano::timer_state::started;
		begin = std::chrono::high_resolution_clock::now ();
		ticks = UNIT::zero ();
		measurements = 0;
	}

	/**
	 * Stops the timer and increases the measurement count. A timer can be started and paused
	 * multiple times (e.g. in a loop).
	 * @return duration
	 */
	UNIT pause ()
	{
		++measurements;
		return stop ();
	}

	/**
	 * Stop timer
	 * @return duration
	 */
	UNIT stop ()
	{
		assert (state == nano::timer_state::started);
		state = nano::timer_state::stopped;

		auto end = std::chrono::high_resolution_clock::now ();
		ticks += std::chrono::duration_cast<UNIT> (end - begin);
		return ticks;
	}

	/**
	 * Return current units.
	 */
	UNIT value ()
	{
		return ticks;
	}

	/** Returns the duration in UNIT since the timer was last started. */
	UNIT since_start ()
	{
		auto end = std::chrono::high_resolution_clock::now ();
		return std::chrono::duration_cast<UNIT> (end - begin);
	}

	/** Returns true if the timer was last started longer than \p duration_a units ago*/
	bool after_deadline (UNIT duration_a)
	{
		auto end = std::chrono::high_resolution_clock::now ();
		return std::chrono::duration_cast<UNIT> (end - begin) > duration_a;
	}

	/** Returns true if the timer was last started shorter than \p duration_a units ago*/
	bool before_deadline (UNIT duration_a)
	{
		auto end = std::chrono::high_resolution_clock::now ();
		return std::chrono::duration_cast<UNIT> (end - begin) < duration_a;
	}

	/** Stop timer and write measurements to \p output_a */
	void stop (std::string & output_a)
	{
		std::ostringstream stream;
		stop (stream);
		output_a = stream.str ();
	}

	/** Stop timer and write measurements to \p stream_a */
	void stop (std::ostream & stream_a)
	{
		stop ();
		print (stream_a);
	}

	/** Print measurements to the \p stream_a */
	void print (std::ostream & stream_a)
	{
		if (ticks >= minimum)
		{
			// Print cumulative children first. Non-cumulative children prints directly.
			for (auto & child : children)
			{
				if (child.measurements > 0)
				{
					child.print (stream_a);
				}
			}

			auto current_parent = parent;
			while (current_parent)
			{
				stream_a << parent->desc << ".";
				current_parent = current_parent->parent;
			}

			stream_a << desc << ": " << ticks.count () << ' ' << unit ();
			if (measurements > 0)
			{
				stream_a << " (" << measurements << " measurements, " << std::setprecision (2) << std::fixed << static_cast<double> (ticks.count ()) / static_cast<double> (measurements) << ' ' << unit () << " avg)";
			}
			stream_a << std::endl;
		}
	}

	/** Returns the SI unit string */
	std::string unit () const
	{
		return typed_unit<UNIT> ();
	}

	nano::timer_state current_state () const
	{
		return state;
	}

private:
	timer * parent{ nullptr };
	std::vector<timer> children;
	nano::timer_state state{ nano::timer_state::stopped };
	std::string desc;
	std::chrono::time_point<std::chrono::high_resolution_clock> begin;
	UNIT ticks{ 0 };
	UNIT minimum{ UNIT::zero () };
	unsigned measurements{ 0 };

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::nanoseconds>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "nanoseconds";
	}

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::microseconds>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "microseconds";
	}

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::milliseconds>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "milliseconds";
	}

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::seconds>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "seconds";
	}

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::minutes>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "minutes";
	}

	template <typename U, std::enable_if_t<std::is_same<U, std::chrono::hours>::value> * = nullptr>
	std::string typed_unit () const
	{
		return "hours";
	}
};

/**
 * The autotimer starts on construction, and stops and prints on destruction.
 */
template <typename UNIT = std::chrono::milliseconds>
class autotimer : public nano::timer<UNIT>
{
public:
	autotimer (std::string description_a, std::ostream & stream_a = std::cout) :
	nano::timer<UNIT> (description_a), stream (stream_a)
	{
		nano::timer<UNIT>::start ();
	}
	~autotimer ()
	{
		nano::timer<UNIT>::stop (stream);
	}

private:
	std::ostream & stream;
};
}
<|endoftext|>


<commit_before>#include "Parser.h"

#include <iostream>
#include <stack>
#include <algorithm>

#include <llvm/Config/config.h>

#include <clang/AST/ASTConsumer.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Frontend/InitHeaderSearch.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Sema/ParseAST.h>

#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/Diagnostic.h>

#include "ClangUtils.h"
#include "SrcGen.h"

// Temporary Hax:
#include "InitPP.cpp"

using std::string;

namespace ccons {

Parser::Parser(const clang::LangOptions& options) :
	_options(options),
	_target(clang::TargetInfo::CreateTargetInfo(LLVM_HOSTTRIPLE))
{
}

clang::ASTContext * Parser::getContext() const
{
	return _ast.get();
}

Parser::InputType Parser::analyzeInput(const string& contextSource,
                                       const string& buffer,
                                       int& indentLevel,
                                       const clang::FunctionDecl*& FD)
{
	clang::SourceManager sm;
	createMemoryBuffer(buffer, "", &sm);
	clang::FileManager fm;
	clang::HeaderSearch headers(fm);
	clang::InitHeaderSearch ihs(headers);
	ihs.AddDefaultEnvVarPaths(_options);
	ihs.AddDefaultSystemIncludePaths(_options);
	ihs.Realize();
	ProxyDiagnosticClient pdc(NULL);
	clang::Diagnostic diag(&pdc);
	clang::Preprocessor PP(diag, _options, *_target, sm, headers);

	InitializePreprocessor(PP);

	std::stack<std::pair<clang::Token, clang::Token> > S; // Tok, PrevTok

	indentLevel = 0;
	PP.EnterMainSourceFile();

	clang::Token Tok, LastTok;
	bool TokWasDo = false;
	PP.Lex(Tok);
	while (Tok.isNot(clang::tok::eof)) {
		if (Tok.is(clang::tok::l_square)) {
			S.push(std::make_pair(Tok, LastTok)); // [
		} else if (Tok.is(clang::tok::l_paren)) {
			S.push(std::make_pair(Tok, LastTok)); // (
		} else if (Tok.is(clang::tok::l_brace)) {
			S.push(std::make_pair(Tok, LastTok)); // {
			indentLevel++;
		} else if (Tok.is(clang::tok::r_square)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_square)) {
				std::cout << "Unmatched [\n";
				return Incomplete;
			}
			TokWasDo = false;
			S.pop();
		} else if (Tok.is(clang::tok::r_paren)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_paren)) {
				std::cout << "Unmatched (\n";
				return Incomplete;
			}
			TokWasDo = false;
			S.pop();
		} else if (Tok.is(clang::tok::r_brace)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_brace)) {
				std::cout << "Unmatched {\n";
				return Incomplete;
			}
			TokWasDo = S.top().second.is(clang::tok::kw_do);
			S.pop();
			indentLevel--;
		}
		LastTok = Tok;
		PP.Lex(Tok);
	}

	// TODO: We need to properly account for indent-level for blocks that do not
	//       have braces... such as:
	//
	//       if (X)
	//         Y;
	//
	// TODO: Do-while without braces doesn't work, e.g.:
	//
	//       do
	//         foo();
	//       while (bar());
	//
	// Both of the above could be solved by some kind of rewriter-pass that would
	// insert implicit braces (or simply a more involved analysis).

	// TokWasDo is used for do { ... } while (...); loops
	if (LastTok.is(clang::tok::semi) || (LastTok.is(clang::tok::r_brace) && !TokWasDo)) {
		if (!S.empty()) return Incomplete;
		// FIXME: send diagnostics to /dev/null
		clang::TextDiagnosticPrinter tdp(llvm::errs(), false, true, false);
		tdp.SetLangOpts(_options);
		ProxyDiagnosticClient pdc(NULL);
		clang::Diagnostic diag(&pdc);
		diag.setSuppressSystemWarnings(true);
		string src = contextSource + buffer;
		clang::SourceManager sm;
		struct : public clang::ASTConsumer {
			unsigned pos;
			unsigned maxPos;
			clang::SourceManager *sm;
			clang::FunctionDecl *FD;
			void HandleTopLevelDecl(clang::Decl *D) {
				if (clang::FunctionDecl *FuD = dyn_cast<clang::FunctionDecl>(D)) {
					clang::SourceLocation Loc = FuD->getTypeSpecStartLoc();
					unsigned offset = sm->getFileOffset(sm->getInstantiationLoc(Loc));
					if (offset == pos) {
						this->FD = FuD;
					}
				}
			}
		} consumer;
		consumer.pos = contextSource.length();
		consumer.maxPos = consumer.pos + buffer.length();
		consumer.sm = &sm;
		consumer.FD = NULL;
		parse(src, &sm, &diag, &consumer);
		if (!pdc.hadErrors() && consumer.FD) {
			FD = consumer.FD;
			return TopLevel;
		}
		return Stmt;
	}

	return Incomplete;
}

void Parser::parse(const string& src,
                   clang::SourceManager *sm,
                   clang::Diagnostic *diag,
                   clang::ASTConsumer *consumer)
{
	createMemoryBuffer(src, "Main", sm);
	clang::HeaderSearch headers(_fm);
	clang::InitHeaderSearch ihs(headers);
	ihs.AddDefaultEnvVarPaths(_options);
	ihs.AddDefaultSystemIncludePaths(_options);
	ihs.Realize();

	_pp.reset(new clang::Preprocessor(*diag, _options, *_target, *sm, headers));

	InitializePreprocessor(*_pp);

	_ast.reset(new clang::ASTContext(_options, *sm, *_target,
		_pp->getIdentifierTable(), _pp->getSelectorTable()));
	clang::ParseAST(*_pp, consumer, *_ast);
}

llvm::MemoryBuffer * Parser::createMemoryBuffer(const string& src,
                                                const char *name,
                                                clang::SourceManager *sm)
{
	llvm::MemoryBuffer *mb =
		llvm::MemoryBuffer::getMemBufferCopy(&*src.begin(), &*src.end(), name);
	assert(mb && "Error creating MemoryBuffer!");
	sm->createMainFileIDForMemBuffer(mb);
	assert(!sm->getMainFileID().isInvalid() && "Error creating MainFileID!");
	return mb;
}

} // namespace ccons
<commit_msg>ignore diagnostics<commit_after>#include "Parser.h"

#include <iostream>
#include <stack>
#include <algorithm>

#include <llvm/Config/config.h>

#include <clang/AST/ASTConsumer.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Frontend/InitHeaderSearch.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Sema/ParseAST.h>

#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/Diagnostic.h>

#include "ClangUtils.h"
#include "SrcGen.h"

// Temporary Hax:
#include "InitPP.cpp"

using std::string;

namespace ccons {

Parser::Parser(const clang::LangOptions& options) :
	_options(options),
	_target(clang::TargetInfo::CreateTargetInfo(LLVM_HOSTTRIPLE))
{
}

clang::ASTContext * Parser::getContext() const
{
	return _ast.get();
}

Parser::InputType Parser::analyzeInput(const string& contextSource,
                                       const string& buffer,
                                       int& indentLevel,
                                       const clang::FunctionDecl*& FD)
{
	clang::SourceManager sm;
	createMemoryBuffer(buffer, "", &sm);
	clang::FileManager fm;
	clang::HeaderSearch headers(fm);
	clang::InitHeaderSearch ihs(headers);
	ihs.AddDefaultEnvVarPaths(_options);
	ihs.AddDefaultSystemIncludePaths(_options);
	ihs.Realize();
	ProxyDiagnosticClient pdc(NULL);
	clang::Diagnostic diag(&pdc);
	clang::Preprocessor PP(diag, _options, *_target, sm, headers);

	InitializePreprocessor(PP);

	std::stack<std::pair<clang::Token, clang::Token> > S; // Tok, PrevTok

	indentLevel = 0;
	PP.EnterMainSourceFile();

	clang::Token Tok, LastTok;
	bool TokWasDo = false;
	PP.Lex(Tok);
	while (Tok.isNot(clang::tok::eof)) {
		if (Tok.is(clang::tok::l_square)) {
			S.push(std::make_pair(Tok, LastTok)); // [
		} else if (Tok.is(clang::tok::l_paren)) {
			S.push(std::make_pair(Tok, LastTok)); // (
		} else if (Tok.is(clang::tok::l_brace)) {
			S.push(std::make_pair(Tok, LastTok)); // {
			indentLevel++;
		} else if (Tok.is(clang::tok::r_square)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_square)) {
				std::cout << "Unmatched [\n";
				return Incomplete;
			}
			TokWasDo = false;
			S.pop();
		} else if (Tok.is(clang::tok::r_paren)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_paren)) {
				std::cout << "Unmatched (\n";
				return Incomplete;
			}
			TokWasDo = false;
			S.pop();
		} else if (Tok.is(clang::tok::r_brace)) {
			if (S.empty() || S.top().first.isNot(clang::tok::l_brace)) {
				std::cout << "Unmatched {\n";
				return Incomplete;
			}
			TokWasDo = S.top().second.is(clang::tok::kw_do);
			S.pop();
			indentLevel--;
		}
		LastTok = Tok;
		PP.Lex(Tok);
	}

	// TODO: We need to properly account for indent-level for blocks that do not
	//       have braces... such as:
	//
	//       if (X)
	//         Y;
	//
	// TODO: Do-while without braces doesn't work, e.g.:
	//
	//       do
	//         foo();
	//       while (bar());
	//
	// Both of the above could be solved by some kind of rewriter-pass that would
	// insert implicit braces (or simply a more involved analysis).

	// TokWasDo is used for do { ... } while (...); loops
	if (LastTok.is(clang::tok::semi) || (LastTok.is(clang::tok::r_brace) && !TokWasDo)) {
		if (!S.empty()) return Incomplete;
		ProxyDiagnosticClient pdc(NULL); // ignore diagnostics
		clang::Diagnostic diag(&pdc);
		diag.setSuppressSystemWarnings(true);
		string src = contextSource + buffer;
		clang::SourceManager sm;
		struct : public clang::ASTConsumer {
			unsigned pos;
			unsigned maxPos;
			clang::SourceManager *sm;
			clang::FunctionDecl *FD;
			void HandleTopLevelDecl(clang::Decl *D) {
				if (clang::FunctionDecl *FuD = dyn_cast<clang::FunctionDecl>(D)) {
					clang::SourceLocation Loc = FuD->getTypeSpecStartLoc();
					unsigned offset = sm->getFileOffset(sm->getInstantiationLoc(Loc));
					if (offset == pos) {
						this->FD = FuD;
					}
				}
			}
		} consumer;
		consumer.pos = contextSource.length();
		consumer.maxPos = consumer.pos + buffer.length();
		consumer.sm = &sm;
		consumer.FD = NULL;
		parse(src, &sm, &diag, &consumer);
		if (!pdc.hadErrors() && consumer.FD) {
			FD = consumer.FD;
			return TopLevel;
		}
		return Stmt;
	}

	return Incomplete;
}

void Parser::parse(const string& src,
                   clang::SourceManager *sm,
                   clang::Diagnostic *diag,
                   clang::ASTConsumer *consumer)
{
	createMemoryBuffer(src, "Main", sm);
	clang::HeaderSearch headers(_fm);
	clang::InitHeaderSearch ihs(headers);
	ihs.AddDefaultEnvVarPaths(_options);
	ihs.AddDefaultSystemIncludePaths(_options);
	ihs.Realize();

	_pp.reset(new clang::Preprocessor(*diag, _options, *_target, *sm, headers));

	InitializePreprocessor(*_pp);

	_ast.reset(new clang::ASTContext(_options, *sm, *_target,
		_pp->getIdentifierTable(), _pp->getSelectorTable()));
	clang::ParseAST(*_pp, consumer, *_ast);
}

llvm::MemoryBuffer * Parser::createMemoryBuffer(const string& src,
                                                const char *name,
                                                clang::SourceManager *sm)
{
	llvm::MemoryBuffer *mb =
		llvm::MemoryBuffer::getMemBufferCopy(&*src.begin(), &*src.end(), name);
	assert(mb && "Error creating MemoryBuffer!");
	sm->createMainFileIDForMemBuffer(mb);
	assert(!sm->getMainFileID().isInvalid() && "Error creating MainFileID!");
	return mb;
}

} // namespace ccons
<|endoftext|>


<commit_before>#include "Piezas.h"
#include <vector>
/** CLASS Piezas
 * Class for representing a Piezas vertical board, which is roughly based
 * on the game "Connect Four" where pieces are placed in a column and
 * fall to the bottom of the column, or on top of other pieces already in
 * that column. For an illustration of the board, see:
 *  https://en.wikipedia.org/wiki/Connect_Four
 *
 * Board coordinates [row,col] should match with:
 * [2,0][2,1][2,2][2,3]
 * [1,0][1,1][1,2][1,3]
 * [0,0][0,1][0,2][0,3]
 * So that a piece dropped in column 2 should take [0,2] and the next one
 * dropped in column 2 should take [1,2].
**/

/**
 * Constructor sets an empty board (default 3 rows, 4 columns) and
 * specifies it is X's turn first
**/
Piezas::Piezas();

/**
 * Resets each board location to the Blank Piece value, with a board of the
 * same size as previously specified
**/
void Piezas::reset();

/**
 * Places a piece of the current turn on the board, returns what
 * piece is placed, and toggles which Piece's turn it is. dropPiece does
 * NOT allow to place a piece in a location where a column is full.
 * In that case, placePiece returns Piece Blank value
 * Out of bounds coordinates return the Piece Invalid value
 * Trying to drop a piece where it cannot be placed loses the player's turn
**/
Piece Piezas::dropPiece(int column);

/**
 * Returns what piece is at the provided coordinates, or Blank if there
 * are no pieces there, or Invalid if the coordinates are out of bounds
**/
Piece Piezas::pieceAt(int row, int column);

/**
 * Returns which Piece has won, if there is a winner, Invalid if the game
 * is not over, or Blank if the board is filled and no one has won ("tie").
 * For a game to be over, all locations on the board must be filled with X's
 * and O's (i.e. no remaining Blank spaces). The winner is which player has
 * the most adjacent pieces in a single line. Lines can go either vertically
 * or horizontally. If both X's and O's have the same max number of pieces in a
 * line, it is a tie.
**/
Piece Piezas::gameState();<commit_msg>added Piezas.cpp<commit_after>#include "Piezas.h"
#include <vector>
#include <iostream>
/** CLASS Piezas
 * Class for representing a Piezas vertical board, which is roughly based
 * on the game "Connect Four" where pieces are placed in a column and
 * fall to the bottom of the column, or on top of other pieces already in
 * that column. For an illustration of the board, see:
 *  https://en.wikipedia.org/wiki/Connect_Four
 *
 * Board coordinates [row,col] should match with:
 * [2,0][2,1][2,2][2,3]
 * [1,0][1,1][1,2][1,3]
 * [0,0][0,1][0,2][0,3]
 * So that a piece dropped in column 2 should take [0,2] and the next one
 * dropped in column 2 should take [1,2].
**/

/**
 * Constructor sets an empty board (default 3 rows, 4 columns) and
 * specifies it is X's turn first
**/
Piezas::Piezas()
{
	board.resize(BOARD_ROWS, std::vector<Piece>(BOARD_COLS, Blank));
	turn = X;

}//end of constructor

/**
 * Resets each board location to the Blank Piece value, with a board of the
 * same size as previously specified
**/
void Piezas::reset()
{
	for(int i=0;i < BOARD_ROWS;i++)
	{
		for(int j=0;j < BOARD_COLS;j++)
		{
			board[i][j]=Blank;
		}
	}
}//end of reset

/**
 * Places a piece of the current turn on the board, returns what
 * piece is placed, and toggles which Piece's turn it is. dropPiece does
 * NOT allow to place a piece in a location where a column is full.
 * In that case, placePiece returns Piece Blank value
 * Out of bounds coordinates return the Piece Invalid value
 * Trying to drop a piece where it cannot be placed loses the player's turn
**/
Piece Piezas::toggle_piece_turn()
{
	if(turn == O)
	{
		turn = X;
	}
	else
	{
		turn = O;
	}
	return turn;
}

Piece Piezas::dropPiece(int column)
{
	//invalid column
	if(column > BOARD_COLS-1)
	{

		toggle_piece_turn();
		return Invalid;
	}
	//column full
	else if(board[0][column] != Blank)
	{

		toggle_piece_turn();
		return Blank;
	}
	else
	{

		Piece retval;
		for(int i = BOARD_ROWS - 1;i >= 0; i--)
		{
			if(board[i][column] == Blank)
			{
				board[i][column] = turn;
				retval = turn;
				toggle_piece_turn();
				break;
			}

		}
		return retval;

	}
}//end of dropPiece

/**
 * Returns what piece is at the provided coordinates, or Blank if there
 * are no pieces there, or Invalid if the coordinates are out of bounds
**/
Piece Piezas::pieceAt(int row, int column)
{
	if(row < 0 || row > BOARD_ROWS-1 || column < 0 || column > BOARD_COLS-1)
	{
		return Invalid;
	}
	return board[row][column];
}

/**
 * Returns which Piece has won, if there is a winner, Invalid if the game
 * is not over, or Blank if the board is filled and no one has won ("tie").
 * For a game to be over, all locations on the board must be filled with X's
 * and O's (i.e. no remaining Blank spaces). The winner is which player has
 * the most adjacent pieces in a single line. Lines can go either vertically
 * or horizontally. If both X's and O's have the same max number of pieces in a
 * line, it is a tie.
**/
Piece Piezas::gameState()
{

 int numx=0;
 int numo=0;
 int maxadjx=0;
 int maxadjo=0;

//check for Blank
  for(int i=0;i<BOARD_ROWS;i++)
  {

    for(int j=0;j<BOARD_COLS;j++)
    {
	if(board[i][j]==Blank)
 	{
        return Invalid;
     	}

    }

  }

//check within rows
  for(int i=0;i<BOARD_ROWS;i++)
  {
    for(int j=0;j<BOARD_COLS;j++)
    {
      if(board[i][j]==O)
      {
        numo++;
        if(numo>maxadjo)
	 {
          maxadjo=numo;
         }
        numx=0;
      }
      else
      {
        numx++;
        if(numx>maxadjx)
	{
         maxadjx=numx;
	}
        numo=0;
      }
    }
    numx=0;
    numo=0;
  }
  numx=0;
  numo=0;

//check within cols
  for(int j=0;j<BOARD_COLS;j++)
  {
    for(int i=0;i<BOARD_ROWS;i++)
    {
      if(board[i][j]==O)
      {
        numo++;
        if(numo>maxadjo)
	{
         maxadjo=numo;
	}
        numx=0;
      }
      else
      {
        numx++;
        if(numx>maxadjx)
	{
         maxadjx=numx;
	}
        numo=0;
      }
    }

    numx=0;
    numo=0;
  }

 if(maxadjx < maxadjo)
 {
    return O;  //O winner
 }
 else if(maxadjo < maxadjx)
 {
    return X;  //X winner
 }
  else if(maxadjx == maxadjo )
  {
    return Blank; //equal
  }
  return Blank;

}//end of gameState
<|endoftext|>


<commit_before>#include "GLWidget.h"

#include "tiny_obj_loader.h"

#include <iostream>

#include <glm/gtx/transform.hpp>
#include <QApplication>

GLWidget::GLWidget ( QWidget* parent, Qt::WindowFlags f ) : QOpenGLWidget ( parent, f )
{

	setFocusPolicy(Qt::ClickFocus);

	connect(&time, &QTimer::timeout, [this]
		{
			this->update();
		});
	time.start(0);

	QSurfaceFormat format;
	format.setMajorVersion(3);
	format.setMinorVersion(3);

	format.setSamples(8);

	setFormat(format);

}

bool GLWidget::event (QEvent* event)
{

	switch(event->type())
	{
	case QEvent::Type::MouseButtonPress:
		{
			auto mousePressEvent = static_cast<QMouseEvent*>(event);
			if(mousePressEvent->button() == Qt::LeftButton)
			{
				isMouseDown = true;
				lastMousePos = { mousePressEvent->x(), mousePressEvent->y() };
				return true;
			}
		}
		break;
	case QEvent::Type::MouseButtonRelease:
		{
			auto mousePressEvent = static_cast<QMouseEvent*>(event);
			if(mousePressEvent->button() == Qt::LeftButton)
			{
				isMouseDown = false;
				return true;
			}
		}
		break;
	case QEvent::Type::MouseMove:
		{
			auto mousePressEvent = static_cast<QMouseEvent*>(event);
			if(isMouseDown)
			{
				glm::ivec2 currentMouse = { mousePressEvent->x(), mousePressEvent->y() };

				glm::ivec2 deltaMouse = currentMouse - lastMousePos;

				auto forVecIntX = glm::rotate((float)deltaMouse.x / 1000.f, glm::vec3{0.f, 0.f, 1.f}) * glm::vec4(forwardVector, 0.f);
				forwardVector = {forVecIntX.x, forVecIntX.y, forVecIntX.z};

				auto forVecIntY = glm::rotate(-(float)deltaMouse.y / 1000.f, glm::vec3{1.f, 0.f, 0.f}) * glm::vec4(forwardVector, 0.f);
				forwardVector = {forVecIntY.x, forVecIntY.y, forVecIntY.z};

				lastMousePos = currentMouse;

				return true;
			}
		}
		break;
	default: break;
	}

	return QOpenGLWidget::event(event);
}

std::array<float, 3> fromRGB(unsigned char r, unsigned char g, unsigned char b)
{
	return{ (float)r / 255.f, (float)g / 255.f, (float)b / 255.f };
}

void GLWidget::markForRegeneration()
{
	needsRegenerate = true;
}

void GLWidget::markForSave(const QString& saveDest)
{
	needsSave = true;
	savePath = saveDest;
}

std::array<float, 3> fromHex(uint32_t color)
{
 return fromRGB(color >> 24, color << 8 >> 24, color << 16 >> 24);
}

void GLWidget::keyPressEvent ( QKeyEvent* event )
{
	QWidget::keyPressEvent ( event );

	switch(event->key())
	{
	case Qt::Key_Q:
		velocity.z += speed; break;
	case Qt::Key_E:
		velocity.z -= speed; break;
	case Qt::Key_A:
		velocity.x += speed; break;
	case Qt::Key_D:
		velocity.x -= speed; break;
	case Qt::Key_W:
		velocity.y += speed; break;
	case Qt::Key_S:
		velocity.y -= speed; break;
	}

}

void GLWidget::keyReleaseEvent ( QKeyEvent* event )
{
	switch(event->key())
	{
	case Qt::Key_Q:
		velocity.z -= speed; break;
	case Qt::Key_E:
		velocity.z += speed; break;
	case Qt::Key_A:
		velocity.x -= speed; break;
	case Qt::Key_D:
		velocity.x += speed; break;
	case Qt::Key_W:
		velocity.y -= speed; break;
	case Qt::Key_S:
		velocity.y += speed; break;
	}
}

void GLWidget::initializeGL()
{
	QOpenGLWidget::initializeGL();

	initializeOpenGLFunctions();

	std::vector<tinyobj::shape_t> shapes;
	std::vector<tinyobj::material_t> mats;

	std::string error;

	// load model
	tinyobj::LoadObj(shapes, mats, error, "thing.obj");

	if (!shapes.size())
	{
		std::cout << error << std::endl;

		exit(-1);
	}

	tinyobj::mesh_t& mesh = shapes[0].mesh;

	numElements = mesh.indices.size();
	numVerts = mesh.positions.size() / 3;

	//setup buffer
	glGenVertexArrays(1, &vertArray);
	glBindVertexArray(vertArray);

	glGenBuffers(1, &vertLocs);
	glBindBuffer(GL_ARRAY_BUFFER, vertLocs);

	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * mesh.positions.size(), mesh.positions.data(), GL_STATIC_DRAW);

	glGenBuffers(1, &indicies);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicies);

	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * mesh.indices.size(), mesh.indices.data(), GL_STATIC_DRAW);

	std::array<float, 3> colorsToChooseFrom[] =
	{
		fromHex(0xda253900),
		fromHex(0x377ac800),
		fromHex(0x5d3da300),
	//	fromHex(0xe3903100),
	//	fromHex(0x7dbe3200),
	//	fromHex(0x38579900),
	//	fromHex(0x89619e00)
	};

	// generate colors
	std::vector<std::array<float, 3>>  colorsData(mesh.positions.size() / 3);

	std::random_device rd;
	std::mt19937 gen(rd());

	std::uniform_int_distribution<> distr(0, 2);

	for (std::array<float, 3>& color : colorsData)
	{

		color = colorsToChooseFrom[distr(gen)];
	}

	glGenBuffers(1, &colors);
	glBindBuffer(GL_ARRAY_BUFFER, colors);

	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * colorsData.size(), colorsData.data(), GL_STATIC_DRAW);

	// load shader
	auto vertShader =
		"#version 330 core\n"
		"layout(location = 0) in vec3 vertLocationIn;\n"
		"layout(location = 1) in vec3 vertColors;\n"
		"uniform mat4 MVP;\n"
		"\n"
		"out vec3 color;\n"
		"\n"
		"void main()\n"
		"{\n"
		"	gl_Position = MVP * vec4(vertLocationIn, 1.f);\n"
		"	\n"
		"	color = vertColors;\n"
		"}\n";

	auto fragShader =
		"#version 330 core\n"
		"in vec3 color;\n"
		"uniform int isRender = 0;\n"
		"out vec3 fragColor;\n"
		"void main()\n"
		"{\n"
		"	fragColor = isRender != 0 ? vec3(.1f, .1f, .1f) : color;\n"
		"}\n";

	// Create the shaders
	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

	int32_t Result = GL_FALSE;
	int InfoLogLength;

	glShaderSource(vertexShader, 1, &vertShader, nullptr);
	glCompileShader(vertexShader);

	// Check Vertex Shader
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &Result);
	glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &InfoLogLength);
	if (InfoLogLength > 1) {
		auto VertexShaderErrorMessage = std::vector<char>(InfoLogLength + 1);
		glGetShaderInfoLog(vertexShader, InfoLogLength, nullptr, VertexShaderErrorMessage.data());
		std::cout << VertexShaderErrorMessage.data();
	}
	else
	{
		std::cout << "\tShader Successfully Compiled";
	}

	// Compile Fragment Shader
	glShaderSource(fragmentShader, 1, &fragShader, nullptr);
	glCompileShader(fragmentShader);

	// Check Fragment Shader
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &Result);
	glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &InfoLogLength);
	if (InfoLogLength > 1) {
		auto FragmentShaderErrorMessage = std::vector<char>(InfoLogLength + 1);
		glGetShaderInfoLog(fragmentShader, InfoLogLength, nullptr, FragmentShaderErrorMessage.data());
		std::cout << FragmentShaderErrorMessage.data();
	}
	else
	{
		std::cout << "\tShader Successfully Compiled";
	}

	// Link the program
	std::cout << "\tLinking program ";
	program = glCreateProgram();
	glAttachShader(program, vertexShader);
	glAttachShader(program, fragmentShader);
	glLinkProgram(program);

	// Check the program
	glGetProgramiv(program, GL_LINK_STATUS, &Result);
	glGetProgramiv(program, GL_INFO_LOG_LENGTH, &InfoLogLength);
	if (InfoLogLength > 1) {
		auto ProgramErrorMessage = std::vector<char>(InfoLogLength + 1);
		glGetProgramInfoLog(program, InfoLogLength, nullptr, ProgramErrorMessage.data());
		std::cout << ProgramErrorMessage.data();
	}

	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

	std::cout << "\tSuccessfully Linked Program.";

}

void GLWidget::paintGL()
{
	QOpenGLWidget::paintGL();

	std::chrono::time_point<std::chrono::system_clock> currentTickTime = std::chrono::system_clock::now();

	std::chrono::duration<double> deltaDuration = currentTickTime - lastTickTime;
	float deltaTime = deltaDuration.count();
	lastTickTime = currentTickTime;

	deltaTime = fabs(deltaTime);

	// apply velocity
	location += velocity.y * deltaTime * forwardVector;
	location += velocity.x * deltaTime * glm::cross(forwardVector, upVector);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	if(needsRegenerate) regenerate();
	needsRegenerate = false;

	glBindVertexArray(vertArray);

	// render!
	glm::mat4 viewMat = glm::lookAt(location, location + forwardVector, upVector);
	glm::mat4 projectionMat = glm::perspective(50.f, 16.f / 10.f, .1f, 100.f);

	glm::mat4 MVPMat = projectionMat * viewMat;

	glm::vec4 a = MVPMat * glm::vec4(-62.8301315, 0.548247993, 51.5535278, 1);

	glUniformMatrix4fv(glGetUniformLocation(program, "MVP"), 1, GL_FALSE, &MVPMat[0][0]);

	glUseProgram(program);
	glBindBuffer(GL_ARRAY_BUFFER, vertLocs);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), nullptr);

	glBindBuffer(GL_ARRAY_BUFFER, colors);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), nullptr);

	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	glUniform1i(glGetUniformLocation(program, "isRender"), GL_FALSE);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicies);
	glDrawElements(GL_TRIANGLES, numElements, GL_UNSIGNED_INT, nullptr);

	glLineWidth(lineSize);
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	glUniform1i(glGetUniformLocation(program, "isRender"), GL_TRUE);

	if(lineSize != -1.f)
		glDrawElements(GL_TRIANGLES, numElements, GL_UNSIGNED_INT, nullptr);

	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);

	//std::vector<GLubyte> pixels(1920 * 1080 * 4);
	//glReadPixels(0, 0, 1920, 1080, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());

	//auto err = lodepng::encode("C:\\Users\\russe\\Documents\\Visual Studio 2015\\Projects\\WallPaperout.png", pixels, 1920, 1080, LCT_RGBA);
	//std::cout << lodepng_error_text(err) << std::endl;

	if(needsSave) save();
	needsSave = false;
}

void GLWidget::regenerate()
{
	std::array<float, 3> colorsToChooseFrom[] =
	{
		fromHex(0xda253900),
		fromHex(0x377ac800),
		fromHex(0x5d3da300),
	//	fromHex(0xe3903100),
	//	fromHex(0x7dbe3200),
	//	fromHex(0x38579900),
	//	fromHex(0x89619e00)
	};

	// generate colors
	std::vector<std::array<float, 3>>  colorsData(numVerts);

	std::random_device rd;
	std::mt19937 gen(rd());

	std::uniform_int_distribution<> distr(0, 2);

	for (std::array<float, 3>& color : colorsData)
	{

		color = colorsToChooseFrom[distr(gen)];
	}

	glBindBuffer(GL_ARRAY_BUFFER, colors);
	glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 3 * numVerts, colorsData.data());

}

void GLWidget::save()
{

}

<commit_msg>Work on saving -- currently I get an OGL error.<commit_after>#include "GLWidget.h"

#include "tiny_obj_loader.h"
#include "lodepng.h"

#include <iostream>
#include <vector>

#include <glm/gtx/transform.hpp>
#include <QApplication>

GLWidget::GLWidget ( QWidget* parent, Qt::WindowFlags f ) : QOpenGLWidget ( parent, f )
{

	setFocusPolicy(Qt::ClickFocus);

	connect(&time, &QTimer::timeout, [this]
		{
			this->update();
		});
	time.start(0);

	QSurfaceFormat format;
	format.setMajorVersion(3);
	format.setMinorVersion(3);

	format.setSamples(8);

	setFormat(format);

}

bool GLWidget::event (QEvent* event)
{

	switch(event->type())
	{
	case QEvent::Type::MouseButtonPress:
		{
			auto mousePressEvent = static_cast<QMouseEvent*>(event);
			if(mousePressEvent->button() == Qt::LeftButton)
			{
				isMouseDown = true;
				lastMousePos = { mousePressEvent->x(), mousePressEvent->y() };
				return true;
			}
		}
		break;
	case QEvent::Type::MouseButtonRelease:
		{
			auto mousePressEvent = static_cast<QMouseEvent*>(event);
			if(mousePressEvent->button() == Qt::LeftButton)
			{
				isMouseDown = false;
				return true;
			}
		}
		break;
	case QEvent::Type::MouseMove:
		{
			auto mousePressEvent = static_cast<QMouseEvent*>(event);
			if(isMouseDown)
			{
				glm::ivec2 currentMouse = { mousePressEvent->x(), mousePressEvent->y() };

				glm::ivec2 deltaMouse = currentMouse - lastMousePos;

				auto forVecIntX = glm::rotate((float)deltaMouse.x / 1000.f, glm::vec3{0.f, 0.f, 1.f}) * glm::vec4(forwardVector, 0.f);
				forwardVector = {forVecIntX.x, forVecIntX.y, forVecIntX.z};

				auto forVecIntY = glm::rotate(-(float)deltaMouse.y / 1000.f, glm::vec3{1.f, 0.f, 0.f}) * glm::vec4(forwardVector, 0.f);
				forwardVector = {forVecIntY.x, forVecIntY.y, forVecIntY.z};

				lastMousePos = currentMouse;

				return true;
			}
		}
		break;
	default: break;
	}

	return QOpenGLWidget::event(event);
}

std::array<float, 3> fromRGB(unsigned char r, unsigned char g, unsigned char b)
{
	return{ (float)r / 255.f, (float)g / 255.f, (float)b / 255.f };
}

void GLWidget::markForRegeneration()
{
	needsRegenerate = true;
}

void GLWidget::markForSave(const QString& saveDest)
{
	needsSave = true;
	savePath = saveDest;
}

std::array<float, 3> fromHex(uint32_t color)
{
 return fromRGB(color >> 24, color << 8 >> 24, color << 16 >> 24);
}

void GLWidget::keyPressEvent ( QKeyEvent* event )
{
	QWidget::keyPressEvent ( event );

	switch(event->key())
	{
	case Qt::Key_Q:
		velocity.z += speed; break;
	case Qt::Key_E:
		velocity.z -= speed; break;
	case Qt::Key_A:
		velocity.x += speed; break;
	case Qt::Key_D:
		velocity.x -= speed; break;
	case Qt::Key_W:
		velocity.y += speed; break;
	case Qt::Key_S:
		velocity.y -= speed; break;
	}

}

void GLWidget::keyReleaseEvent ( QKeyEvent* event )
{
	switch(event->key())
	{
	case Qt::Key_Q:
		velocity.z -= speed; break;
	case Qt::Key_E:
		velocity.z += speed; break;
	case Qt::Key_A:
		velocity.x -= speed; break;
	case Qt::Key_D:
		velocity.x += speed; break;
	case Qt::Key_W:
		velocity.y -= speed; break;
	case Qt::Key_S:
		velocity.y += speed; break;
	}
}

void GLWidget::initializeGL()
{
	QOpenGLWidget::initializeGL();

	initializeOpenGLFunctions();

	std::vector<tinyobj::shape_t> shapes;
	std::vector<tinyobj::material_t> mats;

	std::string error;

	// load model
	tinyobj::LoadObj(shapes, mats, error, "thing.obj");

	if (!shapes.size())
	{
		std::cout << error << std::endl;

		exit(-1);
	}

	tinyobj::mesh_t& mesh = shapes[0].mesh;

	numElements = mesh.indices.size();
	numVerts = mesh.positions.size() / 3;

	//setup buffer
	glGenVertexArrays(1, &vertArray);
	glBindVertexArray(vertArray);

	glGenBuffers(1, &vertLocs);
	glBindBuffer(GL_ARRAY_BUFFER, vertLocs);

	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * mesh.positions.size(), mesh.positions.data(), GL_STATIC_DRAW);

	glGenBuffers(1, &indicies);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicies);

	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * mesh.indices.size(), mesh.indices.data(), GL_STATIC_DRAW);

	glGenBuffers(1, &colors);
	glBindBuffer(GL_ARRAY_BUFFER, colors);

	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * mesh.positions.size(), 0, GL_STATIC_DRAW);
	regenerate();

	// load shader
	auto vertShader =
		"#version 330 core\n"
		"layout(location = 0) in vec3 vertLocationIn;\n"
		"layout(location = 1) in vec3 vertColors;\n"
		"uniform mat4 MVP;\n"
		"\n"
		"out vec3 color;\n"
		"\n"
		"void main()\n"
		"{\n"
		"	gl_Position = MVP * vec4(vertLocationIn, 1.f);\n"
		"	\n"
		"	color = vertColors;\n"
		"}\n";

	auto fragShader =
		"#version 330 core\n"
		"in vec3 color;\n"
		"uniform int isRender = 0;\n"
		"out vec3 fragColor;\n"
		"void main()\n"
		"{\n"
		"	fragColor = isRender != 0 ? vec3(.1f, .1f, .1f) : color;\n"
		"}\n";

	// Create the shaders
	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

	int32_t Result = GL_FALSE;
	int InfoLogLength;

	glShaderSource(vertexShader, 1, &vertShader, nullptr);
	glCompileShader(vertexShader);

	// Check Vertex Shader
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &Result);
	glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &InfoLogLength);
	if (InfoLogLength > 1) {
		auto VertexShaderErrorMessage = std::vector<char>(InfoLogLength + 1);
		glGetShaderInfoLog(vertexShader, InfoLogLength, nullptr, VertexShaderErrorMessage.data());
		std::cout << VertexShaderErrorMessage.data();
	}
	else
	{
		std::cout << "\tShader Successfully Compiled";
	}

	// Compile Fragment Shader
	glShaderSource(fragmentShader, 1, &fragShader, nullptr);
	glCompileShader(fragmentShader);

	// Check Fragment Shader
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &Result);
	glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &InfoLogLength);
	if (InfoLogLength > 1) {
		auto FragmentShaderErrorMessage = std::vector<char>(InfoLogLength + 1);
		glGetShaderInfoLog(fragmentShader, InfoLogLength, nullptr, FragmentShaderErrorMessage.data());
		std::cout << FragmentShaderErrorMessage.data();
	}
	else
	{
		std::cout << "\tShader Successfully Compiled";
	}

	// Link the program
	std::cout << "\tLinking program ";
	program = glCreateProgram();
	glAttachShader(program, vertexShader);
	glAttachShader(program, fragmentShader);
	glLinkProgram(program);

	// Check the program
	glGetProgramiv(program, GL_LINK_STATUS, &Result);
	glGetProgramiv(program, GL_INFO_LOG_LENGTH, &InfoLogLength);
	if (InfoLogLength > 1) {
		auto ProgramErrorMessage = std::vector<char>(InfoLogLength + 1);
		glGetProgramInfoLog(program, InfoLogLength, nullptr, ProgramErrorMessage.data());
		std::cout << ProgramErrorMessage.data();
	}

	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

	std::cout << "\tSuccessfully Linked Program.";

}

void GLWidget::paintGL()
{
	QOpenGLWidget::paintGL();

	std::chrono::time_point<std::chrono::system_clock> currentTickTime = std::chrono::system_clock::now();

	std::chrono::duration<double> deltaDuration = currentTickTime - lastTickTime;
	float deltaTime = deltaDuration.count();
	lastTickTime = currentTickTime;

	deltaTime = fabs(deltaTime);

	// apply velocity
	location += velocity.y * deltaTime * forwardVector;
	location += velocity.x * deltaTime * glm::cross(forwardVector, upVector);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	if(needsRegenerate) regenerate();
	needsRegenerate = false;

	glBindVertexArray(vertArray);

	// render!
	glm::mat4 viewMat = glm::lookAt(location, location + forwardVector, upVector);
	glm::mat4 projectionMat = glm::perspective(50.f, 16.f / 10.f, .1f, 100.f);

	glm::mat4 MVPMat = projectionMat * viewMat;

	glm::vec4 a = MVPMat * glm::vec4(-62.8301315, 0.548247993, 51.5535278, 1);

	glUniformMatrix4fv(glGetUniformLocation(program, "MVP"), 1, GL_FALSE, &MVPMat[0][0]);

	glUseProgram(program);
	glBindBuffer(GL_ARRAY_BUFFER, vertLocs);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), nullptr);

	glBindBuffer(GL_ARRAY_BUFFER, colors);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), nullptr);

	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	glUniform1i(glGetUniformLocation(program, "isRender"), GL_FALSE);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicies);
	glDrawElements(GL_TRIANGLES, numElements, GL_UNSIGNED_INT, nullptr);

	glLineWidth(lineSize);
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	glUniform1i(glGetUniformLocation(program, "isRender"), GL_TRUE);

	if(lineSize != -1.f)
		glDrawElements(GL_TRIANGLES, numElements, GL_UNSIGNED_INT, nullptr);

	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);

	if(needsSave) save();
	needsSave = false;

//	std::cout << std::hex << glGetError() << std::endl;
}

void GLWidget::regenerate()
{
	std::array<float, 3> colorsToChooseFrom[] =
	{
		fromHex(0xda253900),
		fromHex(0x377ac800),
		fromHex(0x5d3da300),
	//	fromHex(0xe3903100),
	//	fromHex(0x7dbe3200),
	//	fromHex(0x38579900),
	//	fromHex(0x89619e00)
	};

	// generate colors
	std::vector<std::array<float, 3>>  colorsData(numVerts);

	std::random_device rd;
	std::mt19937 gen(rd());

	std::uniform_int_distribution<> distr(0, 2);

	for (std::array<float, 3>& color : colorsData)
	{

		color = colorsToChooseFrom[distr(gen)];
	}

	glBindBuffer(GL_ARRAY_BUFFER, colors);
	glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 3 * numVerts, colorsData.data());

}

void GLWidget::save()
{
	std::vector<GLubyte> data(width() * height() * 4);

	//glReadBuffer(GL_FRONT);
	//glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data.data());

	//lodepng::encode(savePath.toStdString(), data.data(), width(), height(), LCT_RGBA, 8);

	std::cout  << glGetError() << std::endl;
}

<|endoftext|>


<commit_before>/*******************************
Copyright (C) 2013-2015 gregoire ANGERAND

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
**********************************/

#include "String.h"
#include "Array.h"
#include <string>
#include <iomanip>
#include <cstring>

namespace n {
namespace core {

typedef String::CounterType SCType;

N_FORCE_INLINE uint sizeForStrAlloc(uint s) {
	uint mod = s % sizeof(uint);
	return s + (mod ? sizeof(uint) - mod : 0);
}

N_FORCE_INLINE char *allocStr(SCType **count, uint s) {
	if(!s) {
		return 0;
	}
	uint allocSize = sizeForStrAlloc(s);
	byte *cptr = (byte *)malloc(allocSize + sizeof(uint) + sizeof(SCType));
	if((uint)cptr % sizeof(SCType)) {
		fatal("Unaligned alloc (this should not happen");
	}
	*count = new(cptr) SCType(1);
	new(cptr + sizeof(SCType)) uint(allocSize);

	return (char *)(cptr + sizeof(SCType) + sizeof(uint));
}

N_FORCE_INLINE void freeStr(SCType **count, char *) {
	if(!*count) {
		return;
	}
	((SCType *)(*count))->~SCType();
	free(*count);
}

N_FORCE_INLINE char *reallocStr(SCType **count, uint s) {
	if(!s) {
		freeStr(count, 0);
		*count = 0;
		return 0;
	}
	SCType *cptr = *count;
	if(!cptr) {
		return allocStr(count, s);
	}
	uint allocated = *(uint *)(cptr + 1);
	uint optAllocSize =  sizeForStrAlloc(s);
	if(s > allocated || allocated + 2 * sizeof(uint) < optAllocSize) {
		cptr = (SCType *)safeRealloc(cptr, optAllocSize + sizeof(uint) + sizeof(SCType));
		*(uint *)(cptr + 1) = optAllocSize;
	}
	*count = cptr;
	return (char *)(cptr + sizeof(SCType) + sizeof(uint));
}

String::String() : length(0), count(0), data(0) {
}

String::String(const char *cst) : String() {
	if(cst) {
		data = allocStr(&count, length = strlen(cst));//(char *)malloc(length * sizeof(char));
		memcpy(data, cst, length * sizeof(char));
	}
}

String::String(const char *cst, uint l) : length(l), count(0), data(0) {
	if(l) {
		data = allocStr(&count, length);//(char *)malloc(length * sizeof(char));
		if(cst) {
			memcpy(data, cst, length * sizeof(char));
		} else {
			*data = '\0';
		}
	}
}

String::String(const String &str) : length(str.length), count(str.count), data(str.data) {
	if(count) {
		++(*count);
	}
}

String::String(String &&str) : String() {
	swap(str);
}

String::~String() {
	if(data) {
		if(isUnique()) {
			freeStr(&count, data);
		} else {
			--(*count);
		}
	}
}

String::String(const String &str, uint beg, uint len) : length(len), count(str.count), data(str.data + beg) {
	if(count) {
		++(*count);
	}
}

void String::replace(const String &oldS, const String &newS) {
	operator=(replaced(oldS, newS));
}

void String::replace(uint beg, uint len, const String &newS) {
	uint ol = length;
	if(newS.size() > len) {
		detach(ol - len + newS.size());
		memmove(data + beg + newS.size(), data + beg + len, (ol - beg - len) * sizeof(char));
		memcpy(data + beg, newS.data, newS.length * sizeof(char));
	} else {
		memmove(data + beg + newS.size(), data + beg + len, (ol - beg - len) * sizeof(char));
		memcpy(data + beg, newS.data, newS.length * sizeof(char));
		detach(ol - len + newS.size());
	}
}

String String::replaced(const String &oldS, const String &newS) const {
	Array<String> concat;
	uint index = find(oldS);
	if(index != (uint)-1) {
		uint from = 0;
		uint offset = oldS.size();
		do {
			concat += subString(from, index - from);
			concat += newS;
			from = index + offset;
			index = find(oldS, from);
		} while(index != (uint)-1);
		concat += subString(from);
	} else {
		return *this;
	}
	return String(concat);
}

String String::replaced(uint beg, uint len, const String &newS) const {
	return String(Array<String>(subString(0, beg), newS, subString(beg + len)));
}

void String::clear() {
	detach(0);
}

uint String::size() const {
	return length;
}

bool String::isEmpty() const {
	return !length;
}

bool String::isNull() const {
	return !data;
}

char const *String::toChar() const {
	if(!data) {
		return (char *)&null;
	}
	detach(length + 1);
	length--;
	data[length] = '\0';
	return data;
}

uint String::find(char c, uint from) const {
	if(!(from < length)) {
		return -1;
	}
	for(uint i = from; i != length; i++) {
		if(data[i] == c) {
			return i;
		}
	}
	return -1;
}

uint String::find(const String &str, uint from) const {
	if(from + str.size() > length) {
		return -1;
	}
	for(uint i = from, l = length - str.length; i <= l; i++) {
		bool matched = true;
		for(uint j = 0; j != str.length; j++) {
			if(data[i + j] != str.data[j]) {
				matched = false;
				break;
			}
		}
		if(matched) {
			return i;
		}
	}
	return -1;
}

bool String::contains(char c) const {
	return find(c) < length;
}

bool String::contains(const String &str) const {
	return find(str) < length;
}

String String::subString(uint beg, uint len) const {
	if(!len) {
		return String();
	}
	return String(*this, beg, len);
}

String String::subString(uint beg) const {
	return subString(beg, length - beg);
}

bool String::beginWith(const String &s) const {
	if(length < s.length) {
		return false;
	}
	if(isNull()) {
		return s.isEmpty();
	}
	if(s.isEmpty()) {
		return true;
	}
	for(uint i = 0; i != s.length; i++) {
		if(data[i] != s.data[i]) {
			return false;
		}
	}
	return true;
}

bool String::endWith(const String &s) const {
	if(length < s.length) {
		return false;
	}
	if(isNull()) {
		return s.isEmpty();
	}
	if(s.isEmpty()) {
		return true;
	}
	uint offset = length - s.length;
	for(uint i = s.length - 1; i; i--) {
		if(data[offset + i] != s.data[i]) {
			return false;
		}
	}
	return true;
}

void String::detach() {
	detach(length);
}

void String::swap(String &str) {
	uint l = str.length;
	char *ch = str.data;
	SCType *c = str.count;
	str.length = length;
	str.data = data;
	str.count = count;
	count = c;
	data = ch;
	length = l;
}

Array<String> String::split(const String &str, bool empties) const {
	Array<String> arr;
	uint p = -1;
	uint from = 0;
	while((p = find(str, from)) != (uint)-1) {
		arr.append(subString(from, p - from));
		from = p + str.size();
	}
	arr.append(subString(from));
	return empties ? arr : arr.filtered([](const String &s) { return !s.isEmpty(); });
}

String String::toLower() const {
	return mapped([](char c) -> char { return tolower(c); });
}

String String::toUpper() const {
	return mapped([](char c) -> char { return toupper(c); });
}

std::string String::toStdString() const {
	return std::string(data, length);
}

String &String::operator+=(const String &s) {
	uint tl = length;
	uint ol = s.length;
	detach(tl + ol);
	memcpy(data + tl, s.data, ol * sizeof(char));
	return *this;
}

String String::operator+(const String &s) const {
	if(isEmpty()) {
		return s;
	}
	if(s.isEmpty()) {
		return *this;
	}
	String str(0, length + s.length);
	memcpy(str.data, data, length * sizeof(char));
	memcpy(str.data + length, s.data, s.length * sizeof(char));
	return str;
}

bool String::operator==(const String &str) const {
	if(str.length != length) {
		return false;
	}
	if(count && count == str.count) {
		return true;
	}
	for(uint i = 0; i != length; i++) {
		if(data[i] != str.data[i]) {
			return false;
		}
	}
	return true;
}

bool String::operator==(const char *str) const {
	for(uint i = 0; i != length; i++) {
		if(data[i] != str[i]) {
			return false;
		}
	}
	return true;
}

bool String::operator!=(const String &str) const {
	return !operator==(str);
}

bool String::operator!=(const char *str) const {
	return !operator==(str);
}

String &String::operator=(const String &s) {
	detach(0);
	data = s.data;
	count = s.count;
	length = s.length;
	if(count) {
		(*count)++;
	}
	return *this;
}

String &String::operator=(String &&s) {
	swap(s);
	return *this;
}

bool String::operator<(const String &s) const {
	if(data && s.data) {
		for(uint i = 0, min = std::min(length, s.length); i != min; i++) {
			if(data[i] < s.data[i]) {
				return true;
			} else if(data[i] > s.data[i]) {
				return false;
			}
		}
	}
	return length < s.length;
}

bool String::operator>(const String &s) const {
	if(data && s.data) {
		for(uint i = 0, min = std::min(length, s.length); i != min; i++) {
			if(data[i] > s.data[i]) {
				return true;
			} else if(data[i] < s.data[i]) {
				return false;
			}
		}
	}
	return length > s.length;
}

String::operator const char *() const {
	return toChar();
}

String::const_iterator String::begin() const {
	return data;
}

String::const_iterator String::end() const {
	return data + length;
}

uint String::getHash() const {
	return data ? hash(data, length) : hash(&null, 1);
}

void String::detach(uint s) const {
	if(s) {
		if(isUnique() && !isSharedSubset()) {
			data = reallocStr(&count, s);
		} else {
			--(*count);
			char *d = allocStr(&count, s);
			memcpy(d, data, std::min(length, s) * sizeof(char));
			data = d;
		}
	} else {
		if(isUnique()) {
			freeStr(&count, data);//free(data);
		}
		count = 0;
		data = 0;
	}
	length = s;
}

bool String::isUnique() const {
	return (!count || *count == 1);
}

bool String::isSharedSubset() const {
	return count && (char *)(count + 1)	!= data;
}

bool String::isShared() const {
	return count && *count > 1;
}

}
}

std::istream &operator>>(std::istream &s, n::core::String &str) {
	std::string st;
	s>>st;
	str = n::core::String(st.c_str());
	return s;
}

std::ostream &operator<<(std::ostream &s, const n::core::String &str) {
	s<<str.toStdString();
	return s;
}

<commit_msg>Fixed String offsets.<commit_after>/*******************************
Copyright (C) 2013-2015 gregoire ANGERAND

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
**********************************/

#include "String.h"
#include "Array.h"
#include <string>
#include <iomanip>
#include <cstring>

namespace n {
namespace core {

typedef String::CounterType SCType;

N_FORCE_INLINE uint sizeForStrAlloc(uint s) {
	uint mod = s % sizeof(uint);
	return s + (mod ? sizeof(uint) - mod : 0);
}

N_FORCE_INLINE char *allocStr(SCType **count, uint s) {
	if(!s) {
		return 0;
	}
	uint allocSize = sizeForStrAlloc(s);
	byte *cptr = (byte *)malloc(allocSize + sizeof(uint) + sizeof(SCType));
	if((uint)cptr % sizeof(SCType)) {
		fatal("Unaligned alloc (this should not happen");
	}
	*count = new(cptr) SCType(1);
	new(cptr + sizeof(SCType)) uint(allocSize);
	return (char *)(cptr + sizeof(SCType) + sizeof(uint));
}

N_FORCE_INLINE void freeStr(SCType **count, char *) {
	if(!*count) {
		return;
	}
	((SCType *)(*count))->~SCType();
	free(*count);
}

N_FORCE_INLINE char *reallocStr(SCType **count, uint s) {
	if(!s) {
		freeStr(count, 0);
		*count = 0;
		return 0;
	}
	SCType *cptr = *count;
	if(!cptr) {
		return allocStr(count, s);
	}
	uint allocated = *(uint *)(cptr + 1);
	uint optAllocSize =  sizeForStrAlloc(s);
	if(s > allocated || allocated + 2 * sizeof(uint) < optAllocSize) {
		cptr = (SCType *)safeRealloc(cptr, optAllocSize + sizeof(uint) + sizeof(SCType));
		*(uint *)(cptr + 1) = optAllocSize;
	}
	*count = cptr;
	return ((char *)cptr) + sizeof(SCType) + sizeof(uint);
}

String::String() : length(0), count(0), data(0) {
}

String::String(const char *cst) : String() {
	if(cst) {
		data = allocStr(&count, length = strlen(cst));//(char *)malloc(length * sizeof(char));
		memcpy(data, cst, length * sizeof(char));
	}
}

String::String(const char *cst, uint l) : length(l), count(0), data(0) {
	if(l) {
		data = allocStr(&count, length);//(char *)malloc(length * sizeof(char));
		if(cst) {
			memcpy(data, cst, length * sizeof(char));
		} else {
			*data = '\0';
		}
	}
}

String::String(const String &str) : length(str.length), count(str.count), data(str.data) {
	if(count) {
		++(*count);
	}
}

String::String(String &&str) : String() {
	swap(str);
}

String::~String() {
	if(data) {
		if(isUnique()) {
			freeStr(&count, data);
		} else {
			--(*count);
		}
	}
}

String::String(const String &str, uint beg, uint len) : length(len), count(str.count), data(str.data + beg) {
	if(count) {
		++(*count);
	}
}

void String::replace(const String &oldS, const String &newS) {
	operator=(replaced(oldS, newS));
}

void String::replace(uint beg, uint len, const String &newS) {
	uint ol = length;
	if(newS.size() > len) {
		detach(ol - len + newS.size());
		memmove(data + beg + newS.size(), data + beg + len, (ol - beg - len) * sizeof(char));
		memcpy(data + beg, newS.data, newS.length * sizeof(char));
	} else {
		memmove(data + beg + newS.size(), data + beg + len, (ol - beg - len) * sizeof(char));
		memcpy(data + beg, newS.data, newS.length * sizeof(char));
		detach(ol - len + newS.size());
	}
}

String String::replaced(const String &oldS, const String &newS) const {
	Array<String> concat;
	uint index = find(oldS);
	if(index != (uint)-1) {
		uint from = 0;
		uint offset = oldS.size();
		do {
			concat += subString(from, index - from);
			concat += newS;
			from = index + offset;
			index = find(oldS, from);
		} while(index != (uint)-1);
		concat += subString(from);
	} else {
		return *this;
	}
	return String(concat);
}

String String::replaced(uint beg, uint len, const String &newS) const {
	return String(Array<String>(subString(0, beg), newS, subString(beg + len)));
}

void String::clear() {
	detach(0);
}

uint String::size() const {
	return length;
}

bool String::isEmpty() const {
	return !length;
}

bool String::isNull() const {
	return !data;
}

char const *String::toChar() const {
	if(!data) {
		return (char *)&null;
	}
	detach(length + 1);
	length--;
	data[length] = '\0';
	return data;
}

uint String::find(char c, uint from) const {
	if(!(from < length)) {
		return -1;
	}
	for(uint i = from; i != length; i++) {
		if(data[i] == c) {
			return i;
		}
	}
	return -1;
}

uint String::find(const String &str, uint from) const {
	if(from + str.size() > length) {
		return -1;
	}
	for(uint i = from, l = length - str.length; i <= l; i++) {
		bool matched = true;
		for(uint j = 0; j != str.length; j++) {
			if(data[i + j] != str.data[j]) {
				matched = false;
				break;
			}
		}
		if(matched) {
			return i;
		}
	}
	return -1;
}

bool String::contains(char c) const {
	return find(c) < length;
}

bool String::contains(const String &str) const {
	return find(str) < length;
}

String String::subString(uint beg, uint len) const {
	if(!len) {
		return String();
	}
	return String(*this, beg, len);
}

String String::subString(uint beg) const {
	return subString(beg, length - beg);
}

bool String::beginWith(const String &s) const {
	if(length < s.length) {
		return false;
	}
	if(isNull()) {
		return s.isEmpty();
	}
	if(s.isEmpty()) {
		return true;
	}
	for(uint i = 0; i != s.length; i++) {
		if(data[i] != s.data[i]) {
			return false;
		}
	}
	return true;
}

bool String::endWith(const String &s) const {
	if(length < s.length) {
		return false;
	}
	if(isNull()) {
		return s.isEmpty();
	}
	if(s.isEmpty()) {
		return true;
	}
	uint offset = length - s.length;
	for(uint i = s.length - 1; i; i--) {
		if(data[offset + i] != s.data[i]) {
			return false;
		}
	}
	return true;
}

void String::detach() {
	detach(length);
}

void String::swap(String &str) {
	uint l = str.length;
	char *ch = str.data;
	SCType *c = str.count;
	str.length = length;
	str.data = data;
	str.count = count;
	count = c;
	data = ch;
	length = l;
}

Array<String> String::split(const String &str, bool empties) const {
	Array<String> arr;
	uint p = -1;
	uint from = 0;
	while((p = find(str, from)) != (uint)-1) {
		arr.append(subString(from, p - from));
		from = p + str.size();
	}
	arr.append(subString(from));
	return empties ? arr : arr.filtered([](const String &s) { return !s.isEmpty(); });
}

String String::toLower() const {
	return mapped([](char c) -> char { return tolower(c); });
}

String String::toUpper() const {
	return mapped([](char c) -> char { return toupper(c); });
}

std::string String::toStdString() const {
	return std::string(data, length);
}

String &String::operator+=(const String &s) {
	uint tl = length;
	uint ol = s.length;
	detach(tl + ol);
	memcpy(data + tl, s.data, ol * sizeof(char));
	return *this;
}

String String::operator+(const String &s) const {
	if(isEmpty()) {
		return s;
	}
	if(s.isEmpty()) {
		return *this;
	}
	String str(0, length + s.length);
	memcpy(str.data, data, length * sizeof(char));
	memcpy(str.data + length, s.data, s.length * sizeof(char));
	return str;
}

bool String::operator==(const String &str) const {
	if(str.length != length) {
		return false;
	}
	if(count && count == str.count) {
		return true;
	}
	for(uint i = 0; i != length; i++) {
		if(data[i] != str.data[i]) {
			return false;
		}
	}
	return true;
}

bool String::operator==(const char *str) const {
	for(uint i = 0; i != length; i++) {
		if(data[i] != str[i]) {
			return false;
		}
	}
	return true;
}

bool String::operator!=(const String &str) const {
	return !operator==(str);
}

bool String::operator!=(const char *str) const {
	return !operator==(str);
}

String &String::operator=(const String &s) {
	detach(0);
	data = s.data;
	count = s.count;
	length = s.length;
	if(count) {
		(*count)++;
	}
	return *this;
}

String &String::operator=(String &&s) {
	swap(s);
	return *this;
}

bool String::operator<(const String &s) const {
	if(data && s.data) {
		for(uint i = 0, min = std::min(length, s.length); i != min; i++) {
			if(data[i] < s.data[i]) {
				return true;
			} else if(data[i] > s.data[i]) {
				return false;
			}
		}
	}
	return length < s.length;
}

bool String::operator>(const String &s) const {
	if(data && s.data) {
		for(uint i = 0, min = std::min(length, s.length); i != min; i++) {
			if(data[i] > s.data[i]) {
				return true;
			} else if(data[i] < s.data[i]) {
				return false;
			}
		}
	}
	return length > s.length;
}

String::operator const char *() const {
	return toChar();
}

String::const_iterator String::begin() const {
	return data;
}

String::const_iterator String::end() const {
	return data + length;
}

uint String::getHash() const {
	return data ? hash(data, length) : hash(&null, 1);
}

void String::detach(uint s) const {
	if(s) {
		if(isUnique()) {
			data = reallocStr(&count, s);
		} else {
			--(*count);
			char *d = allocStr(&count, s);
			memcpy(d, data, std::min(length, s) * sizeof(char));
			data = d;
		}
	} else {
		if(isUnique()) {
			freeStr(&count, data);//free(data);
		}
		count = 0;
		data = 0;
	}
	length = s;
}

bool String::isUnique() const {
	return (!count || *count <= 1);
}

bool String::isSharedSubset() const {
	return count && ((char *)count) + sizeof(SCType) + sizeof(uint)	!= data;
}

bool String::isShared() const {
	return count && *count > 1;
}

}
}

std::istream &operator>>(std::istream &s, n::core::String &str) {
	std::string st;
	s>>st;
	str = n::core::String(st.c_str());
	return s;
}

std::ostream &operator<<(std::ostream &s, const n::core::String &str) {
	s<<str.toStdString();
	return s;
}

<|endoftext|>


<commit_before>//===-- AlphaTargetAsmInfo.cpp - Alpha asm properties -----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by James M. Laskey and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the AlphaTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//

#include "AlphaTargetAsmInfo.h"

using namespace llvm;

AlphaTargetAsmInfo::AlphaTargetAsmInfo(const AlphaTargetMachine &TM) {
  AlignmentIsInBytes = false;
  PrivateGlobalPrefix = "$";
  JumpTableDirective = ".gprel32";
}
<commit_msg>Set the jt section<commit_after>//===-- AlphaTargetAsmInfo.cpp - Alpha asm properties -----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by James M. Laskey and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the AlphaTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//

#include "AlphaTargetAsmInfo.h"

using namespace llvm;

AlphaTargetAsmInfo::AlphaTargetAsmInfo(const AlphaTargetMachine &TM) {
  AlignmentIsInBytes = false;
  PrivateGlobalPrefix = "$";
  JumpTableDirective = ".gprel32";
  JumpTableDataSection = "\t.section .rodata\n";
}
<|endoftext|>