<commit_before>#include <am/bitmap/Ewah.h>

#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>

#include <fstream>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace izenelib::am;
namespace bfs = boost::filesystem;

const char* BITMAP_TEST_DIR_STR = "bitmap";

template<class uword>
bool testRunningLengthWord() {
    cout << "[testing RunningLengthWord]" << endl;
    bool isOk(true);
    uword somenumber(0xABCD);
    RunningLengthWord<uword> rlw(somenumber);
    rlw.setRunningBit(true);
    if (rlw.getRunningBit() != true) {
        cout << "failed to set the running bit " << sizeof (uword) << endl;
        isOk = false;
    }
    for (uword myrl = 0; myrl <= RunningLengthWord<uword>::largestrunninglengthcount; myrl+=RunningLengthWord<uword>::largestrunninglengthcount/10) {
        rlw.setRunningLength(myrl);
        if (rlw.getRunningBit() != true) {
            cout << "failed to set the running bit (2) " << sizeof (uword) << endl;
            isOk = false;
        }
        if (rlw.getRunningLength() != myrl) {
            cout << "failed to set the running length " << sizeof (uword) << endl;
            isOk = false;
        }
    }
    rlw.setRunningLength(12);
    for (uword mylw = 0; mylw <= RunningLengthWord<uword>::largestliteralcount; mylw+=RunningLengthWord<uword>::largestliteralcount/10) {
        rlw.setNumberOfLiteralWords(mylw);
        if (rlw.getRunningBit() != true) {
            cout << "failed to set the running bit (3) " << sizeof (uword) << endl;
            isOk = false;
        }
        if (rlw.getRunningLength() != 12) {
            cout << "failed to set the running length (2) " << sizeof (uword) << endl;
            isOk = false;
        }
        if (rlw.getNumberOfLiteralWords() != mylw) {
            cout << "failed to set the LiteralWords " <<mylw << " "<<sizeof (uword)<<" "<<rlw.getNumberOfLiteralWords() << endl;
            isOk = false;
        }
    }
    rlw.setNumberOfLiteralWords(43);
    rlw.setRunningBit(false);
    if (rlw.getRunningBit() != false) {
        cout << "failed to set the running bit (4) " << sizeof (uword) << endl;
        isOk = false;
    }
    if (rlw.getRunningLength() != 12) {
        cout << "failed to set the running length (3) " << sizeof (uword) << endl;
        isOk = false;
    }
    if (rlw.getNumberOfLiteralWords() != 43) {
        cout << "failed to set the LiteralWords (2) " << sizeof (uword) << endl;
        isOk = false;
    }
    return isOk;
}

template <class uword>
bool testEWAHBoolArrayAppend() {
    cout << "[testing EWAHBoolArrayAppend]" << endl;
    bool isOk(true);
    uword zero = 0;
    uword specialval = 1UL + (1UL << 4)+(static_cast<uword>(1) << (sizeof(uword)*8-1));
    uword notzero = ~zero;
    EWAHBoolArray<uword> myarray1;
    BoolArray<uword> ba1;
    myarray1.add(zero);
    ba1.add(zero);
    myarray1.add(zero);
    ba1.add(zero);
    myarray1.add(zero);
    ba1.add(zero);
    myarray1.add(specialval);
    ba1.add(specialval);
    myarray1.add(specialval);
    ba1.add(specialval);
    myarray1.add(notzero);
    ba1.add(notzero);
    myarray1.add(zero);
    ba1.add(zero);
    EWAHBoolArray<uword> myarray2;
    BoolArray<uword> ba2;
    myarray2.add(notzero);
    ba2.add(notzero);
    myarray2.add(zero);
    ba2.add(zero);
    myarray2.add(notzero);
    ba2.add(notzero);
    myarray2.add(specialval);
    ba2.add(specialval);
    myarray2.add(specialval);
    ba2.add(specialval);
    myarray2.add(notzero);
    ba2.add(notzero);
    BoolArray<uword> aggregate1(ba1);
    BoolArray<uword> aggregate2(ba2);
    aggregate1.append(ba2);
    aggregate2.append(ba1);
    EWAHBoolArray<uword> caggregate1;
    caggregate1.append(myarray1);
    EWAHBoolArray<uword> caggregate2;
    caggregate2.append(myarray2);
    caggregate1.append(myarray2);
    caggregate2.append(myarray1);
    BoolArray<uword> aggregate1a;
    caggregate1.toBoolArray(aggregate1a);
    if (aggregate1a != aggregate1) {
        cout << "aggregate 1 failed" << endl;
        isOk = false;
    }
    BoolArray<uword> aggregate2a;
    caggregate2.toBoolArray(aggregate2a);
    if (aggregate2a != aggregate2) {
        cout << "aggregate 2 failed" << endl;
        isOk = false;
    }
    return isOk;
}

template<class uword>
bool testEWAHBoolArray() {
    cout << "[testing EWAHBoolArray]" << endl;
    bool isOk(true);
    EWAHBoolArray<uword> myarray;
    BoolArray<uword> ba(10 * sizeof (uword) * 8);
    uword zero = 0;
    uword notzero = ~zero;
    myarray.add(zero);
    ba.setWord(0, zero);
    myarray.add(zero);
    ba.setWord(1, zero);
    myarray.add(zero);
    ba.setWord(2, zero);
    uword specialval = 1UL + (1UL << 4)+(static_cast<uword>(1) << (sizeof(uword)*8-1));
    myarray.add(specialval);
    ba.setWord(3, specialval);
    myarray.add(notzero);
    ba.setWord(4, notzero);
    myarray.add(notzero);
    ba.setWord(5, notzero);
    myarray.add(notzero);
    ba.setWord(6, notzero);
    myarray.add(notzero);
    ba.setWord(7, notzero);
    myarray.add(specialval);
    ba.setWord(8, specialval);
    myarray.add(zero);
    ba.setWord(9, zero);
    if (myarray.sizeInBits() != 10 * sizeof (uword) * 8) {
        cout << "expected " << 10 * sizeof (uword) * 8 << " bits but found " << myarray.sizeInBits() << endl;
        isOk = false;
    }

    bfs::path bitmapDir(BITMAP_TEST_DIR_STR);
    boost::filesystem::remove_all(bitmapDir);
    bfs::create_directories(bitmapDir);
    std::string bitmap_dir_str = bitmapDir.string();
    std::string indexfile(bitmap_dir_str+"/testingewahboolarray.bin");

    ofstream out(indexfile.c_str(), ios::out | ios::binary);
    myarray.write(out);
    out.close();
    EWAHBoolArray<uword> lmyarray;
    ifstream in(indexfile.c_str());
    lmyarray.read(in);
    in.close();
    BOOST_CHECK(myarray == lmyarray);
    {
    izene_serialization_febird<EWAHBoolArray<uword> > isb(myarray);
    char* ptr;
    size_t sz;
    isb.write_image(ptr, sz);
    EWAHBoolArray<uword> newarray;

    izene_deserialization_febird<EWAHBoolArray<uword> > idb(ptr, sz);
    idb.read_image(newarray);
    BOOST_CHECK(myarray == newarray);
    }

    EWAHBoolArrayIterator<uword> i = myarray.uncompress();
    EWAHBoolArrayIterator<uword> j = lmyarray.uncompress();
    uint k = 0;
    while (i.hasNext()) {
        if (!j.hasNext()) {
            cout<<"the two arrays don't have the same size?"<<endl;
            isOk = false;
            break;
        }
        uword val = i.next();
        uword val2 = j.next();
        uword valref = ba.getWord(k++);
        if (val != valref) {
            cout<<"the two arrays differ from uncompressed array at "<<k<<" "<< val<< " "<< val2<<" " <<valref << endl;
            isOk = false;
        }
        if (val != val2) {
            cout<<"the two arrays differ at "<<k<<" "<< val<< " "<< val2<<" " <<valref << endl;
            isOk = false;
        }
    }
    return isOk;
}

template<class uword>
bool testEWAHBoolArrayLogical() {
    cout << "[testing EWAHBoolArrayLogical]" << endl;
    bool isOk(true);
    EWAHBoolArray<uword> myarray1;
    EWAHBoolArray<uword> myarray2;
    const uint N=15;
    uword allones = static_cast<uword>(~0L);
    uword x1[N] ={1,54,24,145,0,0,0,allones,allones,allones,43,0,0,0,1};
    uword x2[N] ={allones,0,0,0,0,0,0,0,allones,allones,allones,0,4,0,0};
    uword xand[N];
    uword xxor[N];
    for(uint k = 0; k < N; ++k) {
        myarray1.add(x1[k]);
        myarray2.add(x2[k]);
        xand[k] = x1[k] & x2[k];
        xxor[k] = x1[k] | x2[k];
    }
    EWAHBoolArray<uword> myand;
    EWAHBoolArray<uword> mysparseand;
    EWAHBoolArray<uword> myor;
    myarray1.rawlogicaland(myarray2,myand);
    myarray1.sparselogicaland(myarray2,mysparseand);
    myarray1.rawlogicalor(myarray2,myor);
    EWAHBoolArrayIterator<uword> i = myand.uncompress();
    EWAHBoolArrayIterator<uword> ii = mysparseand.uncompress();
    EWAHBoolArrayIterator<uword> j = myor.uncompress();
    EWAHBoolArrayIterator<uword> it1 = myarray1.uncompress();
    EWAHBoolArrayIterator<uword> it2 = myarray2.uncompress();
    for(uint k = 0; k <N;++k) {
        const uword m1 = it1.next();
        const uword m2 = it2.next();
        if(!i.hasNext()) {
            cout<<"type 1 error"<<endl;
            isOk=false; break;
        }
        if(!ii.hasNext()) {
            cout<<"type 2 error"<<endl;
            isOk=false; break;
        }
        if(!j.hasNext()) {
            cout<<"type 3 error"<<endl;
            isOk=false; break;
        }
        if(i.next()!= xand[k]){
            cout<<"type 4 error"<<endl;
            isOk=false; break;
        }
        if(ii.next()!= xand[k]){
            cout<<"type 5 error"<<endl;
            isOk=false; break;
        }
        const uword jor = j.next();
        if(jor!= xxor[k]){
            cout<<m1<<" or "<< m2<<" = "<< xxor[k] << " but got "<<jor <<endl;
            cout<<"type 6 error OR"<<endl;
            isOk=false; break;
        }
    }
    return isOk;
}

BOOST_AUTO_TEST_SUITE(bitmap_ewah_test)

BOOST_AUTO_TEST_CASE(runningLength)
{
    BOOST_CHECK(testRunningLengthWord<uint16_t > ());
    BOOST_CHECK(testRunningLengthWord<uint32_t > ());
    BOOST_CHECK(testRunningLengthWord<uint64_t > ());
}

BOOST_AUTO_TEST_CASE(ewahBoolArray)
{
    BOOST_CHECK(testEWAHBoolArray<uint16_t > ());
    BOOST_CHECK(testEWAHBoolArray<uint32_t > ());
    BOOST_CHECK(testEWAHBoolArray<uint64_t > ());
}

BOOST_AUTO_TEST_CASE(ewahBoolArrayLogical)
{
    BOOST_CHECK(testEWAHBoolArrayLogical<uint16_t > ());
    BOOST_CHECK(testEWAHBoolArrayLogical<uint32_t > ());
    BOOST_CHECK(testEWAHBoolArrayLogical<uint64_t > ());
}

BOOST_AUTO_TEST_CASE(ewahBoolArrayAppend)
{
    BOOST_CHECK(testEWAHBoolArrayAppend<uint16_t > ());
    BOOST_CHECK(testEWAHBoolArrayAppend<uint32_t > ());
    BOOST_CHECK(testEWAHBoolArrayAppend<uint64_t > ());
}

