mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
Add Set C-API
This should be a minimal C-API needed to deal with Set objects. It supports creating the sets, checking whether an element is the set, adding and removing elements, iterating over the elements, clearing a set, and returning the size of the set. Co-authored-by: Nobuyoshi Nakada <nobu.nakada@gmail.com>
This commit is contained in:
parent
08d4f7893e
commit
2ab38691a2
8 changed files with 322 additions and 3 deletions
62
spec/ruby/optional/capi/ext/set_spec.c
Normal file
62
spec/ruby/optional/capi/ext/set_spec.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "ruby.h"
|
||||
#include "rubyspec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RBOOL(x) ((x) ? Qtrue : Qfalse)
|
||||
|
||||
int yield_element_and_arg(VALUE element, VALUE arg) {
|
||||
return RTEST(rb_yield_values(2, element, arg)) ? ST_CONTINUE : ST_STOP;
|
||||
}
|
||||
|
||||
VALUE set_spec_rb_set_foreach(VALUE self, VALUE set, VALUE arg) {
|
||||
rb_set_foreach(set, yield_element_and_arg, arg);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE set_spec_rb_set_new(VALUE self) {
|
||||
return rb_set_new();
|
||||
}
|
||||
|
||||
VALUE set_spec_rb_set_new_capa(VALUE self, VALUE capa) {
|
||||
return rb_set_new_capa(NUM2INT(capa));
|
||||
}
|
||||
|
||||
VALUE set_spec_rb_set_lookup(VALUE self, VALUE set, VALUE element) {
|
||||
return RBOOL(rb_set_lookup(set, element));
|
||||
}
|
||||
|
||||
VALUE set_spec_rb_set_add(VALUE self, VALUE set, VALUE element) {
|
||||
return RBOOL(rb_set_add(set, element));
|
||||
}
|
||||
|
||||
VALUE set_spec_rb_set_clear(VALUE self, VALUE set) {
|
||||
return rb_set_clear(set);
|
||||
}
|
||||
|
||||
VALUE set_spec_rb_set_delete(VALUE self, VALUE set, VALUE element) {
|
||||
return RBOOL(rb_set_delete(set, element));
|
||||
}
|
||||
|
||||
VALUE set_spec_rb_set_size(VALUE self, VALUE set) {
|
||||
return SIZET2NUM(rb_set_size(set));
|
||||
}
|
||||
|
||||
void Init_set_spec(void) {
|
||||
VALUE cls = rb_define_class("CApiSetSpecs", rb_cObject);
|
||||
rb_define_method(cls, "rb_set_foreach", set_spec_rb_set_foreach, 2);
|
||||
rb_define_method(cls, "rb_set_new", set_spec_rb_set_new, 0);
|
||||
rb_define_method(cls, "rb_set_new_capa", set_spec_rb_set_new_capa, 1);
|
||||
rb_define_method(cls, "rb_set_lookup", set_spec_rb_set_lookup, 2);
|
||||
rb_define_method(cls, "rb_set_add", set_spec_rb_set_add, 2);
|
||||
rb_define_method(cls, "rb_set_clear", set_spec_rb_set_clear, 1);
|
||||
rb_define_method(cls, "rb_set_delete", set_spec_rb_set_delete, 2);
|
||||
rb_define_method(cls, "rb_set_size", set_spec_rb_set_size, 1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
96
spec/ruby/optional/capi/set_spec.rb
Normal file
96
spec/ruby/optional/capi/set_spec.rb
Normal file
|
@ -0,0 +1,96 @@
|
|||
require_relative 'spec_helper'
|
||||
|
||||
load_extension("set")
|
||||
|
||||
describe "C-API Set function" do
|
||||
before :each do
|
||||
@s = CApiSetSpecs.new
|
||||
end
|
||||
|
||||
ruby_version_is "3.5" do
|
||||
describe "rb_set_foreach" do
|
||||
it "calls function with each element and arg" do
|
||||
a = []
|
||||
@s.rb_set_foreach(Set[1, 2], 3) {|*args| a.concat(args) }
|
||||
a.should == [1, 3, 2, 3]
|
||||
end
|
||||
|
||||
it "respects function return value" do
|
||||
a = []
|
||||
@s.rb_set_foreach(Set[1, 2], 3) do |*args|
|
||||
a.concat(args)
|
||||
false
|
||||
end
|
||||
a.should == [1, 3]
|
||||
end
|
||||
end
|
||||
|
||||
describe "rb_set_new" do
|
||||
it "returns a new set" do
|
||||
@s.rb_set_new.should == Set[]
|
||||
end
|
||||
end
|
||||
|
||||
describe "rb_set_new_capa" do
|
||||
it "returns a new set" do
|
||||
@s.rb_set_new_capa(3).should == Set[]
|
||||
end
|
||||
end
|
||||
|
||||
describe "rb_set_lookup" do
|
||||
it "returns whether the element is in the set" do
|
||||
set = Set[1]
|
||||
@s.rb_set_lookup(set, 1).should == true
|
||||
@s.rb_set_lookup(set, 2).should == false
|
||||
end
|
||||
end
|
||||
|
||||
describe "rb_set_add" do
|
||||
it "adds element to set" do
|
||||
set = Set[]
|
||||
@s.rb_set_add(set, 1).should == true
|
||||
set.should == Set[1]
|
||||
@s.rb_set_add(set, 2).should == true
|
||||
set.should == Set[1, 2]
|
||||
end
|
||||
|
||||
it "returns false if element is already in set" do
|
||||
set = Set[1]
|
||||
@s.rb_set_add(set, 1).should == false
|
||||
set.should == Set[1]
|
||||
end
|
||||
end
|
||||
|
||||
describe "rb_set_clear" do
|
||||
it "empties and returns self" do
|
||||
set = Set[1]
|
||||
@s.rb_set_clear(set).should equal(set)
|
||||
set.should == Set[]
|
||||
end
|
||||
end
|
||||
|
||||
describe "rb_set_delete" do
|
||||
it "removes element from set" do
|
||||
set = Set[1, 2]
|
||||
@s.rb_set_delete(set, 1).should == true
|
||||
set.should == Set[2]
|
||||
@s.rb_set_delete(set, 2).should == true
|
||||
set.should == Set[]
|
||||
end
|
||||
|
||||
it "returns false if element is not already in set" do
|
||||
set = Set[2]
|
||||
@s.rb_set_delete(set, 1).should == false
|
||||
set.should == Set[2]
|
||||
end
|
||||
end
|
||||
|
||||
describe "rb_set_size" do
|
||||
it "returns number of elements in set" do
|
||||
@s.rb_set_size(Set[]).should == 0
|
||||
@s.rb_set_size(Set[1]).should == 1
|
||||
@s.rb_set_size(Set[1,2]).should == 2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue