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

#include "primitives/block.h"

#include "hash.h"
#include "tinyformat.h"
#include "utilstrencodings.h"
#include "crypto/common.h"

static const int HASH_MEMORY=128*1024;

#define ROTL(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
//note, this is 64 bytes
static inline void xor_salsa8(uint32_t B[16], const uint32_t Bx[16])
{
    uint32_t x00,x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15;
    int i;

    x00 = (B[ 0] ^= Bx[ 0]);
    x01 = (B[ 1] ^= Bx[ 1]);
    x02 = (B[ 2] ^= Bx[ 2]);
    x03 = (B[ 3] ^= Bx[ 3]);
    x04 = (B[ 4] ^= Bx[ 4]);
    x05 = (B[ 5] ^= Bx[ 5]);
    x06 = (B[ 6] ^= Bx[ 6]);
    x07 = (B[ 7] ^= Bx[ 7]);
    x08 = (B[ 8] ^= Bx[ 8]);
    x09 = (B[ 9] ^= Bx[ 9]);
    x10 = (B[10] ^= Bx[10]);
    x11 = (B[11] ^= Bx[11]);
    x12 = (B[12] ^= Bx[12]);
    x13 = (B[13] ^= Bx[13]);
    x14 = (B[14] ^= Bx[14]);
    x15 = (B[15] ^= Bx[15]);
    for (i = 0; i < 8; i += 2) {
        /* Operate on columns. */
        x04 ^= ROTL(x00 + x12,  7);  x09 ^= ROTL(x05 + x01,  7);
        x14 ^= ROTL(x10 + x06,  7);  x03 ^= ROTL(x15 + x11,  7);

        x08 ^= ROTL(x04 + x00,  9);  x13 ^= ROTL(x09 + x05,  9);
        x02 ^= ROTL(x14 + x10,  9);  x07 ^= ROTL(x03 + x15,  9);

        x12 ^= ROTL(x08 + x04, 13);  x01 ^= ROTL(x13 + x09, 13);
        x06 ^= ROTL(x02 + x14, 13);  x11 ^= ROTL(x07 + x03, 13);

        x00 ^= ROTL(x12 + x08, 18);  x05 ^= ROTL(x01 + x13, 18);
        x10 ^= ROTL(x06 + x02, 18);  x15 ^= ROTL(x11 + x07, 18);

        /* Operate on rows. */
        x01 ^= ROTL(x00 + x03,  7);  x06 ^= ROTL(x05 + x04,  7);
        x11 ^= ROTL(x10 + x09,  7);  x12 ^= ROTL(x15 + x14,  7);

        x02 ^= ROTL(x01 + x00,  9);  x07 ^= ROTL(x06 + x05,  9);
        x08 ^= ROTL(x11 + x10,  9);  x13 ^= ROTL(x12 + x15,  9);

        x03 ^= ROTL(x02 + x01, 13);  x04 ^= ROTL(x07 + x06, 13);
        x09 ^= ROTL(x08 + x11, 13);  x14 ^= ROTL(x13 + x12, 13);

        x00 ^= ROTL(x03 + x02, 18);  x05 ^= ROTL(x04 + x07, 18);
        x10 ^= ROTL(x09 + x08, 18);  x15 ^= ROTL(x14 + x13, 18);
    }
    B[ 0] += x00;
    B[ 1] += x01;
    B[ 2] += x02;
    B[ 3] += x03;
    B[ 4] += x04;
    B[ 5] += x05;
    B[ 6] += x06;
    B[ 7] += x07;
    B[ 8] += x08;
    B[ 9] += x09;
    B[10] += x10;
    B[11] += x11;
    B[12] += x12;
    B[13] += x13;
    B[14] += x14;
    B[15] += x15;
}

uint256 CBlockHeader::GetHash() const
{
    int BLOCK_HEADER_SIZE=80;
  //TODO: definitely not endian safe
    uint8_t data[BLOCK_HEADER_SIZE];
    WriteLE32(&data[0], nVersion);
    memcpy(&data[4], hashPrevBlock.begin(), hashPrevBlock.size());
    memcpy(&data[36], hashMerkleRoot.begin(), hashMerkleRoot.size());
    WriteLE32(&data[68], nTime);
    WriteLE32(&data[72], nBits);
    WriteLE32(&data[76], nNonce);

    //could probably cache this so that we can skip hash generation when the first sha256 hash matches
    uint8_t *hashbuffer = new uint8_t[HASH_MEMORY]; //don't allocate this on stack, since it's huge..
    //allocating on heap adds hardly any overhead on Linux
    int size=HASH_MEMORY;
    CSHA256 sha;
    memset(hashbuffer, 0, 64); //HASH_MEMORY);
    sha.Reset().Write(data, BLOCK_HEADER_SIZE).Finalize(&hashbuffer[0]);
    for (int i = 64; i < size-32; i+=32)
    {
        //i-4 because we use integers for all references against this, and we don't want to go 3 bytes over the defined area
        int randmax = i-4; //we could use size here, but then it's probable to use 0 as the value in most cases
        uint32_t joint[16];
        uint32_t randbuffer[16];
        assert(i-32>0);
        assert(i<size);
        uint32_t randseed[16];
        assert(sizeof(int)*16 == 64);

        //setup randbuffer to be an array of random indexes
        memcpy(randseed, &hashbuffer[i-64], 64);
        if(i>128)
        {
            memcpy(randbuffer, &hashbuffer[i-128], 64);
        }else
        {
            memset(&randbuffer, 0, 64);
        }
        xor_salsa8(randbuffer, randseed);

        memcpy(joint, &hashbuffer[i-32], 32);
        //use the last hash value as the seed
        for (int j = 32; j < 64; j+=4)
        {
            assert((j - 32) / 2 < 16);
            //every other time, change to next random index
            uint32_t rand = randbuffer[(j - 32)/4] % (randmax-32); //randmax - 32 as otherwise we go beyond memory that's already been written to
            assert(j>0 && j<64);
            assert(rand<size);
            assert(j/2 < 64);
            joint[j/4] = *((uint32_t*)&hashbuffer[rand]);
        }
        assert(i>=0 && i+32<size);
        sha.Reset().Write((uint8_t*) joint, 64).Finalize(&hashbuffer[i]);

        //setup randbuffer to be an array of random indexes
        memcpy(randseed, &hashbuffer[i-32], 64); //use last hash value and previous hash value(post-mixing)
        if(i>128)
        {
            memcpy(randbuffer, &hashbuffer[i-128], 64);
        }else
        {
            memset(randbuffer, 0, 64);
        }
        xor_salsa8(randbuffer, randseed);

        //use the last hash value as the seed
        for (int j = 0; j < 32; j+=2)
        {
            assert(j/4 < 16);
            uint32_t rand = randbuffer[j/2] % randmax;
            assert(rand < size);
            assert((j/4)+i >= 0 && (j/4)+i < size);
            assert(j + i -4 < i + 32); //assure we dont' access beyond the hash
            *((uint32_t*)&hashbuffer[rand]) = *((uint32_t*)&hashbuffer[j + i - 4]);
        }
    }
    //note: off-by-one error is likely here...
    for (int i = size-64-1; i >= 64; i -= 64)
    {
      assert(i-64 >= 0);
      assert(i+64<size);
        sha.Reset().Write(&hashbuffer[i], 64).Finalize(&hashbuffer[i-64]);
     }
    uint256 output;
    memcpy((unsigned char*)&output, &hashbuffer[0], 32);
    delete[] hashbuffer;
    return output;
}

uint256 CBlock::BuildMerkleTree(bool* fMutated) const
{
    /* WARNING! If you're reading this because you're learning about crypto
       and/or designing a new system that will use merkle trees, keep in mind
       that the following merkle tree algorithm has a serious flaw related to
       duplicate txids, resulting in a vulnerability (CVE-2012-2459).

       The reason is that if the number of hashes in the list at a given time
       is odd, the last one is duplicated before computing the next level (which
       is unusual in Merkle trees). This results in certain sequences of
       transactions leading to the same merkle root. For example, these two
       trees:

                    A               A
                  /  \            /   \
                B     C         B       C
               / \    |        / \     / \
              D   E   F       D   E   F   F
             / \ / \ / \     / \ / \ / \ / \
             1 2 3 4 5 6     1 2 3 4 5 6 5 6

       for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
       6 are repeated) result in the same root hash A (because the hash of both
       of (F) and (F,F) is C).

       The vulnerability results from being able to send a block with such a
       transaction list, with the same merkle root, and the same block hash as
       the original without duplication, resulting in failed validation. If the
       receiving node proceeds to mark that block as permanently invalid
       however, it will fail to accept further unmodified (and thus potentially
       valid) versions of the same block. We defend against this by detecting
       the case where we would hash two identical hashes at the end of the list
       together, and treating that identically to the block having an invalid
       merkle root. Assuming no double-SHA256 collisions, this will detect all
       known ways of changing the transactions without affecting the merkle
       root.
    */
    vMerkleTree.clear();
    vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
    for (std::vector<CTransaction>::const_iterator it(vtx.begin()); it != vtx.end(); ++it)
        vMerkleTree.push_back(it->GetHash());
    int j = 0;
    bool mutated = false;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        for (int i = 0; i < nSize; i += 2)
        {
            int i2 = std::min(i+1, nSize-1);
            if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) {
                // Two identical hashes at the end of the list at a particular level.
                mutated = true;
            }
            vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),
                                       BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
        }
        j += nSize;
    }
    if (fMutated) {
        *fMutated = mutated;
    }
    return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
}

std::vector<uint256> CBlock::GetMerkleBranch(int nIndex) const
{
    if (vMerkleTree.empty())
        BuildMerkleTree();
    std::vector<uint256> vMerkleBranch;
    int j = 0;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        int i = std::min(nIndex^1, nSize-1);
        vMerkleBranch.push_back(vMerkleTree[j+i]);
        nIndex >>= 1;
        j += nSize;
    }
    return vMerkleBranch;
}

uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
{
    if (nIndex == -1)
        return 0;
    for (std::vector<uint256>::const_iterator it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it)
    {
        if (nIndex & 1)
            hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
        else
            hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
        nIndex >>= 1;
    }
    return hash;
}

std::string CBlock::ToString() const
{
    std::stringstream s;
    s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
        GetHash().ToString(),
        nVersion,
        hashPrevBlock.ToString(),
        hashMerkleRoot.ToString(),
        nTime, nBits, nNonce,
        vtx.size());
    for (unsigned int i = 0; i < vtx.size(); i++)
    {
        s << "  " << vtx[i].ToString() << "\n";
    }
    s << "  vMerkleTree: ";
    for (unsigned int i = 0; i < vMerkleTree.size(); i++)
        s << " " << vMerkleTree[i].ToString();
    s << "\n";
    return s.str();
}
<commit_msg>update block hash to be more optimized and eliminate no-ops<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "primitives/block.h"