BOOST_AUTO_TEST_CASE(ewahBoolArrayBench)
{
    EWAHBoolArray<uint32_t> myarray;
    size_t max = 10000000;
    size_t i = 1;
    size_t maxstep = 10;
    size_t count = 0;
    for(; i < max; )
    {
        i += (1+rand() % maxstep);
        myarray.set(i);
        ++count;
    }
    /*
    EWAHBoolArrayBitIterator<uint32_t> iter = myarray.bit_iterator();

    i = 1;
    while(iter.next())
    {
        BOOST_CHECK((i++) ==iter.getCurr());
    }
    BOOST_CHECK(i = max);
    */
    std::cout<<"count "<<count<<" sizeInBytes "<<myarray.sizeInBytes()<<std::endl;
}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>add bit iterator test case of ewah bitmap<commit_after>#include <am/bitmap/Ewah.h>

#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>

#include <fstream>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace izenelib::am;
namespace bfs = boost::filesystem;

const char* BITMAP_TEST_DIR_STR = "bitmap";

template<class uword>
bool testRunningLengthWord() {
    cout << "[testing RunningLengthWord]" << endl;
    bool isOk(true);
    uword somenumber(0xABCD);
    RunningLengthWord<uword> rlw(somenumber);
    rlw.setRunningBit(true);
    if (rlw.getRunningBit() != true) {
        cout << "failed to set the running bit " << sizeof (uword) << endl;
        isOk = false;
    }
    for (uword myrl = 0; myrl <= RunningLengthWord<uword>::largestrunninglengthcount; myrl+=RunningLengthWord<uword>::largestrunninglengthcount/10) {
        rlw.setRunningLength(myrl);
        if (rlw.getRunningBit() != true) {
            cout << "failed to set the running bit (2) " << sizeof (uword) << endl;
            isOk = false;
        }
        if (rlw.getRunningLength() != myrl) {
            cout << "failed to set the running length " << sizeof (uword) << endl;
            isOk = false;
        }
    }
    rlw.setRunningLength(12);
    for (uword mylw = 0; mylw <= RunningLengthWord<uword>::largestliteralcount; mylw+=RunningLengthWord<uword>::largestliteralcount/10) {
        rlw.setNumberOfLiteralWords(mylw);
        if (rlw.getRunningBit() != true) {
            cout << "failed to set the running bit (3) " << sizeof (uword) << endl;
            isOk = false;
        }
        if (rlw.getRunningLength() != 12) {
            cout << "failed to set the running length (2) " << sizeof (uword) << endl;
            isOk = false;
        }
        if (rlw.getNumberOfLiteralWords() != mylw) {
            cout << "failed to set the LiteralWords " <<mylw << " "<<sizeof (uword)<<" "<<rlw.getNumberOfLiteralWords() << endl;
            isOk = false;
        }
    }
    rlw.setNumberOfLiteralWords(43);
    rlw.setRunningBit(false);
    if (rlw.getRunningBit() != false) {
        cout << "failed to set the running bit (4) " << sizeof (uword) << endl;
        isOk = false;
    }
    if (rlw.getRunningLength() != 12) {
        cout << "failed to set the running length (3) " << sizeof (uword) << endl;
        isOk = false;
    }
    if (rlw.getNumberOfLiteralWords() != 43) {
        cout << "failed to set the LiteralWords (2) " << sizeof (uword) << endl;
        isOk = false;
    }
    return isOk;
}

template <class uword>
bool testEWAHBoolArrayAppend() {
    cout << "[testing EWAHBoolArrayAppend]" << endl;
    bool isOk(true);
    uword zero = 0;
    uword specialval = 1UL + (1UL << 4)+(static_cast<uword>(1) << (sizeof(uword)*8-1));
    uword notzero = ~zero;
    EWAHBoolArray<uword> myarray1;
    BoolArray<uword> ba1;
    myarray1.add(zero);
    ba1.add(zero);
    myarray1.add(zero);
    ba1.add(zero);
    myarray1.add(zero);
    ba1.add(zero);
    myarray1.add(specialval);
    ba1.add(specialval);
    myarray1.add(specialval);
    ba1.add(specialval);
    myarray1.add(notzero);
    ba1.add(notzero);
    myarray1.add(zero);
    ba1.add(zero);
    EWAHBoolArray<uword> myarray2;
    BoolArray<uword> ba2;
    myarray2.add(notzero);
    ba2.add(notzero);
    myarray2.add(zero);
    ba2.add(zero);
    myarray2.add(notzero);
    ba2.add(notzero);
    myarray2.add(specialval);
    ba2.add(specialval);
    myarray2.add(specialval);
    ba2.add(specialval);
    myarray2.add(notzero);
    ba2.add(notzero);
    BoolArray<uword> aggregate1(ba1);
    BoolArray<uword> aggregate2(ba2);
    aggregate1.append(ba2);
    aggregate2.append(ba1);
    EWAHBoolArray<uword> caggregate1;
    caggregate1.append(myarray1);
    EWAHBoolArray<uword> caggregate2;
    caggregate2.append(myarray2);
    caggregate1.append(myarray2);
    caggregate2.append(myarray1);
    BoolArray<uword> aggregate1a;
    caggregate1.toBoolArray(aggregate1a);
    if (aggregate1a != aggregate1) {
        cout << "aggregate 1 failed" << endl;
        isOk = false;
    }
    BoolArray<uword> aggregate2a;
    caggregate2.toBoolArray(aggregate2a);
    if (aggregate2a != aggregate2) {
        cout << "aggregate 2 failed" << endl;
        isOk = false;
    }
    return isOk;
}

template<class uword>
bool testEWAHBoolArray() {
    cout << "[testing EWAHBoolArray]" << endl;
    bool isOk(true);
    EWAHBoolArray<uword> myarray;
    BoolArray<uword> ba(10 * sizeof (uword) * 8);
    uword zero = 0;
    uword notzero = ~zero;
    myarray.add(zero);
    ba.setWord(0, zero);
    myarray.add(zero);
    ba.setWord(1, zero);
    myarray.add(zero);
    ba.setWord(2, zero);
    uword specialval = 1UL + (1UL << 4)+(static_cast<uword>(1) << (sizeof(uword)*8-1));
    myarray.add(specialval);
    ba.setWord(3, specialval);
    myarray.add(notzero);
    ba.setWord(4, notzero);
    myarray.add(notzero);
    ba.setWord(5, notzero);
    myarray.add(notzero);
    ba.setWord(6, notzero);
    myarray.add(notzero);
    ba.setWord(7, notzero);
    myarray.add(specialval);
    ba.setWord(8, specialval);
    myarray.add(zero);
    ba.setWord(9, zero);
    if (myarray.sizeInBits() != 10 * sizeof (uword) * 8) {
        cout << "expected " << 10 * sizeof (uword) * 8 << " bits but found " << myarray.sizeInBits() << endl;
        isOk = false;
    }

    bfs::path bitmapDir(BITMAP_TEST_DIR_STR);
    boost::filesystem::remove_all(bitmapDir);
    bfs::create_directories(bitmapDir);
    std::string bitmap_dir_str = bitmapDir.string();
    std::string indexfile(bitmap_dir_str+"/testingewahboolarray.bin");

    ofstream out(indexfile.c_str(), ios::out | ios::binary);
    myarray.write(out);
    out.close();
    EWAHBoolArray<uword> lmyarray;
    ifstream in(indexfile.c_str());
    lmyarray.read(in);
    in.close();
    BOOST_CHECK(myarray == lmyarray);
    {
    izene_serialization_febird<EWAHBoolArray<uword> > isb(myarray);
    char* ptr;
    size_t sz;
    isb.write_image(ptr, sz);
    EWAHBoolArray<uword> newarray;

    izene_deserialization_febird<EWAHBoolArray<uword> > idb(ptr, sz);
    idb.read_image(newarray);
    BOOST_CHECK(myarray == newarray);
    }

    EWAHBoolArrayIterator<uword> i = myarray.uncompress();
    EWAHBoolArrayIterator<uword> j = lmyarray.uncompress();
    uint k = 0;
    while (i.hasNext()) {
        if (!j.hasNext()) {
            cout<<"the two arrays don't have the same size?"<<endl;
            isOk = false;
            break;
        }
        uword val = i.next();
        uword val2 = j.next();
        uword valref = ba.getWord(k++);
        if (val != valref) {
            cout<<"the two arrays differ from uncompressed array at "<<k<<" "<< val<< " "<< val2<<" " <<valref << endl;
            isOk = false;
        }
        if (val != val2) {
            cout<<"the two arrays differ at "<<k<<" "<< val<< " "<< val2<<" " <<valref << endl;
            isOk = false;
        }
    }
    return isOk;
}

template<class uword>
bool testEWAHBoolArrayLogical() {
    cout << "[testing EWAHBoolArrayLogical]" << endl;
    bool isOk(true);
    EWAHBoolArray<uword> myarray1;
    EWAHBoolArray<uword> myarray2;
    const uint N=15;
    uword allones = static_cast<uword>(~0L);
    uword x1[N] ={1,54,24,145,0,0,0,allones,allones,allones,43,0,0,0,1};
    uword x2[N] ={allones,0,0,0,0,0,0,0,allones,allones,allones,0,4,0,0};
    uword xand[N];
    uword xxor[N];
    for(uint k = 0; k < N; ++k) {
        myarray1.add(x1[k]);
        myarray2.add(x2[k]);
        xand[k] = x1[k] & x2[k];
        xxor[k] = x1[k] | x2[k];
    }
    EWAHBoolArray<uword> myand;
    EWAHBoolArray<uword> mysparseand;
    EWAHBoolArray<uword> myor;
    myarray1.rawlogicaland(myarray2,myand);
    myarray1.sparselogicaland(myarray2,mysparseand);
    myarray1.rawlogicalor(myarray2,myor);
    EWAHBoolArrayIterator<uword> i = myand.uncompress();
    EWAHBoolArrayIterator<uword> ii = mysparseand.uncompress();
    EWAHBoolArrayIterator<uword> j = myor.uncompress();
    EWAHBoolArrayIterator<uword> it1 = myarray1.uncompress();
    EWAHBoolArrayIterator<uword> it2 = myarray2.uncompress();
    for(uint k = 0; k <N;++k) {
        const uword m1 = it1.next();
        const uword m2 = it2.next();
        if(!i.hasNext()) {
            cout<<"type 1 error"<<endl;
            isOk=false; break;
        }
        if(!ii.hasNext()) {
            cout<<"type 2 error"<<endl;
            isOk=false; break;
        }
        if(!j.hasNext()) {
            cout<<"type 3 error"<<endl;
            isOk=false; break;
        }
        if(i.next()!= xand[k]){
            cout<<"type 4 error"<<endl;
            isOk=false; break;
        }
        if(ii.next()!= xand[k]){
            cout<<"type 5 error"<<endl;
            isOk=false; break;
        }
        const uword jor = j.next();
        if(jor!= xxor[k]){
            cout<<m1<<" or "<< m2<<" = "<< xxor[k] << " but got "<<jor <<endl;
            cout<<"type 6 error OR"<<endl;
            isOk=false; break;
        }
    }
    return isOk;
}

BOOST_AUTO_TEST_SUITE(bitmap_ewah_test)

BOOST_AUTO_TEST_CASE(runningLength)
{
    BOOST_CHECK(testRunningLengthWord<uint16_t > ());
    BOOST_CHECK(testRunningLengthWord<uint32_t > ());
    BOOST_CHECK(testRunningLengthWord<uint64_t > ());
}

BOOST_AUTO_TEST_CASE(ewahBoolArray)
{
    BOOST_CHECK(testEWAHBoolArray<uint16_t > ());
    BOOST_CHECK(testEWAHBoolArray<uint32_t > ());
    BOOST_CHECK(testEWAHBoolArray<uint64_t > ());
}

BOOST_AUTO_TEST_CASE(ewahBoolArrayLogical)
{
    BOOST_CHECK(testEWAHBoolArrayLogical<uint16_t > ());
    BOOST_CHECK(testEWAHBoolArrayLogical<uint32_t > ());
    BOOST_CHECK(testEWAHBoolArrayLogical<uint64_t > ());
}

