00001 #ifndef Exc_Ruby__detail__Iterator_Definer__hpp_
00002 #define Exc_Ruby__detail__Iterator_Definer__hpp_
00003
00004 #include "../rb_cpp_method_data.hpp"
00005 #include "../call_ruby_function.hpp"
00006 #include "../detail/ruby_hacks.hpp"
00007
00008 namespace Exc_Ruby
00009 {
00010
00011 namespace detail
00012 {
00013
00014 template<typename Derived_T>
00015 class Iterator_Definer
00016 {
00017 public:
00018 virtual ~Iterator_Definer()
00019 {
00020 }
00021
00022 class Iterator
00023 {
00024 public:
00025 virtual ~Iterator() { }
00026
00027 virtual VALUE call_impl(VALUE self) = 0;
00028
00029 static VALUE call(VALUE self)
00030 {
00031 void * data = rb_cpp_method_data();
00032 Iterator * iterator = static_cast<Iterator *>(data);
00033 return iterator->call_impl(self);
00034 }
00035 };
00036
00037 template<typename T, typename Iterator_T>
00038 class Iterator_Impl
00039 : public Iterator
00040 {
00041 public:
00042 Iterator_Impl(
00043 Iterator_T (T::*begin)(),
00044 Iterator_T (T::*end)())
00045 : begin_(begin)
00046 , end_(end)
00047 {
00048 }
00049
00050 virtual VALUE call_impl(VALUE self)
00051 {
00052
00053
00054 Ruby_Reference<T> obj(self);
00055 Iterator_T it = obj->begin();
00056 Iterator_T end = obj->end();
00057 for(; it != end; ++it)
00058 {
00059 call_ruby_function(rb_yield, to_ruby(*it));
00060 }
00061 return self;
00062 }
00063
00064 private:
00065 Iterator_T (T::*begin_)();
00066 Iterator_T (T::*end_)();
00067 };
00068
00069 template<typename T, typename Iterator_T>
00070 Derived_T & define_iterator(
00071 char const * name,
00072 Iterator_T (T::*begin)(),
00073 Iterator_T (T::*end)())
00074 {
00075 Derived_T & self = static_cast<Derived_T &>(*this);
00076
00077 Iterator * iterator = new Iterator_Impl<T, Iterator_T>(begin, end);
00078 rb_cpp_define_method_with_data(
00079 static_cast<VALUE>(self),
00080 name,
00081 (RUBY_METHOD_FUNC)iterator->call,
00082 0,
00083 iterator);
00084 return self;
00085 }
00086 };
00087
00088 }
00089
00090 }
00091
00092 #endif // Exc_Ruby__detail__Iterator_Definer__hpp_
00093