#include "hash.h"
#include "tinyformat.h"
#include "utilstrencodings.h"
#include "crypto/common.h"

static const int HASH_MEMORY=128*1024;

#define ROTL(a, b) (((a) << (b)) | ((a) >> (32 - (b))))
//note, this is 64 bytes
static inline void xor_salsa8(uint32_t B[16], const uint32_t Bx[16])
{
    uint32_t x00,x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15;
    int i;

    x00 = (B[ 0] ^= Bx[ 0]);
    x01 = (B[ 1] ^= Bx[ 1]);
    x02 = (B[ 2] ^= Bx[ 2]);
    x03 = (B[ 3] ^= Bx[ 3]);
    x04 = (B[ 4] ^= Bx[ 4]);
    x05 = (B[ 5] ^= Bx[ 5]);
    x06 = (B[ 6] ^= Bx[ 6]);
    x07 = (B[ 7] ^= Bx[ 7]);
    x08 = (B[ 8] ^= Bx[ 8]);
    x09 = (B[ 9] ^= Bx[ 9]);
    x10 = (B[10] ^= Bx[10]);
    x11 = (B[11] ^= Bx[11]);
    x12 = (B[12] ^= Bx[12]);
    x13 = (B[13] ^= Bx[13]);
    x14 = (B[14] ^= Bx[14]);
    x15 = (B[15] ^= Bx[15]);
    for (i = 0; i < 8; i += 2) {
        /* Operate on columns. */
        x04 ^= ROTL(x00 + x12,  7);  x09 ^= ROTL(x05 + x01,  7);
        x14 ^= ROTL(x10 + x06,  7);  x03 ^= ROTL(x15 + x11,  7);

        x08 ^= ROTL(x04 + x00,  9);  x13 ^= ROTL(x09 + x05,  9);
        x02 ^= ROTL(x14 + x10,  9);  x07 ^= ROTL(x03 + x15,  9);

        x12 ^= ROTL(x08 + x04, 13);  x01 ^= ROTL(x13 + x09, 13);
        x06 ^= ROTL(x02 + x14, 13);  x11 ^= ROTL(x07 + x03, 13);

        x00 ^= ROTL(x12 + x08, 18);  x05 ^= ROTL(x01 + x13, 18);
        x10 ^= ROTL(x06 + x02, 18);  x15 ^= ROTL(x11 + x07, 18);

        /* Operate on rows. */
        x01 ^= ROTL(x00 + x03,  7);  x06 ^= ROTL(x05 + x04,  7);
        x11 ^= ROTL(x10 + x09,  7);  x12 ^= ROTL(x15 + x14,  7);

        x02 ^= ROTL(x01 + x00,  9);  x07 ^= ROTL(x06 + x05,  9);
        x08 ^= ROTL(x11 + x10,  9);  x13 ^= ROTL(x12 + x15,  9);

        x03 ^= ROTL(x02 + x01, 13);  x04 ^= ROTL(x07 + x06, 13);
        x09 ^= ROTL(x08 + x11, 13);  x14 ^= ROTL(x13 + x12, 13);

        x00 ^= ROTL(x03 + x02, 18);  x05 ^= ROTL(x04 + x07, 18);
        x10 ^= ROTL(x09 + x08, 18);  x15 ^= ROTL(x14 + x13, 18);
    }
    B[ 0] += x00;
    B[ 1] += x01;
    B[ 2] += x02;
    B[ 3] += x03;
    B[ 4] += x04;
    B[ 5] += x05;
    B[ 6] += x06;
    B[ 7] += x07;
    B[ 8] += x08;
    B[ 9] += x09;
    B[10] += x10;
    B[11] += x11;
    B[12] += x12;
    B[13] += x13;
    B[14] += x14;
    B[15] += x15;
}

uint256 CBlockHeader::GetHash() const
{
    int BLOCK_HEADER_SIZE=80;
  //TODO: definitely not endian safe
    uint8_t data[BLOCK_HEADER_SIZE];
    WriteLE32(&data[0], nVersion);
    memcpy(&data[4], hashPrevBlock.begin(), hashPrevBlock.size());
    memcpy(&data[36], hashMerkleRoot.begin(), hashMerkleRoot.size());
    WriteLE32(&data[68], nTime);
    WriteLE32(&data[72], nBits);
    WriteLE32(&data[76], nNonce);

    //could probably cache this so that we can skip hash generation when the first sha256 hash matches
    uint8_t *hashbuffer = new uint8_t[HASH_MEMORY]; //don't allocate this on stack, since it's huge..
    //allocating on heap adds hardly any overhead on Linux
    int size=HASH_MEMORY;
    CSHA256 sha;
    memset(hashbuffer, 0, 64); //HASH_MEMORY);
    sha.Reset().Write(data, BLOCK_HEADER_SIZE).Finalize(&hashbuffer[0]);
    for (int i = 64; i < size-32; i+=32)
    {
        //i-4 because we use integers for all references against this, and we don't want to go 3 bytes over the defined area
        int randmax = i-4; //we could use size here, but then it's probable to use 0 as the value in most cases
        uint32_t joint[16];
        uint32_t randbuffer[16];
        assert(i-32>0);
        assert(i<size);
        uint32_t randseed[16];
        assert(sizeof(int)*16 == 64);

        //setup randbuffer to be an array of random indexes
        memcpy(randseed, &hashbuffer[i-64], 64);
        if(i>128)
        {
            memcpy(randbuffer, &hashbuffer[i-128], 64);
        }else
        {
            memset(&randbuffer, 0, 64);
        }
        xor_salsa8(randbuffer, randseed);

        memcpy(joint, &hashbuffer[i-32], 32);
        //use the last hash value as the seed
        for (int j = 32; j < 64; j+=4)
        {
            assert((j - 32) / 2 < 16);
            //every other time, change to next random index
            uint32_t rand = randbuffer[(j - 32)/4] % (randmax-32); //randmax - 32 as otherwise we go beyond memory that's already been written to
            assert(j>0 && j<64);
            assert(rand<size);
            assert(j/2 < 64);
            joint[j/4] = *((uint32_t*)&hashbuffer[rand]);
        }
        assert(i>=0 && i+32<size);
        sha.Reset().Write((uint8_t*) joint, 64).Finalize(&hashbuffer[i]);

        //setup randbuffer to be an array of random indexes
        memcpy(randseed, &hashbuffer[i-32], 64); //use last hash value and previous hash value(post-mixing)
        if(i>128)
        {
            memcpy(randbuffer, &hashbuffer[i-128], 64);
        }else
        {
            memset(randbuffer, 0, 64);
        }
        xor_salsa8(randbuffer, randseed);

        //use the last hash value as the seed
        for (int j = 0; j < 32; j+=2)
        {
            assert(j/4 < 16);
            uint32_t rand = randbuffer[j/2] % randmax;
            assert(rand < size);
            assert((j/4)+i >= 0 && (j/4)+i < size);
            assert(j + i -4 < i + 32); //assure we dont' access beyond the hash
            *((uint32_t*)&hashbuffer[rand]) = *((uint32_t*)&hashbuffer[j + i - 4]);
        }
    }
    //note: off-by-one error is likely here...
    /** bugged.. actually a no-op
    for (int i = size-64-1; i >= 64; i -= 64)
    {
      assert(i-64 >= 0);
      assert(i+64<size);
        sha.Reset().Write(&hashbuffer[i], 64).Finalize(&hashbuffer[i-64]);
     }
     */
    uint256 output;
    memcpy((unsigned char*)&output, &hashbuffer[0], 32);
    delete[] hashbuffer;
    return output;
}

uint256 CBlock::BuildMerkleTree(bool* fMutated) const
{
    /* WARNING! If you're reading this because you're learning about crypto
       and/or designing a new system that will use merkle trees, keep in mind
       that the following merkle tree algorithm has a serious flaw related to
       duplicate txids, resulting in a vulnerability (CVE-2012-2459).

       The reason is that if the number of hashes in the list at a given time
       is odd, the last one is duplicated before computing the next level (which
       is unusual in Merkle trees). This results in certain sequences of
       transactions leading to the same merkle root. For example, these two
       trees:

                    A               A
                  /  \            /   \
                B     C         B       C
               / \    |        / \     / \
              D   E   F       D   E   F   F
             / \ / \ / \     / \ / \ / \ / \
             1 2 3 4 5 6     1 2 3 4 5 6 5 6

       for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
       6 are repeated) result in the same root hash A (because the hash of both
       of (F) and (F,F) is C).

       The vulnerability results from being able to send a block with such a
       transaction list, with the same merkle root, and the same block hash as
       the original without duplication, resulting in failed validation. If the
       receiving node proceeds to mark that block as permanently invalid
       however, it will fail to accept further unmodified (and thus potentially
       valid) versions of the same block. We defend against this by detecting
       the case where we would hash two identical hashes at the end of the list
       together, and treating that identically to the block having an invalid
       merkle root. Assuming no double-SHA256 collisions, this will detect all
       known ways of changing the transactions without affecting the merkle
       root.
    */
    vMerkleTree.clear();
    vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
    for (std::vector<CTransaction>::const_iterator it(vtx.begin()); it != vtx.end(); ++it)
        vMerkleTree.push_back(it->GetHash());
    int j = 0;
    bool mutated = false;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        for (int i = 0; i < nSize; i += 2)
        {
            int i2 = std::min(i+1, nSize-1);
            if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) {
                // Two identical hashes at the end of the list at a particular level.
                mutated = true;
            }
            vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),
                                       BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
        }
        j += nSize;
    }
    if (fMutated) {
        *fMutated = mutated;
    }
    return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
}

std::vector<uint256> CBlock::GetMerkleBranch(int nIndex) const
{
    if (vMerkleTree.empty())
        BuildMerkleTree();
    std::vector<uint256> vMerkleBranch;
    int j = 0;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        int i = std::min(nIndex^1, nSize-1);
        vMerkleBranch.push_back(vMerkleTree[j+i]);
        nIndex >>= 1;
        j += nSize;
    }
    return vMerkleBranch;
}

uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
{
    if (nIndex == -1)
        return 0;
    for (std::vector<uint256>::const_iterator it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it)
    {
        if (nIndex & 1)
            hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
        else
            hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
        nIndex >>= 1;
    }
    return hash;
}