BOOST_AUTO_TEST_CASE(ewahBoolArrayAppend)
{
    BOOST_CHECK(testEWAHBoolArrayAppend<uint16_t > ());
    BOOST_CHECK(testEWAHBoolArrayAppend<uint32_t > ());
    BOOST_CHECK(testEWAHBoolArrayAppend<uint64_t > ());
}

BOOST_AUTO_TEST_CASE(ewahBoolArrayBench)
{
    EWAHBoolArray<uint32_t> myarray;
    size_t max = 10000000;
    size_t i = 1;
    size_t maxstep = 10;
    size_t count = 0;
    for(; i < max; )
    {
        i += (1+rand() % maxstep);
        myarray.set(i);
        ++count;
    }
    /*
    EWAHBoolArrayBitIterator<uint32_t> iter = myarray.bit_iterator();

    i = 1;
    while(iter.next())
    {
        BOOST_CHECK((i++) ==iter.getCurr());
    }
    BOOST_CHECK(i = max);
    */
    std::cout<<"count "<<count<<" sizeInBytes "<<myarray.sizeInBytes()<<std::endl;
}

BOOST_AUTO_TEST_CASE(ewahBitIterator)
{
    EWAHBoolArray<uint32_t> myarray1;
    BoolArray<uint32_t> boolarray1;
    size_t max = 2000; //10000000;
    size_t maxstep = 100;
    size_t i = 1;

    for(; i < max; )
    {
        myarray1.set(i);
        i += (1 + rand() % maxstep);
    }

    myarray1.toBoolArray(boolarray1);
    EWAHBoolArrayBitIterator<uint32_t> iter = myarray1.bit_iterator();
    while(iter.next())
    {
        BOOST_CHECK( boolarray1.get(iter.getCurr()) == true);
    }
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file createRandomTest.cpp
 * @author Christoph Jentzsch <jentzsch.simulationsoftware@gmail.com>
 * @date 2014
 * Creating a random virtual machine test.
 */

#include <string>
#include <iostream>
#include <chrono>
#include <boost/random.hpp>
#include <boost/filesystem/path.hpp>
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <json_spirit/json_spirit.h>
#include <json_spirit/json_spirit_reader_template.h>
#include <json_spirit/json_spirit_writer_template.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h>
#include <libevmcore/Instruction.h>
#include <libevm/VMFactory.h>
#include "vm.h"

using namespace std;
using namespace json_spirit;
using namespace dev;

void doMyTests(json_spirit::mValue& v);

int main(int argc, char *argv[])
{
	g_logVerbosity = 0;

	// create random code

	boost::random::mt19937 gen;

	auto now = chrono::steady_clock::now().time_since_epoch();
	auto timeSinceEpoch = chrono::duration_cast<chrono::nanoseconds>(now).count();
	gen.seed(static_cast<unsigned int>(timeSinceEpoch));
	boost::random::uniform_int_distribution<> lengthOfCodeDist(2, 16);
	boost::random::uniform_int_distribution<> opcodeDist(0, 255);
	boost::random::uniform_int_distribution<> BlockInfoOpcodeDist(0x41, 0x45);
	boost::random::variate_generator<boost::mt19937&,
			boost::random::uniform_int_distribution<> > randGen(gen, opcodeDist);
	boost::random::variate_generator<boost::mt19937&,
			boost::random::uniform_int_distribution<> > randGenBlockInfoOpcode(gen, BlockInfoOpcodeDist);

	int lengthOfCode  = lengthOfCodeDist(gen);
	string randomCode;

	for (int i = 0; i < lengthOfCode; ++i)
	{
		if (i < 8 && (randGen() < 192))
		{
			randomCode += toHex(toCompactBigEndian((uint8_t)randGenBlockInfoOpcode()));
			continue;
		}

		uint8_t opcode = randGen();
		// disregard all invalid commands, except of one (0x0c)
		if (dev::eth::isValidInstruction(dev::eth::Instruction(opcode)) || opcode == 0x0a)
			randomCode += toHex(toCompactBigEndian(opcode));
		else
			i--;
	}

	const string s =\
"{\n\
	\"randomVMtest\": {\n\
		\"env\" : {\n\
			\"previousHash\" : \"5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6\",\n\
			\"currentNumber\" : \"0\",\n\
			\"currentGasLimit\" : \"115792089237316195423570985008687907853269984665640564039457584007913129639935\",\n\
			\"currentDifficulty\" : \"1\",\n\
			\"currentTimestamp\" : 2,\n\
			\"currentCoinbase\" : \"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba\"\n\
		},\n\
		\"pre\" : {\n\
			\"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6\" : {\n\
				\"balance\" : \"1000000000000000000\",\n\
				\"nonce\" : 0,\n\
				\"code\" : \"random\",\n\
				\"storage\": {}\n\
			}\n\
		},\n\
		\"exec\" : {\n\
			\"address\" : \"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6\",\n\
			\"origin\" : \"cd1722f3947def4cf144679da39c4c32bdc35681\",\n\
			\"caller\" : \"cd1722f3947def4cf144679da39c4c32bdc35681\",\n\
			\"value\" : \"1000000000000000000\",\n\
			\"data\" : \"\",\n\
			\"gasPrice\" : \"100000000000000\",\n\
			\"gas\" : \"10000\"\n\
		}\n\
	}\n\
}";

	mValue v;
	read_string(s, v);

	// insert new random code
	v.get_obj().find("randomVMtest")->second.get_obj().find("pre")->second.get_obj().begin()->second.get_obj()["code"] = "0x" + randomCode + "55";

	// execute code in vm
	doMyTests(v);

	// stream to output for further handling by the bash script
	cout << json_spirit::write_string(v, true);

	return 0;
}

void doMyTests(json_spirit::mValue& v)
{
	for (auto& i: v.get_obj())
	{
		cnote << i.first;
		mObject& o = i.second.get_obj();

		assert(o.count("env") > 0);
		assert(o.count("pre") > 0);
		assert(o.count("exec") > 0);

		dev::test::FakeExtVM fev;
		fev.importEnv(o["env"].get_obj());
		fev.importState(o["pre"].get_obj());

		o["pre"] = mValue(fev.exportState());

		fev.importExec(o["exec"].get_obj());
		if (fev.code.empty())
		{
			fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress));
			fev.code = fev.thisTxCode;
		}

		bytes output;
		auto vm = eth::VMFactory::create(fev.gas);

		u256 gas;
		bool vmExceptionOccured = false;
		try
		{
			output = vm->go(fev, fev.simpleTrace()).toBytes();
			gas = vm->gas();
		}
		catch (eth::VMException const& _e)
		{
			cnote << "VM did throw an exception: " << diagnostic_information(_e);
			vmExceptionOccured = true;
		}
		catch (Exception const& _e)
		{
			cnote << "VM did throw an exception: " << diagnostic_information(_e);
		}
		catch (std::exception const& _e)
		{
			cnote << "VM did throw an exception: " << _e.what();
		}

		// delete null entries in storage for the sake of comparison

		for (auto  &a: fev.addresses)
		{
			vector<u256> keystoDelete;
			for (auto &s: get<2>(a.second))
			{
				if (s.second == 0)
					keystoDelete.push_back(s.first);
			}
			for (auto const key: keystoDelete )
			{
				get<2>(a.second).erase(key);
			}
		}

		o["env"] = mValue(fev.exportEnv());
		o["exec"] = mValue(fev.exportExec());
		if (!vmExceptionOccured)
		{
			o["post"] = mValue(fev.exportState());
			o["callcreates"] = fev.exportCallCreates();
			o["out"] = "0x" + toHex(output);
			fev.push(o, "gas", gas);
			o["logs"] = test::exportLog(fev.sub.logs);
		}
	}
}
<commit_msg>rests current gas limit in vm test<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum 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.

	cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file createRandomTest.cpp
 * @author Christoph Jentzsch <jentzsch.simulationsoftware@gmail.com>
 * @date 2014
 * Creating a random virtual machine test.
 */

#include <string>
#include <iostream>
#include <chrono>
#include <boost/random.hpp>
#include <boost/filesystem/path.hpp>
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <json_spirit/json_spirit.h>
#include <json_spirit/json_spirit_reader_template.h>
#include <json_spirit/json_spirit_writer_template.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h>
#include <libevmcore/Instruction.h>
#include <libevm/VMFactory.h>
#include "vm.h"

using namespace std;
using namespace json_spirit;
using namespace dev;

void doMyTests(json_spirit::mValue& v);

int main(int argc, char *argv[])
{
	g_logVerbosity = 0;

	// create random code

	boost::random::mt19937 gen;

	auto now = chrono::steady_clock::now().time_since_epoch();
	auto timeSinceEpoch = chrono::duration_cast<chrono::nanoseconds>(now).count();
	gen.seed(static_cast<unsigned int>(timeSinceEpoch));
	boost::random::uniform_int_distribution<> lengthOfCodeDist(2, 16);
	boost::random::uniform_int_distribution<> opcodeDist(0, 255);
	boost::random::uniform_int_distribution<> BlockInfoOpcodeDist(0x41, 0x45);
	boost::random::variate_generator<boost::mt19937&,
			boost::random::uniform_int_distribution<> > randGen(gen, opcodeDist);
	boost::random::variate_generator<boost::mt19937&,
			boost::random::uniform_int_distribution<> > randGenBlockInfoOpcode(gen, BlockInfoOpcodeDist);

	int lengthOfCode  = lengthOfCodeDist(gen);
	string randomCode;

	for (int i = 0; i < lengthOfCode; ++i)
	{
		if (i < 8 && (randGen() < 192))
		{
			randomCode += toHex(toCompactBigEndian((uint8_t)randGenBlockInfoOpcode()));
			continue;
		}

		uint8_t opcode = randGen();
		// disregard all invalid commands, except of one (0x0c)
		if (dev::eth::isValidInstruction(dev::eth::Instruction(opcode)) || opcode == 0x0a)
			randomCode += toHex(toCompactBigEndian(opcode));
		else
			i--;
	}

	const string s =\
"{\n\
	\"randomVMtest\": {\n\
		\"env\" : {\n\
			\"previousHash\" : \"5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6\",\n\
			\"currentNumber\" : \"0\",\n\
			\"currentGasLimit\" : \"1000000\",\n\
			\"currentDifficulty\" : \"115792089237316195423570985008687907853269984665640564039457584007913129639935\",\n\
			\"currentTimestamp\" : 2,\n\
			\"currentCoinbase\" : \"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba\"\n\
		},\n\
		\"pre\" : {\n\
			\"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6\" : {\n\
				\"balance\" : \"1000000000000000000\",\n\
				\"nonce\" : 0,\n\
				\"code\" : \"random\",\n\
				\"storage\": {}\n\
			}\n\
		},\n\
		\"exec\" : {\n\
			\"address\" : \"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6\",\n\
			\"origin\" : \"cd1722f3947def4cf144679da39c4c32bdc35681\",\n\
			\"caller\" : \"cd1722f3947def4cf144679da39c4c32bdc35681\",\n\
			\"value\" : \"1000000000000000000\",\n\
			\"data\" : \"\",\n\
			\"gasPrice\" : \"100000000000000\",\n\
			\"gas\" : \"10000\"\n\
		}\n\
	}\n\
}";

	mValue v;
	read_string(s, v);

	// insert new random code
	v.get_obj().find("randomVMtest")->second.get_obj().find("pre")->second.get_obj().begin()->second.get_obj()["code"] = "0x" + randomCode + "55";

	// execute code in vm
	doMyTests(v);

	// stream to output for further handling by the bash script
	cout << json_spirit::write_string(v, true);

	return 0;
}

