digital_trees_and_sets 0.4.0
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.
- 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
|
+
|