00001 #include <ruby.h>
00002 #include <set>
00003 #include <algorithm>
00004
00005 using namespace std;
00006
00007 static VALUE cValueSet;
00008 static ID id_new;
00009
00010 typedef std::set<VALUE> ValueSet;
00011 static ValueSet& get_wrapped_set(VALUE self)
00012 {
00013 ValueSet* object = 0;
00014 Data_Get_Struct(self, ValueSet, object);
00015 return *object;
00016 }
00017
00018 static void value_set_mark(ValueSet const* set) { std::for_each(set->begin(), set->end(), rb_gc_mark); }
00019 static void value_set_free(ValueSet const* set) { delete set; }
00020 static VALUE value_set_alloc(VALUE klass)
00021 {
00022 ValueSet* cxx_set = new ValueSet;
00023 return Data_Wrap_Struct(klass, value_set_mark, value_set_free, cxx_set);
00024 }
00025
00026
00027
00028
00029
00030 static VALUE value_set_empty_p(VALUE self)
00031 {
00032 ValueSet& set = get_wrapped_set(self);
00033 return set.empty() ? Qtrue : Qfalse;
00034 }
00035
00036
00037
00038
00039
00040
00041 static VALUE value_set_size(VALUE self)
00042 {
00043 ValueSet& set = get_wrapped_set(self);
00044 return INT2NUM(set.size());
00045 }
00046
00047
00048
00049
00050
00051
00052 static VALUE value_set_each(VALUE self)
00053 {
00054 ValueSet& set = get_wrapped_set(self);
00055 for (ValueSet::iterator it = set.begin(); it != set.end();)
00056 {
00057
00058
00059 ValueSet::iterator this_it = it++;
00060 rb_yield(*this_it);
00061 }
00062 return self;
00063 }
00064
00065
00066
00067
00068
00069
00070 static VALUE value_set_delete_if(VALUE self)
00071 {
00072 ValueSet& set = get_wrapped_set(self);
00073 for (ValueSet::iterator it = set.begin(); it != set.end();)
00074 {
00075
00076
00077 ValueSet::iterator this_it = it++;
00078 bool do_delete = RTEST(rb_yield(*this_it));
00079 if (do_delete)
00080 set.erase(this_it);
00081 }
00082 return self;
00083 }
00084
00085
00086
00087
00088
00089
00090 static VALUE value_set_include_p(VALUE vself, VALUE vother)
00091 {
00092 ValueSet const& self = get_wrapped_set(vself);
00093 return self.find(vother) == self.end() ? Qfalse : Qtrue;
00094 }
00095
00096
00097
00098
00099 static VALUE value_set_to_value_set(VALUE self) { return self; }
00100
00101
00102
00103
00104
00105
00106 static VALUE value_set_dup(VALUE vself, VALUE vother)
00107 {
00108 ValueSet const& self = get_wrapped_set(vself);
00109 VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
00110 ValueSet& result = get_wrapped_set(vresult);
00111 for (ValueSet::const_iterator it = self.begin(); it != self.end(); ++it)
00112 result.insert(result.end(), *it);
00113
00114 return vresult;
00115 }
00116
00117
00118
00119
00120
00121
00122 static VALUE value_set_include_all_p(VALUE vself, VALUE vother)
00123 {
00124 ValueSet const& self = get_wrapped_set(vself);
00125 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00126 rb_raise(rb_eArgError, "expected a ValueSet");
00127 ValueSet const& other = get_wrapped_set(vother);
00128 return std::includes(self.begin(), self.end(), other.begin(), other.end()) ? Qtrue : Qfalse;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138 static VALUE value_set_union(VALUE vself, VALUE vother)
00139 {
00140 ValueSet const& self = get_wrapped_set(vself);
00141 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00142 rb_raise(rb_eArgError, "expected a ValueSet");
00143 ValueSet const& other = get_wrapped_set(vother);
00144
00145 VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
00146 ValueSet& result = get_wrapped_set(vresult);
00147 std::set_union(self.begin(), self.end(), other.begin(), other.end(),
00148 std::inserter(result, result.end()));
00149 return vresult;
00150 }
00151
00152
00153
00154
00155
00156
00157 static VALUE value_set_merge(VALUE vself, VALUE vother)
00158 {
00159 ValueSet& self = get_wrapped_set(vself);
00160 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00161 rb_raise(rb_eArgError, "expected a ValueSet");
00162 ValueSet const& other = get_wrapped_set(vother);
00163
00164 self.insert(other.begin(), other.end());
00165 return vself;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174 static VALUE value_set_intersection_bang(VALUE vself, VALUE vother)
00175 {
00176 ValueSet& self = get_wrapped_set(vself);
00177 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00178 rb_raise(rb_eArgError, "expected a ValueSet");
00179 ValueSet const& other = get_wrapped_set(vother);
00180
00181 ValueSet result;
00182 std::set_intersection(self.begin(), self.end(), other.begin(), other.end(),
00183 std::inserter(result, result.end()));
00184 self.swap(result);
00185 return vself;
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195 static VALUE value_set_intersection(VALUE vself, VALUE vother)
00196 {
00197 ValueSet const& self = get_wrapped_set(vself);
00198 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00199 rb_raise(rb_eArgError, "expected a ValueSet");
00200 ValueSet const& other = get_wrapped_set(vother);
00201
00202 VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
00203 ValueSet& result = get_wrapped_set(vresult);
00204 std::set_intersection(self.begin(), self.end(), other.begin(), other.end(),
00205 std::inserter(result, result.end()));
00206 return vresult;
00207 }
00208
00209
00210
00211
00212
00213
00214 static VALUE value_set_intersects(VALUE vself, VALUE vother)
00215 {
00216 ValueSet const& self = get_wrapped_set(vself);
00217 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00218 rb_raise(rb_eArgError, "expected a ValueSet");
00219 ValueSet const& other = get_wrapped_set(vother);
00220
00221 ValueSet::const_iterator
00222 self_it = self.begin(),
00223 self_end = self.end(),
00224 other_it = other.begin(),
00225 other_end = other.end();
00226
00227 while(self_it != self_end && other_it != other_end)
00228 {
00229 if (*self_it < *other_it)
00230 ++self_it;
00231 else if (*other_it < *self_it)
00232 ++other_it;
00233 else
00234 return Qtrue;
00235 }
00236 return Qfalse;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245 static VALUE value_set_difference_bang(VALUE vself, VALUE vother)
00246 {
00247 ValueSet& self = get_wrapped_set(vself);
00248 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00249 rb_raise(rb_eArgError, "expected a ValueSet");
00250 ValueSet const& other = get_wrapped_set(vother);
00251
00252 ValueSet result;
00253 std::set_difference(self.begin(), self.end(), other.begin(), other.end(),
00254 std::inserter(result, result.end()));
00255 self.swap(result);
00256 return vself;
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266 static VALUE value_set_difference(VALUE vself, VALUE vother)
00267 {
00268 ValueSet const& self = get_wrapped_set(vself);
00269 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00270 rb_raise(rb_eArgError, "expected a ValueSet");
00271 ValueSet const& other = get_wrapped_set(vother);
00272
00273 VALUE vresult = rb_funcall2(cValueSet, id_new, 0, NULL);
00274 ValueSet& result = get_wrapped_set(vresult);
00275 std::set_difference(self.begin(), self.end(), other.begin(), other.end(),
00276 std::inserter(result, result.end()));
00277 return vresult;
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287 static VALUE value_set_insert(VALUE vself, VALUE v)
00288 {
00289 ValueSet& self = get_wrapped_set(vself);
00290 bool exists = self.insert(v).second;
00291 return exists ? Qtrue : Qfalse;
00292 }
00293
00294
00295
00296
00297
00298
00299 static VALUE value_set_delete(VALUE vself, VALUE v)
00300 {
00301 ValueSet& self = get_wrapped_set(vself);
00302 size_t count = self.erase(v);
00303 return count > 0 ? Qtrue : Qfalse;
00304 }
00305
00306
00307
00308
00309
00310
00311 static VALUE value_set_equal(VALUE vself, VALUE vother)
00312 {
00313 ValueSet const& self = get_wrapped_set(vself);
00314 if (!RTEST(rb_obj_is_kind_of(vother, cValueSet)))
00315 return Qfalse;
00316 ValueSet const& other = get_wrapped_set(vother);
00317 return (self == other) ? Qtrue : Qfalse;
00318 }
00319
00320
00321
00322
00323
00324
00325 static VALUE value_set_clear(VALUE self)
00326 {
00327 get_wrapped_set(self).clear();
00328 return self;
00329 }
00330
00331
00332
00333
00334
00335
00336 static VALUE value_set_initialize_copy(VALUE vself, VALUE vother)
00337 {
00338 ValueSet const& other = get_wrapped_set(vother);
00339 set<VALUE> new_set(other.begin(), other.end());
00340 get_wrapped_set(vself).swap(new_set);
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