rb_lovely 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6257def0a1d18050a37cfe61c6b6a07ebcc557b4
4
- data.tar.gz: 8500185c4d547bf45bd83ba3ecdc48dddae95ebb
3
+ metadata.gz: 2496d7e867af251fca88b09f09d803be15a9a0d5
4
+ data.tar.gz: 5f03cdfc07649d4f67fab1717086174b7d9499cc
5
5
  SHA512:
6
- metadata.gz: 8618d167887a777da7b37f2389555678528f3b5b919b44a39dec8686b0aa66805b3e9885c92f3f7cd3af075252125fd6f620d7777d3a4dae73ebf11d9ab5384e
7
- data.tar.gz: 411c88e8103e448542c8d39c8d5dbbcd9c5753529b21d2d021321bf4e8724da60276e9a9c53fa8b0be219285800d0455c111035b33960794fbe7d159083837a4
6
+ metadata.gz: b887607522f3a5e4afd85672cd6b085b5e6f791b741ca88f887057e381a42903d7ae06191b1130fe4449f80228ab7111b93f8d51e32c5ef06d7b094d924cbcb8
7
+ data.tar.gz: 73595cc2d2b79eda119ea76d2b2c9efdf44f781dee8915a1b7259885e56c19be2d5736ec0e7e489f2b2f60886da1b48ffed055e8b245444594b384475a483842
@@ -1,21 +1,10 @@
1
- #ifndef RB_LOVELY_SETS_SET_HPP
2
- #define RB_LOVELY_SETS_SET_HPP
1
+ #ifndef RB_LOVELY_SETS_CONTAINER_HPP
2
+ #define RB_LOVELY_SETS_CONTAINER_HPP
3
3
 
4
4
  #include "ruby_util.hpp"
5
5
 
6
6
  namespace rb_lovely {
7
7
 
8
- template <class T>
9
- VALUE containerLength(VALUE self) {
10
- T* set = rubyCast<T>(self);
11
- return INT2NUM(set->size());
12
- }
13
-
14
- template <class T>
15
- static void initSet(VALUE rbSet) {
16
- rb_define_method(rbSet, "length", RUBY_METHOD_FUNC(containerLength<T>), 0);
17
- }
18
-
19
8
  auto toS = [](VALUE val) { return RSTRING_PTR(rb_funcall(val, to_sSym, 0)); };
20
9
 
21
10
  }
@@ -7,6 +7,8 @@ namespace rb_lovely {
7
7
  VALUE equalitySym;
8
8
  VALUE to_sSym;
9
9
  VALUE hashSym;
10
+ VALUE compareSym;
11
+ VALUE callSym;
10
12
  }
11
13
 
