rb_lovely 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|