Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implement CAPI function rb_enumeratorize.

  • Loading branch information...
commit 2f8d170bbf8bbcdd3cf3f030af78cdbef5b35b3b 1 parent b007451
Ian Leitch ileitch authored
39 spec/ruby/optional/capi/enumerator_spec.rb
View
@@ -0,0 +1,39 @@
+require File.expand_path('../spec_helper', __FILE__)
+
+load_extension("enumerator")
+
+describe "C-API Enumerator function" do
+ before :each do
+ @s = CApiEnumeratorSpecs.new
+ end
+
+ describe "rb_enumeratorize" do
+ before do
+ @enumerable = [1, 2, 3]
+ end
+
+ it "constructs a new Enumerator for the given object, method and arguments" do
+ enumerator = @s.rb_enumeratorize(@enumerable, :each, :arg1, :arg2)
+ enumerator.class.should == Enumerable::Enumerator
+ end
+
+ it "enumerates the given object" do
+ enumerator = @s.rb_enumeratorize(@enumerable, :each)
+ enumerated = []
+ enumerator.each { |i| enumerated << i }
+ enumerated.should == @enumerable
+ end
+
+ it "uses the given method for enumeration" do
+ enumerator = @s.rb_enumeratorize(@enumerable, :awesome_each)
+ @enumerable.should_receive(:awesome_each)
+ enumerator.each {}
+ end
+
+ it "passes the given arguments to the enumeration method" do
+ enumerator = @s.rb_enumeratorize(@enumerable, :each, :arg1, :arg2)
+ @enumerable.should_receive(:each).with(:arg1, :arg2)
+ enumerator.each {}
+ end
+ end
+end
11 spec/ruby/optional/capi/ext/constants_spec.c
View
@@ -155,6 +155,12 @@ static VALUE constants_spec_rb_cMethod(VALUE self) {
}
#endif
+#ifdef HAVE_RB_CENUMERATOR
+static VALUE constants_spec_rb_cEnumerator(VALUE self) {
+ return rb_cEnumerator;
+}
+#endif
+
#ifdef HAVE_RB_MCOMPARABLE
static VALUE constants_spec_rb_mComparable(VALUE self) {
return rb_mComparable;
@@ -469,6 +475,10 @@ void Init_constants_spec() {
rb_define_method(cls, "rb_cMethod", constants_spec_rb_cMethod, 0);
#endif
+#ifdef HAVE_RB_CENUMERATOR
+ rb_define_method(cls, "rb_cEnumerator", constants_spec_rb_cEnumerator, 0);
+#endif
+
#ifdef HAVE_RB_MCOMPARABLE
rb_define_method(cls, "rb_mComparable", constants_spec_rb_mComparable, 0);
#endif
@@ -481,7 +491,6 @@ void Init_constants_spec() {
rb_define_method(cls, "rb_mKernel", constants_spec_rb_mKernel, 0);
#endif
-
#ifdef HAVE_RB_EARGERROR
rb_define_method(cls, "rb_eArgError", constants_spec_rb_eArgError, 0);
#endif
27 spec/ruby/optional/capi/ext/enumerator_spec.c
View
@@ -0,0 +1,27 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_RB_ENUMERATORIZE
+VALUE enumerator_spec_rb_enumeratorize(int argc, VALUE *argv, VALUE self) {
+ VALUE obj, meth, args;
+ rb_scan_args(argc, argv, "2*", &obj, &meth, &args);
+ return rb_enumeratorize(obj, meth, RARRAY_LEN(args), RARRAY_PTR(args));
+}
+#endif
+
+void Init_enumerator_spec() {
+ VALUE cls;
+ cls = rb_define_class("CApiEnumeratorSpecs", rb_cObject);
+
+#ifdef HAVE_RB_ENUMERATORIZE
+ rb_define_method(cls, "rb_enumeratorize", enumerator_spec_rb_enumeratorize, -1);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
4 spec/ruby/optional/capi/ext/rubyspec.h
View
@@ -129,6 +129,7 @@
#define HAVE_RB_CSYMBOL 1
#define HAVE_RB_CTHREAD 1
#define HAVE_RB_CTRUECLASS 1
+#define HAVE_RB_CNUMERATOR 1
#define HAVE_RB_EARGERROR 1
#define HAVE_RB_EEOFERROR 1
#define HAVE_RB_EEXCEPTION 1
@@ -220,6 +221,9 @@
#define HAVE_RB_LONG2INT 1
#endif
+/* Enumerable */
+#define HAVE_RB_ENUMERATORIZE 1
+
/* Exception */
#define HAVE_RB_EXC_NEW 1
#define HAVE_RB_EXC_NEW2 1
5 vm/capi/18/include/ruby.h
View
@@ -233,6 +233,7 @@ extern "C" {
cCApiEncCompatError,
cCApiWaitReadable,
cCApiWaitWritable,
+ cCApiEnumerator,
// MUST be last
cCApiMaxConstant
@@ -417,6 +418,7 @@ struct RFile {
#define rb_cRational (capi_get_constant(cCApiRational))
#define rb_cComplex (capi_get_constant(cCApiComplex))
#define rb_cEncoding (capi_get_constant(cCApiEncoding))
+#define rb_cEnumerator (capi_get_constant(cCApiEnumerator))
/* Global Module objects. */
@@ -1740,6 +1742,9 @@ VALUE rb_uint2big(unsigned long number);
/** Retrieve the nth match for the given MatchData */
VALUE rb_reg_nth_match(long nth, VALUE match_data);
+ /** New Enumerator. */
+ VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv);
+
// include an extconf.h if one is provided
#ifdef RUBY_EXTCONF_H
#include RUBY_EXTCONF_H
5 vm/capi/19/include/ruby/ruby.h
View
@@ -271,6 +271,7 @@ typedef void (*RUBY_DATA_FUNC)(void*);
cCApiEncCompatError,
cCApiWaitReadable,
cCApiWaitWritable,
+ cCApiEnumerator,
// MUST be last
cCApiMaxConstant
@@ -457,6 +458,7 @@ struct RFile {
#define rb_cRational (capi_get_constant(cCApiRational))
#define rb_cComplex (capi_get_constant(cCApiComplex))
#define rb_cEncoding (capi_get_constant(cCApiEncoding))
+#define rb_cEnumerator (capi_get_constant(cCApiEnumerator))
/* Global Module objects. */
@@ -1870,6 +1872,9 @@ VALUE rb_uint2big(unsigned long number);
/** Retrieve the nth match for the given MatchData */
VALUE rb_reg_nth_match(long nth, VALUE match_data);
+ /** New Enumerator. */
+ VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv);
+
// include an extconf.h if one is provided
#ifdef RUBY_EXTCONF_H
#include RUBY_EXTCONF_H
1  vm/capi/capi.cpp
View
@@ -88,6 +88,7 @@ namespace rubinius {
map[cCApiMethod] = "Method";
map[cCApiRational] = "Rational";
map[cCApiComplex] = "Complex";
+ map[cCApiEnumerator] = "Enumerable::Enumerator";
map[cCApiArgumentError] = "ArgumentError";
map[cCApiEOFError] = "EOFError";
20 vm/capi/enumerator.cpp
View
@@ -0,0 +1,20 @@
+#include "capi/capi.hpp"
+#include "capi/18/include/ruby.h"
+
+using namespace rubinius;
+using namespace rubinius::capi;
+
+extern "C" {
+ VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv) {
+ VALUE* args = (VALUE*)alloca(sizeof(VALUE) * (argc + 2));
+
+ args[0] = obj;
+ args[1] = meth;
+
+ for(int i = 0; i < argc; i++) {
+ args[i + 2] = argv[i];
+ }
+
+ return rb_funcall2(rb_cEnumerator, rb_intern("new"), argc + 2, args);
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.