void doMyTests(json_spirit::mValue& v)
{
	for (auto& i: v.get_obj())
	{
		cnote << i.first;
		mObject& o = i.second.get_obj();

		assert(o.count("env") > 0);
		assert(o.count("pre") > 0);
		assert(o.count("exec") > 0);

		dev::test::FakeExtVM fev;
		fev.importEnv(o["env"].get_obj());
		fev.importState(o["pre"].get_obj());

		o["pre"] = mValue(fev.exportState());

		fev.importExec(o["exec"].get_obj());
		if (fev.code.empty())
		{
			fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress));
			fev.code = fev.thisTxCode;
		}

		bytes output;
		auto vm = eth::VMFactory::create(fev.gas);

		u256 gas;
		bool vmExceptionOccured = false;
		try
		{
			output = vm->go(fev, fev.simpleTrace()).toBytes();
			gas = vm->gas();
		}
		catch (eth::VMException const& _e)
		{
			cnote << "VM did throw an exception: " << diagnostic_information(_e);
			vmExceptionOccured = true;
		}
		catch (Exception const& _e)
		{
			cnote << "VM did throw an exception: " << diagnostic_information(_e);
		}
		catch (std::exception const& _e)
		{
			cnote << "VM did throw an exception: " << _e.what();
		}

		// delete null entries in storage for the sake of comparison

		for (auto  &a: fev.addresses)
		{
			vector<u256> keystoDelete;
			for (auto &s: get<2>(a.second))
			{
				if (s.second == 0)
					keystoDelete.push_back(s.first);
			}
			for (auto const key: keystoDelete )
			{
				get<2>(a.second).erase(key);
			}
		}

		o["env"] = mValue(fev.exportEnv());
		o["exec"] = mValue(fev.exportExec());
		if (!vmExceptionOccured)
		{
			o["post"] = mValue(fev.exportState());
			o["callcreates"] = fev.exportCallCreates();
			o["out"] = "0x" + toHex(output);
			fev.push(o, "gas", gas);
			o["logs"] = test::exportLog(fev.sub.logs);
		}
	}
}
<|endoftext|>


<commit_before>#include <cppunit/extensions/HelperMacros.h>
#include "csv_iterator.hpp"

#include <vector>
#include <string>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>

class csv_iteratorTest : public CppUnit::TestFixture {
    CPPUNIT_TEST_SUITE(csv_iteratorTest);
    CPPUNIT_TEST(testDereference);
    CPPUNIT_TEST(testCheckEqualityOfEmpties);
    CPPUNIT_TEST(testCheckEqualityOfDifferentIterators);
    CPPUNIT_TEST(testCheckEqualityInitializedIterators);
    CPPUNIT_TEST(testIteratorFeedWithValues);
    CPPUNIT_TEST(testIteratorFeedWithDoubles);
    CPPUNIT_TEST(testFillTuple);
    CPPUNIT_TEST_SUITE_END();

    typedef boost::tuple<int,int> TwoIntRecord;
    typedef boost::tuple<int,int,int> ThreeIntRecord;

    typedef boost::tuple<double,double> TwoDoubleRecord;

    typedef boost::tuple<int,std::string,double> ThreeMixedRecord;

    public:

    void setUp(){
    }

    void tearDown(){
    }

    void testDereference(){
        csv::iterator<TwoIntRecord> it;
        TwoIntRecord expected;
        CPPUNIT_ASSERT_EQUAL(expected, *it);
    }

    void testCheckEqualityOfEmpties(){
        csv::iterator<TwoIntRecord> it, it2;
        CPPUNIT_ASSERT(it == it2);
    }

    void testCheckEqualityOfDifferentIterators() {
        std::vector<std::string> values;
        csv::iterator<TwoIntRecord> it, it2(values.begin(), values.end());
        CPPUNIT_ASSERT(it != it2);
    }

    void testCheckEqualityInitializedIterators() {
        std::vector<std::string> values;
        csv::iterator<TwoIntRecord> it(values.begin(),values.end()), it2(values.begin(),values.end());

        // No iterator equals the other
        CPPUNIT_ASSERT(it != it2);
    }

    void testIteratorFeedWithValues(){
        std::vector<std::string> values = {"1","2"};
        csv::iterator<TwoIntRecord> it(values.begin(), values.end());

        TwoIntRecord expected;
        boost::tuples::get<0>(expected) = 1;
        boost::tuples::get<1>(expected) = 2;

        CPPUNIT_ASSERT_EQUAL(expected,*it);
    }

    void testIteratorFeedWithDoubles(){
        std::vector<std::string> values = {"1.4","2.5"};
        csv::iterator<TwoDoubleRecord> it(values.begin(), values.end());

        TwoDoubleRecord expected;
        boost::tuples::get<0>(expected) = 1.4;
        boost::tuples::get<1>(expected) = 2.5;

        CPPUNIT_ASSERT_EQUAL(expected,*it);
    }

    void testFillTuple() {
       ThreeIntRecord expected, obtained;
       std::vector<std::string> values = {"1","2","3"};

       csv::details::helper<ThreeIntRecord,2>::fill(obtained, values.begin());

       boost::tuples::get<0>(expected) = 1;
       boost::tuples::get<1>(expected) = 2;
       boost::tuples::get<2>(expected) = 3;
       CPPUNIT_ASSERT_EQUAL(expected,obtained);
    }
};

CPPUNIT_TEST_SUITE_REGISTRATION(csv_iteratorTest);

<commit_msg>Testing with mixed data in the tuple<commit_after>#include <cppunit/extensions/HelperMacros.h>
#include "csv_iterator.hpp"

#include <vector>
#include <string>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>

class csv_iteratorTest : public CppUnit::TestFixture {
    CPPUNIT_TEST_SUITE(csv_iteratorTest);
    CPPUNIT_TEST(testDereference);
    CPPUNIT_TEST(testCheckEqualityOfEmpties);
    CPPUNIT_TEST(testCheckEqualityOfDifferentIterators);
    CPPUNIT_TEST(testCheckEqualityInitializedIterators);
    CPPUNIT_TEST(testIteratorFeedWithValues);
    CPPUNIT_TEST(testIteratorFeedWithDoubles);
    CPPUNIT_TEST(testFillTuple);
    CPPUNIT_TEST(testFillTupleWithMixedRecords);
    CPPUNIT_TEST_SUITE_END();

    typedef boost::tuple<int,int> TwoIntRecord;
    typedef boost::tuple<int,int,int> ThreeIntRecord;

    typedef boost::tuple<double,double> TwoDoubleRecord;

    typedef boost::tuple<int,std::string,double> ThreeMixedRecord;

    public:

    void setUp(){
    }

    void tearDown(){
    }

    void testDereference(){
        csv::iterator<TwoIntRecord> it;
        TwoIntRecord expected;
        CPPUNIT_ASSERT_EQUAL(expected, *it);
    }

    void testCheckEqualityOfEmpties(){
        csv::iterator<TwoIntRecord> it, it2;
        CPPUNIT_ASSERT(it == it2);
    }

    void testCheckEqualityOfDifferentIterators() {
        std::vector<std::string> values;
        csv::iterator<TwoIntRecord> it, it2(values.begin(), values.end());
        CPPUNIT_ASSERT(it != it2);
    }

    void testCheckEqualityInitializedIterators() {
        std::vector<std::string> values;
        csv::iterator<TwoIntRecord> it(values.begin(),values.end()), it2(values.begin(),values.end());

        // No iterator equals the other
        CPPUNIT_ASSERT(it != it2);
    }

    void testIteratorFeedWithValues(){
        std::vector<std::string> values = {"1","2"};
        csv::iterator<TwoIntRecord> it(values.begin(), values.end());

        TwoIntRecord expected;
        boost::tuples::get<0>(expected) = 1;
        boost::tuples::get<1>(expected) = 2;

        CPPUNIT_ASSERT_EQUAL(expected,*it);
    }

    void testIteratorFeedWithDoubles(){
        std::vector<std::string> values = {"1.4","2.5"};
        csv::iterator<TwoDoubleRecord> it(values.begin(), values.end());

        TwoDoubleRecord expected;
        boost::tuples::get<0>(expected) = 1.4;
        boost::tuples::get<1>(expected) = 2.5;

        CPPUNIT_ASSERT_EQUAL(expected,*it);
    }

    void testFillTuple() {
        ThreeIntRecord expected, obtained;
        std::vector<std::string> values = {"1","2","3"};

        csv::details::helper<ThreeIntRecord,2>::fill(obtained, values.begin());

        boost::tuples::get<0>(expected) = 1;
        boost::tuples::get<1>(expected) = 2;
        boost::tuples::get<2>(expected) = 3;
        CPPUNIT_ASSERT_EQUAL(expected,obtained);
    }

    void testFillTupleWithMixedRecords(){
        ThreeMixedRecord expected, obtained;
        std::vector<std::string> values = {"1","hola","2.4"};
        csv::details::helper<ThreeMixedRecord,2>::fill(obtained, values.begin());

        boost::tuples::get<0>(expected) = 1;
        boost::tuples::get<1>(expected) = "hola";
        boost::tuples::get<2>(expected) = 2.4;
        CPPUNIT_ASSERT_EQUAL(expected,obtained);
    }
};

CPPUNIT_TEST_SUITE_REGISTRATION(csv_iteratorTest);

<|endoftext|>


<commit_before>// Copyright (c) 2018-2019 Kari Karvonen, OH1KK

#include "ext.h"	// all calls to the extension interface begin with "ext_", e.g. ext_register()

#include "kiwi.h"
#include "cfg.h"
#include "str.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/wait.h>

//#define ANT_SWITCH_DEBUG_MSG	true
#define ANT_SWITCH_DEBUG_MSG	false

char * ant_switch_queryantennas() {
	char *cmd, *reply;
	static char selected_antennas[64];
	int n;
	asprintf(&cmd, "/root/extensions/ant_switch/frontend/ant-switch-frontend s");
	reply = non_blocking_cmd(cmd, NULL);
	n = sscanf(kstr_sp(reply), "Selected antennas: %64s", selected_antennas);
	free(cmd);
	//printf("frontend: s n=%d reply=<%s>\n", n, kstr_sp(reply));
	if (!n) printf("ant_switch_queryantenna BAD STATUS? <%s>\n", kstr_sp(reply));
	kstr_free(reply);
	return(selected_antennas);
}

int ant_switch_setantenna(char* antenna) {
    char *cmd, *reply;
	int status;
	int n;
    asprintf(&cmd, "/root/extensions/ant_switch/frontend/ant-switch-frontend %s", antenna);
	//printf("frontend: %s\n", antenna);
	reply = non_blocking_cmd(cmd, NULL);
	free(cmd);
	kstr_free(reply);
	return(0);
}

int ant_switch_toggleantenna(char* antenna) {
    char *cmd, *reply;
	int status;
	int n;
    asprintf(&cmd, "/root/extensions/ant_switch/frontend/ant-switch-frontend t%s", antenna);
	//printf("frontend: t%s\n", antenna);
	reply = non_blocking_cmd(cmd, NULL);
	free(cmd);
	kstr_free(reply);
	return(0);
}

int ant_switch_validate_cmd(char *cmd) {
    return (cmd[0] >= '1' && cmd[0] <= '9');
}

bool ant_switch_read_denyswitching(int rx_chan) {
    bool deny = false;
    bool error;
    int deny_val = cfg_int("ant_switch.denyswitching", &error, CFG_OPTIONAL);

    #if (VERSION_MAJ > 1) || (VERSION_MAJ == 1 && VERSION_MIN >= 448)
        // values used by admin menu
        #define ALLOW_EVERYONE 0
        #define ALLOW_LOCAL_ONLY 1
        #define ALLOW_LOCAL_OR_PASSWORD_ONLY 2

        if (error) deny_val = ALLOW_EVERYONE;
        ext_auth_e auth = ext_auth(rx_chan);
        if (deny_val == ALLOW_LOCAL_ONLY && auth != AUTH_LOCAL) deny = true;
        if (deny_val == ALLOW_LOCAL_OR_PASSWORD_ONLY && auth == AUTH_USER) deny = true;
        //rcprintf(rx_chan, "ANTSW deny_val=%d auth=%d => deny=%d\n", deny_val, auth, deny);
    #else
        // error handling: if deny parameter is not defined, or it is 0, then switching is allowed
        if (error) deny_val = 0;
        deny = (deny_val == 1);
    #endif

    return (deny)? true : false;
}

