digital_trees_and_sets 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +47 -0
- data/ext/extconf.rb +2 -0
- data/ext/judy.h +622 -0
- data/ext/judy1.c +14608 -0
- data/ext/judy_compat.h +156 -0
- data/ext/judy_hash.c +227 -0
- data/ext/judy_set.c +146 -0
- data/ext/judyl.c +14695 -0
- data/test/all.rb +9 -0
- data/test/judy_bench.rb +64 -0
- data/test/judy_hash.rb +129 -0
- data/test/judy_set.rb +91 -0
- metadata +59 -0
data/ext/judy_compat.h
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
// A non existently thin (inline) layer to sanitize judy calling interface
|
2
|
+
|
3
|
+
// working with the assumption that NULL is not a valid value
|
4
|
+
|
5
|
+
// Function are get/set/delete , first/next/bycount/length , clear/mem (memtotal?)
|
6
|
+
|
7
|
+
// Indexes are VALUE's
|
8
|
+
// All numbers also VALUES (though not converted) (rembering that a value is short for unsigned long int)
|
9
|
+
// Both Judy1 and JudyL go as Tree, as typecheking is done the layer above and their void* anyway
|
10
|
+
// Interface uses Tree* for consitency on all functions
|
11
|
+
// Using Qfalse which actualy is NULL (as we use VALUE not pointers)
|
12
|
+
|
13
|
+
#include "judy.h"
|
14
|
+
#include "ruby.h"
|
15
|
+
|
16
|
+
static inline int basic_type(VALUE x){
|
17
|
+
return (x == Qnil || x == Qtrue || x == Qfalse || FIXNUM_P(x) || SYMBOL_P(x) ) ;
|
18
|
+
}
|
19
|
+
static inline void check_index_basic(VALUE i){ // for judy_hash/set
|
20
|
+
if(!basic_type(i)) rb_raise(rb_eArgError ,"Key must be int or symbol, not %s" , RSTRING_PTR(rb_funcall(i,rb_intern("to_s"),0)));
|
21
|
+
}
|
22
|
+
|
23
|
+
typedef struct {
|
24
|
+
VALUE count ;
|
25
|
+
void* judy ;
|
26
|
+
} tree_object;
|
27
|
+
|
28
|
+
typedef Pvoid_t Tree;
|
29
|
+
|
30
|
+
static inline int judy_set_has(Tree* set , VALUE index){
|
31
|
+
return Judy1Test(*set, index , PJE0) ;
|
32
|
+
}
|
33
|
+
static inline VALUE judy_set_set(Tree* set , VALUE index){
|
34
|
+
int was;
|
35
|
+
was = Judy1Set(set, index , PJE0) ;
|
36
|
+
return was ? Qtrue : Qfalse ;
|
37
|
+
}
|
38
|
+
static inline VALUE judy_set_delete(Tree* set , VALUE index){
|
39
|
+
int was;
|
40
|
+
was = Judy1Unset(set, index , PJE0) ;
|
41
|
+
return was ? Qtrue : Qfalse ;
|
42
|
+
}
|
43
|
+
|
44
|
+
static inline VALUE judy_set_first_index(Tree* set){
|
45
|
+
VALUE index = 0 ;
|
46
|
+
VALUE continu = 0 ;
|
47
|
+
continu = Judy1First(*set, &index, PJE0);
|
48
|
+
return continu ? index : Qfalse ;
|
49
|
+
}
|
50
|
+
static inline VALUE judy_set_next_index(Tree* set , VALUE index){
|
51
|
+
VALUE continu = 0 ;
|
52
|
+
continu = Judy1Next(*set, &index, PJE0);
|
53
|
+
return continu ? index : Qfalse ;
|
54
|
+
}
|
55
|
+
static inline VALUE judy_set_last_index(Tree* set){
|
56
|
+
VALUE index = -1 ;
|
57
|
+
VALUE continu = 0 ;
|
58
|
+
continu = Judy1Last(*set, &index, PJE0);
|
59
|
+
return continu ? index : Qfalse ;
|
60
|
+
}
|
61
|
+
static inline VALUE judy_set_prev_index(Tree* set , VALUE index){
|
62
|
+
VALUE continu = 0 ;
|
63
|
+
continu = Judy1Prev(*set, &index, PJE0);
|
64
|
+
return continu ? index : Qfalse ;
|
65
|
+
}
|
66
|
+
static inline VALUE judy_set_at_count(Tree* set , VALUE at){
|
67
|
+
VALUE index = Qfalse ;
|
68
|
+
VALUE continu;
|
69
|
+
continu = Judy1ByCount(*set, NUM2INT(at) , &index, PJE0);
|
70
|
+
return continu ? index : Qfalse ;
|
71
|
+
}
|
72
|
+
|
73
|
+
static inline VALUE judy_set_length(Tree* set){
|
74
|
+
VALUE c;
|
75
|
+
c = Judy1Count(*set, 0 , -1 , PJE0) ;
|
76
|
+
return UINT2NUM(c) ;
|
77
|
+
}
|
78
|
+
static inline void judy_set_clear(Tree* set){
|
79
|
+
Judy1FreeArray(set , PJE0) ;
|
80
|
+
}
|
81
|
+
static inline VALUE judy_set_mem(Tree* set){
|
82
|
+
VALUE c;
|
83
|
+
c = Judy1MemUsed(*set) ;
|
84
|
+
return UINT2NUM(c) ;
|
85
|
+
}
|
86
|
+
|
87
|
+
static inline tree_object* judy_array_at_index(Tree* array , VALUE index){
|
88
|
+
tree_object** val;
|
89
|
+
val = (tree_object**)JudyLGet(*array, index , PJE0) ;
|
90
|
+
if(val == NULL) return NULL;
|
91
|
+
return *val;
|
92
|
+
}
|
93
|
+
static inline tree_object* judy_array_set(Tree* array , VALUE index , tree_object* value ){
|
94
|
+
tree_object* was = NULL ;
|
95
|
+
tree_object** there;
|
96
|
+
there = (tree_object**)JudyLIns(array, index , PJE0) ;
|
97
|
+
if( *there != NULL ) was = *there ;
|
98
|
+
*there = value ;
|
99
|
+
return was ;
|
100
|
+
}
|
101
|
+
static inline tree_object* judy_array_delete(Tree* array , VALUE index){
|
102
|
+
tree_object* was ;
|
103
|
+
was = judy_array_at_index(array , index);
|
104
|
+
JudyLDel(array, index , PJE0) ;
|
105
|
+
return was ;
|
106
|
+
}
|
107
|
+
|
108
|
+
static inline VALUE judy_array_first_index(Tree* array){
|
109
|
+
VALUE index = 0;
|
110
|
+
VALUE* here;
|
111
|
+
here = (VALUE*)JudyLFirst(*array, &index, PJE0);
|
112
|
+
if(here == NULL) index = Qfalse ;
|
113
|
+
return index;
|
114
|
+
}
|
115
|
+
static inline VALUE judy_array_next_index(Tree* array , VALUE i){
|
116
|
+
VALUE index = i;
|
117
|
+
VALUE* here;
|
118
|
+
here = (VALUE*)JudyLNext(*array, &index, PJE0);
|
119
|
+
if(here == NULL) index = Qfalse ;
|
120
|
+
return index;
|
121
|
+
}
|
122
|
+
static inline VALUE judy_array_last_index(Tree* array){
|
123
|
+
VALUE index = -1;
|
124
|
+
VALUE* here;
|
125
|
+
here = (VALUE*)JudyLLast(*array, &index, PJE0);
|
126
|
+
if(here == NULL) index = Qfalse ;
|
127
|
+
return index;
|
128
|
+
}
|
129
|
+
static inline VALUE judy_array_prev_index(Tree* array , VALUE i){
|
130
|
+
VALUE index = i;
|
131
|
+
VALUE* here;
|
132
|
+
here = (VALUE*)JudyLPrev(*array, &index, PJE0);
|
133
|
+
if(here == NULL) index = Qfalse ;
|
134
|
+
return index;
|
135
|
+
}
|
136
|
+
static inline tree_object* judy_array_at_count(Tree* array , VALUE at){
|
137
|
+
tree_object** val;
|
138
|
+
VALUE index;
|
139
|
+
val = (tree_object**)JudyLByCount(*array, NUM2INT(at) , &index, PJE0);
|
140
|
+
if(val == NULL ) return NULL;
|
141
|
+
return *val;
|
142
|
+
}
|
143
|
+
|
144
|
+
static inline VALUE judy_array_length(Tree* array){
|
145
|
+
VALUE c;
|
146
|
+
c = JudyLCount(*array, 0 , -1 , PJE0) ;
|
147
|
+
return UINT2NUM(c) ;
|
148
|
+
}
|
149
|
+
static inline void judy_array_clear(Tree* array){
|
150
|
+
JudyLFreeArray(array , PJE0) ;
|
151
|
+
}
|
152
|
+
static inline VALUE judy_array_mem(Tree* array){
|
153
|
+
VALUE c;
|
154
|
+
c = JudyLMemUsed(*array) ;
|
155
|
+
return UINT2NUM(c) ;
|
156
|
+
}
|
data/ext/judy_hash.c
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
/************************************************
|
2
|
+
Author : Torsten Rueger , Copyright 2002-20011
|
3
|
+
License: GPL v.2 see LICENSE
|
4
|
+
************************************************/
|
5
|
+
#include "judy_compat.h"
|
6
|
+
|
7
|
+
// The class JudyHash is a RubyHash replacement. At least to the degree that the implementation is complete.
|
8
|
+
// Also it really only takes int and symbol as keys
|
9
|
+
|
10
|
+
|
11
|
+
typedef Tree JudyHash; // JudyHash == pcvoid_t
|
12
|
+
|
13
|
+
// Get_Hash converts from the ruby world to c judy-pointers
|
14
|
+
// Basically all functions available from ruby start with a call to Get_Hash
|
15
|
+
JudyHash * Get_Hash(VALUE obj) {
|
16
|
+
tree_object* object ;//= DATA_PTR(obj);
|
17
|
+
Check_Type(obj , T_DATA);
|
18
|
+
object = DATA_PTR(obj);
|
19
|
+
// assert( JudyHash == object->class) ;
|
20
|
+
return (JudyHash*) &(object->judy) ;
|
21
|
+
}
|
22
|
+
|
23
|
+
VALUE ruby_JudyHash_clear(VALUE self) {
|
24
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
25
|
+
JudyLFreeArray( p_hash, PJE0);
|
26
|
+
return self;
|
27
|
+
}
|
28
|
+
|
29
|
+
void gc_mark_hash( tree_object* hash){
|
30
|
+
VALUE value , index ;
|
31
|
+
if(hash == NULL) return ;
|
32
|
+
index = judy_array_first_index(&(hash->judy));
|
33
|
+
while (index != Qfalse) {
|
34
|
+
value = (VALUE) judy_array_at_index(&(hash->judy) , index);
|
35
|
+
rb_gc_mark(value );
|
36
|
+
index = judy_array_next_index(&(hash->judy), index);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
void gc_free_hash( tree_object* p_hash){
|
40
|
+
if(p_hash == NULL) return;
|
41
|
+
JudyLFreeArray( &(p_hash->judy), PJE0);
|
42
|
+
free(p_hash);
|
43
|
+
}
|
44
|
+
|
45
|
+
VALUE ruby_JudyHash_allocate(VALUE self) {
|
46
|
+
tree_object* tree = malloc( sizeof(tree_object) ) ;
|
47
|
+
tree->judy = NULL;
|
48
|
+
return Data_Wrap_Struct(self, gc_mark_hash, gc_free_hash, tree);
|
49
|
+
}
|
50
|
+
|
51
|
+
VALUE ruby_JudyHash_getitem(VALUE self , VALUE index) {
|
52
|
+
VALUE val;
|
53
|
+
JudyHash *p_hash ;
|
54
|
+
if( index == Qnil ) return Qnil ;
|
55
|
+
p_hash = Get_Hash(self);
|
56
|
+
check_index_basic(index);
|
57
|
+
val = (VALUE)judy_array_at_index(p_hash, index);
|
58
|
+
return (val == 0) ? Qnil : val;
|
59
|
+
}
|
60
|
+
|
61
|
+
VALUE ruby_JudyHash_has_key(VALUE self , VALUE index) {
|
62
|
+
JudyHash *p_hash ;
|
63
|
+
VALUE val;
|
64
|
+
if( index == Qnil ) return Qnil ;
|
65
|
+
p_hash = Get_Hash(self) ;
|
66
|
+
check_index_basic(index);
|
67
|
+
if(!p_hash) return Qfalse;
|
68
|
+
val = (VALUE)judy_array_at_index(p_hash, index);
|
69
|
+
return (val == 0) ? Qfalse : Qtrue;
|
70
|
+
}
|
71
|
+
|
72
|
+
VALUE ruby_JudyHash_delete(VALUE self , VALUE index) {
|
73
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
74
|
+
tree_object * was;
|
75
|
+
check_index_basic(index);
|
76
|
+
if( index == Qnil ) return Qfalse ;
|
77
|
+
was = judy_array_delete(p_hash , index);
|
78
|
+
return (was == NULL) ? Qfalse : Qtrue ;
|
79
|
+
}
|
80
|
+
|
81
|
+
VALUE ruby_JudyHash_setitem(VALUE self , VALUE index , VALUE value ) {
|
82
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
83
|
+
tree_object *was;
|
84
|
+
check_index_basic(index);
|
85
|
+
if( index == Qnil ) return Qnil ;
|
86
|
+
was = judy_array_set(p_hash , index , (tree_object*)value);
|
87
|
+
return value;
|
88
|
+
}
|
89
|
+
|
90
|
+
VALUE ruby_JudyHash_length(VALUE self) {
|
91
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
92
|
+
return judy_array_length(p_hash);
|
93
|
+
}
|
94
|
+
|
95
|
+
VALUE ruby_JudyHash_each_key(VALUE self) {
|
96
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
97
|
+
VALUE index = judy_array_first_index(p_hash);
|
98
|
+
while (index != Qfalse) {
|
99
|
+
rb_yield(index);
|
100
|
+
index = judy_array_next_index(p_hash, index);
|
101
|
+
}
|
102
|
+
return self;
|
103
|
+
}
|
104
|
+
|
105
|
+
VALUE ruby_JudyHash_keys(VALUE self) {
|
106
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
107
|
+
VALUE index = judy_array_first_index(p_hash);
|
108
|
+
VALUE array = rb_ary_new();
|
109
|
+
while (index != Qfalse) {
|
110
|
+
rb_ary_push(array , (VALUE)index);
|
111
|
+
index = judy_array_next_index(p_hash, index);
|
112
|
+
}
|
113
|
+
return array;
|
114
|
+
}
|
115
|
+
|
116
|
+
VALUE ruby_JudyHash_each(VALUE self) {
|
117
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
118
|
+
VALUE index = Qfalse;
|
119
|
+
VALUE value = Qnil;
|
120
|
+
if(p_hash == NULL) return self;
|
121
|
+
index = judy_array_first_index(p_hash);
|
122
|
+
while (index != Qfalse) {
|
123
|
+
value = (VALUE) judy_array_at_index(p_hash , index);
|
124
|
+
rb_yield_values(2 , index , value );
|
125
|
+
index = judy_array_next_index(p_hash, index);
|
126
|
+
}
|
127
|
+
return self;
|
128
|
+
}
|
129
|
+
|
130
|
+
VALUE ruby_JudyHash_empty(VALUE self) {
|
131
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
132
|
+
int c;
|
133
|
+
if( ! p_hash ) return Qtrue;
|
134
|
+
c = JudyLCount(*p_hash, 0 , -1 , PJE0) ;
|
135
|
+
return (0 == c) ? Qtrue : Qfalse ;
|
136
|
+
}
|
137
|
+
|
138
|
+
VALUE ruby_JudyHash_by_count(VALUE self, VALUE num) {
|
139
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
140
|
+
VALUE val;
|
141
|
+
check_index_basic(num);
|
142
|
+
val = (VALUE)judy_array_at_count(p_hash, num);
|
143
|
+
return (val == 0) ? Qnil : val;
|
144
|
+
}
|
145
|
+
|
146
|
+
VALUE ruby_JudyHash_mem_used(VALUE self) {
|
147
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
148
|
+
return judy_array_mem(p_hash);
|
149
|
+
}
|
150
|
+
|
151
|
+
VALUE ruby_JudyHash_first_index(VALUE self) {
|
152
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
153
|
+
VALUE val = (VALUE)judy_array_first_index(p_hash);
|
154
|
+
return (val == 0) ? Qnil : val;
|
155
|
+
}
|
156
|
+
|
157
|
+
VALUE ruby_JudyHash_next_index(VALUE self, VALUE in) {
|
158
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
159
|
+
VALUE val;
|
160
|
+
check_index_basic(in);
|
161
|
+
val = (VALUE)judy_array_next_index(p_hash, in);
|
162
|
+
return (val == 0) ? Qnil : val;
|
163
|
+
}
|
164
|
+
|
165
|
+
VALUE ruby_JudyHash_last_index(VALUE self) {
|
166
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
167
|
+
VALUE val = (VALUE)judy_array_last_index(p_hash);
|
168
|
+
return (val == 0) ? Qnil : val;
|
169
|
+
}
|
170
|
+
VALUE ruby_JudyHash_prev_index(VALUE self, VALUE in) {
|
171
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
172
|
+
VALUE val;
|
173
|
+
check_index_basic(in);
|
174
|
+
val = (VALUE)judy_array_prev_index(p_hash, in);
|
175
|
+
return (val == 0) ? Qnil : val;
|
176
|
+
}
|
177
|
+
|
178
|
+
VALUE ruby_JudyHash_includeq(VALUE self, VALUE dat) {
|
179
|
+
JudyHash *p_hash = Get_Hash(self) ;
|
180
|
+
VALUE index = judy_array_first_index(p_hash);
|
181
|
+
VALUE value = Qnil;
|
182
|
+
while (index != Qfalse) {
|
183
|
+
value = (VALUE) judy_array_at_index(p_hash , index);
|
184
|
+
if( dat == value ) return index;
|
185
|
+
index = judy_array_next_index(p_hash, index);
|
186
|
+
}
|
187
|
+
return Qfalse;
|
188
|
+
}
|
189
|
+
|
190
|
+
VALUE ruby_Hash_mem_used(VALUE hash) {
|
191
|
+
if (!RHASH(hash)->ntbl ) return Qnil;
|
192
|
+
return UINT2NUM(st_memsize(RHASH(hash)->ntbl));
|
193
|
+
}
|
194
|
+
|
195
|
+
extern void Init_JudySet(void);
|
196
|
+
|
197
|
+
/* Ruby calls this when it loads the module. Define all public functions
|
198
|
+
and initialize variables */
|
199
|
+
void Init_digital_trees_and_sets(){
|
200
|
+
VALUE cJudyHash_klass = rb_define_class("JudyHash", rb_cObject);
|
201
|
+
rb_include_module(cJudyHash_klass, rb_eval_string("Enumerable"));
|
202
|
+
rb_define_singleton_method(cJudyHash_klass, "new", ruby_JudyHash_allocate, 0);
|
203
|
+
rb_define_method(cJudyHash_klass, "[]=", ruby_JudyHash_setitem, 2);
|
204
|
+
rb_define_method(cJudyHash_klass, "set", ruby_JudyHash_setitem, 2);
|
205
|
+
rb_define_method(cJudyHash_klass, "delete", ruby_JudyHash_delete, 1);
|
206
|
+
rb_define_method(cJudyHash_klass, "get", ruby_JudyHash_getitem, 1);
|
207
|
+
rb_define_method(cJudyHash_klass, "[]", ruby_JudyHash_getitem, 1);
|
208
|
+
rb_define_method(cJudyHash_klass, "do_get", ruby_JudyHash_getitem, 1);
|
209
|
+
rb_define_method(cJudyHash_klass, "length", ruby_JudyHash_length, 0);
|
210
|
+
rb_define_method(cJudyHash_klass, "empty?", ruby_JudyHash_empty, 0);
|
211
|
+
rb_define_method(cJudyHash_klass, "count", ruby_JudyHash_length, 0);
|
212
|
+
rb_define_method(cJudyHash_klass, "each_key", ruby_JudyHash_each_key, 0);
|
213
|
+
rb_define_method(cJudyHash_klass, "each", ruby_JudyHash_each, 0);
|
214
|
+
rb_define_method(cJudyHash_klass, "keys", ruby_JudyHash_keys, 0);
|
215
|
+
rb_define_method(cJudyHash_klass, "by_count", ruby_JudyHash_by_count, 1);
|
216
|
+
rb_define_method(cJudyHash_klass, "mem_used", ruby_JudyHash_mem_used, 0);
|
217
|
+
rb_define_method(cJudyHash_klass, "first_index", ruby_JudyHash_first_index, 0);
|
218
|
+
rb_define_method(cJudyHash_klass, "next_index", ruby_JudyHash_next_index, 1);
|
219
|
+
rb_define_method(cJudyHash_klass, "last_index", ruby_JudyHash_last_index, 0);
|
220
|
+
rb_define_method(cJudyHash_klass, "clear", ruby_JudyHash_clear, 0);
|
221
|
+
rb_define_method(cJudyHash_klass, "include?", ruby_JudyHash_includeq, 1);
|
222
|
+
rb_define_method(cJudyHash_klass, "has_key?", ruby_JudyHash_has_key, 1);
|
223
|
+
// for testing
|
224
|
+
rb_define_method(rb_cHash, "mem_used", ruby_Hash_mem_used, 0);
|
225
|
+
|
226
|
+
Init_JudySet();
|
227
|
+
}
|
data/ext/judy_set.c
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
/************************************************
|
2
|
+
Author : Torsten Rueger , Copyright 2002-20011
|
3
|
+
License: GPL v.2 see LICENSE
|
4
|
+
************************************************/
|
5
|
+
#include "judy_compat.h"
|
6
|
+
|
7
|
+
// The class JudySet is a Ruby Api to a judy set. It only takes ints and symbols though
|
8
|
+
|
9
|
+
typedef Tree JudySet; // JudySet == pcvoid_t
|
10
|
+
|
11
|
+
static inline JudySet * Get_Set(VALUE obj) {
|
12
|
+
tree_object* object;
|
13
|
+
Check_Type(obj, T_DATA);
|
14
|
+
object = DATA_PTR(obj);
|
15
|
+
return (JudySet*) &(object->judy) ;
|
16
|
+
}
|
17
|
+
|
18
|
+
void gc_free_set(tree_object* set){
|
19
|
+
judy_set_clear(&(set->judy));
|
20
|
+
free(set);
|
21
|
+
}
|
22
|
+
|
23
|
+
VALUE ruby_JudySet_allocate(VALUE self) {
|
24
|
+
tree_object* set = malloc( sizeof(tree_object) ) ;
|
25
|
+
set->judy = NULL;
|
26
|
+
return Data_Wrap_Struct(self, NULL, gc_free_set, set); // NULL means no marking
|
27
|
+
}
|
28
|
+
|
29
|
+
VALUE ruby_JudySet_delete(VALUE self , VALUE index) {
|
30
|
+
JudySet *p_set;
|
31
|
+
if( index == Qnil ) return Qnil ;
|
32
|
+
p_set = Get_Set(self) ;
|
33
|
+
check_index_basic(index);
|
34
|
+
return judy_set_delete(p_set , index) ;
|
35
|
+
}
|
36
|
+
|
37
|
+
VALUE ruby_JudySet_set(VALUE self , VALUE index , VALUE value ) {
|
38
|
+
JudySet *p_set;
|
39
|
+
if( index == Qnil ) return Qnil ;
|
40
|
+
if( value == Qnil || value == Qfalse ) return ruby_JudySet_delete(self , index) ;
|
41
|
+
p_set = Get_Set(self) ;
|
42
|
+
check_index_basic(index);
|
43
|
+
return judy_set_set(p_set , index);
|
44
|
+
}
|
45
|
+
|
46
|
+
VALUE ruby_JudySet_add(VALUE self , VALUE index ) {
|
47
|
+
JudySet *p_set;
|
48
|
+
if( index == Qnil ) return Qnil ;
|
49
|
+
p_set = Get_Set(self) ;
|
50
|
+
check_index_basic(index);
|
51
|
+
return judy_set_set(p_set , index);
|
52
|
+
}
|
53
|
+
|
54
|
+
VALUE ruby_JudySet_get(VALUE self , VALUE index) {
|
55
|
+
JudySet *p_set;
|
56
|
+
if( index == Qnil ) return Qnil ;
|
57
|
+
p_set = Get_Set(self) ;
|
58
|
+
check_index_basic(index);
|
59
|
+
return judy_set_has(p_set , index) ? Qtrue : Qfalse ;
|
60
|
+
}
|
61
|
+
|
62
|
+
VALUE ruby_JudySet_length(VALUE self) {
|
63
|
+
JudySet *p_set = Get_Set(self) ;
|
64
|
+
return judy_set_length(p_set);
|
65
|
+
}
|
66
|
+
|
67
|
+
VALUE ruby_JudySet_by_count(VALUE self, VALUE num) {
|
68
|
+
JudySet *p_set = Get_Set(self) ;
|
69
|
+
check_index_basic(num);
|
70
|
+
return judy_set_at_count(p_set, num ) ;
|
71
|
+
}
|
72
|
+
|
73
|
+
VALUE ruby_JudySet_mem_used(VALUE self) {
|
74
|
+
JudySet *p_set = Get_Set(self) ;
|
75
|
+
return judy_set_mem(p_set);
|
76
|
+
}
|
77
|
+
|
78
|
+
VALUE ruby_JudySet_first_index(VALUE self) {
|
79
|
+
JudySet *p_set = Get_Set(self) ;
|
80
|
+
return judy_set_first_index(p_set);
|
81
|
+
}
|
82
|
+
|
83
|
+
VALUE ruby_JudySet_next_index(VALUE self, VALUE index) {
|
84
|
+
JudySet *p_set = Get_Set(self) ;
|
85
|
+
check_index_basic(index);
|
86
|
+
return judy_set_next_index(p_set, index);
|
87
|
+
}
|
88
|
+
|
89
|
+
VALUE ruby_JudySet_last_index(VALUE self) {
|
90
|
+
JudySet *p_set = Get_Set(self) ;
|
91
|
+
return judy_set_last_index(p_set);
|
92
|
+
}
|
93
|
+
|
94
|
+
VALUE ruby_JudySet_clear(VALUE self) {
|
95
|
+
JudySet *p_set = Get_Set(self) ;
|
96
|
+
VALUE len = ruby_JudySet_length(self) ;
|
97
|
+
judy_set_clear(p_set);
|
98
|
+
return len;
|
99
|
+
}
|
100
|
+
|
101
|
+
VALUE ruby_JudySet_each(VALUE self) {
|
102
|
+
JudySet *p_set = Get_Set(self) ;
|
103
|
+
VALUE index = judy_set_first_index(p_set);
|
104
|
+
while(index != Qfalse ){
|
105
|
+
rb_yield(index);
|
106
|
+
index = judy_set_next_index(p_set, index);
|
107
|
+
}
|
108
|
+
return self;
|
109
|
+
}
|
110
|
+
|
111
|
+
VALUE ruby_JudySet_sum(VALUE self ) {
|
112
|
+
long int ret = 0;
|
113
|
+
JudySet *p_set = Get_Set(self) ;
|
114
|
+
VALUE index = judy_set_first_index(p_set);
|
115
|
+
while(index != Qfalse ){
|
116
|
+
ret += NUM2LONG(index) ;
|
117
|
+
index = judy_set_next_index(p_set, index);
|
118
|
+
}
|
119
|
+
return LONG2NUM(ret);
|
120
|
+
}
|
121
|
+
|
122
|
+
void Init_JudySet(void) {
|
123
|
+
VALUE cJudySet_klass = rb_define_class("JudySet", rb_cObject);
|
124
|
+
rb_include_module(cJudySet_klass, rb_eval_string("Enumerable"));
|
125
|
+
rb_define_singleton_method(cJudySet_klass, "new", ruby_JudySet_allocate, 0);
|
126
|
+
rb_define_method(cJudySet_klass, "do_set", ruby_JudySet_set, 2);
|
127
|
+
rb_define_method(cJudySet_klass, "set", ruby_JudySet_set, 2);
|
128
|
+
rb_define_method(cJudySet_klass, "[]=", ruby_JudySet_set, 2);
|
129
|
+
rb_define_method(cJudySet_klass, "add", ruby_JudySet_add, 1);
|
130
|
+
rb_define_method(cJudySet_klass, "delete", ruby_JudySet_delete, 1);
|
131
|
+
rb_define_method(cJudySet_klass, "unset", ruby_JudySet_delete, 1);
|
132
|
+
rb_define_method(cJudySet_klass, "get", ruby_JudySet_get, 1);
|
133
|
+
rb_define_method(cJudySet_klass, "do_get", ruby_JudySet_get, 1);
|
134
|
+
rb_define_method(cJudySet_klass, "[]", ruby_JudySet_get, 1);
|
135
|
+
rb_define_method(cJudySet_klass, "length", ruby_JudySet_length, 0);
|
136
|
+
rb_define_method(cJudySet_klass, "by_count", ruby_JudySet_by_count, 1);
|
137
|
+
rb_define_method(cJudySet_klass, "mem_used", ruby_JudySet_mem_used, 0);
|
138
|
+
rb_define_method(cJudySet_klass, "first_index", ruby_JudySet_first_index, 0);
|
139
|
+
rb_define_method(cJudySet_klass, "next_index", ruby_JudySet_next_index, 1);
|
140
|
+
rb_define_method(cJudySet_klass, "last_index", ruby_JudySet_last_index, 0);
|
141
|
+
rb_define_method(cJudySet_klass, "clear", ruby_JudySet_clear, 0);
|
142
|
+
rb_define_method(cJudySet_klass, "each", ruby_JudySet_each, 0);
|
143
|
+
rb_define_method(cJudySet_klass, "each_index", ruby_JudySet_each, 0);
|
144
|
+
rb_define_method(cJudySet_klass, "sum", ruby_JudySet_sum, 2);
|
145
|
+
}
|
146
|
+
|