2009-04-16 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

Rewritten array operation functions.
	* src/BitfieldMan.cc
	* src/array_fun.h
	* test/array_funTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2009-04-16 13:43:23 +00:00
parent e19447a54b
commit d2d4f67bbe
4 changed files with 196 additions and 224 deletions

View File

@ -1,3 +1,10 @@
2009-04-16 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Rewritten array operation functions.
* src/BitfieldMan.cc
* src/array_fun.h
* test/array_funTest.cc
2009-04-14 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Removed unused variable 'query'

View File

@ -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<unsigned char> 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<unsigned char> 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<typename Array>
@ -266,39 +276,46 @@ bool BitfieldMan::getFirstMissingIndex(size_t& index, const Array& bitfield, siz
bool BitfieldMan::getFirstMissingUnusedIndex(size_t& index) const
{
array_fun<unsigned char> 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<unsigned char> 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<unsigned char> 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<unsigned char> 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<unsigned char> 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<unsigned char> 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<unsigned char> 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 {

View File

@ -40,164 +40,6 @@
namespace aria2 {
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[](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[](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[](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[](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>());
}
// calculate length of array
template<typename T, size_t N>
@ -272,6 +114,122 @@ public:
}
};
// Expression Template for array
namespace expr {
template<typename T>
struct Expr {
Expr(const T& expOp):_expOp(expOp) {}
typename T::returnType operator[](size_t index) const
{
return _expOp(index);
}
const T& _expOp;
};
template<typename T>
struct And
{
typedef T returnType;
static inline T apply(T lhs, T rhs) { return lhs&rhs; }
};
template<typename T>
struct Noop
{
typedef T returnType;
static inline T apply(T arg) { return arg; }
};
template<typename T>
struct Negate
{
typedef T returnType;
static inline T apply(T arg) { return ~arg; }
};
template<typename T1, typename T2, typename BinOp>
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<typename T, typename UnOp>
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<typename T, typename UnOp>
struct ExpUnOp<T*, UnOp>
{
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<typename T, size_t N>
Expr<ExpUnOp<T(&)[N], Noop<T> > > arrayRef(T (&t)[N])
{
typedef ExpUnOp<T(&)[N], Noop<T> > ExpUnOpT;
return Expr<ExpUnOpT>(ExpUnOpT(t));
}
template<typename T>
Expr<ExpUnOp<T*, Noop<T> > > array(T* a)
{
typedef ExpUnOp<T*, Noop<T> > ExpUnOpT;
return Expr<ExpUnOpT>(ExpUnOpT(a));
}
template<typename T>
Expr<ExpUnOp<Expr<T>, Negate<typename T::returnType> > >
operator~(const Expr<T>& arg)
{
typedef ExpUnOp<Expr<T>, Negate<typename T::returnType> > ExpUnOpT;
return Expr<ExpUnOpT>(ExpUnOpT(arg));
}
template<typename T1, typename T2>
Expr<ExpBinOp<Expr<T1>, Expr<T2>, And<typename T1::returnType> > >
operator&(const Expr<T1>& lhs, const Expr<T2>& rhs)
{
typedef ExpBinOp<Expr<T1>, Expr<T2>, And<typename T1::returnType> > ExpBinOpT;
return Expr<ExpBinOpT>(ExpBinOpT(lhs, rhs));
}
} // namespace expr
} // namespace aria2
#endif // _D_ARRAY_FUN_H_

View File

@ -1,13 +1,13 @@
#include "array_fun.h"
#include <cppunit/extensions/HelperMacros.h>
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<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]);
CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, (~arrayRef(a))[0]);
CPPUNIT_ASSERT_EQUAL((unsigned char)0xaa, (~array((unsigned char*)a))[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]);
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<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]);
CPPUNIT_ASSERT_EQUAL((unsigned char)0x0a, (arrayRef(a1)&arrayRef(a2))[0]);
CPPUNIT_ASSERT_EQUAL((unsigned char)0x05, (arrayRef(a1)&arrayRef(a2))[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]);
CPPUNIT_ASSERT_EQUAL((unsigned char)0xa0, (arrayRef(a1)&~arrayRef(a2))[0]);
CPPUNIT_ASSERT_EQUAL((unsigned char)0x50, (arrayRef(a1)&~arrayRef(a2))[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]);
CPPUNIT_ASSERT_EQUAL((unsigned char)0xa0, (~arrayRef(a2)&arrayRef(a1))[0]);
CPPUNIT_ASSERT_EQUAL((unsigned char)0x50, (~arrayRef(a2)&arrayRef(a1))[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]);
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()