bool ant_switch_read_denymixing() {
    int result = cfg_int("ant_switch.denymixing", NULL, CFG_OPTIONAL);
    // error handling: if deny parameter is not defined, or it is 0, then mixing is allowed
    if (result == 1) return true; else return false;
}

bool ant_switch_read_denymultiuser() {
    int result = cfg_int("ant_switch.denymultiuser", NULL, CFG_OPTIONAL);
    // error handling: if deny parameter is not defined, or it is 0, then switching is allowed
    if (result == 1) {
        // option is set. Now check if more than 1 user online rx_util.cpp current_nusers variable
        if (current_nusers > 1) return true; else return false;
    } else {
        return false;
    }
}

bool ant_switch_read_thunderstorm() {
    int result = cfg_int("ant_switch.thunderstorm", NULL, CFG_OPTIONAL);
    // error handling: if deny parameter is not defined, or it is 0, then mixing is allowed
    if (result == 1) return true; else return false;
}

bool ant_switch_msgs(char *msg, int rx_chan)
{
	int n=0;
	char antenna[256];

	//rcprintf(rx_chan, "### ant_switch_msgs <%s>\n", msg);

	if (strcmp(msg, "SET ext_server_init") == 0) {
		ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT ready");
		return true;
	}

    n = sscanf(msg, "SET Antenna=%s", antenna);
    if (n == 1) {
        //rcprintf(rx_chan, "ant_switch: %s\n", msg);
        if (ant_switch_read_denyswitching(rx_chan) == true || ant_switch_read_denymultiuser() == true) {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenySwitching=1");
            return true;
        } else {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenySwitching=0");
        }

        if (ant_switch_validate_cmd(antenna)) {
            if (ant_switch_read_denymixing() == 1) {
                ant_switch_setantenna(antenna);
            } else {
                ant_switch_toggleantenna(antenna);
            }
        } else {
            rcprintf(rx_chan, "ant_switch: Command not valid SET Antenna=%s", antenna);
        }

        return true;
    }

    if (strcmp(msg, "GET Antenna") == 0) {
        char *selected_antennas = ant_switch_queryantennas();
        ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT Antenna=%s", selected_antennas);

        // setup user notification of antenna change
        #if (VERSION_MAJ > 1) || (VERSION_MAJ == 1 && VERSION_MIN >= 449)
            static char last_selected_antennas[64];
            if (strncmp(selected_antennas, last_selected_antennas, 64)) {
                char *s;
                if (strcmp(selected_antennas, "g") == 0)
                    s = (char *) "All antennas now grounded.";
                else
                    s = stprintf("Selected antennas are now: %s", selected_antennas);
                static u4_t seq;
                ext_notify_connected(rx_chan, seq++, s);
                kiwi_strncpy(last_selected_antennas, selected_antennas, 64);
            }
        #endif

        if (ant_switch_read_denyswitching(rx_chan) == true || ant_switch_read_denymultiuser() == true) {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenySwitching=1");
        } else {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenySwitching=0");
        }

        if (ant_switch_read_denymixing() == true) {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenyMixing=1");
        } else {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenyMixing=0");
        }

        if (ant_switch_read_thunderstorm() == true) {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT Thunderstorm=1");
            // also ground antenna if not grounded
            if (strcmp(selected_antennas, "g")!=0)  {
                char* groundall=(char*)"g\0";
                ant_switch_setantenna(groundall);
                ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT Antenna=g");
            }
            return true;
        } else {
                ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT Thunderstorm=0");
        }

        return true;
    }

    int freq_offset_ant;
    n = sscanf(msg, "SET freq_offset=%d", &freq_offset_ant);
    if (n == 1) {
        //rcprintf(rx_chan, "ant_switch: freq_offset %d\n", freq_offset_ant);
        cfg_set_float_save("freq_offset", (double) freq_offset_ant);
        freq_offset = freq_offset_ant;
        return true;
    }

    return false;
}

void ant_switch_close(int rx_chan)
{
    // do nothing
}

void ant_switch_main();

ext_t ant_switch_ext = {
	"ant_switch",
	ant_switch_main,
	ant_switch_close,
	ant_switch_msgs,
};

void ant_switch_main()
{
	ext_register(&ant_switch_ext);
}
<commit_msg>prevent buffer overflow<commit_after>// Copyright (c) 2018-2019 Kari Karvonen, OH1KK

#include "ext.h"	// all calls to the extension interface begin with "ext_", e.g. ext_register()

#include "kiwi.h"
#include "cfg.h"
#include "str.h"

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/wait.h>

//#define ANT_SWITCH_DEBUG_MSG	true
#define ANT_SWITCH_DEBUG_MSG	false

char * ant_switch_queryantennas() {
	char *cmd, *reply;
	static char selected_antennas[64 + SPACE_FOR_NULL];
	int n;
	asprintf(&cmd, "/root/extensions/ant_switch/frontend/ant-switch-frontend s");
	reply = non_blocking_cmd(cmd, NULL);
	n = sscanf(kstr_sp(reply), "Selected antennas: %64s", selected_antennas);
	free(cmd);
	//printf("frontend: s n=%d reply=<%s>\n", n, kstr_sp(reply));
	if (!n) printf("ant_switch_queryantenna BAD STATUS? <%s>\n", kstr_sp(reply));
	kstr_free(reply);
	return(selected_antennas);
}

int ant_switch_setantenna(char* antenna) {
    char *cmd, *reply;
	int status;
	int n;
    asprintf(&cmd, "/root/extensions/ant_switch/frontend/ant-switch-frontend %s", antenna);
	//printf("frontend: %s\n", antenna);
	reply = non_blocking_cmd(cmd, NULL);
	free(cmd);
	kstr_free(reply);
	return(0);
}

int ant_switch_toggleantenna(char* antenna) {
    char *cmd, *reply;
	int status;
	int n;
    asprintf(&cmd, "/root/extensions/ant_switch/frontend/ant-switch-frontend t%s", antenna);
	//printf("frontend: t%s\n", antenna);
	reply = non_blocking_cmd(cmd, NULL);
	free(cmd);
	kstr_free(reply);
	return(0);
}

int ant_switch_validate_cmd(char *cmd) {
    return (cmd[0] >= '1' && cmd[0] <= '9');
}

bool ant_switch_read_denyswitching(int rx_chan) {
    bool deny = false;
    bool error;
    int deny_val = cfg_int("ant_switch.denyswitching", &error, CFG_OPTIONAL);

    #if (VERSION_MAJ > 1) || (VERSION_MAJ == 1 && VERSION_MIN >= 448)
        // values used by admin menu
        #define ALLOW_EVERYONE 0
        #define ALLOW_LOCAL_ONLY 1
        #define ALLOW_LOCAL_OR_PASSWORD_ONLY 2

        if (error) deny_val = ALLOW_EVERYONE;
        ext_auth_e auth = ext_auth(rx_chan);
        if (deny_val == ALLOW_LOCAL_ONLY && auth != AUTH_LOCAL) deny = true;
        if (deny_val == ALLOW_LOCAL_OR_PASSWORD_ONLY && auth == AUTH_USER) deny = true;
        //rcprintf(rx_chan, "ANTSW deny_val=%d auth=%d => deny=%d\n", deny_val, auth, deny);
    #else
        // error handling: if deny parameter is not defined, or it is 0, then switching is allowed
        if (error) deny_val = 0;
        deny = (deny_val == 1);
    #endif

    return (deny)? true : false;
}

bool ant_switch_read_denymixing() {
    int result = cfg_int("ant_switch.denymixing", NULL, CFG_OPTIONAL);
    // error handling: if deny parameter is not defined, or it is 0, then mixing is allowed
    if (result == 1) return true; else return false;
}

bool ant_switch_read_denymultiuser() {
    int result = cfg_int("ant_switch.denymultiuser", NULL, CFG_OPTIONAL);
    // error handling: if deny parameter is not defined, or it is 0, then switching is allowed
    if (result == 1) {
        // option is set. Now check if more than 1 user online rx_util.cpp current_nusers variable
        if (current_nusers > 1) return true; else return false;
    } else {
        return false;
    }
}

bool ant_switch_read_thunderstorm() {
    int result = cfg_int("ant_switch.thunderstorm", NULL, CFG_OPTIONAL);
    // error handling: if deny parameter is not defined, or it is 0, then mixing is allowed
    if (result == 1) return true; else return false;
}

bool ant_switch_msgs(char *msg, int rx_chan)
{
	int n=0;
	char antenna[256];

	//rcprintf(rx_chan, "### ant_switch_msgs <%s>\n", msg);

	if (strcmp(msg, "SET ext_server_init") == 0) {
		ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT ready");
		return true;
	}

    n = sscanf(msg, "SET Antenna=%s", antenna);
    if (n == 1) {
        //rcprintf(rx_chan, "ant_switch: %s\n", msg);
        if (ant_switch_read_denyswitching(rx_chan) == true || ant_switch_read_denymultiuser() == true) {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenySwitching=1");
            return true;
        } else {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenySwitching=0");
        }

        if (ant_switch_validate_cmd(antenna)) {
            if (ant_switch_read_denymixing() == 1) {
                ant_switch_setantenna(antenna);
            } else {
                ant_switch_toggleantenna(antenna);
            }
        } else {
            rcprintf(rx_chan, "ant_switch: Command not valid SET Antenna=%s", antenna);
        }

        return true;
    }

    if (strcmp(msg, "GET Antenna") == 0) {
        char *selected_antennas = ant_switch_queryantennas();
        ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT Antenna=%s", selected_antennas);

        // setup user notification of antenna change
        #if (VERSION_MAJ > 1) || (VERSION_MAJ == 1 && VERSION_MIN >= 449)
            static char last_selected_antennas[64];
            if (strncmp(selected_antennas, last_selected_antennas, 64)) {
                char *s;
                if (strcmp(selected_antennas, "g") == 0)
                    s = (char *) "All antennas now grounded.";
                else
                    s = stprintf("Selected antennas are now: %s", selected_antennas);
                static u4_t seq;
                ext_notify_connected(rx_chan, seq++, s);
                kiwi_strncpy(last_selected_antennas, selected_antennas, 64);
            }
        #endif

        if (ant_switch_read_denyswitching(rx_chan) == true || ant_switch_read_denymultiuser() == true) {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenySwitching=1");
        } else {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenySwitching=0");
        }

        if (ant_switch_read_denymixing() == true) {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenyMixing=1");
        } else {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT AntennaDenyMixing=0");
        }

        if (ant_switch_read_thunderstorm() == true) {
            ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT Thunderstorm=1");
            // also ground antenna if not grounded
            if (strcmp(selected_antennas, "g")!=0)  {
                char* groundall=(char*)"g\0";
                ant_switch_setantenna(groundall);
                ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT Antenna=g");
            }
            return true;
        } else {
                ext_send_msg(rx_chan, ANT_SWITCH_DEBUG_MSG, "EXT Thunderstorm=0");
        }

        return true;
    }

    int freq_offset_ant;
    n = sscanf(msg, "SET freq_offset=%d", &freq_offset_ant);
    if (n == 1) {
        //rcprintf(rx_chan, "ant_switch: freq_offset %d\n", freq_offset_ant);
        cfg_set_float_save("freq_offset", (double) freq_offset_ant);
        freq_offset = freq_offset_ant;
        return true;
    }

    return false;
}

void ant_switch_close(int rx_chan)
{
    // do nothing
}

void ant_switch_main();

ext_t ant_switch_ext = {
	"ant_switch",
	ant_switch_main,
	ant_switch_close,
	ant_switch_msgs,
};