std::string CBlock::ToString() const
{
    std::stringstream s;
    s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
        GetHash().ToString(),
        nVersion,
        hashPrevBlock.ToString(),
        hashMerkleRoot.ToString(),
        nTime, nBits, nNonce,
        vtx.size());
    for (unsigned int i = 0; i < vtx.size(); i++)
    {
        s << "  " << vtx[i].ToString() << "\n";
    }
    s << "  vMerkleTree: ";
    for (unsigned int i = 0; i < vMerkleTree.size(); i++)
        s << " " << vMerkleTree[i].ToString();
    s << "\n";
    return s.str();
}
<|endoftext|>


<commit_before>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if !defined(REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680)
#define REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680

#include <xalanc/PlatformSupport/ArenaBlockBase.hpp>

XALAN_CPP_NAMESPACE_BEGIN

template<bool> struct CompileTimeError;

template<> struct CompileTimeError<true>{};

#define XALAN_STATIC_CHECK(expr) CompileTimeError<bool(expr)>()

template <class ObjectType,
#if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS)
		 class size_Type>
#else
		 class size_Type  = unsigned short >
#endif

class ReusableArenaBlock : public ArenaBlockBase<ObjectType, size_Type>
{

public:

	typedef ArenaBlockBase<ObjectType, size_Type>	BaseClassType;

	typedef typename BaseClassType::size_type		size_type;

	struct NextBlock
	{
        enum { VALID_OBJECT_STAMP = 0xffddffdd };

		size_type		next;
		const int		verificationStamp;

		NextBlock( size_type _next):
			next(_next),
			verificationStamp(VALID_OBJECT_STAMP)
		{
		}

		bool
		isValidFor( size_type  rightBorder ) const
		{
			return ( ( verificationStamp == VALID_OBJECT_STAMP ) &&
				( next <= rightBorder ) ) ? true : false ;
		}
	};

	/*
	 * Construct an ArenaBlock of the specified size
	 * of objects.
	 *
	 * @param theBlockSize The size of the block (the number of objects it can contain).
	 */
	ReusableArenaBlock(size_type	theBlockSize) :
		BaseClassType(theBlockSize),
		m_firstFreeBlock(0),
		m_nextFreeBlock(0)

	{
		XALAN_STATIC_CHECK(sizeof(ObjectType) >= sizeof(NextBlock));

		for( size_type i = 0; i < this->m_blockSize; ++i )
		{
			new ( reinterpret_cast<NextBlock*>(&(this->m_objectBlock[i])) ) NextBlock( (size_type)(i + 1) );
		}
	}

	~ReusableArenaBlock()
	{
		size_type removedObjects = 0;

		NextBlock* pStruct = 0;

		for ( size_type i = 0 ; i < this->m_blockSize && (removedObjects < this->m_objectCount) ; ++i )
		{
			pStruct = reinterpret_cast<NextBlock*>(&(this->m_objectBlock[i]));

			if ( isOccupiedBlock(pStruct) )
			{
				this->m_objectBlock[i].~ObjectType();

				++removedObjects;
			}
		}
	}

	/*
	 * Allocate a block.  Once the object is constructed, you must call
	 * commitAllocation().
	 *
	 * @return a pointer to the new block.
	 */
	ObjectType*
	allocateBlock()
	{
		if ( this->m_objectCount == this->m_blockSize )
		{
			assert ( this->m_firstFreeBlock == (this->m_blockSize + 1) );

			return 0;
		}
		else
		{
			assert( this->m_objectCount < this->m_blockSize );

			ObjectType*		theResult = 0;

			assert ( this->m_firstFreeBlock <= this->m_blockSize );
			assert ( this->m_nextFreeBlock <= this->m_blockSize );

			// check if any part was allocated but not commited
			if( this->m_firstFreeBlock != this->m_nextFreeBlock)
			{
				// return then againg the previouse allocated block and wait for commitment
				theResult = this->m_objectBlock + this->m_firstFreeBlock;
			}
			else
			{
				theResult = this->m_objectBlock + this->m_firstFreeBlock;

				assert(size_type( theResult - this->m_objectBlock ) < this->m_blockSize);

				this->m_nextFreeBlock = (reinterpret_cast<NextBlock*>(theResult))->next;

				assert ( ( reinterpret_cast<NextBlock*>(theResult ))->isValidFor( this->m_blockSize ) );
				assert ( this->m_nextFreeBlock <= this->m_blockSize );

				++this->m_objectCount;
			}

			return theResult;
		}
	}

	/*
	 * Commit the previous allocation.
	 *
	 * @param theBlock the address that was returned by allocateBlock()
	 */
	void
	commitAllocation(ObjectType* /*	theBlock */)
	{
		this->m_firstFreeBlock = this->m_nextFreeBlock;

		assert ( this->m_objectCount <= this->m_blockSize );
	}

	/*
	 * Destroy the object, and return the block to the free list.
	 * The behavior is undefined if the object pointed to is not
	 * owned by the block.
	 *
	 * @param theObject the address of the object.
	 */
	void
	destroyObject(ObjectType*	theObject)
	{
		// check if any uncommited block is there, add it to the list
		if ( this->m_firstFreeBlock != this->m_nextFreeBlock )
		{
			// return it to pull of the free blocks
			void* const     p = this->m_objectBlock + this->m_firstFreeBlock;

			new (p) NextBlock(this->m_nextFreeBlock);

			this->m_nextFreeBlock = this->m_firstFreeBlock;
		}

		assert(ownsObject(theObject) == true);
		assert(shouldDestroyBlock(theObject));

		theObject->~ObjectType();

		new (theObject) NextBlock(this->m_firstFreeBlock);

		m_firstFreeBlock = this->m_nextFreeBlock = size_type(theObject - this->m_objectBlock);

		assert (this->m_firstFreeBlock <= this->m_blockSize);

		--this->m_objectCount;
	}

	/*
	 * Determine if this block owns the specified object.  Note
	 * that even if the object address is within our block, this
	 * call will return false if no object currently occupies the
	 * block.  See also ownsBlock().
	 *
	 * @param theObject the address of the object.
	 * @return true if we own the object, false if not.
	 */
	bool
	ownsObject(const ObjectType*	theObject) const
	{
		assert ( theObject != 0 );

		return isOccupiedBlock( reinterpret_cast<const NextBlock*>(theObject) );
	}

protected:

	/*
	 * Determine if the block should be destroyed.  Returns true,
	 * unless the object is on the free list.  The behavior is
	 * undefined if the object pointed to is not owned by the
	 * block.
	 *
	 * @param theObject the address of the object
	 * @return true if block should be destroyed, false if not.
	 */
	bool
	shouldDestroyBlock(const ObjectType*	theObject) const
	{
		assert( size_type(theObject - this->m_objectBlock) < this->m_blockSize);

        return !isOnFreeList(theObject);
	}

	bool
	isOccupiedBlock(const NextBlock*    block)const
	{
		assert( block !=0 );

		return !( ownsBlock(reinterpret_cast<const ObjectType*>(block)) && block->isValidFor(this->m_blockSize) );
	}

private:

	// Not implemented...
	ReusableArenaBlock(const ReusableArenaBlock<ObjectType>&);

	ReusableArenaBlock<ObjectType>&
	operator=(const ReusableArenaBlock<ObjectType>&);

	bool
	operator==(const ReusableArenaBlock<ObjectType>&) const;

	/*
	 * Determine if the block is on the free list.  The behavior is
	 * undefined if the object pointed to is not owned by the
	 * block.
	 *
	 * @param theObject the address of the object
	 * @return true if block is on the free list, false if not.
	 */
	bool
	isOnFreeList(const ObjectType*	theObject) const
	{
		if ( this->m_objectCount == 0 )
		{
			return false;
		}
		else
		{
			ObjectType*     pRunPtr = this->m_objectBlock + this->m_firstFreeBlock;

			for ( size_type i = 0; i < (this->m_blockSize - this->m_objectCount); ++i)
			{
				assert ( ownsBlock( pRunPtr ) );

				if (pRunPtr == theObject)
				{
					return true;
				}
				else
				{
					NextBlock* const    p = reinterpret_cast<NextBlock*>(pRunPtr);

					assert( p->isValidFor( this->m_blockSize ) );

					pRunPtr = this->m_objectBlock + p->next;
				}
			}

			return false;
		}
	}

    // Data members...
	size_type   m_firstFreeBlock;

	size_type	m_nextFreeBlock;
};

XALAN_CPP_NAMESPACE_END

#endif	// !defined(REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680)
<commit_msg>Fixed use of typedef and signed/unsigned mismatch.<commit_after>/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if !defined(REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680)
#define REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680

#include <xalanc/PlatformSupport/ArenaBlockBase.hpp>

XALAN_CPP_NAMESPACE_BEGIN

template<bool> struct CompileTimeError;

template<> struct CompileTimeError<true>{};

#define XALAN_STATIC_CHECK(expr) CompileTimeError<bool(expr)>()

template <class ObjectType,
#if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS)
		 class size_Type>
#else
		 class size_Type  = unsigned short >
#endif

class ReusableArenaBlock : public ArenaBlockBase<ObjectType, size_Type>
{

public:

	typedef ArenaBlockBase<ObjectType, size_Type>	BaseClassType;

	typedef typename BaseClassType::size_type		size_type;

	struct NextBlock
	{
        enum { VALID_OBJECT_STAMP = 0xffddffdd };

		size_type		next;
		const int		verificationStamp;

		NextBlock( size_type _next):
			next(_next),
			verificationStamp(VALID_OBJECT_STAMP)
		{
		}

		bool
		isValidFor( size_type  rightBorder ) const
		{
			return ( ( verificationStamp == size_type(VALID_OBJECT_STAMP)) &&
				( next <= rightBorder ) ) ? true : false ;
		}
	};

	/*
	 * Construct an ArenaBlock of the specified size
	 * of objects.
	 *
	 * @param theBlockSize The size of the block (the number of objects it can contain).
	 */
	ReusableArenaBlock(size_type	theBlockSize) :
		BaseClassType(theBlockSize),
		m_firstFreeBlock(0),
		m_nextFreeBlock(0)

	{
		XALAN_STATIC_CHECK(sizeof(ObjectType) >= sizeof(NextBlock));

		for( size_type i = 0; i < this->m_blockSize; ++i )
		{
			new ( reinterpret_cast<NextBlock*>(&(this->m_objectBlock[i])) ) NextBlock( (size_type)(i + 1) );
		}
	}

	~ReusableArenaBlock()
	{
		size_type removedObjects = 0;

		NextBlock* pStruct = 0;

		for ( size_type i = 0 ; i < this->m_blockSize && (removedObjects < this->m_objectCount) ; ++i )
		{
			pStruct = reinterpret_cast<NextBlock*>(&(this->m_objectBlock[i]));

			if ( isOccupiedBlock(pStruct) )
			{
				this->m_objectBlock[i].~ObjectType();

				++removedObjects;
			}
		}
	}

