diff --git a/ChangeLog b/ChangeLog index 4530c77b..cf206de1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-04-16 Tatsuhiro Tsujikawa + + Rewritten array operation functions. + * src/BitfieldMan.cc + * src/array_fun.h + * test/array_funTest.cc + 2009-04-14 Tatsuhiro Tsujikawa Removed unused variable 'query' diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc index 74ebe56b..ae1cb218 100644 --- a/src/BitfieldMan.cc +++ b/src/BitfieldMan.cc @@ -42,6 +42,8 @@ #include "array_fun.h" #include "bitfield.h" +using namespace aria2::expr; + namespace aria2 { BitfieldMan::BitfieldMan(size_t blockLength, uint64_t totalLength) @@ -227,24 +229,32 @@ bool BitfieldMan::getMissingIndex(size_t& index, const unsigned char* peerBitfie if(bitfieldLength != length) { return false; } - array_fun bf = array_and(array_negate(bitfield), peerBitfield); if(filterEnabled) { - bf = array_and(bf, filterBitfield); + return getMissingIndexRandomly + (index, + ~array(bitfield)&array(peerBitfield)&array(filterBitfield), + bitfieldLength); + } else { + return getMissingIndexRandomly + (index, ~array(bitfield)&array(peerBitfield), bitfieldLength); } - return getMissingIndexRandomly(index, bf, bitfieldLength); } bool BitfieldMan::getMissingUnusedIndex(size_t& index, const unsigned char* peerBitfield, size_t length) const { if(bitfieldLength != length) { return false; } - array_fun bf = array_and(array_and(array_negate(bitfield), - array_negate(useBitfield)), - peerBitfield); if(filterEnabled) { - bf = array_and(bf, filterBitfield); + return getMissingIndexRandomly + (index, + ~array(bitfield)&~array(useBitfield)&array(peerBitfield)&array(filterBitfield), + bitfieldLength); + } else { + return getMissingIndexRandomly + (index, + ~array(bitfield)&~array(useBitfield)&array(peerBitfield), + bitfieldLength); } - return getMissingIndexRandomly(index, bf, bitfieldLength); } template @@ -266,39 +276,46 @@ bool BitfieldMan::getFirstMissingIndex(size_t& index, const Array& bitfield, siz bool BitfieldMan::getFirstMissingUnusedIndex(size_t& index) const { - array_fun bf = array_and(array_negate(bitfield), - array_negate(useBitfield)); if(filterEnabled) { - bf = array_and(bf, filterBitfield); + return getFirstMissingIndex + (index, ~array(bitfield)&~array(useBitfield)&array(filterBitfield), + bitfieldLength); + } else { + return getFirstMissingIndex + (index, ~array(bitfield)&~array(useBitfield), + bitfieldLength); } - return getFirstMissingIndex(index, bf, bitfieldLength); } bool BitfieldMan::getFirstMissingIndex(size_t& index) const { - array_fun bf = array_negate(bitfield); if(filterEnabled) { - bf = array_and(bf, filterBitfield); + return getFirstMissingIndex(index, ~array(bitfield)&array(filterBitfield), + bitfieldLength); + } else { + return getFirstMissingIndex(index, ~array(bitfield), bitfieldLength); } - return getFirstMissingIndex(index, bf, bitfieldLength); } bool BitfieldMan::getMissingIndex(size_t& index) const { - array_fun bf = array_negate(bitfield); if(filterEnabled) { - bf = array_and(bf, filterBitfield); + return getMissingIndexRandomly + (index, ~array(bitfield)&array(filterBitfield), bitfieldLength); + } else { + return getMissingIndexRandomly(index, ~array(bitfield), bitfieldLength); } - return getMissingIndexRandomly(index, bf, bitfieldLength); } bool BitfieldMan::getMissingUnusedIndex(size_t& index) const { - array_fun bf = array_and(array_negate(bitfield), - array_negate(useBitfield)); if(filterEnabled) { - bf = array_and(bf, filterBitfield); + return getMissingIndexRandomly + (index, ~array(bitfield)&~array(useBitfield)&array(filterBitfield), + bitfieldLength); + } else { + return getMissingIndexRandomly + (index, ~array(bitfield)&~array(useBitfield), bitfieldLength); } - return getMissingIndexRandomly(index, bf, bitfieldLength); } size_t BitfieldMan::getStartIndex(size_t index) const { @@ -368,11 +385,12 @@ bool BitfieldMan::getAllMissingIndexes(unsigned char* misbitfield, size_t len) const { assert(len == bitfieldLength); - array_fun bf = array_negate(bitfield); if(filterEnabled) { - bf = array_and(bf, filterBitfield); + return copyBitfield + (misbitfield, ~array(bitfield)&array(filterBitfield), blocks); + } else { + return copyBitfield(misbitfield, ~array(bitfield), blocks); } - return copyBitfield(misbitfield, bf, blocks); } bool BitfieldMan::getAllMissingIndexes(unsigned char* misbitfield, size_t len, @@ -383,12 +401,15 @@ bool BitfieldMan::getAllMissingIndexes(unsigned char* misbitfield, size_t len, if(bitfieldLength != peerBitfieldLength) { return false; } - array_fun bf = array_and(array_negate(bitfield), - peerBitfield); if(filterEnabled) { - bf = array_and(bf, filterBitfield); + return copyBitfield + (misbitfield, ~array(bitfield)&array(peerBitfield)&array(filterBitfield), + blocks); + } else { + return copyBitfield + (misbitfield, ~array(bitfield)&array(peerBitfield), + blocks); } - return copyBitfield(misbitfield, bf, blocks); } bool BitfieldMan::getAllMissingUnusedIndexes(unsigned char* misbitfield, @@ -400,13 +421,17 @@ bool BitfieldMan::getAllMissingUnusedIndexes(unsigned char* misbitfield, if(bitfieldLength != peerBitfieldLength) { return false; } - array_fun bf = array_and(array_and(array_negate(bitfield), - array_negate(useBitfield)), - peerBitfield); if(filterEnabled) { - bf = array_and(bf, filterBitfield); + return copyBitfield + (misbitfield, + ~array(bitfield)&~array(useBitfield)&array(peerBitfield)&array(filterBitfield), + blocks); + } else { + return copyBitfield + (misbitfield, + ~array(bitfield)&~array(useBitfield)&array(peerBitfield), + blocks); } - return copyBitfield(misbitfield, bf, blocks); } size_t BitfieldMan::countMissingBlock() const { diff --git a/src/array_fun.h b/src/array_fun.h index f7f4dd14..479e24b0 100644 --- a/src/array_fun.h +++ b/src/array_fun.h @@ -40,164 +40,6 @@ namespace aria2 { -template -class bit_negate:public std::unary_function { -public: - T operator()(const T& t) const - { - return ~t; - } -}; - -template -class bit_and:public std::binary_function { -public: - T operator()(const T& t1, const T& t2) const - { - return t1&t2; - } -}; - -template -class array_function_base { -public: - virtual ~array_function_base() {} - - virtual R operator[](size_t index) const = 0; - - virtual array_function_base* clone() const = 0; -}; - -template -class array_unary_function:public array_function_base { -private: - A _a; - F _f; -public: - array_unary_function(A a, F f):_a(a), _f(f) {} - - virtual typename F::result_type operator[](size_t index) const - { - return _f(_a[index]); - } - - virtual array_function_base* clone() const - { - return new array_unary_function(*this); - } -}; - -template -class array_binary_function:public array_function_base{ -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[](size_t index) const - { - return _f(_a[index], _b[index]); - } - - virtual array_function_base* clone() const - { - return new array_binary_function(*this); - } -}; - -template -class array_fun { -private: - array_function_base* _p; -public: - template - array_fun(A a, F f):_p(new array_unary_function(a, f)) {} - - template - array_fun(A a, B b, F f):_p(new array_binary_function(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[](size_t index) const - { - return (*_p)[index]; - } - - typedef R result_type; -}; - -template -array_fun -array_negate(A a) -{ - return array_fun(a, bit_negate()); -} - -template -array_fun -array_negate(T* a) -{ - return array_fun(a, bit_negate()); -} - -template -array_fun -array_negate(A a) -{ - return array_fun(a, bit_negate()); -} - -template -array_fun -array_and(A a, B b) -{ - return array_fun(a, b, bit_and()); -} - -template -array_fun -array_and(T* a, T* b) -{ - return array_fun(a, b, bit_and()); -} - -template -array_fun -array_and(T a, T b) -{ - return array_fun(a, b, bit_and()); -} - -template -array_fun -array_and(A a, B b) -{ - return array_fun(a, b, bit_and()); -} - -template -array_fun -array_and(A a, B b) -{ - return array_fun(a, b, bit_and()); -} - // calculate length of array template @@ -272,6 +114,122 @@ public: } }; +// Expression Template for array + +namespace expr { + +template +struct Expr { + Expr(const T& expOp):_expOp(expOp) {} + + typename T::returnType operator[](size_t index) const + { + return _expOp(index); + } + + const T& _expOp; +}; + +template +struct And +{ + typedef T returnType; + static inline T apply(T lhs, T rhs) { return lhs&rhs; } +}; + +template +struct Noop +{ + typedef T returnType; + static inline T apply(T arg) { return arg; } +}; + +template +struct Negate +{ + typedef T returnType; + static inline T apply(T arg) { return ~arg; } +}; + +template +struct ExpBinOp +{ + typedef typename BinOp::returnType returnType; + + ExpBinOp(const T1& lhs, const T2& rhs):_lhs(lhs), _rhs(rhs) {} + + returnType operator()(size_t index) const + { + return BinOp::apply(_lhs[index], _rhs[index]); + } + + const T1& _lhs; + const T2& _rhs; +}; + +template +struct ExpUnOp +{ + typedef typename UnOp::returnType returnType; + + ExpUnOp(const T& arg):_arg(arg) {} + + returnType operator()(size_t index) const + { + return UnOp::apply(_arg[index]); + } + + const T& _arg; +}; + +// Partial specialization for pointers +template +struct ExpUnOp +{ + typedef typename UnOp::returnType returnType; + + ExpUnOp(const T* arg):_arg(arg) {} + + returnType operator()(size_t index) const + { + return UnOp::apply(_arg[index]); + } + + const T* _arg; +}; + +template +Expr > > arrayRef(T (&t)[N]) +{ + typedef ExpUnOp > ExpUnOpT; + return Expr(ExpUnOpT(t)); +} + +template +Expr > > array(T* a) +{ + typedef ExpUnOp > ExpUnOpT; + return Expr(ExpUnOpT(a)); +} + +template +Expr, Negate > > +operator~(const Expr& arg) +{ + typedef ExpUnOp, Negate > ExpUnOpT; + return Expr(ExpUnOpT(arg)); +} + +template +Expr, Expr, And > > +operator&(const Expr& lhs, const Expr& rhs) +{ + typedef ExpBinOp, Expr, And > ExpBinOpT; + return Expr(ExpBinOpT(lhs, rhs)); +} + +} // namespace expr + } // namespace aria2 #endif // _D_ARRAY_FUN_H_ diff --git a/test/array_funTest.cc b/test/array_funTest.cc index cc7b5f10..e00f1c8d 100644 --- a/test/array_funTest.cc +++ b/test/array_funTest.cc @@ -1,13 +1,13 @@ #include "array_fun.h" #include +using namespace aria2::expr; + namespace aria2 { 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(testArrayLength); @@ -33,49 +33,31 @@ public: CPPUNIT_TEST_SUITE_REGISTRATION(array_funTest); -void array_funTest::testBit_negate() -{ - unsigned char b = 0xaa; - CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, bit_negate()(b)); -} - -void array_funTest::testBit_and() -{ - unsigned char b = 0xaa; - CPPUNIT_ASSERT_EQUAL((unsigned char)0x0a, bit_and()(b, 0x0a)); -} - void array_funTest::testArray_negate() { unsigned char a[] = { 0xaa, 0x55 }; - array_fun f = array_negate((unsigned char*)a); - CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, f[0]); - CPPUNIT_ASSERT_EQUAL((unsigned char)0xaa, f[1]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, (~arrayRef(a))[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0xaa, (~array((unsigned char*)a))[1]); - array_fun ff = array_negate(f); - CPPUNIT_ASSERT_EQUAL((unsigned char)0xaa, ff[0]); - CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, ff[1]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0xaa, (~~arrayRef(a))[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, (~~arrayRef(a))[1]); } void array_funTest::testArray_and() { unsigned char a1[] = { 0xaa, 0x55 }; unsigned char a2[] = { 0x1a, 0x25 }; - array_fun 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]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x0a, (arrayRef(a1)&arrayRef(a2))[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x05, (arrayRef(a1)&arrayRef(a2))[1]); - array_fun 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]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0xa0, (arrayRef(a1)&~arrayRef(a2))[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x50, (arrayRef(a1)&~arrayRef(a2))[1]); - array_fun 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]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0xa0, (~arrayRef(a2)&arrayRef(a1))[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x50, (~arrayRef(a2)&arrayRef(a1))[1]); - array_fun 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]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x45, (~arrayRef(a1)&~arrayRef(a2))[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x8a, (~arrayRef(a1)&~arrayRef(a2))[1]); } void array_funTest::testArrayLength()