void ant_switch_main()
{
	ext_register(&ant_switch_ext);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <GPIOClass.h>

using namespace std;

int main (void)
{

    string inputstate;
    GPIOClass* gpio4 = new GPIOClass("4"); //create new GPIO object to be attached to  GPIO4
    GPIOClass* gpio17 = new GPIOClass("17"); //create new GPIO object to be attached to  GPIO17

    gpio4->export_gpio(); //export GPIO4
    gpio17->export_gpio(); //export GPIO17

    cout << " GPIO pins exported" << endl;

    gpio17->setdir_gpio("in"); //GPIO4 set to output
    gpio4->setdir_gpio("out"); // GPIO17 set to input

    cout << " Set GPIO pin directions" << endl;

    while(1)
    {
        usleep(500000);  // wait for 0.5 seconds
        gpio17->getval_gpio(inputstate); //read state of GPIO17 input pin
        cout << "Current input pin state is " << inputstate  <<endl;
        if(inputstate == "0") // if input pin is at state "0" i.e. button pressed
        {
            cout << "input pin state is "Pressed ".n Will check input pin state again in 20ms "<<endl;
                usleep(20000);
                    cout << "Checking again ....." << endl;
                    gpio17->getval_gpio(inputstate); // checking again to ensure that state "0" is due to button press and not noise
            if(inputstate == "0")
            {
                cout << "input pin state is definitely "Pressed". Turning LED ON" <<endl;
                gpio4->setval_gpio("1"); // turn LED ON

                cout << " Waiting until pin is unpressed....." << endl;
                while (inputstate == "0"){
                gpio17->getval_gpio(inputstate);
                };
                cout << "pin is unpressed" << endl;

            }
            else
                cout << "input pin state is definitely "UnPressed". That was just noise." <<endl;

        }
        gpio4->setval_gpio("0");

    }
    cout << "Exiting....." << endl;
    return 0;
}
<commit_msg>Update TestGPIO.cpp<commit_after>#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <GPIOClass.h>

using namespace std;

int main ()
{

    string inputstate;
    GPIOClass* gpio4 = new GPIOClass("4"); //create new GPIO object to be attached to  GPIO4
    GPIOClass* gpio17 = new GPIOClass("17"); //create new GPIO object to be attached to  GPIO17

    gpio4->export_gpio(); //export GPIO4
    gpio17->export_gpio(); //export GPIO17

    cout << " GPIO pins exported" << endl;

    gpio17->setdir_gpio("in"); //GPIO4 set to output
    gpio4->setdir_gpio("out"); // GPIO17 set to input

    cout << " Set GPIO pin directions" << endl;

    while(1)
    {
        usleep(500000);  // wait for 0.5 seconds
        gpio17->getval_gpio(inputstate); //read state of GPIO17 input pin
        cout << "Current input pin state is " << inputstate  <<endl;
        if(inputstate == "0") // if input pin is at state "0" i.e. button pressed
        {
            cout << "input pin state is "Pressed ".n Will check input pin state again in 20ms "<<endl;
                usleep(20000);
                    cout << "Checking again ....." << endl;
                    gpio17->getval_gpio(inputstate); // checking again to ensure that state "0" is due to button press and not noise
            if(inputstate == "0")
            {
                cout << "input pin state is definitely "Pressed". Turning LED ON" <<endl;
                gpio4->setval_gpio("1"); // turn LED ON

                cout << " Waiting until pin is unpressed....." << endl;
                while (inputstate == "0"){
                gpio17->getval_gpio(inputstate);
                };
                cout << "pin is unpressed" << endl;

            }
            else
                cout << "input pin state is definitely "UnPressed". That was just noise." <<endl;

        }
        gpio4->setval_gpio("0");

    }
    cout << "Exiting....." << endl;
    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2000 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 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
 *    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 this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: elab_sig.cc,v 1.8 2001/01/04 04:47:51 steve Exp $"
#endif

# include  "Module.h"
# include "PExpr.h"
# include  "PGate.h"
# include  "PTask.h"
# include  "PWire.h"
# include  "netlist.h"
# include  "util.h"

bool Module::elaborate_sig(Design*des, NetScope*scope) const
{
      bool flag = true;

	// Get all the explicitly declared wires of the module and
	// start the signals list with them.
      const map<string,PWire*>&wl = get_wires();

      for (map<string,PWire*>::const_iterator wt = wl.begin()
		 ; wt != wl.end()
		 ; wt ++ ) {

	    (*wt).second->elaborate_sig(des, scope);
      }

	// Get all the gates of the module and elaborate them by
	// connecting them to the signals. The gate may be simple or
	// complex. What we are looking for is gates that are modules
	// that can create scopes and signals.

      const list<PGate*>&gl = get_gates();

      for (list<PGate*>::const_iterator gt = gl.begin()
		 ; gt != gl.end()
		 ; gt ++ ) {

	    flag &= (*gt)->elaborate_sig(des, scope);
      }

      typedef map<string,PFunction*>::const_iterator mfunc_it_t;

      for (mfunc_it_t cur = funcs_.begin()
		 ; cur != funcs_.end() ;  cur ++) {
	    NetScope*fscope = scope->child((*cur).first);
	    if (scope == 0) {
		  cerr << (*cur).second->get_line() << ": internal error: "
		       << "Child scope for function " << (*cur).first
		       << " missing in " << scope->name() << "." << endl;
		  des->errors += 1;
		  continue;
	    }

	    (*cur).second->elaborate_sig(des, fscope);
      }

	// After all the wires are elaborated, we are free to
	// elaborate the ports of the tasks defined within this
	// module. Run through them now.

      typedef map<string,PTask*>::const_iterator mtask_it_t;

      for (mtask_it_t cur = tasks_.begin()
		 ; cur != tasks_.end() ;  cur ++) {
	    NetScope*tscope = scope->child((*cur).first);
	    assert(tscope);
	    (*cur).second->elaborate_sig(des, tscope);
      }

      return flag;
}

bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
				  Module*rmod) const
{
	// Missing module instance names have already been rejected.
      assert(get_name() != "");

      if (msb_) {
	    cerr << get_line() << ": sorry: Module instantiation arrays "
		  "are not yet supported." << endl;
	    des->errors += 1;
	    return false;
      }

	// I know a priori that the elaborate_scope created the scope
	// already, so just look it up as a child of the current scope.
      NetScope*my_scope = scope->child(get_name());
      assert(my_scope);

      return rmod->elaborate_sig(des, my_scope);
}

/*
 * A function definition exists within an elaborated module.
 */
void PFunction::elaborate_sig(Design*des, NetScope*scope) const
{
      string fname = scope->basename();
      assert(scope->type() == NetScope::FUNC);

      svector<NetNet*>ports (ports_? ports_->count()+1 : 1);

	/* Get the reg for the return value. I know the name of the
	   reg variable, and I know that it is in this scope, so look
	   it up directly. */
      ports[0] = scope->find_signal(scope->basename());
      if (ports[0] == 0) {
	    cerr << get_line() << ": internal error: function scope "
		 << scope->name() << " is missing return reg "
		 << fname << "." << endl;
	    scope->dump(cerr);
	    des->errors += 1;
	    return;
      }

      for (unsigned idx = 0 ;  idx < ports_->count() ;  idx += 1) {

	      /* Parse the port name into the task name and the reg
		 name. We know by design that the port name is given
		 as two components: <func>.<port>. */

	    string pname = (*ports_)[idx]->name();
	    string ppath = parse_first_name(pname);

	    if (ppath != scope->basename()) {
		  cerr << get_line() << ": internal error: function "
		       << "port " << (*ports_)[idx]->name()
		       << " has wrong name for function "
		       << scope->name() << "." << endl;
		  des->errors += 1;
	    }

	    NetNet*tmp = scope->find_signal(pname);
	    if (tmp == 0) {
		  cerr << get_line() << ": internal error: function "
		       << scope->name() << " is missing port "
		       << pname << "." << endl;
		  scope->dump(cerr);
		  des->errors += 1;
	    }

	    ports[idx+1] = tmp;
      }

      NetFuncDef*def = new NetFuncDef(scope, ports);
      scope->set_func_def(def);
}

/*
 * A task definition is a scope within an elaborated module. When we
 * are elaborating signals, the scopes have already been created, as
 * have the reg objects that are the parameters of this task. The
 * elaborate_sig method of PTask is therefore left to connect the
 * signals to the ports of the NetTaskDef definition. We know for
 * certain that signals exist (They are in my scope!) so the port
 * binding is sure to work.
 */
void PTask::elaborate_sig(Design*des, NetScope*scope) const
{
      assert(scope->type() == NetScope::TASK);

      svector<NetNet*>ports (ports_? ports_->count() : 0);
      for (unsigned idx = 0 ;  idx < ports.count() ;  idx += 1) {

	      /* Parse the port name into the task name and the reg
		 name. We know by design that the port name is given
		 as two components: <task>.<port>. */

	    string pname = (*ports_)[idx]->name();
	    string ppath = parse_first_name(pname);
	    assert(pname != "");

	      /* check that the current scope really does have the
		 name of the first component of the task port name. Do
		 this by looking up the task scope in the parent of
		 the current scope. */
	    if (scope->parent()->child(ppath) != scope) {
		  cerr << "internal error: task scope " << ppath
		       << " not the same as scope " << scope->name()
		       << "?!" << endl;
		  return;
	    }

	      /* Find the signal for the port. We know by definition
		 that it is in the scope of the task, so look only in
		 the scope. */
	    NetNet*tmp = scope->find_signal(pname);

	    if (tmp == 0) {
		  cerr << get_line() << ": internal error: "
		       << "Could not find port " << pname
		       << " in scope " << scope->name() << endl;
		  scope->dump(cerr);
	    }

	    ports[idx] = tmp;
      }

      NetTaskDef*def = new NetTaskDef(scope->name(), ports);
      scope->set_task_def(def);
}

bool PGate::elaborate_sig(Design*des, NetScope*scope) const
{
      return true;
}

/*
 * Elaborate a source wire. The "wire" is the declaration of wires,
 * registers, ports and memories. The parser has already merged the
 * multiple properties of a wire (i.e. "input wire") so come the
 * elaboration this creates an object in the design that represent the
 * defined item.
 */
void PWire::elaborate_sig(Design*des, NetScope*scope) const
{
	/* The parser may produce hierarchical names for wires. I here
	   follow the scopes down to the base where I actually want to
	   elaborate the NetNet object. */
      string basename = name_;
      for (;;) {
	    string p = parse_first_name(basename);
	    if (basename == "") {
		  basename = p;
		  break;
	    }

	    scope = scope->child(p);
	    assert(scope);
      }

      const string path = scope->name();
      NetNet::Type wtype = type_;
      if (wtype == NetNet::IMPLICIT)
	    wtype = NetNet::WIRE;
      if (wtype == NetNet::IMPLICIT_REG)
	    wtype = NetNet::REG;

      unsigned wid = 1;
      long lsb = 0, msb = 0;

      if (msb_.count()) {
	    svector<long>mnum (msb_.count());
	    svector<long>lnum (msb_.count());

	      /* There may be multiple declarations of ranges, because
		 the symbol may have its range declared in i.e. input
		 and reg declarations. Calculate *all* the numbers
		 here. I will resolve the values later. */

	    for (unsigned idx = 0 ;  idx < msb_.count() ;  idx += 1) {
		  verinum*mval = msb_[idx]->eval_const(des,path);
		  if (mval == 0) {
			cerr << msb_[idx]->get_line() << ": error: "
			      "Unable to evaluate constant expression ``" <<
			      *msb_[idx] << "''." << endl;
			des->errors += 1;
			return;
		  }
		  verinum*lval = lsb_[idx]->eval_const(des, path);
		  if (lval == 0) {
			cerr << lsb_[idx]->get_line() << ": error: "
			      "Unable to evaluate constant expression ``" <<
			      *lsb_[idx] << "''." << endl;
			des->errors += 1;
			return;
		  }

		  mnum[idx] = mval->as_long();
		  lnum[idx] = lval->as_long();
		  delete mval;
		  delete lval;
	    }

	      /* Make sure all the values for msb and lsb match by
		 value. If not, report an error. */
	    for (unsigned idx = 1 ;  idx < msb_.count() ;  idx += 1) {
		  if ((mnum[idx] != mnum[0]) || (lnum[idx] != lnum[0])) {
			cerr << get_line() << ": error: Inconsistent width, "
			      "[" << mnum[idx] << ":" << lnum[idx] << "]"
			      " vs. [" << mnum[0] << ":" << lnum[0] << "]"
			      " for signal ``" << basename << "''" << endl;
			des->errors += 1;
			return;
		  }
	    }

	    lsb = lnum[0];
	    msb = mnum[0];
	    if (mnum[0] > lnum[0])
		  wid = mnum[0] - lnum[0] + 1;
	    else
		  wid = lnum[0] - mnum[0] + 1;

      }

      if (lidx_ || ridx_) {
	    assert(lidx_ && ridx_);

	      // If the register has indices, then this is a
	      // memory. Create the memory object.
	    verinum*lval = lidx_->eval_const(des, path);
	    verinum*rval = ridx_->eval_const(des, path);

	    if ((lval == 0) || (rval == 0)) {
		  cerr << get_line() << ": internal error: There is "
		       << "a problem evaluating indices for ``"
		       << basename << "''." << endl;
		  des->errors += 1;
		  return;
	    }

	    assert(lval);
	    assert(rval);

	    long lnum = lval->as_long();
	    long rnum = rval->as_long();
	    delete lval;
	    delete rval;
	    NetMemory*sig = new NetMemory(scope, path+"."+basename,
					  wid, lnum, rnum);

      } else {

	    NetNet*sig = new NetNet(scope, path + "." +basename, wtype, msb, lsb);
	    sig->set_line(*this);
	    sig->port_type(port_type_);
	    sig->set_signed(get_signed());
	    sig->set_attributes(attributes);
      }
}

/*
 * $Log: elab_sig.cc,v $
 * Revision 1.8  2001/01/04 04:47:51  steve
 *  Add support for << is signal indices.
 *
 * Revision 1.7  2000/12/11 00:31:43  steve
 *  Add support for signed reg variables,
 *  simulate in t-vvm signed comparisons.
 *
 * Revision 1.6  2000/12/04 17:37:04  steve
 *  Add Attrib class for holding NetObj attributes.
 *
 * Revision 1.5  2000/11/20 00:58:40  steve
 *  Add support for supply nets (PR#17)
 *
 * Revision 1.4  2000/09/07 22:37:48  steve
 *  ack, detect when lval fails.
 *
 * Revision 1.3  2000/07/30 18:25:43  steve
 *  Rearrange task and function elaboration so that the
 *  NetTaskDef and NetFuncDef functions are created during
 *  signal enaboration, and carry these objects in the
 *  NetScope class instead of the extra, useless map in
 *  the Design class.
 *
 * Revision 1.2  2000/07/14 06:12:57  steve
 *  Move inital value handling from NetNet to Nexus
 *  objects. This allows better propogation of inital
 *  values.
 *
 *  Clean up constant propagation  a bit to account
 *  for regs that are not really values.
 *
 * Revision 1.1  2000/05/02 16:27:38  steve
 *  Move signal elaboration to a seperate pass.
 *
 */

<commit_msg> Detect port direction attached to non-ports.<commit_after>/*
 * Copyright (c) 2000 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 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
 *    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 this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: elab_sig.cc,v 1.9 2001/01/07 07:00:31 steve Exp $"
#endif

# include  "Module.h"
# include  "PExpr.h"
# include  "PGate.h"
# include  "PTask.h"
# include  "PWire.h"
# include  "netlist.h"
# include  "util.h"

/*
 * This local function checks if a named signal is connected to a
 * port. It looks in the array of ports passed, for NetEIdent objects
 * within the port_t that have a matching name.
 */
static bool signal_is_in_port(const svector<Module::port_t*>&ports,
			      const string&name)
{
      for (unsigned idx = 0 ;  idx < ports.count() ;  idx += 1) {

	    Module::port_t*pp = ports[idx];
	      // Skip internally unconnected ports.
	    if (pp == 0)
		  continue;

	      // This port has an internal connection. In this case,
	      // the port has 0 or more NetEIdent objects concatenated
	      // together that form the port.
	    for (unsigned cc = 0 ;  cc < pp->expr.count() ;  cc += 1) {
		  assert(pp->expr[cc]);
		  if (pp->expr[cc]->name() == name)
			return true;
	    }
      }

      return false;
}

bool Module::elaborate_sig(Design*des, NetScope*scope) const
{
      bool flag = true;

	// Get all the explicitly declared wires of the module and
	// start the signals list with them.
      const map<string,PWire*>&wl = get_wires();

      for (map<string,PWire*>::const_iterator wt = wl.begin()
		 ; wt != wl.end()
		 ; wt ++ ) {

	    PWire*cur = (*wt).second;
	    cur->elaborate_sig(des, scope);

	      // If this wire is a signal of the module (as opposed to
	      // a port of a function) and is a port, then check that
	      // the module knows about it.
	    NetNet*sig = scope->find_signal(cur->name());
	    if (sig && (sig->scope() == scope)
		&& (cur->get_port_type() != NetNet::NOT_A_PORT)) {
		  string name = (*wt).first;

		  if (! signal_is_in_port(ports_, name)) {

			cerr << cur->get_line() << ": error: Signal "
			     << name << " has a declared direction "
			     << "but is not a port." << endl;
			des->errors += 1;
		  }
	    }
      }

	// Get all the gates of the module and elaborate them by
	// connecting them to the signals. The gate may be simple or
	// complex. What we are looking for is gates that are modules
	// that can create scopes and signals.

      const list<PGate*>&gl = get_gates();

      for (list<PGate*>::const_iterator gt = gl.begin()
		 ; gt != gl.end()
		 ; gt ++ ) {

	    flag &= (*gt)->elaborate_sig(des, scope);
      }

      typedef map<string,PFunction*>::const_iterator mfunc_it_t;

      for (mfunc_it_t cur = funcs_.begin()
		 ; cur != funcs_.end() ;  cur ++) {
	    NetScope*fscope = scope->child((*cur).first);
	    if (scope == 0) {
		  cerr << (*cur).second->get_line() << ": internal error: "
		       << "Child scope for function " << (*cur).first
		       << " missing in " << scope->name() << "." << endl;
		  des->errors += 1;
		  continue;
	    }

	    (*cur).second->elaborate_sig(des, fscope);
      }

	// After all the wires are elaborated, we are free to
	// elaborate the ports of the tasks defined within this
	// module. Run through them now.

      typedef map<string,PTask*>::const_iterator mtask_it_t;

      for (mtask_it_t cur = tasks_.begin()
		 ; cur != tasks_.end() ;  cur ++) {
	    NetScope*tscope = scope->child((*cur).first);
	    assert(tscope);
	    (*cur).second->elaborate_sig(des, tscope);
      }

      return flag;
}

bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
				  Module*rmod) const
{
	// Missing module instance names have already been rejected.
      assert(get_name() != "");

      if (msb_) {
	    cerr << get_line() << ": sorry: Module instantiation arrays "
		  "are not yet supported." << endl;
	    des->errors += 1;
	    return false;
      }

	// I know a priori that the elaborate_scope created the scope
	// already, so just look it up as a child of the current scope.
      NetScope*my_scope = scope->child(get_name());
      assert(my_scope);

      return rmod->elaborate_sig(des, my_scope);
}

/*
 * A function definition exists within an elaborated module.
 */
void PFunction::elaborate_sig(Design*des, NetScope*scope) const
{
      string fname = scope->basename();
      assert(scope->type() == NetScope::FUNC);

      svector<NetNet*>ports (ports_? ports_->count()+1 : 1);

	/* Get the reg for the return value. I know the name of the
	   reg variable, and I know that it is in this scope, so look
	   it up directly. */
      ports[0] = scope->find_signal(scope->basename());
      if (ports[0] == 0) {
	    cerr << get_line() << ": internal error: function scope "
		 << scope->name() << " is missing return reg "
		 << fname << "." << endl;
	    scope->dump(cerr);
	    des->errors += 1;
	    return;
      }

      for (unsigned idx = 0 ;  idx < ports_->count() ;  idx += 1) {

	      /* Parse the port name into the task name and the reg
		 name. We know by design that the port name is given
		 as two components: <func>.<port>. */

	    string pname = (*ports_)[idx]->name();
	    string ppath = parse_first_name(pname);

	    if (ppath != scope->basename()) {
		  cerr << get_line() << ": internal error: function "
		       << "port " << (*ports_)[idx]->name()
		       << " has wrong name for function "
		       << scope->name() << "." << endl;
		  des->errors += 1;
	    }

	    NetNet*tmp = scope->find_signal(pname);
	    if (tmp == 0) {
		  cerr << get_line() << ": internal error: function "
		       << scope->name() << " is missing port "
		       << pname << "." << endl;
		  scope->dump(cerr);
		  des->errors += 1;
	    }

	    ports[idx+1] = tmp;
      }

      NetFuncDef*def = new NetFuncDef(scope, ports);
      scope->set_func_def(def);
}

/*
 * A task definition is a scope within an elaborated module. When we
 * are elaborating signals, the scopes have already been created, as
 * have the reg objects that are the parameters of this task. The
 * elaborate_sig method of PTask is therefore left to connect the
 * signals to the ports of the NetTaskDef definition. We know for
 * certain that signals exist (They are in my scope!) so the port
 * binding is sure to work.
 */
void PTask::elaborate_sig(Design*des, NetScope*scope) const
{
      assert(scope->type() == NetScope::TASK);

      svector<NetNet*>ports (ports_? ports_->count() : 0);
      for (unsigned idx = 0 ;  idx < ports.count() ;  idx += 1) {

	      /* Parse the port name into the task name and the reg
		 name. We know by design that the port name is given
		 as two components: <task>.<port>. */

	    string pname = (*ports_)[idx]->name();
	    string ppath = parse_first_name(pname);
	    assert(pname != "");

	      /* check that the current scope really does have the
		 name of the first component of the task port name. Do
		 this by looking up the task scope in the parent of
		 the current scope. */
	    if (scope->parent()->child(ppath) != scope) {
		  cerr << "internal error: task scope " << ppath
		       << " not the same as scope " << scope->name()
		       << "?!" << endl;
		  return;
	    }

	      /* Find the signal for the port. We know by definition
		 that it is in the scope of the task, so look only in
		 the scope. */
	    NetNet*tmp = scope->find_signal(pname);

	    if (tmp == 0) {
		  cerr << get_line() << ": internal error: "
		       << "Could not find port " << pname
		       << " in scope " << scope->name() << endl;
		  scope->dump(cerr);
	    }

	    ports[idx] = tmp;
      }

      NetTaskDef*def = new NetTaskDef(scope->name(), ports);
      scope->set_task_def(def);
}

bool PGate::elaborate_sig(Design*des, NetScope*scope) const
{
      return true;
}

/*
 * Elaborate a source wire. The "wire" is the declaration of wires,
 * registers, ports and memories. The parser has already merged the
 * multiple properties of a wire (i.e. "input wire") so come the
 * elaboration this creates an object in the design that represent the
 * defined item.
 */