	/*
	 * Allocate a block.  Once the object is constructed, you must call
	 * commitAllocation().
	 *
	 * @return a pointer to the new block.
	 */
	ObjectType*
	allocateBlock()
	{
		if ( this->m_objectCount == this->m_blockSize )
		{
			assert ( this->m_firstFreeBlock == (this->m_blockSize + 1) );

			return 0;
		}
		else
		{
			assert( this->m_objectCount < this->m_blockSize );

			ObjectType*		theResult = 0;

			assert ( this->m_firstFreeBlock <= this->m_blockSize );
			assert ( this->m_nextFreeBlock <= this->m_blockSize );

			// check if any part was allocated but not commited
			if( this->m_firstFreeBlock != this->m_nextFreeBlock)
			{
				// return then againg the previouse allocated block and wait for commitment
				theResult = this->m_objectBlock + this->m_firstFreeBlock;
			}
			else
			{
				theResult = this->m_objectBlock + this->m_firstFreeBlock;

				assert(size_type( theResult - this->m_objectBlock ) < this->m_blockSize);

				this->m_nextFreeBlock = (reinterpret_cast<NextBlock*>(theResult))->next;

				assert ( ( reinterpret_cast<NextBlock*>(theResult ))->isValidFor( this->m_blockSize ) );
				assert ( this->m_nextFreeBlock <= this->m_blockSize );

				++this->m_objectCount;
			}

			return theResult;
		}
	}

	/*
	 * Commit the previous allocation.
	 *
	 * @param theBlock the address that was returned by allocateBlock()
	 */
	void
	commitAllocation(ObjectType* /*	theBlock */)
	{
		this->m_firstFreeBlock = this->m_nextFreeBlock;

		assert ( this->m_objectCount <= this->m_blockSize );
	}

	/*
	 * Destroy the object, and return the block to the free list.
	 * The behavior is undefined if the object pointed to is not
	 * owned by the block.
	 *
	 * @param theObject the address of the object.
	 */
	void
	destroyObject(ObjectType*	theObject)
	{
		// check if any uncommited block is there, add it to the list
		if ( this->m_firstFreeBlock != this->m_nextFreeBlock )
		{
			// return it to pull of the free blocks
			void* const     p = this->m_objectBlock + this->m_firstFreeBlock;

			new (p) NextBlock(this->m_nextFreeBlock);

			this->m_nextFreeBlock = this->m_firstFreeBlock;
		}

		assert(ownsObject(theObject) == true);
		assert(shouldDestroyBlock(theObject));

		theObject->~ObjectType();

		new (theObject) NextBlock(this->m_firstFreeBlock);

		m_firstFreeBlock = this->m_nextFreeBlock = size_type(theObject - this->m_objectBlock);

		assert (this->m_firstFreeBlock <= this->m_blockSize);

		--this->m_objectCount;
	}

	/*
	 * Determine if this block owns the specified object.  Note
	 * that even if the object address is within our block, this
	 * call will return false if no object currently occupies the
	 * block.  See also ownsBlock().
	 *
	 * @param theObject the address of the object.
	 * @return true if we own the object, false if not.
	 */
	bool
	ownsObject(const ObjectType*	theObject) const
	{
		assert ( theObject != 0 );

		return isOccupiedBlock( reinterpret_cast<const NextBlock*>(theObject) );
	}

protected:

	/*
	 * Determine if the block should be destroyed.  Returns true,
	 * unless the object is on the free list.  The behavior is
	 * undefined if the object pointed to is not owned by the
	 * block.
	 *
	 * @param theObject the address of the object
	 * @return true if block should be destroyed, false if not.
	 */
	bool
	shouldDestroyBlock(const ObjectType*	theObject) const
	{
		assert( size_type(theObject - this->m_objectBlock) < this->m_blockSize);

        return !isOnFreeList(theObject);
	}

	bool
	isOccupiedBlock(const NextBlock*    block)const
	{
		assert( block !=0 );

		return !( ownsBlock(reinterpret_cast<const ObjectType*>(block)) && block->isValidFor(this->m_blockSize) );
	}

private:

	// Not implemented...
	ReusableArenaBlock(const ReusableArenaBlock<ObjectType>&);

	ReusableArenaBlock<ObjectType>&
	operator=(const ReusableArenaBlock<ObjectType>&);

	bool
	operator==(const ReusableArenaBlock<ObjectType>&) const;

	/*
	 * Determine if the block is on the free list.  The behavior is
	 * undefined if the object pointed to is not owned by the
	 * block.
	 *
	 * @param theObject the address of the object
	 * @return true if block is on the free list, false if not.
	 */
	bool
	isOnFreeList(const ObjectType*	theObject) const
	{
		if ( this->m_objectCount == 0 )
		{
			return false;
		}
		else
		{
			ObjectType*     pRunPtr = this->m_objectBlock + this->m_firstFreeBlock;

			for ( size_type i = 0; i < (this->m_blockSize - this->m_objectCount); ++i)
			{
				assert ( ownsBlock( pRunPtr ) );

				if (pRunPtr == theObject)
				{
					return true;
				}
				else
				{
					NextBlock* const    p = reinterpret_cast<NextBlock*>(pRunPtr);

					assert( p->isValidFor( this->m_blockSize ) );

					pRunPtr = this->m_objectBlock + p->next;
				}
			}

			return false;
		}
	}

    // Data members...
	size_type   m_firstFreeBlock;

	size_type	m_nextFreeBlock;
};

XALAN_CPP_NAMESPACE_END

#endif	// !defined(REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680)
<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include "types/type.h"
#include "core/value.h"
#include "core/cexception.h"
#include "modules/std/core/function.h"

#include <algorithm>

