00001 #include <ruby.h>
00002 #include <set>
00003 #include <algorithm>
00004 #include "ruby_allocator.hh"
00005
00006 using namespace std;
00007
00008 static VALUE cValueSet;
00009 static ID id_new;
00010
00011 typedef std::set<VALUE, std::less<VALUE>, ruby_allocator<VALUE> > ValueSet;
00012 static ValueSet& get_wrapped_set(VALUE self)
00013 {
00014 ValueSet* object = 0;
00015 Data_Get_Struct(self, ValueSet, object);
00016 return *object;
00017 }
00018
00019 static void value_set_mark(ValueSet const* set) { std::for_each(set->begin(), set->end(), rb_gc_mark); }
00020 static void value_set_free(ValueSet const* set) { delete set; }
00021 static VALUE value_set_alloc(VALUE klass)
00022 {
00023 ValueSet* cxx_set = new ValueSet;
00024 return Data_Wrap_Struct(klass, value_set_mark, value_set_free, cxx_set);
00025 }
00026
00027
00028
00029
00030
00031 static VALUE value_set_empty_p(VALUE self)
00032 {
00033 ValueSet& set = get_wrapped_set(self);
00034 return set.empty() ? Qtrue : Qfalse;
00035 }
00036
00037
00038
00039
00040
00041
00042 static VALUE value_set_size(VALUE self)
00043 {
00044 ValueSet& set = get_wrapped_set(self);
00045 return INT2NUM(set.size());
00046 }
00047
00048
00049
00050
00051
00052
00053 static VALUE value_set_each(VALUE self)
00054 {
00055 ValueSet& set = get_wrapped_set(self);
00056 for (ValueSet::iterator it = set.begin(); it != set.end();)
00057 {
00058
00059
00060 ValueSet::iterator this_it = it++;
00061 rb_yield(*this_it);
00062 }
00063 return self;
00064 }
00065
00066
00067
00068
00069
00070
00071 static VALUE value_set_delete_if(VALUE self)
00072 {
00073 ValueSet& set = get_wrapped_set(self);
00074 for (ValueSet::iterator it = set.begin(); it != set.end();)
00075 {
00076
00077
00078 ValueSet::iterator this_it = it++;
00079 bool do_delete = RTEST(rb_yield(*this_it));
00080 if (do_delete)
00081 set.erase(this_it);
00082 }
00083 return self;
00084 }
00085
00086
00087
00088
00089
00090
00091 static VALUE value_set_include_p(VALUE vself, VALUE vother)
00092 {
00093 ValueSet const& self = get_wrapped_set(vself);
00094 return self.find(vother) == self.end() ? Qfalse : Qtrue;
00095 }
00096
00097
00098
00099
00100 static VALUE value_set_to_value_set(VALUE self) { return self; }
00101
00102
00103
00104
00105
00106
00107 static VALUE value_set_dup(VALUE vself, VALUE vother)
00108 {
00109 ValueSet const& self = get_wrapped_set(vself);
00110 VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
00111 ValueSet& result = get_wrapped_set(vresult);
00112 for (ValueSet::const_iterator it = self.begin(); it != self.end(); ++it)
00113 result.insert(result.end(), *it);
00114
00115 return vresult;
00116 }
00117
00118
00119
00120
00121
00122
00123 static VALUE value_set_include_all_p(VALUE vself, VALUE vother)
00124 {
00125 ValueSet const& self = get_wrapped_set(vself);
00126 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00127 rb_raise(rb_eArgError, "expected a ValueSet");
00128 ValueSet const& other = get_wrapped_set(vother);
00129 return std::includes(self.begin(), self.end(), other.begin(), other.end()) ? Qtrue : Qfalse;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139 static VALUE value_set_union(VALUE vself, VALUE vother)
00140 {
00141 ValueSet const& self = get_wrapped_set(vself);
00142 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00143 rb_raise(rb_eArgError, "expected a ValueSet");
00144 ValueSet const& other = get_wrapped_set(vother);
00145
00146 VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
00147 ValueSet& result = get_wrapped_set(vresult);
00148 std::set_union(self.begin(), self.end(), other.begin(), other.end(),
00149 std::inserter(result, result.end()));
00150 return vresult;
00151 }
00152
00153
00154
00155
00156
00157
00158 static VALUE value_set_merge(VALUE vself, VALUE vother)
00159 {
00160 ValueSet& self = get_wrapped_set(vself);
00161 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00162 rb_raise(rb_eArgError, "expected a ValueSet");
00163 ValueSet const& other = get_wrapped_set(vother);
00164
00165 self.insert(other.begin(), other.end());
00166 return vself;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175 static VALUE value_set_intersection_bang(VALUE vself, VALUE vother)
00176 {
00177 ValueSet& self = get_wrapped_set(vself);
00178 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00179 rb_raise(rb_eArgError, "expected a ValueSet");
00180 ValueSet const& other = get_wrapped_set(vother);
00181
00182 ValueSet result;
00183 std::set_intersection(self.begin(), self.end(), other.begin(), other.end(),
00184 std::inserter(result, result.end()));
00185 self.swap(result);
00186 return vself;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196 static VALUE value_set_intersection(VALUE vself, VALUE vother)
00197 {
00198 ValueSet const& self = get_wrapped_set(vself);
00199 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00200 rb_raise(rb_eArgError, "expected a ValueSet");
00201 ValueSet const& other = get_wrapped_set(vother);
00202
00203 VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
00204 ValueSet& result = get_wrapped_set(vresult);
00205 std::set_intersection(self.begin(), self.end(), other.begin(), other.end(),
00206 std::inserter(result, result.end()));
00207 return vresult;
00208 }
00209
00210
00211
00212
00213
00214
00215 static VALUE value_set_intersects(VALUE vself, VALUE vother)
00216 {
00217 ValueSet const& self = get_wrapped_set(vself);
00218 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00219 rb_raise(rb_eArgError, "expected a ValueSet");
00220 ValueSet const& other = get_wrapped_set(vother);
00221
00222 ValueSet::const_iterator
00223 self_it = self.begin(),
00224 self_end = self.end(),
00225 other_it = other.begin(),
00226 other_end = other.end();
00227
00228 while(self_it != self_end && other_it != other_end)
00229 {
00230 if (*self_it < *other_it)
00231 ++self_it;
00232 else if (*other_it < *self_it)
00233 ++other_it;
00234 else
00235 return Qtrue;
00236 }
00237 return Qfalse;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246 static VALUE value_set_difference_bang(VALUE vself, VALUE vother)
00247 {
00248 ValueSet& self = get_wrapped_set(vself);
00249 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00250 rb_raise(rb_eArgError, "expected a ValueSet");
00251 ValueSet const& other = get_wrapped_set(vother);
00252
00253 ValueSet result;
00254 std::set_difference(self.begin(), self.end(), other.begin(), other.end(),
00255 std::inserter(result, result.end()));
00256 if (result.size() != self.size())
00257 self.swap(result);
00258 return vself;
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268 static VALUE value_set_difference(VALUE vself, VALUE vother)
00269 {
00270 ValueSet const& self = get_wrapped_set(vself);
00271 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00272 rb_raise(rb_eArgError, "expected a ValueSet");
00273 ValueSet const& other = get_wrapped_set(vother);
00274
00275 VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
00276 ValueSet& result = get_wrapped_set(vresult);
00277 std::set_difference(self.begin(), self.end(), other.begin(), other.end(),
00278 std::inserter(result, result.end()));
00279 return vresult;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289 static VALUE value_set_insert(VALUE vself, VALUE v)
00290 {
00291 ValueSet& self = get_wrapped_set(vself);
00292 bool exists = self.insert(v).second;
00293 return exists ? Qtrue : Qfalse;
00294 }
00295
00296
00297
00298
00299
00300
00301 static VALUE value_set_delete(VALUE vself, VALUE v)
00302 {
00303 ValueSet& self = get_wrapped_set(vself);
00304 size_t count = self.erase(v);
00305 return count > 0 ? Qtrue : Qfalse;
00306 }
00307
00308
00309
00310
00311
00312
00313 static VALUE value_set_equal(VALUE vself, VALUE vother)
00314 {
00315 ValueSet const& self = get_wrapped_set(vself);
00316 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00317 return Qfalse;
00318 ValueSet const& other = get_wrapped_set(vother);
00319 return (self == other) ? Qtrue : Qfalse;
00320 }
00321
00322
00323
00324
00325
00326
00327 static VALUE value_set_clear(VALUE self)
00328 {
00329 get_wrapped_set(self).clear();
00330 return self;
00331 }
00332
00333
00334
00335
00336
00337
00338 static VALUE value_set_initialize_copy(VALUE vself, VALUE vother)
00339 {
00340 get_wrapped_set(vself) = get_wrapped_set(vother);
00341 return vself;
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 static VALUE array_to_value_set(VALUE self)
00356 {
00357 VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
00358 ValueSet& result = get_wrapped_set(vresult);
00359
00360 long size = RARRAY_LEN(self);
00361 for (int i = 0; i < size; ++i)
00362 result.insert(rb_ary_entry(self, i));
00363
00364 return vresult;
00365 }
00366
00367 #ifndef RUBINIUS
00368 static VALUE enumerable_to_value_set_i(VALUE i, VALUE* memo)
00369 {
00370 ValueSet& result = *reinterpret_cast<ValueSet*>(memo);
00371 result.insert(i);
00372 return Qnil;
00373 }
00374
00375
00376
00377
00378
00379
00380 static VALUE enumerable_to_value_set(VALUE self)
00381 {
00382 VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
00383 ValueSet& result = get_wrapped_set(vresult);
00384
00385 rb_iterate(rb_each, self, RUBY_METHOD_FUNC(enumerable_to_value_set_i), reinterpret_cast<VALUE>(&result));
00386 return vresult;
00387 }
00388 #endif
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 extern "C" void Init_value_set()
00400 {
00401 #ifndef RUBINIUS
00402 rb_define_method(rb_mEnumerable, "to_value_set", RUBY_METHOD_FUNC(enumerable_to_value_set), 0);
00403 #endif
00404 rb_define_method(rb_cArray, "to_value_set", RUBY_METHOD_FUNC(array_to_value_set), 0);
00405
00406 cValueSet = rb_define_class("ValueSet", rb_cObject);
00407 id_new = rb_intern("new");
00408 rb_define_alloc_func(cValueSet, value_set_alloc);
00409 rb_define_method(cValueSet, "each", RUBY_METHOD_FUNC(value_set_each), 0);
00410 rb_define_method(cValueSet, "include?", RUBY_METHOD_FUNC(value_set_include_p), 1);
00411 rb_define_method(cValueSet, "include_all?", RUBY_METHOD_FUNC(value_set_include_all_p), 1);
00412 rb_define_method(cValueSet, "union", RUBY_METHOD_FUNC(value_set_union), 1);
00413 rb_define_method(cValueSet, "intersection", RUBY_METHOD_FUNC(value_set_intersection), 1);
00414 rb_define_method(cValueSet, "intersection!", RUBY_METHOD_FUNC(value_set_intersection_bang), 1);
00415 rb_define_method(cValueSet, "intersects?", RUBY_METHOD_FUNC(value_set_intersects), 1);
00416 rb_define_method(cValueSet, "difference", RUBY_METHOD_FUNC(value_set_difference), 1);
00417 rb_define_method(cValueSet, "difference!", RUBY_METHOD_FUNC(value_set_difference_bang), 1);
00418 rb_define_method(cValueSet, "insert", RUBY_METHOD_FUNC(value_set_insert), 1);
00419 rb_define_method(cValueSet, "merge", RUBY_METHOD_FUNC(value_set_merge), 1);
00420 rb_define_method(cValueSet, "delete", RUBY_METHOD_FUNC(value_set_delete), 1);
00421 rb_define_method(cValueSet, "==", RUBY_METHOD_FUNC(value_set_equal), 1);
00422 rb_define_method(cValueSet, "to_value_set", RUBY_METHOD_FUNC(value_set_to_value_set), 0);
00423 rb_define_method(cValueSet, "dup", RUBY_METHOD_FUNC(value_set_dup), 0);
00424 rb_define_method(cValueSet, "empty?", RUBY_METHOD_FUNC(value_set_empty_p), 0);
00425 rb_define_method(cValueSet, "size", RUBY_METHOD_FUNC(value_set_size), 0);
00426 rb_define_method(cValueSet, "clear", RUBY_METHOD_FUNC(value_set_clear), 0);
00427 rb_define_method(cValueSet, "initialize_copy", RUBY_METHOD_FUNC(value_set_initialize_copy), 1);
00428 rb_define_method(cValueSet, "delete_if", RUBY_METHOD_FUNC(value_set_delete_if), 0);
00429 }
00430
00431