void PWire::elaborate_sig(Design*des, NetScope*scope) const
{
	/* The parser may produce hierarchical names for wires. I here
	   follow the scopes down to the base where I actually want to
	   elaborate the NetNet object. */
      string basename = name_;
      for (;;) {
	    string p = parse_first_name(basename);
	    if (basename == "") {
		  basename = p;
		  break;
	    }

	    scope = scope->child(p);
	    assert(scope);
      }

      const string path = scope->name();
      NetNet::Type wtype = type_;
      if (wtype == NetNet::IMPLICIT)
	    wtype = NetNet::WIRE;
      if (wtype == NetNet::IMPLICIT_REG)
	    wtype = NetNet::REG;

      unsigned wid = 1;
      long lsb = 0, msb = 0;

      if (msb_.count()) {
	    svector<long>mnum (msb_.count());
	    svector<long>lnum (msb_.count());

	      /* There may be multiple declarations of ranges, because
		 the symbol may have its range declared in i.e. input
		 and reg declarations. Calculate *all* the numbers
		 here. I will resolve the values later. */

	    for (unsigned idx = 0 ;  idx < msb_.count() ;  idx += 1) {
		  verinum*mval = msb_[idx]->eval_const(des,path);
		  if (mval == 0) {
			cerr << msb_[idx]->get_line() << ": error: "
			      "Unable to evaluate constant expression ``" <<
			      *msb_[idx] << "''." << endl;
			des->errors += 1;
			return;
		  }
		  verinum*lval = lsb_[idx]->eval_const(des, path);
		  if (lval == 0) {
			cerr << lsb_[idx]->get_line() << ": error: "
			      "Unable to evaluate constant expression ``" <<
			      *lsb_[idx] << "''." << endl;
			des->errors += 1;
			return;
		  }

		  mnum[idx] = mval->as_long();
		  lnum[idx] = lval->as_long();
		  delete mval;
		  delete lval;
	    }

	      /* Make sure all the values for msb and lsb match by
		 value. If not, report an error. */
	    for (unsigned idx = 1 ;  idx < msb_.count() ;  idx += 1) {
		  if ((mnum[idx] != mnum[0]) || (lnum[idx] != lnum[0])) {
			cerr << get_line() << ": error: Inconsistent width, "
			      "[" << mnum[idx] << ":" << lnum[idx] << "]"
			      " vs. [" << mnum[0] << ":" << lnum[0] << "]"
			      " for signal ``" << basename << "''" << endl;
			des->errors += 1;
			return;
		  }
	    }

	    lsb = lnum[0];
	    msb = mnum[0];
	    if (mnum[0] > lnum[0])
		  wid = mnum[0] - lnum[0] + 1;
	    else
		  wid = lnum[0] - mnum[0] + 1;

      }

      if (lidx_ || ridx_) {
	    assert(lidx_ && ridx_);

	      // If the register has indices, then this is a
	      // memory. Create the memory object.
	    verinum*lval = lidx_->eval_const(des, path);
	    verinum*rval = ridx_->eval_const(des, path);

	    if ((lval == 0) || (rval == 0)) {
		  cerr << get_line() << ": internal error: There is "
		       << "a problem evaluating indices for ``"
		       << basename << "''." << endl;
		  des->errors += 1;
		  return;
	    }

	    assert(lval);
	    assert(rval);

	    long lnum = lval->as_long();
	    long rnum = rval->as_long();
	    delete lval;
	    delete rval;
	    NetMemory*sig = new NetMemory(scope, path+"."+basename,
					  wid, lnum, rnum);

      } else {

	    NetNet*sig = new NetNet(scope, path + "." +basename, wtype, msb, lsb);
	    sig->set_line(*this);
	    sig->port_type(port_type_);
	    sig->set_signed(get_signed());
	    sig->set_attributes(attributes);
      }
}

/*
 * $Log: elab_sig.cc,v $
 * Revision 1.9  2001/01/07 07:00:31  steve
 *  Detect port direction attached to non-ports.
 *
 * Revision 1.8  2001/01/04 04:47:51  steve
 *  Add support for << is signal indices.
 *
 * Revision 1.7  2000/12/11 00:31:43  steve
 *  Add support for signed reg variables,
 *  simulate in t-vvm signed comparisons.
 *
 * Revision 1.6  2000/12/04 17:37:04  steve
 *  Add Attrib class for holding NetObj attributes.
 *
 * Revision 1.5  2000/11/20 00:58:40  steve
 *  Add support for supply nets (PR#17)
 *
 * Revision 1.4  2000/09/07 22:37:48  steve
 *  ack, detect when lval fails.
 *
 * Revision 1.3  2000/07/30 18:25:43  steve
 *  Rearrange task and function elaboration so that the
 *  NetTaskDef and NetFuncDef functions are created during
 *  signal enaboration, and carry these objects in the
 *  NetScope class instead of the extra, useless map in
 *  the Design class.
 *
 * Revision 1.2  2000/07/14 06:12:57  steve
 *  Move inital value handling from NetNet to Nexus
 *  objects. This allows better propogation of inital
 *  values.
 *
 *  Clean up constant propagation  a bit to account
 *  for regs that are not really values.
 *
 * Revision 1.1  2000/05/02 16:27:38  steve
 *  Move signal elaboration to a seperate pass.
 *
 */

<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      rdo_resource.inl
  \author      (dluschan@rk9.bmstu.ru)
  \date      15.06.2011
  \brief     RDOResource inline implementation
  \indent    4T
*/

// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/rdomacros.h"
#include "simulator/runtime/namespace.h"
// --------------------------------------------------------------------------------

OPEN_RDO_RUNTIME_NAMESPACE

// --------------------------------------------------------------------------------
// -------------------- RDOResource
// --------------------------------------------------------------------------------
inline void RDOResource::setRuntime(CREF(LPRDORuntime) pRuntime)
{
	UNUSED(pRuntime);

	/// @todo
	NEVER_REACH_HERE;
}

inline tstring RDOResource::whoAreYou()
{
	return _T("rdoRes");
}

inline void RDOResource::makeTemporary(rbool value)
{
	m_temporary = value;
}

inline RDOResource::ConvertStatus RDOResource::getState() const
{
	return m_state;
}

inline void RDOResource::setState(RDOResource::ConvertStatus value)
{
	m_state = value;
}

inline rbool RDOResource::checkType(ruint type) const
{
	return m_type == type;
}

inline CREF(LPIResourceType) RDOResource::getResType() const
{
	return m_resType;
}

inline ruint RDOResource::getType() const
{
	return m_type;
}

inline CREF(RDOResource::ParamList) RDOResource::getParamList() const
{
	return m_paramList;
}

inline CREF(RDOValue) RDOResource::getParam(ruint index) const
{
	ASSERT(index < m_paramList.size());
	return m_paramList[index];
}

inline REF(RDOValue) RDOResource::getParamRaw(ruint index)
{
	setState(CS_Keep);
	return getParam(index);
}

inline void RDOResource::setParam(ruint index, CREF(RDOValue) value)
{
	ASSERT(index < m_paramList.size());
	setState(CS_Keep);
	m_paramList[index] = value;
}

inline ruint RDOResource::paramsCount() const
{
	return m_paramList.size();
}

inline void RDOResource::appendParams(CREF(ParamCIt) from_begin, CREF(ParamCIt) from_end)
{
	m_paramList.insert(m_paramList.end(), from_begin, from_end);
}

inline rbool RDOResource::canFree() const
{
	return m_referenceCount == 0;
}

inline void RDOResource::incRef()
{
	++m_referenceCount;
}

inline void RDOResource::decRef()
{
	--m_referenceCount;
}

inline tstring RDOResource::traceTypeId()
{
	return m_typeId.empty() ? (m_typeId = getTypeId()) : m_typeId;
}

CLOSE_RDO_RUNTIME_NAMESPACE
<commit_msg>* revert revision 10751<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      rdo_resource.inl
  \author      (dluschan@rk9.bmstu.ru)
  \date      15.06.2011
  \brief     RDOResource inline implementation
  \indent    4T
*/

// ----------------------------------------------------------------------- INCLUDES
// ----------------------------------------------------------------------- SYNOPSIS
#include "utils/rdomacros.h"
#include "simulator/runtime/namespace.h"
// --------------------------------------------------------------------------------

OPEN_RDO_RUNTIME_NAMESPACE

// --------------------------------------------------------------------------------
// -------------------- RDOResource
// --------------------------------------------------------------------------------
inline void RDOResource::setRuntime(CREF(LPRDORuntime) pRuntime)
{
	UNUSED(pRuntime);

	/// @todo
	NEVER_REACH_HERE;
}

inline tstring RDOResource::whoAreYou()
{
	return _T("rdoRes");
}

inline void RDOResource::makeTemporary(rbool value)
{
	m_temporary = value;
}

inline RDOResource::ConvertStatus RDOResource::getState() const
{
	return m_state;
}

inline void RDOResource::setState(RDOResource::ConvertStatus value)
{
	m_state = value;
}

inline rbool RDOResource::checkType(ruint type) const
{
	return m_type == type;
}

inline CREF(LPIResourceType) RDOResource::getResType() const
{
	return m_resType;
}

inline ruint RDOResource::getType() const
{
	return m_type;
}

inline CREF(RDOResource::ParamList) RDOResource::getParamList() const
{
	return m_paramList;
}

inline CREF(RDOValue) RDOResource::getParam(ruint index) const
{
	ASSERT(index < m_paramList.size());
	return m_paramList[index];
}

inline REF(RDOValue) RDOResource::getParamRaw(ruint index)
{
	ASSERT(index < m_paramList.size());
	setState(CS_Keep);
	return m_paramList[index];
}

inline void RDOResource::setParam(ruint index, CREF(RDOValue) value)
{
	ASSERT(index < m_paramList.size());
	setState(CS_Keep);
	m_paramList[index] = value;
}

inline ruint RDOResource::paramsCount() const
{
	return m_paramList.size();
}

inline void RDOResource::appendParams(CREF(ParamCIt) from_begin, CREF(ParamCIt) from_end)
{
	m_paramList.insert(m_paramList.end(), from_begin, from_end);
}

inline rbool RDOResource::canFree() const
{
	return m_referenceCount == 0;
}

inline void RDOResource::incRef()
{
	++m_referenceCount;
}

inline void RDOResource::decRef()
{
	--m_referenceCount;
}

inline tstring RDOResource::traceTypeId()
{
	return m_typeId.empty() ? (m_typeId = getTypeId()) : m_typeId;
}

CLOSE_RDO_RUNTIME_NAMESPACE
<|endoftext|>


<commit_before>// Copyright © 2014-2016 Ryan Leckey, All Rights Reserved.

// Distributed under the MIT License
// See accompanying file LICENSE

#include <boost/filesystem.hpp>

#include <string>

#include "arrow/parser.hpp"

using arrow::Parser;
namespace fs = boost::filesystem;

Parser::Parser(
  std::shared_ptr<std::istream> is, const std::string& filename
) : _t(is, filename) {
}

auto Parser::parse() -> std::shared_ptr<ast::Node> {
  // Declare the top-level, automatic module
  // The name of the module is built from the name of the given file
  auto stem = fs::path(_t._filename).stem().string();
  auto mod = std::make_shared<ast::Module>(Span(_t._filename), stem);

  // Attempt to match statements until the end of the stream
  while (!_t.empty()) {
    // Parse a statement (try)
    auto statement = parse_statement();
    if (statement) {
      // Add it to the module
      mod->statements.push_back(statement);
    }
  }

  return mod;
}
<commit_msg>Plug a hole in the parser<commit_after>// Copyright © 2014-2016 Ryan Leckey, All Rights Reserved.

// Distributed under the MIT License
// See accompanying file LICENSE

#include <boost/filesystem.hpp>

#include <string>

#include "arrow/parser.hpp"
#include "arrow/log.hpp"

using arrow::Parser;
namespace fs = boost::filesystem;

Parser::Parser(
  std::shared_ptr<std::istream> is, const std::string& filename
) : _t(is, filename) {
}

auto Parser::parse() -> std::shared_ptr<ast::Node> {
  // Declare the top-level, automatic module
  // The name of the module is built from the name of the given file
  auto stem = fs::path(_t._filename).stem().string();
  auto mod = std::make_shared<ast::Module>(Span(_t._filename), stem);

  // Attempt to match statements until the end of the stream
  while (!_t.empty()) {
    // Parse a statement (try)
    auto statement = parse_statement();
    if (statement) {
      // Add it to the module
      mod->statements.push_back(statement);
    } else {
      auto tok = _t.pop();
      Log::get().error("unexpected: {}", *tok);
    }
  }

  return mod;
}
<|endoftext|>