12
14
  extern "C" {
@@ -9,6 +9,8 @@ extern VALUE cmpMethSym;
9
9
  extern VALUE equalitySym;
10
10
  extern VALUE to_sSym;
11
11
  extern VALUE hashSym;
12
+ extern VALUE callSym;
13
+ extern VALUE compareSym;
12
14
 
13
15
  template <class T>
14
16
  void rubyDelete(T *obj) {
@@ -33,6 +35,8 @@ static void initRubyUtil() {
33
35
  equalitySym = rb_intern("==");
34
36
  to_sSym = rb_intern("to_s");
35
37
  hashSym = rb_intern("hash");
38
+ callSym = rb_intern("call");
39
+ compareSym = ID2SYM(rb_intern("compare"));
36
40
  }
37
41
 
38
42
  }
@@ -12,8 +12,10 @@ namespace rb_lovely { namespace hybrid {
12
12
 
13
13
  struct member {
14
14
  bool operator<(member const& rhs) const {
15
- auto cmpVal = rb_funcall(val, cmpMethSym, 1, rhs.val);
16
- return NUM2INT(cmpVal) < 0;
15
+ auto cmpResult = compareProc != Qnil ?
16
+ rb_funcall(compareProc, callSym, 2, val, rhs.val) :
17
+ rb_funcall(val, cmpMethSym, 1, rhs.val);
18
+ return NUM2INT(cmpResult) < 0;
17
19
  }
18
20
 
19
21
  bool operator==(member const& rhs) const {
@@ -22,8 +24,10 @@ struct member {
22
24
  }
23
25
 
24
26
  // also cache as two element array?
25
- member(VALUE _key, VALUE _val) : key(_key), val(_val) {}
27
+ member(VALUE _compareProc, VALUE _key, VALUE _val)
28
+ : compareProc(_compareProc), key(_key), val(_val) {}
26
29
 
30
+ VALUE compareProc;
27
31
  VALUE key;
28
32
  VALUE val;
29
33
  };
@@ -36,19 +40,42 @@ std::size_t hash_value(member const& member) {
36
40
 
37
41
  namespace mi = boost::multi_index;
38
42
 
39
- typedef boost::multi_index_container<
40
- member,
41
- mi::indexed_by<
42
- mi::hashed_unique< mi::member<member, VALUE, &member::key> >,
43
- mi::ordered_non_unique< mi::identity<member> >
44
- >
45
- > Hash;
43
+ struct Hash {
44
+ boost::multi_index_container<
45
+ member,
46
+ mi::indexed_by<
47
+ mi::hashed_unique< mi::member<member, VALUE, &member::key> >,
48
+ mi::ordered_non_unique< mi::identity<member> >
49
+ >
50
+ > container;
51
+
52
+ // proc used to compare values
53
+ VALUE compareProc = Qnil;
54
+ };
55
+
56
+ VALUE hashLength(VALUE self) {
57
+ Hash* hash = rubyCast<Hash>(self);
58
+ return INT2NUM(hash->container.size());
59
+ }
46
60
 
47
61
  VALUE hashInitialize(int argc, VALUE *argv, VALUE self) {
62
+ Hash* hash = rubyCast<Hash>(self);
48
63
  if (argc == 1) {
49
64
  auto array = rb_check_array_type(argv[0]);
50
65
  if (array == Qnil) {
51
- rb_raise(rb_eArgError, "Expected array");
66
+ auto kwArgs = rb_check_hash_type(argv[0]);
67
+ if (kwArgs == Qnil) {
68
+ rb_raise(rb_eArgError, "Expected array");
69
+ }
70
+ else {
71
+ auto compareProc = rb_hash_aref(kwArgs, compareSym);
72
+ if (compareProc == Qnil) {
73
+ rb_raise(rb_eArgError, "Expected compare keyword");
74
+ }
75
+ else {
76
+ hash->compareProc = compareProc;
77
+ }
78
+ }
52
79
  }
53
80
  else {
54
81
  auto len = RARRAY_LEN(array);
@@ -56,9 +83,8 @@ VALUE hashInitialize(int argc, VALUE *argv, VALUE self) {
56
83
  rb_raise(rb_eArgError, "Expected even number of parameters");
57
84
  }
58
85
  else {
59
- Hash* hash = rubyCast<Hash>(self);
60
86
  for (auto i = 0; i < len; i += 2) {
61
- hash->insert(member(rb_ary_entry(array, i), rb_ary_entry(array, i + 1)));
87
+ hash->container.insert(member(hash->compareProc, rb_ary_entry(array, i), rb_ary_entry(array, i + 1)));
62
88
  }
63
89
  }
64
90
  }
@@ -69,18 +95,18 @@ VALUE hashInitialize(int argc, VALUE *argv, VALUE self) {
69
95
  VALUE hashUpdate(VALUE self, VALUE key, VALUE val) {
70
96
  Hash* hash = rubyCast<Hash>(self);
71
97
  // TODO: overwrite value
72
- auto it = hash->find(key);
73
- if (it != hash->end())
74
- hash->replace(it, member(key, val));
98
+ auto it = hash->container.find(key);
99
+ if (it != hash->container.end())
100
+ hash->container.replace(it, member(hash->compareProc, key, val));
75
101
  else
76
- hash->insert(member(key, val));
102
+ hash->container.insert(member(hash->compareProc, key, val));
77
103
  return self;
78
104
  }
79
105
 
80
106
  VALUE hashGet(VALUE self, VALUE key) {
81
107
  Hash* hash = rubyCast<Hash>(self);
82
- auto it = hash->find(key);
83
- if (it == hash->end()) {
108
+ auto it = hash->container.find(key);
109
+ if (it == hash->container.end()) {
84
110
  return Qnil;
85
111
  }
86
112
  else {
@@ -95,7 +121,7 @@ VALUE hashEach(VALUE self) {
95
121
  }
96
122
  else {
97
123
  Hash* hash = rubyCast<Hash>(self);
98
- for (auto const& member : hash->get<1>()) {
124
+ for (auto const& member : hash->container.get<1>()) {
99
125
  rb_yield_values(2, member.key, member.val);
100
126
  }
101
127
  }
@@ -107,8 +133,8 @@ VALUE hashToString(VALUE self) {
107
133
  std::stringstream str;
108
134
  str << "RbLovely::SortedHash {";
109
135
  Hash* hash = rubyCast<Hash>(self);
110
- if (! hash->empty()) {
111
- auto& idx = hash->get<1>();
136
+ if (! hash->container.empty()) {
137
+ auto& idx = hash->container.get<1>();
112
138
  auto it = idx.begin();
113
139
  str << ' ' << toS(it->key) << " => " << toS(it->val);
114
140
  for (++it; it != idx.end(); ++it) {
@@ -123,38 +149,38 @@ VALUE hashToString(VALUE self) {
123
149
 
124
150
  VALUE hashFirst(VALUE self) {
125
151
  Hash* hash = rubyCast<Hash>(self);
126
- return hash->empty() ? Qnil : hash->get<1>().begin()->val;
152
+ return hash->container.empty() ? Qnil : hash->container.get<1>().begin()->val;
127
153
  }
128
154
 
129
155
  VALUE hashLast(VALUE self) {
130
156
  Hash* hash = rubyCast<Hash>(self);
131
- if (hash->empty())
157
+ if (hash->container.empty())
132
158
  return Qnil;
133
159
 
134
- auto last = hash->get<1>().end();
160
+ auto last = hash->container.get<1>().end();
135
161
  --last;
136
162
  return last->val;
137
163
  }
138
164
 
139
165
  VALUE hashMutatingDelete(VALUE self, VALUE toDelete) {
140
166
  Hash* hash = rubyCast<Hash>(self);
141
- auto it = hash->find(toDelete);
142
- if (it == hash->end()) {
167
+ auto it = hash->container.find(toDelete);
168
+ if (it == hash->container.end()) {
143
169
  return Qnil;
144
170
  }
145
171
  else {
146
172
  auto valBackup = it->val;
147
- hash->erase(it);
173
+ hash->container.erase(it);
148
174
  return valBackup;
149
175
  }
150
176
  }
151
177
 
152
178
  VALUE hashShift(VALUE self) {
153
179
  Hash* hash = rubyCast<Hash>(self);
154
- if (hash->empty())
180
+ if (hash->container.empty())
155
181
  return Qnil;
156
182
 
157
- auto& idx = hash->get<1>();
183
+ auto& idx = hash->container.get<1>();
158
184
  auto bak = idx.begin()->val;
159
185
  idx.erase(idx.begin());
160
186
  return bak;
@@ -162,10 +188,10 @@ VALUE hashShift(VALUE self) {
162
188
 
163
189
  VALUE hashPop(VALUE self) {
164
190
  Hash* hash = rubyCast<Hash>(self);
165
- if (hash->empty())
191
+ if (hash->container.empty())
166
192
  return Qnil;
167
193
 
168
- auto& idx = hash->get<1>();
194
+ auto& idx = hash->container.get<1>();
169
195
  auto last = idx.end();
170
196
  --last;
171
197
  auto bak = last->val;
@@ -175,8 +201,8 @@ VALUE hashPop(VALUE self) {
175
201
 
176
202
  VALUE hashHas(VALUE self, VALUE key) {
177
203
  Hash* hash = rubyCast<Hash>(self);
178
- auto it = hash->find(key);
179
- return it == hash->end() ? Qfalse : Qtrue;
204
+ auto it = hash->container.find(key);
205
+ return it == hash->container.end() ? Qfalse : Qtrue;
180
206
  }
181
207
 
182
208
  } }
@@ -191,7 +217,7 @@ extern "C" {
191
217
  rb_include_module(rbHash, rb_const_get(rb_cObject, rb_intern("Enumerable")));
192
218
 
193
219
  rb_define_method(rbHash, "initialize", RUBY_METHOD_FUNC(hashInitialize), -1);
194
- initSet<Hash>(rbHash);
220
+ rb_define_method(rbHash, "length", RUBY_METHOD_FUNC(hashLength), 0);
195
221
  rb_define_method(rbHash, "[]=", RUBY_METHOD_FUNC(hashUpdate), 2);
196
222
  rb_define_method(rbHash, "[]", RUBY_METHOD_FUNC(hashGet), 1);
197
223
  rb_define_method(rbHash, "each", RUBY_METHOD_FUNC(hashEach), 0);
@@ -35,6 +35,11 @@ VALUE setInitialize(int argc, VALUE *argv, VALUE self) {
35
35
  return self;
36
36
  }
37
37
 
38
+ VALUE setLength(VALUE self) {
39
+ Set* set = rubyCast<Set>(self);
40
+ return INT2NUM(set->size());
41
+ }
42
+
38
43
  VALUE setAdd(VALUE self, VALUE val) {
39
44
  Set* set = rubyCast<Set>(self);
40
45
  set->insert(val);
@@ -195,7 +200,7 @@ extern "C" {
195
200
  rb_include_module(rbSet, rb_const_get(rb_cObject, rb_intern("Enumerable")));
196
201
 
197
202
  rb_define_method(rbSet, "initialize", RUBY_METHOD_FUNC(setInitialize), -1);
198
- initSet<Set>(rbSet);
203
+ rb_define_method(rbSet, "length", RUBY_METHOD_FUNC(setLength), 0);
199
204
  rb_define_method(rbSet, "add", RUBY_METHOD_FUNC(setAdd), 1);
200
205
  rb_define_method(rbSet, "<<", RUBY_METHOD_FUNC(setAdd), 1);
201
206
  rb_define_method(rbSet, "each", RUBY_METHOD_FUNC(setEach), 0);
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rb_lovely
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Pike