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 +4 -4
- data/ext/rb_lovely/container.hpp +2 -13
- data/ext/rb_lovely/package.cpp +2 -0
- data/ext/rb_lovely/ruby_util.hpp +4 -0
- data/ext/rb_lovely/sorted_hash.cpp +61 -35
- data/ext/rb_lovely/sorted_set.cpp +6 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2496d7e867af251fca88b09f09d803be15a9a0d5
|
4
|
+
data.tar.gz: 5f03cdfc07649d4f67fab1717086174b7d9499cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b887607522f3a5e4afd85672cd6b085b5e6f791b741ca88f887057e381a42903d7ae06191b1130fe4449f80228ab7111b93f8d51e32c5ef06d7b094d924cbcb8
|
7
|
+
data.tar.gz: 73595cc2d2b79eda119ea76d2b2c9efdf44f781dee8915a1b7259885e56c19be2d5736ec0e7e489f2b2f60886da1b48ffed055e8b245444594b384475a483842
|
data/ext/rb_lovely/container.hpp
CHANGED
@@ -1,21 +1,10 @@
|
|
1
|
-
#ifndef
|
2
|
-
#define
|
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
|
}
|
data/ext/rb_lovely/package.cpp
CHANGED
data/ext/rb_lovely/ruby_util.hpp
CHANGED
@@ -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
|
16
|
-
|
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
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
mi::
|
43
|
-
|
44
|
-
|
45
|
-
>
|
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
|
-
|
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
|
-
|
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
|
-
|
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);
|