Browse Source

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
Tatsuhiro Tsujikawa 16 years ago
parent
commit
d2d4f67bbe
4 changed files with 196 additions and 224 deletions
  1. 7 0
      ChangeLog
  2. 59 34
      src/BitfieldMan.cc
  3. 116 158
      src/array_fun.h
  4. 14 32
      test/array_funTest.cc

+ 7 - 0
ChangeLog

@@ -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'

+ 59 - 34
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<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 {

+ 116 - 158
src/array_fun.h

@@ -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_

+ 14 - 32
test/array_funTest.cc

@@ -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()