summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2008-01-11 13:32:00 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2008-01-11 13:32:00 +0000
commit83c82f3ec2fc04184258166d575ad21f791f44c4 (patch)
tree4404abca87693979a0a8adb5c68f4cbb58588cb8
parent5b8358b4d5917491093a04bddc867559b63bf52f (diff)
2008-01-11 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Rewritten get*Missing*Index functions. Now no need to allocate memory each time these functions are called. * src/BitfieldMan.{h, cc} * test/BitfieldManTest.cc * src/array_fun.h * test/array_funTest.cc Now BitfieldMan::countBlock() returns BitfieldMan::blocks. Added new BitfieldMan::countFilteredBlock() to get the number of blocks filtered. Removed unnecessary cast to int32_t. * src/BitfieldMan.{h, cc}
-rw-r--r--ChangeLog14
-rw-r--r--src/BitfieldMan.cc172
-rw-r--r--src/BitfieldMan.h21
-rw-r--r--src/array_fun.h198
-rw-r--r--test/BitfieldManTest.cc249
-rw-r--r--test/array_funTest.cc67
6 files changed, 603 insertions, 118 deletions
diff --git a/ChangeLog b/ChangeLog
index 3f99f190..31526336 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2008-01-11 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
+
+ Rewritten get*Missing*Index functions. Now no need to allocate memory
+ each time these functions are called.
+ * src/BitfieldMan.{h, cc}
+ * test/BitfieldManTest.cc
+ * src/array_fun.h
+ * test/array_funTest.cc
+
+ Now BitfieldMan::countBlock() returns BitfieldMan::blocks.
+ Added new BitfieldMan::countFilteredBlock() to get the number of blocks
+ filtered. Removed unnecessary cast to int32_t.
+ * src/BitfieldMan.{h, cc}
+
2008-01-10 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Fixed the bug that EX_TOO_LONG_PAYLOAD exception is thrown if just
diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc
index 32f3a99c..2a4a04d2 100644
--- a/src/BitfieldMan.cc
+++ b/src/BitfieldMan.cc
@@ -34,6 +34,7 @@
/* copyright --> */
#include "BitfieldMan.h"
#include "Util.h"
+#include "array_fun.h"
#include <string.h>
BitfieldMan::BitfieldMan(int32_t blockLength, int64_t totalLength)
@@ -131,8 +132,9 @@ int32_t BitfieldMan::getNthBitIndex(const unsigned char bitfield, int32_t nth) c
return index;
}
+template<typename Array>
int32_t
-BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield,
+BitfieldMan::getMissingIndexRandomly(const Array& bitfield,
int32_t bitfieldLength) const
{
/*
@@ -192,47 +194,35 @@ int32_t BitfieldMan::getMissingIndex(const unsigned char* peerBitfield, int32_t
if(bitfieldLength != length) {
return -1;
}
- unsigned char* tempBitfield = new unsigned char[bitfieldLength];
- for(int32_t i = 0; i < bitfieldLength; ++i) {
- tempBitfield[i] = peerBitfield[i] & ~bitfield[i];
- if(filterEnabled) {
- tempBitfield[i] &= filterBitfield[i];
- }
+ array_fun<unsigned char> bf = array_and(array_negate(bitfield), peerBitfield);
+ if(filterEnabled) {
+ bf = array_and(bf, filterBitfield);
}
- int32_t index = getMissingIndexRandomly(tempBitfield, bitfieldLength);
- delete [] tempBitfield;
- return index;
+ return getMissingIndexRandomly(bf, bitfieldLength);
}
int32_t BitfieldMan::getMissingUnusedIndex(const unsigned char* peerBitfield, int32_t length) const {
if(bitfieldLength != length) {
return -1;
}
- unsigned char* tempBitfield = new unsigned char[bitfieldLength];
- for(int32_t i = 0; i < bitfieldLength; ++i) {
- tempBitfield[i] = peerBitfield[i] & ~bitfield[i] & ~useBitfield[i];
- if(filterEnabled) {
- tempBitfield[i] &= filterBitfield[i];
- }
+ array_fun<unsigned char> bf = array_and(array_and(array_negate(bitfield),
+ array_negate(useBitfield)),
+ peerBitfield);
+ if(filterEnabled) {
+ bf = array_and(bf, filterBitfield);
}
- int32_t index = getMissingIndexRandomly(tempBitfield, bitfieldLength);
- delete [] tempBitfield;
- return index;
+ return getMissingIndexRandomly(bf, bitfieldLength);
}
-int32_t BitfieldMan::getFirstMissingUnusedIndex(const unsigned char* peerBitfield, int32_t length) const {
- if(bitfieldLength != length) {
- return -1;
- }
+template<typename Array>
+int32_t BitfieldMan::getFirstMissingIndex(const Array& bitfield, int32_t bitfieldLength) const
+{
for(int32_t i = 0; i < bitfieldLength; ++i) {
- unsigned char bit = peerBitfield[i] & ~bitfield[i] & ~useBitfield[i];
- if(filterEnabled) {
- bit &= filterBitfield[i];
- }
- for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
- unsigned char mask = 1 << bs;
- if(bit & mask) {
- return i*8+7-bs;
+ int32_t base = i*8;
+ for(int32_t bi = 0; bi < 8 && base+bi < blocks; ++bi) {
+ unsigned char mask = 128 >> bi;
+ if(bitfield[i] & mask) {
+ return base+bi;
}
}
}
@@ -240,40 +230,38 @@ int32_t BitfieldMan::getFirstMissingUnusedIndex(const unsigned char* peerBitfiel
}
int32_t BitfieldMan::getFirstMissingUnusedIndex() const {
- for(int32_t i = 0; i < bitfieldLength; ++i) {
- unsigned char bit = ~bitfield[i] & ~useBitfield[i];
- if(filterEnabled) {
- bit &= filterBitfield[i];
- }
- for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
- unsigned char mask = 1 << bs;
- if(bit & mask) {
- return i*8+7-bs;
- }
- }
+ array_fun<unsigned char> bf = array_and(array_negate(bitfield),
+ array_negate(useBitfield));
+ if(filterEnabled) {
+ bf = array_and(bf, filterBitfield);
}
- return -1;
+ return getFirstMissingIndex(bf, bitfieldLength);
+}
+
+int32_t BitfieldMan::getFirstMissingIndex() const
+{
+ array_fun<unsigned char> bf = array_negate(bitfield);
+ if(filterEnabled) {
+ bf = array_and(bf, filterBitfield);
+ }
+ return getFirstMissingIndex(bf, bitfieldLength);
}
int32_t BitfieldMan::getMissingIndex() const {
- unsigned char* tempBitfield = new unsigned char[bitfieldLength];
- for(int32_t i = 0; i < bitfieldLength; ++i) {
- tempBitfield[i] = ~bitfield[i];
- if(filterEnabled) {
- tempBitfield[i] &= filterBitfield[i];
- }
+ array_fun<unsigned char> bf = array_negate(bitfield);
+ if(filterEnabled) {
+ bf = array_and(bf, filterBitfield);
}
- int32_t index = getMissingIndexRandomly(tempBitfield, bitfieldLength);
- delete [] tempBitfield;
- return index;
+ return getMissingIndexRandomly(bf, bitfieldLength);
}
int32_t BitfieldMan::getMissingUnusedIndex() const {
- unsigned char* tempBitfield = new unsigned char[bitfieldLength];
- memset(tempBitfield, 0xff, bitfieldLength);
- int32_t index = getMissingUnusedIndex(tempBitfield, bitfieldLength);
- delete [] tempBitfield;
- return index;
+ array_fun<unsigned char> bf = array_and(array_negate(bitfield),
+ array_negate(useBitfield));
+ if(filterEnabled) {
+ bf = array_and(bf, filterBitfield);
+ }
+ return getMissingIndexRandomly(bf, bitfieldLength);
}
// [startIndex, endIndex)
@@ -298,8 +286,7 @@ public:
};
int32_t BitfieldMan::getStartIndex(int32_t index) const {
- while(index < (int32_t)blocks &&
- (isUseBitSet(index) || isBitSet(index))) {
+ while(index < blocks && (isUseBitSet(index) || isBitSet(index))) {
index++;
}
if((int32_t)blocks <= index) {
@@ -310,8 +297,7 @@ int32_t BitfieldMan::getStartIndex(int32_t index) const {
}
int32_t BitfieldMan::getEndIndex(int32_t index) const {
- while(index < (int32_t)blocks &&
- (!isUseBitSet(index) && !isBitSet(index))) {
+ while(index < blocks && (!isUseBitSet(index) && !isBitSet(index))) {
index++;
}
return index;
@@ -320,9 +306,8 @@ int32_t BitfieldMan::getEndIndex(int32_t index) const {
int32_t BitfieldMan::getSparseMissingUnusedIndex() const {
Range maxRange;
int32_t index = 0;
- int32_t blocks = countBlock();
Range currentRange;
- while(index < (int32_t)blocks) {
+ while(index < blocks) {
currentRange.startIndex = getStartIndex(index);
if(currentRange.startIndex == -1) {
break;
@@ -346,41 +331,40 @@ int32_t BitfieldMan::getSparseMissingUnusedIndex() const {
}
}
-BlockIndexes BitfieldMan::getAllMissingIndexes() const {
+template<typename Array>
+BlockIndexes BitfieldMan::getAllMissingIndexes(const Array& bitfield, int32_t bitfieldLength) const
+{
BlockIndexes missingIndexes;
for(int32_t i = 0; i < bitfieldLength; ++i) {
- unsigned char bit = ~bitfield[i];
- if(filterEnabled) {
- bit &= filterBitfield[i];
- }
- for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
- unsigned char mask = 1 << bs;
- if(bit & mask) {
- missingIndexes.push_back(i*8+7-bs);
+ int32_t base = i*8;
+ for(int32_t bi = 0; bi < 8 && base+bi < blocks; ++bi) {
+ unsigned char mask = 128 >> bi;
+ if(bitfield[i] & mask) {
+ missingIndexes.push_back(base+bi);
}
}
}
return missingIndexes;
}
+BlockIndexes BitfieldMan::getAllMissingIndexes() const {
+ array_fun<unsigned char> bf = array_negate(bitfield);
+ if(filterEnabled) {
+ bf = array_and(bf, filterBitfield);
+ }
+ return getAllMissingIndexes(bf, bitfieldLength);
+}
+
BlockIndexes BitfieldMan::getAllMissingIndexes(const unsigned char* peerBitfield, int32_t peerBitfieldLength) const {
- BlockIndexes missingIndexes;
if(bitfieldLength != peerBitfieldLength) {
- return missingIndexes;
+ return BlockIndexes();
}
- for(int32_t i = 0; i < bitfieldLength; ++i) {
- unsigned char bit = peerBitfield[i] & ~bitfield[i];
- if(filterEnabled) {
- bit &= filterBitfield[i];
- }
- for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) {
- unsigned char mask = 1 << bs;
- if(bit & mask) {
- missingIndexes.push_back(i*8+7-bs);
- }
- }
+ array_fun<unsigned char> bf = array_and(array_negate(bitfield),
+ peerBitfield);
+ if(filterEnabled) {
+ bf = array_and(bf, filterBitfield);
}
- return missingIndexes;
+ return getAllMissingIndexes(bf, bitfieldLength);
}
int32_t BitfieldMan::countMissingBlock() const {
@@ -402,12 +386,12 @@ int32_t BitfieldMan::countMissingBlockNow() const {
}
}
+int32_t BitfieldMan::countFilteredBlock() const {
+ return cachedNumFilteredBlock;
+}
+
int32_t BitfieldMan::countBlock() const {
- if(filterEnabled) {
- return cachedNumFilteredBlock;
- } else {
- return blocks;
- }
+ return blocks;
}
int32_t BitfieldMan::countFilteredBlockNow() const {
@@ -419,7 +403,7 @@ int32_t BitfieldMan::countFilteredBlockNow() const {
}
bool BitfieldMan::setBitInternal(unsigned char* bitfield, int32_t index, bool on) {
- if((int32_t)blocks <= index) { return false; }
+ if(blocks <= index) { return false; }
unsigned char mask = 128 >> index%8;
if(on) {
bitfield[index/8] |= mask;
@@ -479,7 +463,7 @@ bool BitfieldMan::isAllBitSet() const {
}
bool BitfieldMan::isBitSetInternal(const unsigned char* bitfield, int32_t index) const {
- if(index < 0 || (int32_t)blocks <= index) { return false; }
+ if(index < 0 || blocks <= index) { return false; }
unsigned char mask = 128 >> index%8;
return (bitfield[index/8] & mask) != 0;
}
@@ -535,7 +519,7 @@ void BitfieldMan::addFilter(int64_t offset, int64_t length) {
}
int32_t startBlock = offset/blockLength;
int32_t endBlock = (offset+length-1)/blockLength;
- for(int i = startBlock; i <= endBlock && i < (int32_t)blocks; i++) {
+ for(int i = startBlock; i <= endBlock && i < blocks; i++) {
setFilterBit(i);
}
updateCache();
diff --git a/src/BitfieldMan.h b/src/BitfieldMan.h
index fbbf60ae..8e976413 100644
--- a/src/BitfieldMan.h
+++ b/src/BitfieldMan.h
@@ -63,6 +63,17 @@ private:
int32_t countSetBit(const unsigned char* bitfield, int32_t len) const;
int32_t getNthBitIndex(const unsigned char bit, int32_t nth) const;
int32_t getMissingIndexRandomly(const unsigned char* bitfield, int32_t len) const;
+
+ template<typename Array>
+ int32_t
+ getMissingIndexRandomly(const Array& bitfield,
+ int32_t bitfieldLength) const;
+ template<typename Array>
+ int32_t getFirstMissingIndex(const Array& bitfield, int32_t bitfieldLength) const;
+
+ template<typename Array>
+ BlockIndexes getAllMissingIndexes(const Array& bitfield, int32_t bitfieldLength) const;
+
bool isBitSetInternal(const unsigned char* bitfield, int32_t index) const;
bool setBitInternal(unsigned char* bitfield, int32_t index, bool on);
bool setFilterBit(int32_t index);
@@ -112,9 +123,9 @@ public:
}
int32_t getBlockLength(int32_t index) const {
- if(index == (int32_t)(blocks-1)) {
+ if(index == blocks-1) {
return getLastBlockLength();
- } else if(0 <= index && index < (int32_t)(blocks-1)) {
+ } else if(0 <= index && index < blocks-1) {
return getBlockLength();
} else {
return 0;
@@ -146,6 +157,10 @@ public:
/**
* affected by filter
*/
+ int32_t getFirstMissingIndex() const;
+ /**
+ * affected by filter
+ */
int32_t getMissingUnusedIndex(const unsigned char* bitfield, int32_t len) const;
/**
* affected by filter
@@ -194,6 +209,8 @@ public:
/**
* affected by filter
*/
+ int32_t countFilteredBlock() const;
+
int32_t countBlock() const;
/**
* affected by filter
diff --git a/src/array_fun.h b/src/array_fun.h
new file mode 100644
index 00000000..d9ac1c26
--- /dev/null
+++ b/src/array_fun.h
@@ -0,0 +1,198 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_ARRAY_FUN_H_
+#define _D_ARRAY_FUN_H_
+
+#include <functional>
+
+template<typename T>
+class bit_negate:public std::unary_function<T, T> {
+public:
+ T operator()(const T& t) const
+ {
+ return ~t;
+ }
+};
+
+template<typename T>
+class bit_and:public std::binary_function<T, T, T> {
+public:
+ T operator()(const T& t1, const T& t2) const
+ {
+ return t1&t2;
+ }
+};
+
+template<typename R>
+class array_function_base {
+public:
+ virtual ~array_function_base() {}
+
+ virtual R operator[](std::size_t index) const = 0;
+
+ virtual array_function_base* clone() const = 0;
+};
+
+template<typename A, typename F>
+class array_unary_function:public array_function_base<typename F::result_type> {
+private:
+ A _a;
+ F _f;
+public:
+ array_unary_function(A a, F f):_a(a), _f(f) {}
+
+ virtual typename F::result_type operator[](std::size_t index) const
+ {
+ return _f(_a[index]);
+ }
+
+ virtual array_function_base<typename F::result_type>* clone() const
+ {
+ return new array_unary_function(*this);
+ }
+};
+
+template<typename A, typename B, typename F>
+class array_binary_function:public array_function_base<typename F::result_type>{
+private:
+ A _a;
+ B _b;
+ F _f;
+public:
+ array_binary_function(A a, B b, F f):_a(a), _b(b), _f(f) {}
+
+ virtual typename F::result_type operator[](std::size_t index) const
+ {
+ return _f(_a[index], _b[index]);
+ }
+
+ virtual array_function_base<typename F::result_type>* clone() const
+ {
+ return new array_binary_function(*this);
+ }
+};
+
+template<typename R>
+class array_fun {
+private:
+ array_function_base<R>* _p;
+public:
+ template<typename A, typename F>
+ array_fun(A a, F f):_p(new array_unary_function<A, F>(a, f)) {}
+
+ template<typename A, typename B, typename F>
+ array_fun(A a, B b, F f):_p(new array_binary_function<A, B, F>(a, b, f)) {}
+
+ array_fun(const array_fun& af):_p(af._p->clone()) {}
+
+ ~array_fun()
+ {
+ delete _p;
+ }
+
+ array_fun& operator=(const array_fun& af)
+ {
+ if(this != &af) {
+ delete _p;
+ _p = af._p->clone();
+ }
+ return *this;
+ }
+
+ R operator[](std::size_t index) const
+ {
+ return (*_p)[index];
+ }
+
+ typedef R result_type;
+};
+
+template<typename R, typename A>
+array_fun<R>
+array_negate(A a)
+{
+ return array_fun<R>(a, bit_negate<R>());
+}
+
+template<typename T>
+array_fun<T>
+array_negate(T* a)
+{
+ return array_fun<T>(a, bit_negate<T>());
+}
+
+template<typename A>
+array_fun<typename A::result_type>
+array_negate(A a)
+{
+ return array_fun<typename A::result_type>(a, bit_negate<typename A::result_type>());
+}
+
+template<typename R, typename A, typename B>
+array_fun<R>
+array_and(A a, B b)
+{
+ return array_fun<R>(a, b, bit_and<R>());
+}
+
+template<typename T>
+array_fun<T>
+array_and(T* a, T* b)
+{
+ return array_fun<T>(a, b, bit_and<T>());
+}
+
+template<typename T>
+array_fun<typename T::result_type>
+array_and(T a, T b)
+{
+ return array_fun<typename T::result_type>(a, b, bit_and<typename T::result_type>());
+}
+
+template<typename A, typename B>
+array_fun<typename A::result_type>
+array_and(A a, B b)
+{
+ return array_fun<typename A::result_type>(a, b, bit_and<typename A::result_type>());
+}
+
+template<typename A, typename B>
+array_fun<typename B::result_type>
+array_and(A a, B b)
+{
+ return array_fun<typename B::result_type>(a, b, bit_and<typename B::result_type>());
+}
+
+#endif // _D_ARRAY_FUN_H_
diff --git a/test/BitfieldManTest.cc b/test/BitfieldManTest.cc
index 2418ed34..2ab69298 100644
--- a/test/BitfieldManTest.cc
+++ b/test/BitfieldManTest.cc
@@ -1,16 +1,13 @@
#include "BitfieldMan.h"
#include "FixedNumberRandomizer.h"
-#include "BitfieldManFactory.h"
-#include <string>
#include <cppunit/extensions/HelperMacros.h>
-using namespace std;
-
class BitfieldManTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(BitfieldManTest);
CPPUNIT_TEST(testGetBlockSize);
CPPUNIT_TEST(testGetFirstMissingUnusedIndex);
+ CPPUNIT_TEST(testGetFirstMissingIndex);
CPPUNIT_TEST(testIsAllBitSet);
CPPUNIT_TEST(testFilter);
CPPUNIT_TEST(testGetMissingIndex);
@@ -19,6 +16,12 @@ class BitfieldManTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testIsBitSetOffsetRange);
CPPUNIT_TEST(testGetMissingUnusedLength);
CPPUNIT_TEST(testSetBitRange);
+ CPPUNIT_TEST(testGetAllMissingIndexes);
+ CPPUNIT_TEST(testGetAllMissingIndexes_noarg);
+ CPPUNIT_TEST(testGetMissingUnusedIndex);
+ CPPUNIT_TEST(testGetMissingIndex_noarg);
+ CPPUNIT_TEST(testGetMissingUnusedIndex_noarg);
+ CPPUNIT_TEST(testCountFilteredBlock);
CPPUNIT_TEST_SUITE_END();
private:
RandomizerHandle fixedNumberRandomizer;
@@ -35,14 +38,22 @@ public:
void testGetBlockSize();
void testGetFirstMissingUnusedIndex();
+ void testGetFirstMissingIndex();
+ void testGetMissingIndex();
+ void testGetMissingIndex_noarg();
+ void testGetMissingUnusedIndex();
+ void testGetMissingUnusedIndex_noarg();
+ void testGetAllMissingIndexes();
+ void testGetAllMissingIndexes_noarg();
+
void testIsAllBitSet();
void testFilter();
- void testGetMissingIndex();
void testGetSparceMissingUnusedIndex();
void testGetSparceMissingUnusedIndex_setBit();
void testIsBitSetOffsetRange();
void testGetMissingUnusedLength();
void testSetBitRange();
+ void testCountFilteredBlock();
};
@@ -58,27 +69,116 @@ void BitfieldManTest::testGetBlockSize() {
CPPUNIT_ASSERT_EQUAL((int32_t)0, bt2.getBlockLength(11));
}
-void BitfieldManTest::testGetFirstMissingUnusedIndex() {
- BitfieldMan bt1(1024, 1024*10);
- unsigned char bitfield[2];
- memset(bitfield, 0xff, sizeof(bitfield));
+void BitfieldManTest::testGetFirstMissingUnusedIndex()
+{
+ {
+ BitfieldMan bt1(1024, 1024*10);
+
+ CPPUNIT_ASSERT_EQUAL(0, bt1.getFirstMissingUnusedIndex());
+ bt1.setUseBit(0);
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingUnusedIndex());
+ bt1.unsetUseBit(0);
+ bt1.setBit(0);
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingUnusedIndex());
+ bt1.setAllBit();
+ CPPUNIT_ASSERT_EQUAL(-1, bt1.getFirstMissingUnusedIndex());
+ }
+ {
+ BitfieldMan bt1(1024, 1024*10);
+
+ bt1.addFilter(1024, 1024*10);
+ bt1.enableFilter();
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingUnusedIndex());
+ bt1.setUseBit(1);
+ CPPUNIT_ASSERT_EQUAL(2, bt1.getFirstMissingUnusedIndex());
+ bt1.setBit(2);
+ CPPUNIT_ASSERT_EQUAL(3, bt1.getFirstMissingUnusedIndex());
+ }
+}
- CPPUNIT_ASSERT_EQUAL((int32_t)0, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield)));
- CPPUNIT_ASSERT(bt1.setUseBit(0));
- CPPUNIT_ASSERT_EQUAL((int32_t)1, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield)));
- CPPUNIT_ASSERT(bt1.unsetUseBit(0));
- CPPUNIT_ASSERT_EQUAL((int32_t)0, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield)));
- CPPUNIT_ASSERT(bt1.setBit(0));
- CPPUNIT_ASSERT_EQUAL((int32_t)1, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield)));
+void BitfieldManTest::testGetFirstMissingIndex()
+{
+ {
+ BitfieldMan bt1(1024, 1024*10);
+
+ CPPUNIT_ASSERT_EQUAL(0, bt1.getFirstMissingIndex());
+ bt1.setUseBit(0);
+ CPPUNIT_ASSERT_EQUAL(0, bt1.getFirstMissingIndex());
+ bt1.unsetUseBit(0);
+ bt1.setBit(0);
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingIndex());
+ bt1.setAllBit();
+ CPPUNIT_ASSERT_EQUAL(-1, bt1.getFirstMissingIndex());
+ }
+ {
+ BitfieldMan bt1(1024, 1024*10);
+
+ bt1.addFilter(1024, 1024*10);
+ bt1.enableFilter();
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingIndex());
+ bt1.setUseBit(1);
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingIndex());
+ bt1.setBit(1);
+ CPPUNIT_ASSERT_EQUAL(2, bt1.getFirstMissingIndex());
+ }
+}
- for(int i = 0; i < 8; i++) {
- CPPUNIT_ASSERT(bt1.setBit(i));
+void BitfieldManTest::testGetMissingUnusedIndex_noarg()
+{
+ {
+ BitfieldMan bt1(1024, 1024*10);
+ bt1.setRandomizer(fixedNumberRandomizer);
+
+ CPPUNIT_ASSERT_EQUAL(0, bt1.getMissingUnusedIndex());
+ bt1.setUseBit(0);
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingUnusedIndex());
+ bt1.unsetUseBit(0);
+ bt1.setBit(0);
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingUnusedIndex());
+ bt1.setAllBit();
+ CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingUnusedIndex());
}
- CPPUNIT_ASSERT_EQUAL((int32_t)8, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield)));
+ {
+ BitfieldMan bt1(1024, 1024*10);
+ bt1.setRandomizer(fixedNumberRandomizer);
+
+ bt1.addFilter(1024, 1024*10);
+ bt1.enableFilter();
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingUnusedIndex());
+ bt1.setUseBit(1);
+ CPPUNIT_ASSERT_EQUAL(2, bt1.getMissingUnusedIndex());
+ bt1.setBit(2);
+ CPPUNIT_ASSERT_EQUAL(3, bt1.getMissingUnusedIndex());
+ }
+}
- CPPUNIT_ASSERT_EQUAL((int32_t)8, bt1.getFirstMissingUnusedIndex());
- CPPUNIT_ASSERT(bt1.setUseBit(8));
- CPPUNIT_ASSERT_EQUAL((int32_t)9, bt1.getFirstMissingUnusedIndex());
+void BitfieldManTest::testGetMissingIndex_noarg()
+{
+ {
+ BitfieldMan bt1(1024, 1024*10);
+ bt1.setRandomizer(fixedNumberRandomizer);
+
+ CPPUNIT_ASSERT_EQUAL(0, bt1.getMissingIndex());
+ bt1.setUseBit(0);
+ CPPUNIT_ASSERT_EQUAL(0, bt1.getMissingIndex());
+ bt1.unsetUseBit(0);
+ bt1.setBit(0);
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingIndex());
+ bt1.setAllBit();
+ CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingIndex());
+ }
+ {
+ BitfieldMan bt1(1024, 1024*10);
+ bt1.setRandomizer(fixedNumberRandomizer);
+
+ bt1.addFilter(1024, 1024*10);
+ bt1.enableFilter();
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingIndex());
+ bt1.setUseBit(1);
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingIndex());
+ bt1.setBit(1);
+ CPPUNIT_ASSERT_EQUAL(2, bt1.getMissingIndex());
+ }
}
void BitfieldManTest::testIsAllBitSet() {
@@ -178,6 +278,11 @@ void BitfieldManTest::testGetMissingIndex() {
};
CPPUNIT_ASSERT_EQUAL((int32_t)0, bt1.getMissingIndex(bitArray, 32));
+ bt1.addFilter(1024, 1024*256);
+ bt1.enableFilter();
+ CPPUNIT_ASSERT_EQUAL((int32_t)1, bt1.getMissingIndex(bitArray, 32));
+ bt1.disableFilter();
+
unsigned char bitArray2[] = {
0x0f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
@@ -354,3 +459,103 @@ void BitfieldManTest::testSetBitRange()
}
CPPUNIT_ASSERT_EQUAL(int64_t(5*blockLength), bf.getCompletedLength());
}
+
+void BitfieldManTest::testGetAllMissingIndexes_noarg()
+{
+ int32_t blockLength = 16*1024;
+ int64_t totalLength = 1024*1024;
+ BitfieldMan bf(blockLength, totalLength);
+
+ CPPUNIT_ASSERT_EQUAL((size_t)64, bf.getAllMissingIndexes().size());
+ for(int32_t i = 0; i < 63; ++i) {
+ bf.setBit(i);
+ }
+ CPPUNIT_ASSERT_EQUAL((size_t)1, bf.getAllMissingIndexes().size());
+ CPPUNIT_ASSERT_EQUAL(63, bf.getAllMissingIndexes().front());
+}
+
+void BitfieldManTest::testGetAllMissingIndexes()
+{
+ int32_t blockLength = 16*1024;
+ int64_t totalLength = 1024*1024;
+ BitfieldMan bf(blockLength, totalLength);
+ BitfieldMan peerBf(blockLength, totalLength);
+ peerBf.setAllBit();
+
+ CPPUNIT_ASSERT_EQUAL((size_t)64, bf.getAllMissingIndexes(peerBf.getBitfield(),
+ peerBf.getBitfieldLength()).size());
+ for(int32_t i = 0; i < 62; ++i) {
+ bf.setBit(i);
+ }
+ peerBf.unsetBit(62);
+
+ {
+ Integers indexes = bf.getAllMissingIndexes(peerBf.getBitfield(),
+ peerBf.getBitfieldLength());
+
+ CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size());
+ CPPUNIT_ASSERT_EQUAL(63, indexes.front());
+ }
+}
+
+void BitfieldManTest::testGetMissingUnusedIndex()
+{
+ BitfieldMan bt1(1024, 1024*256);
+ bt1.setRandomizer(fixedNumberRandomizer);
+
+ unsigned char bitArray[] = {
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ };
+ CPPUNIT_ASSERT_EQUAL(0, bt1.getMissingUnusedIndex(bitArray, 32));
+
+ bt1.addFilter(1024, 1024*256);
+ bt1.enableFilter();
+ CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingUnusedIndex(bitArray, 32));
+ bt1.setUseBit(1);
+ CPPUNIT_ASSERT_EQUAL(2, bt1.getMissingUnusedIndex(bitArray, 32));
+ bt1.disableFilter();
+
+ bt1.setBit(0);
+ CPPUNIT_ASSERT_EQUAL(2, bt1.getMissingUnusedIndex(bitArray, 32));
+
+ bt1.setAllBit();
+ CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingUnusedIndex(bitArray, 32));
+
+ bt1.clearAllBit();
+ bt1.setAllUseBit();
+ CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingUnusedIndex(bitArray, 32));
+
+ unsigned char bitArray4[] = {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ };
+
+ CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingUnusedIndex(bitArray4, 32));
+}
+
+void BitfieldManTest::testCountFilteredBlock()
+{
+ BitfieldMan bt(1024, 1024*256);
+ CPPUNIT_ASSERT_EQUAL(256, bt.countBlock());
+ CPPUNIT_ASSERT_EQUAL(0, bt.countFilteredBlock());
+ bt.addFilter(1024, 1024*256);
+ bt.enableFilter();
+ CPPUNIT_ASSERT_EQUAL(256, bt.countBlock());
+ CPPUNIT_ASSERT_EQUAL(255, bt.countFilteredBlock());
+ bt.disableFilter();
+ CPPUNIT_ASSERT_EQUAL(256, bt.countBlock());
+ CPPUNIT_ASSERT_EQUAL(0, bt.countFilteredBlock());
+}
diff --git a/test/array_funTest.cc b/test/array_funTest.cc
new file mode 100644
index 00000000..32fe0b6f
--- /dev/null
+++ b/test/array_funTest.cc
@@ -0,0 +1,67 @@
+#include "array_fun.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class array_funTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(array_funTest);
+ CPPUNIT_TEST(testBit_negate);
+ CPPUNIT_TEST(testBit_and);
+ CPPUNIT_TEST(testArray_negate);
+ CPPUNIT_TEST(testArray_and);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void testBit_negate();
+ void testBit_and();
+ void testArray_negate();
+ void testArray_and();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(array_funTest);
+
+void array_funTest::testBit_negate()
+{
+ unsigned char b = 0xaa;
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, bit_negate<unsigned char>()(b));
+}
+
+void array_funTest::testBit_and()
+{
+ unsigned char b = 0xaa;
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0x0a, bit_and<unsigned char>()(b, 0x0a));
+}
+
+void array_funTest::testArray_negate()
+{
+ unsigned char a[] = { 0xaa, 0x55 };
+ array_fun<unsigned char> f = array_negate((unsigned char*)a);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, f[0]);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0xaa, f[1]);
+
+ array_fun<unsigned char> ff = array_negate(f);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0xaa, ff[0]);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, ff[1]);
+}
+
+void array_funTest::testArray_and()
+{
+ unsigned char a1[] = { 0xaa, 0x55 };
+ unsigned char a2[] = { 0x1a, 0x25 };
+ array_fun<unsigned char> f = array_and((unsigned char*)a1, (unsigned char*)a2);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0x0a, f[0]);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0x05, f[1]);
+
+ array_fun<unsigned char> f2 = array_and((unsigned char*)a1, array_negate(a2));
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0xa0, f2[0]);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0x50, f2[1]);
+
+ array_fun<unsigned char> f3 = array_and(array_negate(a2), (unsigned char*)a1);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0xa0, f3[0]);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0x50, f3[1]);
+
+ array_fun<unsigned char> f4 = array_and(array_negate(a1), array_negate(a2));
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0x45, f4[0]);
+ CPPUNIT_ASSERT_EQUAL((unsigned char)0x8a, f4[1]);
+}