namespace clever {

TypeObject::~TypeObject()
{
	MemberMap::const_iterator it(m_members.begin()),
		end(m_members.end());

	while (it != end) {
		clever_delref((*it).second);
		++it;
	}
}

void TypeObject::copyMembers(const Type* type)
{
	const MemberMap& members = type->getMembers();

	if (members.size() > 0) {
		MemberMap::const_iterator it(members.begin()), end(members.end());

		for (; it != end; ++it) {
			addMember(it->first, it->second->clone());
		}
	}
/*
	const PropertyMap& props(type->getProperties());

	if (props.size() > 0) {
		PropertyMap::const_iterator it(props.begin()), end(props.end());

		for (; it != end; ++it) {
			addProperty(it->first, it->second->clone());
		}
	}

	const MethodMap& methods(type->getMethods());

	if (methods.size() > 0) {
		MethodMap::const_iterator it(methods.begin()), end(methods.end());

		for (; it != end; ++it) {
			addMethod(it->first, it->second);
		}
	}
*/
}

void Type::deallocMembers()
{
	MemberMap::iterator it(m_members.begin()), end(m_members.end());

	while (it != end) {
		clever_delref((*it).second);
		(*it).second = 0;
		++it;
	}
}

Function* Type::addMethod(Function* func)
{
	Value* val = new Value;

	clever_assert_not_null(func);

	val->setObj(CLEVER_FUNC_TYPE, func);
	addMember(CSTRING(func->getName()), val);

	return func;
}

const Function* Type::getMethod(const CString* name) const
{
	Value* val = getMember(name);

	if (val && val->isFunction()) {
		return static_cast<Function*>(val->getObj());
	}

	return NULL;
}

Value* Type::getProperty(const CString* name) const
{
	Value* val = getMember(name);

	if (val && !val->isFunction()) {
		return val;
	}

	return NULL;
}

const MethodMap Type::getMethods() const
{
	MemberMap::const_iterator it(m_members.begin()),
		end(m_members.end());

	MethodMap mm;

	while (it != end) {
		if (it->second->isFunction()) {
			mm.insert(MethodMap::value_type(
				it->first, static_cast<Function*>(it->second->getObj())));
		}
		++it;
	}

	return mm;
}

const PropertyMap Type::getProperties() const
{
	MemberMap::const_iterator it(m_members.begin()),
		end(m_members.end());

	PropertyMap pm;

	while (it != end) {
		if (!it->second->isFunction()) {
			pm.insert(*it);
		}
		++it;
	}

	return pm;
}

CLEVER_TYPE_OPERATOR(Type::add)
{
	clever_throw("Cannot use + operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::sub)
{
	clever_throw("Cannot use - operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::mul)
{
	clever_throw("Cannot use * operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::div)
{
	clever_throw("Cannot use / operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::mod)
{
	clever_throw("Cannot use % operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::greater)
{
	clever_throw("Cannot use > operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::greater_equal)
{
	clever_throw("Cannot use >= operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::less)
{
	clever_throw("Cannot use < operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::less_equal)
{
	clever_throw("Cannot use <= operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::equal)
{
	clever_throw("Cannot use == operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::not_equal)
{
	clever_throw("Cannot use != operator with %s type", getName().c_str());
}

CLEVER_TYPE_AT_OPERATOR(Type::at_op)
{
	clever_throw("Cannot use [] operator with %s type", getName().c_str());
	return NULL;
}

CLEVER_TYPE_UNARY_OPERATOR(Type::not_op)
{
	clever_throw("Cannot use ! operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::bw_and)
{
	clever_throw("Cannot use & operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::bw_or)
{
	clever_throw("Cannot use | operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::bw_xor)
{
	clever_throw("Cannot use ^ operator with %s type", getName().c_str());
}

CLEVER_TYPE_UNARY_OPERATOR(Type::bw_not)
{
	clever_throw("Cannot use ~ operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::bw_ls)
{
	clever_throw("Cannot use << operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::bw_rs)
{
	clever_throw("Cannot use >> operator with %s type", getName().c_str());
}

void Type::increment(Value* value, const VM* vm, CException* exception) const
{
	clever_throw("Cannot use ++ operator with %s type", getName().c_str());
}

void Type::decrement(Value* value, const VM* vm, CException* exception) const
{
	clever_throw("Cannot use -- operator with %s type", getName().c_str());
}

void Type::setConstructor(MethodPtr method) {
	Function* func = new Function(getName(), method);
	m_ctor = func;
	addMethod(func);
}

void Type::setDestructor(MethodPtr method) {
	Function* func = new Function(getName(), method);
	m_dtor = func;
	addMethod(func);
}

} // clever
<commit_msg>- Remove unused code<commit_after>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include "types/type.h"
#include "core/value.h"
#include "core/cexception.h"
#include "modules/std/core/function.h"

#include <algorithm>

namespace clever {

TypeObject::~TypeObject()
{
	MemberMap::const_iterator it(m_members.begin()),
		end(m_members.end());

	while (it != end) {
		clever_delref((*it).second);
		++it;
	}
}

void TypeObject::copyMembers(const Type* type)
{
	const MemberMap& members = type->getMembers();

	if (members.size() > 0) {
		MemberMap::const_iterator it(members.begin()), end(members.end());

		for (; it != end; ++it) {
			addMember(it->first, it->second->clone());
		}
	}
}

void Type::deallocMembers()
{
	MemberMap::iterator it(m_members.begin()), end(m_members.end());

	while (it != end) {
		clever_delref((*it).second);
		(*it).second = 0;
		++it;
	}
}

Function* Type::addMethod(Function* func)
{
	Value* val = new Value;

	clever_assert_not_null(func);

	val->setObj(CLEVER_FUNC_TYPE, func);
	addMember(CSTRING(func->getName()), val);

	return func;
}

const Function* Type::getMethod(const CString* name) const
{
	Value* val = getMember(name);

	if (val && val->isFunction()) {
		return static_cast<Function*>(val->getObj());
	}

	return NULL;
}

Value* Type::getProperty(const CString* name) const
{
	Value* val = getMember(name);

	if (val && !val->isFunction()) {
		return val;
	}

	return NULL;
}

const MethodMap Type::getMethods() const
{
	MemberMap::const_iterator it(m_members.begin()),
		end(m_members.end());

	MethodMap mm;

	while (it != end) {
		if (it->second->isFunction()) {
			mm.insert(MethodMap::value_type(
				it->first, static_cast<Function*>(it->second->getObj())));
		}
		++it;
	}

	return mm;
}

const PropertyMap Type::getProperties() const
{
	MemberMap::const_iterator it(m_members.begin()),
		end(m_members.end());

	PropertyMap pm;

	while (it != end) {
		if (!it->second->isFunction()) {
			pm.insert(*it);
		}
		++it;
	}

	return pm;
}

CLEVER_TYPE_OPERATOR(Type::add)
{
	clever_throw("Cannot use + operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::sub)
{
	clever_throw("Cannot use - operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::mul)
{
	clever_throw("Cannot use * operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::div)
{
	clever_throw("Cannot use / operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::mod)
{
	clever_throw("Cannot use % operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::greater)
{
	clever_throw("Cannot use > operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::greater_equal)
{
	clever_throw("Cannot use >= operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::less)
{
	clever_throw("Cannot use < operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::less_equal)
{
	clever_throw("Cannot use <= operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::equal)
{
	clever_throw("Cannot use == operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::not_equal)
{
	clever_throw("Cannot use != operator with %s type", getName().c_str());
}

CLEVER_TYPE_AT_OPERATOR(Type::at_op)
{
	clever_throw("Cannot use [] operator with %s type", getName().c_str());
	return NULL;
}

CLEVER_TYPE_UNARY_OPERATOR(Type::not_op)
{
	clever_throw("Cannot use ! operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::bw_and)
{
	clever_throw("Cannot use & operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::bw_or)
{
	clever_throw("Cannot use | operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::bw_xor)
{
	clever_throw("Cannot use ^ operator with %s type", getName().c_str());
}

CLEVER_TYPE_UNARY_OPERATOR(Type::bw_not)
{
	clever_throw("Cannot use ~ operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::bw_ls)
{
	clever_throw("Cannot use << operator with %s type", getName().c_str());
}

CLEVER_TYPE_OPERATOR(Type::bw_rs)
{
	clever_throw("Cannot use >> operator with %s type", getName().c_str());
}

void Type::increment(Value* value, const VM* vm, CException* exception) const
{
	clever_throw("Cannot use ++ operator with %s type", getName().c_str());
}

void Type::decrement(Value* value, const VM* vm, CException* exception) const
{
	clever_throw("Cannot use -- operator with %s type", getName().c_str());
}

void Type::setConstructor(MethodPtr method) {
	Function* func = new Function(getName(), method);
	m_ctor = func;
	addMethod(func);
}

void Type::setDestructor(MethodPtr method) {
	Function* func = new Function(getName(), method);
	m_dtor = func;
	addMethod(func);
}

} // clever
<|endoftext|>


<commit_before>/*=====================================================================

 QGroundControl Open Source Ground Control Station

 (c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL 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.

 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

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

 ======================================================================*/

/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "AirframeComponentController.h"
#include "AirframeComponentAirframes.h"
#include "QGCMAVLink.h"
#include "UASManager.h"
#include "AutoPilotPluginManager.h"
#include "QGCApplication.h"
#include "QGCMessageBox.h"

#include <QVariant>
#include <QQmlProperty>

bool AirframeComponentController::_typesRegistered = false;

AirframeComponentController::AirframeComponentController(void) :
    _currentVehicleIndex(0),
    _autostartId(0),
    _showCustomConfigPanel(false)
{
    if (!_typesRegistered) {
        _typesRegistered = true;
        qmlRegisterUncreatableType<AirframeType>("QGroundControl.Controllers", 1, 0, "AiframeType", "Can only reference AirframeType");
        qmlRegisterUncreatableType<Airframe>("QGroundControl.Controllers", 1, 0, "Aiframe", "Can only reference Airframe");
    }

    QStringList usedParams;
    usedParams << "SYS_AUTOSTART" << "SYS_AUTOCONFIG";
    if (!_allParametersExists(FactSystem::defaultComponentId, usedParams)) {
        return;
    }

    // Load up member variables

    bool autostartFound = false;
    _autostartId = getParameterFact(FactSystem::defaultComponentId, "SYS_AUTOSTART")->value().toInt();

    for (const AirframeComponentAirframes::AirframeType_t* pType=&AirframeComponentAirframes::rgAirframeTypes[0]; pType->name != NULL; pType++) {
        AirframeType* airframeType = new AirframeType(pType->name, pType->imageResource, this);
        Q_CHECK_PTR(airframeType);

        int index = 0;
        for (const AirframeComponentAirframes::AirframeInfo_t* pInfo=&pType->rgAirframeInfo[0]; pInfo->name != NULL; pInfo++) {
            if (_autostartId == pInfo->autostartId) {
                Q_ASSERT(!autostartFound);
                autostartFound = true;
                _currentAirframeType = pType->name;
                _currentVehicleName = pInfo->name;
                _currentVehicleIndex = index;
            }
            airframeType->addAirframe(pInfo->name, pInfo->autostartId);
            index++;
        }

        _airframeTypes.append(QVariant::fromValue(airframeType));
    }

    if (_autostartId != 0 && !autostartFound) {
        _showCustomConfigPanel = true;
        emit showCustomConfigPanelChanged(true);
    }
}

AirframeComponentController::~AirframeComponentController()
{

}

void AirframeComponentController::changeAutostart(void)
{
	if (UASManager::instance()->getUASList().count() > 1) {
		QGCMessageBox::warning("Airframe Config", "You cannot change airframe configuration while connected to multiple vehicles.");
		return;
	}

    qgcApp()->setOverrideCursor(Qt::WaitCursor);

    getParameterFact(-1, "SYS_AUTOSTART")->setValue(_autostartId);
    getParameterFact(-1, "SYS_AUTOCONFIG")->setValue(1);

    // Wait for the parameters to flow through system
    qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
    QGC::SLEEP::sleep(1);
    qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);

    // Reboot board

    _uas->executeCommand(MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0);
    qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
    QGC::SLEEP::sleep(1);
    qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
    LinkManager::instance()->disconnectAll();

    qgcApp()->restoreOverrideCursor();
}

AirframeType::AirframeType(const QString& name, const QString& imageResource, QObject* parent) :
    QObject(parent),
    _name(name),
    _imageResource(imageResource)
{

}

AirframeType::~AirframeType()
{

}

void AirframeType::addAirframe(const QString& name, int autostartId)
{
    Airframe* airframe = new Airframe(name, autostartId);
    Q_CHECK_PTR(airframe);

    _airframes.append(QVariant::fromValue(airframe));
}

Airframe::Airframe(const QString& name, int autostartId, QObject* parent) :
    QObject(parent),
    _name(name),
    _autostartId(autostartId)
{

}

Airframe::~Airframe()
{

}
<commit_msg>Bump param wait time<commit_after>/*=====================================================================

 QGroundControl Open Source Ground Control Station

 (c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL 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.

 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

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

 ======================================================================*/

/// @file
///     @author Don Gagne <don@thegagnes.com>

#include "AirframeComponentController.h"
#include "AirframeComponentAirframes.h"
#include "QGCMAVLink.h"
#include "UASManager.h"
#include "AutoPilotPluginManager.h"
#include "QGCApplication.h"
#include "QGCMessageBox.h"

#include <QVariant>
#include <QQmlProperty>

bool AirframeComponentController::_typesRegistered = false;

AirframeComponentController::AirframeComponentController(void) :
    _currentVehicleIndex(0),
    _autostartId(0),
    _showCustomConfigPanel(false)
{
    if (!_typesRegistered) {
        _typesRegistered = true;
        qmlRegisterUncreatableType<AirframeType>("QGroundControl.Controllers", 1, 0, "AiframeType", "Can only reference AirframeType");
        qmlRegisterUncreatableType<Airframe>("QGroundControl.Controllers", 1, 0, "Aiframe", "Can only reference Airframe");
    }

    QStringList usedParams;
    usedParams << "SYS_AUTOSTART" << "SYS_AUTOCONFIG";
    if (!_allParametersExists(FactSystem::defaultComponentId, usedParams)) {
        return;
    }

    // Load up member variables

    bool autostartFound = false;
    _autostartId = getParameterFact(FactSystem::defaultComponentId, "SYS_AUTOSTART")->value().toInt();

    for (const AirframeComponentAirframes::AirframeType_t* pType=&AirframeComponentAirframes::rgAirframeTypes[0]; pType->name != NULL; pType++) {
        AirframeType* airframeType = new AirframeType(pType->name, pType->imageResource, this);
        Q_CHECK_PTR(airframeType);

        int index = 0;
        for (const AirframeComponentAirframes::AirframeInfo_t* pInfo=&pType->rgAirframeInfo[0]; pInfo->name != NULL; pInfo++) {
            if (_autostartId == pInfo->autostartId) {
                Q_ASSERT(!autostartFound);
                autostartFound = true;
                _currentAirframeType = pType->name;
                _currentVehicleName = pInfo->name;
                _currentVehicleIndex = index;
            }
            airframeType->addAirframe(pInfo->name, pInfo->autostartId);
            index++;
        }

        _airframeTypes.append(QVariant::fromValue(airframeType));
    }

    if (_autostartId != 0 && !autostartFound) {
        _showCustomConfigPanel = true;
        emit showCustomConfigPanelChanged(true);
    }
}

AirframeComponentController::~AirframeComponentController()
{

}

void AirframeComponentController::changeAutostart(void)
{
	if (UASManager::instance()->getUASList().count() > 1) {
		QGCMessageBox::warning("Airframe Config", "You cannot change airframe configuration while connected to multiple vehicles.");
		return;
	}

    qgcApp()->setOverrideCursor(Qt::WaitCursor);

    getParameterFact(-1, "SYS_AUTOSTART")->setValue(_autostartId);
    getParameterFact(-1, "SYS_AUTOCONFIG")->setValue(1);

    // FactSystem doesn't currently have a mechanism to wait for the parameters to come backf from the board.
    // So instead we wait for enough time for the parameters to hoepfully make it to the board.
    qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
    QGC::SLEEP::sleep(3);
    qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);

    // Reboot board

    _uas->executeCommand(MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0);
    qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
    QGC::SLEEP::sleep(1);
    qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
    LinkManager::instance()->disconnectAll();

    qgcApp()->restoreOverrideCursor();
}

AirframeType::AirframeType(const QString& name, const QString& imageResource, QObject* parent) :
    QObject(parent),
    _name(name),
    _imageResource(imageResource)
{

}

AirframeType::~AirframeType()
{

}

void AirframeType::addAirframe(const QString& name, int autostartId)
{
    Airframe* airframe = new Airframe(name, autostartId);
    Q_CHECK_PTR(airframe);

    _airframes.append(QVariant::fromValue(airframe));
}

Airframe::Airframe(const QString& name, int autostartId, QObject* parent) :
    QObject(parent),
    _name(name),
    _autostartId(autostartId)
{

}

Airframe::~Airframe()
{

}
<|endoftext|>


<commit_before>#ifndef DICE_IOPERATION_H
#define DICE_IOPERATION_H

#include "../stdafx.hpp"
#include "DiceRoll/Operations/RollResult.h"

//Base for a Decorator Pattern
class IOperation
{
protected:
    // DELETE THIS
    std::vector<int> _elements;
    int _count;
    //END OF DELETE
    /**
     * \brief Suboperation that will be evaluated before current.
     *
     * Stores an object that is a child of IOperation interface.
     * By default, _componentOp.evaluate() is called before
     * this->execute() and results are merged together.
     */
    IOperation * const _componentOp;

    /**
     * \brief Executes current operation.
     *
     * This is a method that does all the heavy lifting for an operation.
     *
     * \return
     * Returns unique pointer to RollResult which stores current operation result.
     * Don't mistake it with evaluate()!
     */
    virtual std::unique_ptr<RollResult> execute() = 0;

public:
    IOperation(IOperation* op) : _componentOp(op) {}

    // Executes all operations.
    // By default, merges _componentOp's RollResult with its.
    /**
     * \brief Evaluates all suboperations and executes itself.
     *
     * By default it calls evaluate() on it's suboperation (_componentOp)
     * and then appends the result by its own.
     *
     * \return Unique pointer to the result of executing current operation
     * and all suboperations.
     */
    virtual inline std::unique_ptr<RollResult> evaluate()
    {
	std::unique_ptr<RollResult> result = _componentOp->evaluate();
	result->append(execute().get());
	return result;
    }
    //DELETE THIS
    virtual std::string toString() const
    {
        std::string result = "";
        for (auto& element : _elements)
            result += std::to_string(element) + " ";
        return result;
    }
    inline int getCount() const { return _count; }
    inline const std::vector<int> &getElements() const { return _elements; }
    //END OF DELETE
};

#endif //DICE_IOPERATION_H
<commit_msg>Changed the wording in evaluate() doc to be more comprehensible.<commit_after>#ifndef DICE_IOPERATION_H
#define DICE_IOPERATION_H

#include "../stdafx.hpp"
#include "DiceRoll/Operations/RollResult.h"

//Base for a Decorator Pattern
class IOperation
{
protected:
    // DELETE THIS
    std::vector<int> _elements;
    int _count;
    //END OF DELETE
    /**
     * \brief Suboperation that will be evaluated before current.
     *
     * Stores an object that is a child of IOperation interface.
     * By default, _componentOp.evaluate() is called before
     * this->execute() and results are merged together.
     */
    IOperation * const _componentOp;

    /**
     * \brief Executes current operation.
     *
     * This is a method that does all the heavy lifting for an operation.
     *
     * \return
     * Returns unique pointer to RollResult which stores current operation result.
     * Don't mistake it with evaluate()!
     */
    virtual std::unique_ptr<RollResult> execute() = 0;

public:
    IOperation(IOperation* op) : _componentOp(op) {}

    // Executes all operations.
    // By default, merges _componentOp's RollResult with its.
    /**
     * \brief Evaluates all suboperations and executes itself.
     *
     * By default it calls evaluate() on it's suboperation (_componentOp)
     * and then merges the result with its own.
     *
     * \return Unique pointer to the result of executing current operation
     * and all suboperations.
     */
    virtual inline std::unique_ptr<RollResult> evaluate()
    {
	std::unique_ptr<RollResult> result = _componentOp->evaluate();
	result->append(execute().get());
	return result;
    }
    //DELETE THIS
    virtual std::string toString() const
    {
        std::string result = "";
        for (auto& element : _elements)
            result += std::to_string(element) + " ";
        return result;
    }
    inline int getCount() const { return _count; }
    inline const std::vector<int> &getElements() const { return _elements; }
    //END OF DELETE
};

#endif //DICE_IOPERATION_H
<|endoftext|>


<commit_before>// coding: utf-8
/* Copyright (c) 2014, Roboterclub Aachen e. V.
 * All Rights Reserved.
 *
 * The file is part of the xpcc library and is released under the 3-clause BSD
 * license. See the file `LICENSE` for the full license governing this code.
 */
// ----------------------------------------------------------------------------

#ifndef XPCC__NRF24_CONFIG_HPP
#   error "Don't include this file directly, use 'nrf24_config.hpp' instead!"
#endif

#include "nrf24_config.hpp"
#include "nrf24_definitions.hpp"

#include <stdint.h>

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::powerUp()
{
    Nrf24Phy::setBits(NrfRegister::CONFIG, Config::PWR_UP);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::powerDown()
{
    Nrf24Phy::clearBits(NrfRegister::CONFIG, Config::PWR_UP);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setChannel(uint8_t channel)
{
    Nrf24Phy::writeRegister(NrfRegister::RF_CH, channel);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setMode(Mode mode)
{
    if(mode == Mode::Rx)
    {
        Nrf24Phy::setBits(NrfRegister::CONFIG, Config::PRIM_RX);
    } else
    {
        Nrf24Phy::clearBits(NrfRegister::CONFIG, Config::PRIM_RX);
    }
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setSpeed(Speed speed)
{
    if(speed == Speed::kBps250)
    {
        Nrf24Phy::clearBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_HIGH);
        Nrf24Phy::setBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_LOW);
    }
    else if(speed == Speed::MBps1)
    {
        Nrf24Phy::clearBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_LOW);
        Nrf24Phy::clearBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_HIGH);
    }
    else if(speed == Speed::MBps1)
    {
        Nrf24Phy::setBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_HIGH);
        Nrf24Phy::clearBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_LOW);
    }
}

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

template<typename Nrf24Phy>
void xpcc::Nrf24Config<Nrf24Phy>::setCrc(Crc crc)
{
    if(crc == Crc::NoCrc)
    {
        Nrf24Phy::clearBits(NrfRegister::CONFIG, Config::EN_CRC);

    } else
    {
        Nrf24Phy::setBits(NrfRegister::CONFIG, Config::EN_CRC);

        if (crc == Crc::Crc1Byte)
        {
            Nrf24Phy::clearBits(NrfRegister::CONFIG, Config::CRC0);
        }
        else if (crc == Crc::Crc2Byte)
        {
            Nrf24Phy::setBits(NrfRegister::CONFIG, Config::CRC0);
        }
    }
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setAddressWidth(AddressWidth width)
{
    Nrf24Phy::writeRegister(NrfRegister::SETUP_AW, static_cast<uint8_t>(width));
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setRfPower(RfPower power)
{
    Nrf24Phy::writeRegister(NrfRegister::RF_SETUP, static_cast<uint8_t>(power) << 1);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setAutoRetransmitDelay(AutoRetransmitDelay delay)
{
    Nrf24Phy::writeRegister(NrfRegister::SETUP_RETR, static_cast<uint8_t>(delay) << 4);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setAutoRetransmitCount(AutoRetransmitCount count)
{
    Nrf24Phy::writeRegister(NrfRegister::SETUP_RETR, static_cast<uint8_t>(count));
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::enableFeatureNoAck()
{
    Nrf24Phy::setBits(NrfRegister::FEATURE, Feature::EN_DYN_ACK);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::disableFeatureNoAck()
{
    Nrf24Phy::clearBits(NrfRegister::FEATURE, Feature::EN_DYN_ACK);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::enablePipe(Pipe_t pipe, bool enableAutoAck)
{

    uint16_t payload_length = Nrf24Phy::getPayloadLength();

    NrfRegister_t reg = NrfRegister::RX_PW_P0;
    reg.value += pipe.value;

    /* Set payload width for pipe */
    Nrf24Phy::writeRegister(reg, payload_length);

    /* Enable or disable auto acknowledgement for this pipe */
    if(enableAutoAck)
    {
        Nrf24Phy::setBits(NrfRegister::EN_AA, (1 << pipe.value));
    } else
    {
        Nrf24Phy::clearBits(NrfRegister::EN_AA, (1 << pipe.value));
    }

    /* enable pipe */
    Nrf24Phy::setBits(NrfRegister::EN_RX_ADDR, (1 << pipe.value));
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::disablePipe(Pipe_t pipe)
{
    /* DISABLE pipe */
    Nrf24Phy::clearBits(NrfRegister::EN_RX_ADDR, (1 << pipe.value));
}

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

template<typename Nrf24Phy>
typename xpcc::Nrf24Config<Nrf24Phy>::Pipe_t
xpcc::Nrf24Config<Nrf24Phy>::getPayloadPipe()
{
    uint8_t status = Nrf24Phy::readStatus();

    return static_cast<Pipe_t>((status & (uint8_t)Status::RX_P_NO) >> 1);
}
<commit_msg>nrf24-config: fix wrong parameter type in enablePipe<commit_after>// coding: utf-8
/* Copyright (c) 2014, Roboterclub Aachen e. V.
 * All Rights Reserved.
 *
 * The file is part of the xpcc library and is released under the 3-clause BSD
 * license. See the file `LICENSE` for the full license governing this code.
 */
// ----------------------------------------------------------------------------

#ifndef XPCC__NRF24_CONFIG_HPP
#   error "Don't include this file directly, use 'nrf24_config.hpp' instead!"
#endif

#include "nrf24_config.hpp"
#include "nrf24_definitions.hpp"

#include <stdint.h>

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::powerUp()
{
    Nrf24Phy::setBits(NrfRegister::CONFIG, Config::PWR_UP);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::powerDown()
{
    Nrf24Phy::clearBits(NrfRegister::CONFIG, Config::PWR_UP);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setChannel(uint8_t channel)
{
    Nrf24Phy::writeRegister(NrfRegister::RF_CH, channel);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setMode(Mode mode)
{
    if(mode == Mode::Rx)
    {
        Nrf24Phy::setBits(NrfRegister::CONFIG, Config::PRIM_RX);
    } else
    {
        Nrf24Phy::clearBits(NrfRegister::CONFIG, Config::PRIM_RX);
    }
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setSpeed(Speed speed)
{
    if(speed == Speed::kBps250)
    {
        Nrf24Phy::clearBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_HIGH);
        Nrf24Phy::setBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_LOW);
    }
    else if(speed == Speed::MBps1)
    {
        Nrf24Phy::clearBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_LOW);
        Nrf24Phy::clearBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_HIGH);
    }
    else if(speed == Speed::MBps1)
    {
        Nrf24Phy::setBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_HIGH);
        Nrf24Phy::clearBits(NrfRegister::RF_SETUP, RfSetup::RF_DR_LOW);
    }
}

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

template<typename Nrf24Phy>
void xpcc::Nrf24Config<Nrf24Phy>::setCrc(Crc crc)
{
    if(crc == Crc::NoCrc)
    {
        Nrf24Phy::clearBits(NrfRegister::CONFIG, Config::EN_CRC);

    } else
    {
        Nrf24Phy::setBits(NrfRegister::CONFIG, Config::EN_CRC);

        if (crc == Crc::Crc1Byte)
        {
            Nrf24Phy::clearBits(NrfRegister::CONFIG, Config::CRC0);
        }
        else if (crc == Crc::Crc2Byte)
        {
            Nrf24Phy::setBits(NrfRegister::CONFIG, Config::CRC0);
        }
    }
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setAddressWidth(AddressWidth width)
{
    Nrf24Phy::writeRegister(NrfRegister::SETUP_AW, static_cast<uint8_t>(width));
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setRfPower(RfPower power)
{
    Nrf24Phy::writeRegister(NrfRegister::RF_SETUP, static_cast<uint8_t>(power) << 1);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setAutoRetransmitDelay(AutoRetransmitDelay delay)
{
    Nrf24Phy::writeRegister(NrfRegister::SETUP_RETR, static_cast<uint8_t>(delay) << 4);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::setAutoRetransmitCount(AutoRetransmitCount count)
{
    Nrf24Phy::writeRegister(NrfRegister::SETUP_RETR, static_cast<uint8_t>(count));
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::enableFeatureNoAck()
{
    Nrf24Phy::setBits(NrfRegister::FEATURE, Feature::EN_DYN_ACK);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::disableFeatureNoAck()
{
    Nrf24Phy::clearBits(NrfRegister::FEATURE, Feature::EN_DYN_ACK);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::enablePipe(Pipe_t pipe, bool enableAutoAck)
{

    uint16_t payload_length = Nrf24Phy::getPayloadLength();

    NrfRegister_t reg = NrfRegister::RX_PW_P0;
    reg.value += pipe.value;

    /* Set payload width for pipe */
    Nrf24Phy::writeRegister(reg, payload_length);

    Flags_t pipe_flag = static_cast<Flags_t>(1 << pipe.value);

    /* Enable or disable auto acknowledgement for this pipe */
    if(enableAutoAck)
    {
        Nrf24Phy::setBits(NrfRegister::EN_AA, pipe_flag);
    } else
    {
        Nrf24Phy::clearBits(NrfRegister::EN_AA, pipe_flag);
    }

    /* enable pipe */
    Nrf24Phy::setBits(NrfRegister::EN_RX_ADDR, pipe_flag);
}

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

template<typename Nrf24Phy>
void
xpcc::Nrf24Config<Nrf24Phy>::disablePipe(Pipe_t pipe)
{
    /* DISABLE pipe */
    Nrf24Phy::clearBits(NrfRegister::EN_RX_ADDR, (1 << pipe.value));
}

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

template<typename Nrf24Phy>
typename xpcc::Nrf24Config<Nrf24Phy>::Pipe_t
xpcc::Nrf24Config<Nrf24Phy>::getPayloadPipe()
{
    uint8_t status = Nrf24Phy::readStatus();

    return static_cast<Pipe_t>((status & (uint8_t)Status::RX_P_NO) >> 1);
}
<|endoftext|>


<commit_before>#include <babylon/meshes/builders/cylinder_builder.h>

#include <babylon/meshes/builders/mesh_builder_options.h>
#include <babylon/meshes/mesh.h>
#include <babylon/meshes/vertex_data.h>

namespace BABYLON {

MeshPtr CylinderBuilder::CreateCylinder(const std::string& name, CylinderOptions& options,
                                        Scene* scene)
{
  auto cylinder = Mesh::New(name, scene);

  options.sideOrientation = Mesh::_GetDefaultSideOrientation(options.sideOrientation);
  cylinder->_originalBuilderSideOrientation = *options.sideOrientation;

  auto vertexData = VertexData::CreateCylinder(options);

  vertexData->applyToMesh(*cylinder, options.updatable);

  return cylinder;
}

} // end of namespace BABYLON
<commit_msg>const correctness<commit_after>#include <babylon/meshes/builders/cylinder_builder.h>

#include <babylon/meshes/builders/mesh_builder_options.h>
#include <babylon/meshes/mesh.h>
#include <babylon/meshes/vertex_data.h>

namespace BABYLON {

MeshPtr CylinderBuilder::CreateCylinder(const std::string& name, CylinderOptions& options,
                                        Scene* scene)
{
  const auto cylinder = Mesh::New(name, scene);

  options.sideOrientation = Mesh::_GetDefaultSideOrientation(options.sideOrientation);
  cylinder->_originalBuilderSideOrientation = *options.sideOrientation;

  const auto vertexData = VertexData::CreateCylinder(options);

  vertexData->applyToMesh(*cylinder, options.updatable);

  return cylinder;
}

} // end of namespace BABYLON
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include "FreeTypeFont.h"
#include FT_GLYPH_H

#include <osgDB/WriteFile>

FreeTypeFont::FreeTypeFont(const std::string& filename, FT_Face face):
    _filename(filename),
    _face(face)
{
}

void FreeTypeFont::setSize(unsigned int width, unsigned int height)
{
    FT_Error error = FT_Set_Pixel_Sizes( _face,   /* handle to face object            */
                                         width,      /* pixel_width                      */
                                         height );   /* pixel_height */

    if (error)
    {
        std::cout<<"FT_Set_Pixel_Sizes() - error "<<error<<std::endl;
    }
    else
    {
        _width = width;
        _height = height;
    }

}

osgText::Font::Glyph* FreeTypeFont::getGlyph(unsigned int charcode)
{
    // search for glyph amoungst existing glyphs.
    GlyphMap::iterator itr = _glyphMap.find(charcode);
    if (itr!=_glyphMap.end()) return itr->second.get();

    FT_Error error = FT_Load_Char( _face, charcode, FT_LOAD_RENDER|FT_LOAD_NO_BITMAP );
    if (error)
    {
        std::cout << "FT_Load_Char(...) error "<<error<<std::endl;
        return 0;
    }

    FT_GlyphSlot glyphslot = _face->glyph;

    int rows = glyphslot->bitmap.rows;
    int width = glyphslot->bitmap.width;
    int pitch = glyphslot->bitmap.pitch;
    unsigned char* buffer = glyphslot->bitmap.buffer;

    osg::ref_ptr<Glyph> glyph = new Glyph;
    unsigned char* data = new unsigned char[width*rows*2];
    glyph->setImage(width,rows,1,
                    GL_LUMINANCE_ALPHA,
                    GL_LUMINANCE_ALPHA,GL_UNSIGNED_BYTE,
                    data,
                    osg::Image::USE_NEW_DELETE,
                    1);

    // copy image across to osgText::Glyph image.
    for(int r=rows-1;r>=0;--r)
    {
        unsigned char* ptr = buffer+r*pitch;
        for(int c=0;c<width;++c,++ptr)
        {
            (*data++)=255;
            (*data++)=*ptr;
        }
    }

    FT_Glyph_Metrics* metrics = &(glyphslot->metrics);

    glyph->setFont(this);
    glyph->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX/64.0f,(float)(metrics->horiBearingY-metrics->height)/64.0f)); // bottom left.
    glyph->setHorizontalAdvance((float)metrics->horiAdvance/64.0f);
    glyph->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX/64.0f,(float)(metrics->vertBearingY-metrics->height)/64.0f)); // top middle.
    glyph->setVerticalAdvance((float)metrics->vertAdvance/64.0f);

    addGlyph(charcode,glyph.get());

    return glyph.get();

}

osg::Vec2 FreeTypeFont::getKerning(unsigned int leftcharcode,unsigned int rightcharcode)
{
    if (!FT_HAS_KERNING(_face)) return osg::Vec2(0.0f,0.0f);

    // convert character code to glyph index
    FT_UInt left = FT_Get_Char_Index( _face, leftcharcode );
    FT_UInt right = FT_Get_Char_Index( _face, rightcharcode );

    // get the kerning distances.
    FT_Vector  kerning;
    FT_Error error = FT_Get_Kerning( _face,                     // handle to face object
                                     left,                      // left glyph index
                                     right,                     // right glyph index
                                     ft_kerning_default,        // kerning mode
                                     &kerning );                // target vector

    if (error)
    {
        return osg::Vec2(0.0f,0.0f);
    }

    return osg::Vec2((float)kerning.x/64.0f,(float)kerning.y/64.0f);
}

bool FreeTypeFont::hasVertical() const
{
    return FT_HAS_VERTICAL(_face);
}
<commit_msg>Fix for warning under Windows.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include "FreeTypeFont.h"
#include FT_GLYPH_H

#include <osgDB/WriteFile>

FreeTypeFont::FreeTypeFont(const std::string& filename, FT_Face face):
    _filename(filename),
    _face(face)
{
}

void FreeTypeFont::setSize(unsigned int width, unsigned int height)
{
    FT_Error error = FT_Set_Pixel_Sizes( _face,   /* handle to face object            */
                                         width,      /* pixel_width                      */
                                         height );   /* pixel_height */

    if (error)
    {
        std::cout<<"FT_Set_Pixel_Sizes() - error "<<error<<std::endl;
    }
    else
    {
        _width = width;
        _height = height;
    }

}

osgText::Font::Glyph* FreeTypeFont::getGlyph(unsigned int charcode)
{
    // search for glyph amoungst existing glyphs.
    GlyphMap::iterator itr = _glyphMap.find(charcode);
    if (itr!=_glyphMap.end()) return itr->second.get();

    FT_Error error = FT_Load_Char( _face, charcode, FT_LOAD_RENDER|FT_LOAD_NO_BITMAP );
    if (error)
    {
        std::cout << "FT_Load_Char(...) error "<<error<<std::endl;
        return 0;
    }

    FT_GlyphSlot glyphslot = _face->glyph;

    int rows = glyphslot->bitmap.rows;
    int width = glyphslot->bitmap.width;
    int pitch = glyphslot->bitmap.pitch;
    unsigned char* buffer = glyphslot->bitmap.buffer;

    osg::ref_ptr<Glyph> glyph = new Glyph;
    unsigned char* data = new unsigned char[width*rows*2];
    glyph->setImage(width,rows,1,
                    GL_LUMINANCE_ALPHA,
                    GL_LUMINANCE_ALPHA,GL_UNSIGNED_BYTE,
                    data,
                    osg::Image::USE_NEW_DELETE,
                    1);

    // copy image across to osgText::Glyph image.
    for(int r=rows-1;r>=0;--r)
    {
        unsigned char* ptr = buffer+r*pitch;
        for(int c=0;c<width;++c,++ptr)
        {
            (*data++)=255;
            (*data++)=*ptr;
        }
    }

    FT_Glyph_Metrics* metrics = &(glyphslot->metrics);

    glyph->setFont(this);
    glyph->setHorizontalBearing(osg::Vec2((float)metrics->horiBearingX/64.0f,(float)(metrics->horiBearingY-metrics->height)/64.0f)); // bottom left.
    glyph->setHorizontalAdvance((float)metrics->horiAdvance/64.0f);
    glyph->setVerticalBearing(osg::Vec2((float)metrics->vertBearingX/64.0f,(float)(metrics->vertBearingY-metrics->height)/64.0f)); // top middle.
    glyph->setVerticalAdvance((float)metrics->vertAdvance/64.0f);

    addGlyph(charcode,glyph.get());

    return glyph.get();

}

osg::Vec2 FreeTypeFont::getKerning(unsigned int leftcharcode,unsigned int rightcharcode)
{
    if (!FT_HAS_KERNING(_face)) return osg::Vec2(0.0f,0.0f);

    // convert character code to glyph index
    FT_UInt left = FT_Get_Char_Index( _face, leftcharcode );
    FT_UInt right = FT_Get_Char_Index( _face, rightcharcode );

    // get the kerning distances.
    FT_Vector  kerning;
    FT_Error error = FT_Get_Kerning( _face,                     // handle to face object
                                     left,                      // left glyph index
                                     right,                     // right glyph index
                                     ft_kerning_default,        // kerning mode
                                     &kerning );                // target vector

    if (error)
    {
        return osg::Vec2(0.0f,0.0f);
    }

    return osg::Vec2((float)kerning.x/64.0f,(float)kerning.y/64.0f);
}

bool FreeTypeFont::hasVertical() const
{
    return FT_HAS_VERTICAL(_face)!=0;
}
<|endoftext|>


<commit_before>#include "BooPHF.h"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <random>
#include <algorithm>
#include <fstream>

using namespace std;

//example with user provided custom hasher for uint64_t type :

class Custom_string_Hasher
{
public:
	// the class should have operator () with this signature :
	uint64_t operator ()   (std::string key, uint64_t seed=0) const
	{

		uint64_t hash  =  hash_fn(key);
		hash ^= seed;

		return hash;
	}

     std::hash<std::string> hash_fn;
};

//then tell BBhash to use this custom hash : (also appears below, line 104)
typedef boomphf::mphf<  std::string, Custom_string_Hasher  > boophf_t;

//from http://stackoverflow.com/questions/440133/how-do-i-create-a-random-alpha-numeric-string-in-c
void gen_random(char *s, const int len) {
	static const char alphanum[] =
	"0123456789"
	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	"abcdefghijklmnopqrstuvwxyz";

	for (int i = 0; i < len; ++i) {
		s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
	}

	s[len] = 0;
}

int main (int argc, char* argv[]){

	//PARAMETERS
	u_int64_t nelem = 1000000;
	uint nthreads = 1;

	if(argc !=3 ){
		printf("Usage :\n");
		printf("%s <nelem> <nthreads> \n",argv[0]);
		return EXIT_FAILURE;
	}

	if(argc ==3 ){
		nelem = strtoul(argv[1], NULL,0);
		nthreads = atoi(argv[2]);
	}

	uint64_t ii, jj;
	std::vector<std::string> data;

	int string_size = 18;
	/////  generation of random strings

	char * tempchar = (char *) malloc(sizeof(string_size)*sizeof(char));
	string lolstr;
	ifstream inputfile("StringFile.txt",ios::in);
	for (u_int64_t i = 0; i < nelem; i++){
		//RANDOM STRINGS
		//~ gen_random(tempchar,string_size);
		//~ data.push_back((string)tempchar);
		//STRING READ FROM FILE
		getline(inputfile,lolstr);
		data.push_back(lolstr);
	}

	//////////////////
	// at this point, array data contains a set of nelem random unique keys

	boophf_t * bphf = NULL;
	double t_begin,t_end; struct timeval timet;

	printf("Construct a BooPHF with  %lli elements  \n",nelem);

	gettimeofday(&timet, NULL); t_begin = timet.tv_sec +(timet.tv_usec/1000000.0);

	// mphf takes as input a c++ range. A std::vector is already a c++ range

	double gammaFactor = 2.0; // lowest bit/elem is achieved with gamma=1, higher values lead to larger mphf but faster construction/query
	// gamma = 2 is a good tradeoff (leads to approx 3.7 bits/key )

	//build the mphf
	bphf = new boomphf::mphf<std::string,Custom_string_Hasher>(nelem,data,nthreads,gammaFactor);

	gettimeofday(&timet, NULL); t_end = timet.tv_sec +(timet.tv_usec/1000000.0);
	double elapsed = t_end - t_begin;

	printf("BooPHF constructed perfect hash for %llu keys in %.2fs\n", nelem,elapsed);
	printf("boophf  bits/elem : %f\n",(float) (bphf->totalBitSize())/nelem);
	gettimeofday(&timet, NULL); t_begin = timet.tv_sec +(timet.tv_usec/1000000.0);
	//query mphf like this
	for (u_int64_t i = 0; i < 1000000; i++){
		uint64_t  idx = bphf->lookup(data[i]);
	}
	gettimeofday(&timet, NULL); t_end = timet.tv_sec +(timet.tv_usec/1000000.0);
	double elapsed2 = t_end - t_begin;
	printf("Query of 1M key  in %.2fs\n", nelem,elapsed2);

	delete bphf;
	return EXIT_SUCCESS;
}
<commit_msg>string example<commit_after>#include "BooPHF.h"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <random>
#include <algorithm>
#include <fstream>

using namespace std;

//example with user provided custom hasher for uint64_t type :

class Custom_string_Hasher
{
public:
	// the class should have operator () with this signature :
	uint64_t operator ()   (std::string key, uint64_t seed=0) const
	{

		uint64_t hash  =  hash_fn(key);
		hash ^= seed;

		return hash;
	}

     std::hash<std::string> hash_fn;
};

//then tell BBhash to use this custom hash : (also appears below, line 104)
typedef boomphf::mphf<  std::string, Custom_string_Hasher  > boophf_t;

//from http://stackoverflow.com/questions/440133/how-do-i-create-a-random-alpha-numeric-string-in-c
void gen_random(char *s, const int len) {
	static const char alphanum[] =
	"0123456789"
	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	"abcdefghijklmnopqrstuvwxyz";

	for (int i = 0; i < len; ++i) {
		s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
	}

	s[len] = 0;
}

int main (int argc, char* argv[]){

	//PARAMETERS
	u_int64_t nelem = 1000000;
	uint nthreads = 1;

	if(argc !=3 ){
		printf("Usage :\n");
		printf("%s <nelem> <nthreads> \n",argv[0]);
		return EXIT_FAILURE;
	}

	if(argc ==3 ){
		nelem = strtoul(argv[1], NULL,0);
		nthreads = atoi(argv[2]);
	}

	uint64_t ii, jj;
	std::vector<std::string> data;

	int string_size = 100;
	/////  generation of random strings

	char * tempchar = (char *) malloc(string_size*sizeof(char));

	//string lolstr;
	//ifstream inputfile("StringFile.txt",ios::in);
	for (u_int64_t i = 0; i < nelem; i++){
		//RANDOM STRINGS
		 gen_random(tempchar,string_size);
		 data.push_back((string)tempchar);

		//STRING READ FROM FILE
		//getline(inputfile,lolstr);
		//data.push_back(lolstr);
	}

	//////////////////
	// at this point, array data contains a set of nelem random unique keys

	boophf_t * bphf = NULL;
	double t_begin,t_end; struct timeval timet;

	printf("Construct a BooPHF with  %lli elements  \n",nelem);

	gettimeofday(&timet, NULL); t_begin = timet.tv_sec +(timet.tv_usec/1000000.0);

	// mphf takes as input a c++ range. A std::vector is already a c++ range

	double gammaFactor = 2.0; // lowest bit/elem is achieved with gamma=1, higher values lead to larger mphf but faster construction/query
	// gamma = 2 is a good tradeoff (leads to approx 3.7 bits/key )

	//build the mphf
	bphf = new boomphf::mphf<std::string,Custom_string_Hasher>(nelem,data,nthreads,gammaFactor);

	gettimeofday(&timet, NULL); t_end = timet.tv_sec +(timet.tv_usec/1000000.0);
	double elapsed = t_end - t_begin;

	printf("BooPHF constructed perfect hash for %llu keys in %.2fs\n", nelem,elapsed);
	printf("boophf  bits/elem : %f\n",(float) (bphf->totalBitSize())/nelem);
	gettimeofday(&timet, NULL); t_begin = timet.tv_sec +(timet.tv_usec/1000000.0);
	//query mphf like this
	for (u_int64_t i = 0; i < 1000000; i++){
		uint64_t  idx = bphf->lookup(data[i]);
	}
	gettimeofday(&timet, NULL); t_end = timet.tv_sec +(timet.tv_usec/1000000.0);
	double elapsed2 = t_end - t_begin;
	printf("Query of %llu key  in %.2fs\n", nelem,elapsed2);

	delete bphf;
	return EXIT_SUCCESS;
}
<|endoftext|>