diff --git a/pvDataApp/misc/bitSet.cpp b/pvDataApp/misc/bitSet.cpp index bccb391..e5660a9 100644 --- a/pvDataApp/misc/bitSet.cpp +++ b/pvDataApp/misc/bitSet.cpp @@ -9,6 +9,7 @@ */ #include "string.h" #include "stdio.h" +#include #include #include #include @@ -199,6 +200,8 @@ namespace epics { namespace pvData { } BitSet& BitSet::operator&=(const BitSet& set) { + // Check for self-assignment! + if (this == &set) return *this; while (wordsInUse > set.wordsInUse) words[--wordsInUse] = 0; @@ -213,76 +216,49 @@ namespace epics { namespace pvData { } BitSet& BitSet::operator|=(const BitSet& set) { - - uint32 wordsInCommon; + // Check for self-assignment! + if (this == &set) return *this; + uint32 wordsInCommon = wordsInUse; + if(wordsInUse>set.wordsInUse) wordsInCommon = set.wordsInUse; if (wordsInUse < set.wordsInUse) { - wordsInCommon = wordsInUse; - //ensureCapacity(set.wordsInUse); - //wordsInUse = set.wordsInUse; + ensureCapacity(set.wordsInUse); + wordsInUse = set.wordsInUse; } - else - wordsInCommon = set.wordsInUse; - // Perform logical OR on words in common - uint32 i = 0; - for (; i < wordsInCommon; i++) + for (uint32 i =0; i < wordsInCommon; i++) { words[i] |= set.words[i]; - - // TODO what to do if BitSets are not the same size !!! - + } + // Copy any remaining words + for(uint32 i=wordsInCommon; iset.wordsInUse) wordsInCommon = set.wordsInUse; if (wordsInUse < set.wordsInUse) { - wordsInCommon = wordsInUse; - //ensureCapacity(set.wordsInUse); - //wordsInUse = set.wordsInUse; + ensureCapacity(set.wordsInUse); + wordsInUse = set.wordsInUse; } - else - wordsInCommon = set.wordsInUse; - - // Perform logical XOR on words in common - uint32 i = 0; - for (; i < wordsInCommon; i++) + // Perform logical OR on words in common + for (uint32 i =0; i < wordsInCommon; i++) { words[i] ^= set.words[i]; - - // TODO what to do if BitSets are not the same size !!! - - recalculateWordsInUse(); - - return *this; - } - - BitSet& BitSet::operator-=(const BitSet& set) { - - uint32 wordsInCommon; - if (wordsInUse < set.wordsInUse) { - wordsInCommon = wordsInUse; - //ensureCapacity(set.wordsInUse); - //wordsInUse = set.wordsInUse; + } + // Copy any remaining words + for(uint32 i=wordsInCommon; i #include #include #include @@ -96,12 +97,16 @@ void testOperators(FILE *fd) { assert(b1 == b2); // OR test - b1.set(65); - b1.set(106); + b2.set(65); + b2.set(106); b2.set(105); b1 |= b2; std::string str; b1.toString(&str); assert(str == "{1, 65, 105, 106}"); + b1.clear(); + b1 |= b2; + str.clear(); b1.toString(&str); + assert(str == "{1, 65, 105, 106}"); // AND test b1.set(128); @@ -112,15 +117,13 @@ void testOperators(FILE *fd) { b1.set(128); b1 ^= b2; assert(b1.cardinality() == 1 && b1.get(128) == true); - - // a AND (NOT b) - b2 -= b1; - str.clear(); b2.toString(&str); - assert(str == "{1, 105}"); + b1.clear(); + b2.clear(); b1.set(1); - b2 -= b1; - str.clear(); b2.toString(&str); - assert(b2.cardinality() == 1 && b2.get(105) == true); + b2.set(256); + b1 ^= b2; + assert(b1.cardinality() == 2 && b1.get(1) == true && b1.get(256) == true); + // assign b1 = b2; diff --git a/testApp/misc/testOverrunBitSet.cpp b/testApp/misc/testOverrunBitSet.cpp new file mode 100644 index 0000000..82790f7 --- /dev/null +++ b/testApp/misc/testOverrunBitSet.cpp @@ -0,0 +1,141 @@ +/* testOverrunBitSet.cpp */ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvData is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +/* Author: Marty Kraimer Date: 2013.09.16 */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace epics::pvData; +using std::cout; +using std::endl; + +static StandardPVFieldPtr standardPVField = getStandardPVField(); + +void test() +{ + String buffer; + String properties("alarm,timeStamp,display"); + PVStructurePtr pvStructure = standardPVField->scalar(pvDouble,properties); + PVDoublePtr pvValue = pvStructure->getDoubleField("value"); + uint32 valueOffset = pvValue->getFieldOffset(); + PVStructurePtr pvAlarm = pvStructure->getStructureField("alarm"); + PVIntPtr pvSeverity = pvAlarm->getIntField("severity"); + PVStringPtr pvMessage = pvAlarm->getStringField("message"); + uint32 severityOffset = pvSeverity->getFieldOffset(); + uint32 messageOffset = pvMessage->getFieldOffset(); + PVStructurePtr pvTimeStamp = pvStructure->getStructureField("timeStamp"); + PVLongPtr pvSeconds = pvTimeStamp->getLongField("secondsPastEpoch"); + PVIntPtr pvNanoSeconds = pvTimeStamp->getIntField("nanoSeconds"); + PVIntPtr pvUserTag = pvTimeStamp->getIntField("userTag"); + uint32 timeStampOffset = pvTimeStamp->getFieldOffset(); + uint32 secondsOffset = pvSeconds->getFieldOffset(); + uint32 nanoSecondsOffset = pvNanoSeconds->getFieldOffset(); + uint32 userTagOffset = pvUserTag->getFieldOffset(); + uint32 nfields = pvStructure->getNumberFields(); + BitSetPtr changeBitSet = BitSet::create(nfields); + BitSetPtr userChangeBitSet = BitSet::create(nfields); + BitSetPtr userOverrunBitSet = BitSet::create(nfields); + pvValue->put(1.0); changeBitSet->set(valueOffset); + pvSeverity->put(2); changeBitSet->set(severityOffset); + pvMessage->put("error"); changeBitSet->set(messageOffset); + pvSeconds->put(1); changeBitSet->set(secondsOffset); + pvNanoSeconds->put(1000000); changeBitSet->set(nanoSecondsOffset); + pvUserTag->put(1); changeBitSet->set(userTagOffset); + userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get()); + (*userChangeBitSet)|=(*changeBitSet.get()); + changeBitSet->clear(); + pvValue->put(2.0); changeBitSet->set(valueOffset); + pvSeverity->put(0); changeBitSet->set(severityOffset); + pvMessage->put(""); changeBitSet->set(messageOffset); + pvSeconds->put(2); changeBitSet->set(secondsOffset); + pvNanoSeconds->put(0); changeBitSet->set(nanoSecondsOffset); + pvUserTag->put(0); changeBitSet->set(userTagOffset); + userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get()); + (*userChangeBitSet)|=(*changeBitSet.get()); + testOk1(userChangeBitSet->cardinality()==6); + testOk1(userChangeBitSet->get(valueOffset)); + testOk1(userChangeBitSet->get(severityOffset)); + testOk1(userChangeBitSet->get(messageOffset)); + testOk1(userChangeBitSet->get(secondsOffset)); + testOk1(userChangeBitSet->get(nanoSecondsOffset)); + testOk1(userChangeBitSet->get(userTagOffset)); + testOk1(userOverrunBitSet->cardinality()==6); + testOk1(userOverrunBitSet->get(valueOffset)); + testOk1(userOverrunBitSet->get(severityOffset)); + testOk1(userOverrunBitSet->get(messageOffset)); + testOk1(userOverrunBitSet->get(secondsOffset)); + testOk1(userOverrunBitSet->get(nanoSecondsOffset)); + testOk1(userOverrunBitSet->get(userTagOffset)); + + BitSetUtil::compress(userChangeBitSet,pvStructure); + BitSetUtil::compress(userOverrunBitSet,pvStructure); + testOk1(userChangeBitSet->cardinality()==4); + testOk1(userChangeBitSet->get(valueOffset)); + testOk1(userChangeBitSet->get(severityOffset)); + testOk1(userChangeBitSet->get(messageOffset)); + testOk1(userChangeBitSet->get(timeStampOffset)); + testOk1(userOverrunBitSet->cardinality()==4); + testOk1(userOverrunBitSet->get(valueOffset)); + testOk1(userOverrunBitSet->get(severityOffset)); + testOk1(userOverrunBitSet->get(messageOffset)); + testOk1(userOverrunBitSet->get(timeStampOffset)); + + changeBitSet->clear(); + userChangeBitSet->clear(); + userOverrunBitSet->clear(); + pvValue->put(1.0); changeBitSet->set(valueOffset); + pvSeconds->put(3); changeBitSet->set(secondsOffset); + pvNanoSeconds->put(0); changeBitSet->set(nanoSecondsOffset); + userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get()); + (*userChangeBitSet)|=(*changeBitSet.get()); + testOk1(userChangeBitSet->cardinality()==3); + testOk1(userChangeBitSet->get(valueOffset)); + testOk1(userChangeBitSet->get(secondsOffset)); + testOk1(userChangeBitSet->get(nanoSecondsOffset)); + testOk1(userOverrunBitSet->cardinality()==0); + + changeBitSet->clear(); + pvValue->put(2.0); changeBitSet->set(valueOffset); + userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get()); + (*userChangeBitSet)|=(*changeBitSet.get()); + testOk1(userChangeBitSet->cardinality()==3); + testOk1(userChangeBitSet->get(valueOffset)); + testOk1(userChangeBitSet->get(secondsOffset)); + testOk1(userChangeBitSet->get(nanoSecondsOffset)); + testOk1(userOverrunBitSet->cardinality()==1); + testOk1(userOverrunBitSet->get(valueOffset)); + + BitSetUtil::compress(userChangeBitSet,pvStructure); + BitSetUtil::compress(userOverrunBitSet,pvStructure); + testOk1(userChangeBitSet->cardinality()==3); + testOk1(userChangeBitSet->get(valueOffset)); + testOk1(userChangeBitSet->get(secondsOffset)); + testOk1(userChangeBitSet->get(nanoSecondsOffset)); + testOk1(userOverrunBitSet->cardinality()==1); + testOk1(userOverrunBitSet->get(valueOffset)); +} + + +MAIN(testOverrunBitSet`) +{ + testPlan(41); + testDiag("Tests for changeBitSet and overrunBitSet"); + test(); + return testDone(); +} +