ruby-tokyotyrant 0.3.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/ext/extconf.rb ADDED
@@ -0,0 +1,39 @@
1
+ # ENV["RC_ARCHS"] = `uname -m`.chomp if `uname -sr` =~ /^Darwin/
2
+ #
3
+ # require 'mkmf'
4
+ #
5
+
6
+ if RUBY_PLATFORM =~ /darwin/
7
+ ENV["RC_ARCHS"] = `uname -m`.chomp if `uname -sr` =~ /^Darwin/
8
+
9
+ # On PowerPC the defaults are fine
10
+ ENV["RC_ARCHS"] = '' if `uname -m` =~ /^Power Macintosh/
11
+ end
12
+
13
+ # Loads mkmf which is used to make makefiles for Ruby extensions
14
+ require 'mkmf'
15
+
16
+ # Give it a name
17
+ extension_name = 'tokyo_tyrant'
18
+
19
+ dir_config("tokyo_tyrant")
20
+
21
+ # NOTE: use GCC flags unless Visual C compiler is used
22
+ $CFLAGS << ' -Wall ' unless RUBY_PLATFORM =~ /mswin/
23
+
24
+ if RUBY_VERSION < '1.8.6'
25
+ $CFLAGS << ' -DRUBY_LESS_THAN_186'
26
+ end
27
+
28
+ # Do the work
29
+
30
+ find_library(*['tokyotyrant', "tcrdbnew", dir_config('libtokyotyrant').last].compact) or
31
+ raise "shared library 'libtokyotyrant' not found"
32
+
33
+ ['tctdb.h',
34
+ 'tcrdb.h'].each do |header|
35
+ find_header(*[header, dir_config('libtokyotyrant').first].compact) or
36
+ raise "header file '#{header}' not found"
37
+ end
38
+
39
+ create_makefile 'tokyo_tyrant'
@@ -0,0 +1,147 @@
1
+ #include <tokyo_tyrant.h>
2
+
3
+ extern VALUE StringRaw(const char *buf, int bsiz){
4
+ VALUE vval;
5
+ int i;
6
+ vval = rb_str_buf_new2("");
7
+ char s[5];
8
+
9
+ for(i=0;i<bsiz;i++){
10
+ char c = *buf++;
11
+ s[0] = c;
12
+ rb_str_buf_cat(vval, s, 1);
13
+ }
14
+ // buf -= bsiz;
15
+ // rb_str_buf_cat2(vval, "");
16
+ return vval;
17
+ }
18
+
19
+ extern VALUE StringValueEx(VALUE vobj){
20
+ if (rb_respond_to(vobj, rb_intern("to_tokyo_tyrant"))) {
21
+ return rb_convert_type(vobj, T_STRING, "String", "to_tokyo_tyrant");
22
+ } else if (rb_respond_to(vobj, rb_intern("to_s"))) {
23
+ return rb_convert_type(vobj, T_STRING, "String", "to_s");
24
+ } else {
25
+ rb_raise(rb_eArgError, "can't stringify object");
26
+ }
27
+ return StringValue(vobj);
28
+ }
29
+
30
+ extern TCLIST *varytolist(VALUE vary){
31
+ VALUE vval;
32
+ TCLIST *list;
33
+ int i, num;
34
+ num = RARRAY_LEN(vary);
35
+ list = tclistnew2(num);
36
+ for(i = 0; i < num; i++){
37
+ vval = rb_ary_entry(vary, i);
38
+ vval = StringValueEx(vval);
39
+ tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
40
+ }
41
+ return list;
42
+ }
43
+
44
+ extern VALUE listtovary(TCLIST *list){
45
+ VALUE vary;
46
+ const char *vbuf;
47
+ int i, num, vsiz;
48
+ num = tclistnum(list);
49
+ vary = rb_ary_new2(num);
50
+ for(i = 0; i < num; i++){
51
+ vbuf = tclistval(list, i, &vsiz);
52
+ rb_ary_push(vary, rb_str_new(vbuf, vsiz));
53
+ }
54
+ return vary;
55
+ }
56
+
57
+ extern TCMAP *vhashtomap(VALUE vhash){
58
+ VALUE vkeys, vkey, vval;
59
+ TCMAP *map;
60
+ int i, num;
61
+ map = tcmapnew2(31);
62
+ vkeys = rb_funcall(vhash, rb_intern("keys"), 0);
63
+ num = RARRAY_LEN(vkeys);
64
+ for(i = 0; i < num; i++){
65
+ vkey = rb_ary_entry(vkeys, i);
66
+ vval = rb_hash_aref(vhash, vkey);
67
+ vkey = StringValueEx(vkey);
68
+ vval = StringValueEx(vval);
69
+ tcmapput(map, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vval), RSTRING_LEN(vval));
70
+ }
71
+ return map;
72
+ }
73
+
74
+ extern VALUE maptovhash(TCMAP *map){
75
+ const char *kbuf;
76
+ int ksiz, vsiz;
77
+ VALUE vhash;
78
+ vhash = rb_hash_new();
79
+ tcmapiterinit(map);
80
+ while((kbuf = tcmapiternext(map, &ksiz)) != NULL){
81
+ const char *vbuf = tcmapiterval(kbuf, &vsiz);
82
+ rb_hash_aset(vhash, rb_str_new(kbuf, ksiz), StringRaw(vbuf, vsiz));
83
+ }
84
+ return vhash;
85
+ }
86
+
87
+ extern TCMAP *varytomap(VALUE vary){
88
+ int i;
89
+ TCLIST *keys;
90
+ TCMAP *recs = tcmapnew();
91
+ keys = varytolist(vary);
92
+ for(i = 0; i < tclistnum(keys); i++){
93
+ int ksiz;
94
+ const char *kbuf = tclistval(keys, i, &ksiz);
95
+ tcmapput(recs, kbuf, ksiz, "", 0);
96
+ }
97
+ tclistdel(keys);
98
+ return recs;
99
+ }
100
+
101
+ extern TCLIST *vhashtolist(VALUE vhash){
102
+ /*
103
+ Seems like something like this might work just as well
104
+ vary = rb_hash_to_a(vhash);
105
+ vary = rb_ary_flatten(vary);
106
+ args = varytolist(vary);
107
+ */
108
+
109
+ VALUE vkeys, vkey, vval;
110
+ TCLIST *list;
111
+ int i, num;
112
+ vkeys = rb_funcall(vhash, rb_intern("keys"), 0);
113
+ num = RARRAY_LEN(vkeys);
114
+ list = tclistnew2(num);
115
+ for(i = 0; i < num; i++){
116
+ vkey = rb_ary_entry(vkeys, i);
117
+ vval = rb_hash_aref(vhash, vkey);
118
+ vkey = StringValueEx(vkey);
119
+ vval = StringValueEx(vval);
120
+ tclistpush(list, RSTRING_PTR(vkey), RSTRING_LEN(vkey));
121
+ tclistpush(list, RSTRING_PTR(vval), RSTRING_LEN(vval));
122
+ }
123
+ return list;
124
+ }
125
+
126
+ VALUE mTokyoTyrant;
127
+ VALUE eTokyoTyrantError;
128
+ VALUE cDB;
129
+ VALUE cTable;
130
+ VALUE cQuery;
131
+
132
+ void Init_tokyo_tyrant(){
133
+ mTokyoTyrant = rb_define_module("TokyoTyrant");
134
+ eTokyoTyrantError = rb_define_class("TokyoTyrantError", rb_eStandardError);
135
+ init_mod();
136
+
137
+ cDB = rb_define_class_under(mTokyoTyrant, "DB", rb_cObject);
138
+ rb_include_module(cDB, mTokyoTyrant);
139
+ init_db();
140
+
141
+ cTable = rb_define_class_under(mTokyoTyrant, "Table", rb_cObject);
142
+ rb_include_module(cTable, mTokyoTyrant);
143
+ init_table();
144
+
145
+ cQuery = rb_define_class_under(mTokyoTyrant, "Query", rb_cObject);
146
+ init_query();
147
+ }
@@ -0,0 +1,48 @@
1
+ #ifndef RUBY_TOKYOTYRANT
2
+ #define RUBY_TOKYOTYRANT
3
+
4
+ #include <ruby.h>
5
+ #include <string.h>
6
+ #include <math.h>
7
+ #include <time.h>
8
+ #include <locale.h>
9
+ #include <tcrdb.h>
10
+ #include <tokyo_tyrant_module.h>
11
+ #include <tokyo_tyrant_db.h>
12
+ #include <tokyo_tyrant_table.h>
13
+ #include <tokyo_tyrant_query.h>
14
+
15
+ #define RDBVNDATA "@rdb"
16
+ #define RDBQRYVNDATA "@rdbquery"
17
+ #define NUMBUFSIZ 32
18
+ #define TTPUT 0
19
+ #define TTPUTKEEP 1
20
+ #define TTPUTCAT 2
21
+ #define TTPUTNR 3
22
+
23
+ #if !defined(RSTRING_PTR)
24
+ #define RSTRING_PTR(TC_s) (RSTRING(TC_s)->ptr)
25
+ #endif
26
+ #if !defined(RSTRING_LEN)
27
+ #define RSTRING_LEN(TC_s) (RSTRING(TC_s)->len)
28
+ #endif
29
+ #if !defined(RARRAY_LEN)
30
+ #define RARRAY_LEN(TC_a) (RARRAY(TC_a)->len)
31
+ #endif
32
+
33
+ extern VALUE mTokyoTyrant;
34
+ extern VALUE eTokyoTyrantError;
35
+ extern VALUE cDB;
36
+ extern VALUE cTable;
37
+ extern VALUE cQuery;
38
+
39
+ extern VALUE StringRaw(const char *buf, int bsiz);
40
+ extern VALUE StringValueEx(VALUE vobj);
41
+ extern TCLIST *varytolist(VALUE vary);
42
+ extern VALUE listtovary(TCLIST *list);
43
+ extern TCMAP *vhashtomap(VALUE vhash);
44
+ extern VALUE maptovhash(TCMAP *map);
45
+ extern TCMAP *varytomap(VALUE vhash);
46
+ extern TCLIST *vhashtolist(VALUE vhash);
47
+
48
+ #endif
@@ -0,0 +1,227 @@
1
+ #include <tokyo_tyrant_db.h>
2
+
3
+ static VALUE cDB_put_method(VALUE vself, VALUE vkey, VALUE vstr, int method){
4
+ bool res;
5
+ TCRDB *db = mTokyoTyrant_getdb(vself);
6
+
7
+ vkey = StringValueEx(vkey);
8
+ vstr = StringValueEx(vstr);
9
+
10
+ switch(method){
11
+ case TTPUT:
12
+ res = tcrdbput(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
13
+ break;
14
+ case TTPUTKEEP:
15
+ res = tcrdbputkeep(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
16
+ break;
17
+ case TTPUTCAT:
18
+ res = tcrdbputcat(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
19
+ break;
20
+ case TTPUTNR:
21
+ res = tcrdbputnr(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr));
22
+ break;
23
+ default:
24
+ res = false;
25
+ break;
26
+ }
27
+
28
+ if(!res) mTokyoTyrant_exception(vself);
29
+
30
+ return Qtrue;
31
+ }
32
+
33
+ static VALUE cDB_put(VALUE vself, VALUE vkey, VALUE vstr){
34
+ return cDB_put_method(vself, vkey, vstr, TTPUT);
35
+ }
36
+
37
+ static VALUE cDB_mput(VALUE vself, VALUE vhash){
38
+ VALUE vary;
39
+ TCLIST *list, *args;
40
+ TCRDB *db = mTokyoTyrant_getdb(vself);
41
+
42
+ args = vhashtolist(vhash);
43
+ list = tcrdbmisc(db, "putlist", 0, args);
44
+ vary = listtovary(list);
45
+ tclistdel(args);
46
+ tclistdel(list);
47
+ return vary;
48
+ }
49
+
50
+ static VALUE cDB_putkeep(VALUE vself, VALUE vkey, VALUE vstr){
51
+ return cDB_put_method(vself, vkey, vstr, TTPUTKEEP);
52
+ }
53
+
54
+ static VALUE cDB_putcat(VALUE vself, VALUE vkey, VALUE vstr){
55
+ return cDB_put_method(vself, vkey, vstr, TTPUTCAT);
56
+ }
57
+
58
+ static VALUE cDB_putnr(VALUE vself, VALUE vkey, VALUE vstr){
59
+ return cDB_put_method(vself, vkey, vstr, TTPUTNR);
60
+ }
61
+
62
+ static VALUE cDB_putshl(VALUE vself, VALUE vkey, VALUE vstr, VALUE vwidth){
63
+ bool res;
64
+ TCRDB *db = mTokyoTyrant_getdb(vself);
65
+
66
+ vkey = StringValueEx(vkey);
67
+ vstr = StringValueEx(vstr);
68
+
69
+ res = tcrdbputshl(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), RSTRING_PTR(vstr), RSTRING_LEN(vstr), FIXNUM_P(vwidth));
70
+
71
+ if(!res) mTokyoTyrant_exception(vself);
72
+
73
+ return Qtrue;
74
+ }
75
+
76
+ static VALUE cDB_get(VALUE vself, VALUE vkey){
77
+ VALUE vval;
78
+ char *buf;
79
+ int bsiz, ecode;
80
+ TCRDB *db = mTokyoTyrant_getdb(vself);
81
+
82
+ // this is ugly
83
+ vkey = StringValueEx(vkey);
84
+ if(!(buf = tcrdbget(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey), &bsiz))){
85
+ if ((ecode = tcrdbecode(db))) {
86
+ if (ecode != TTENOREC) mTokyoTyrant_exception(vself);
87
+ }
88
+ return Qnil;
89
+ } else {
90
+ vval = StringRaw(buf, bsiz);
91
+ }
92
+
93
+ tcfree(buf);
94
+ return vval;
95
+ }
96
+
97
+ static VALUE cDB_mget(int argc, VALUE *argv, VALUE vself){
98
+ VALUE vkeys, vhash, vvalue;
99
+ TCMAP *recs;
100
+ TCRDB *db = mTokyoTyrant_getdb(vself);
101
+ rb_scan_args(argc, argv, "*", &vkeys);
102
+
103
+ // I really hope there is a better way to do this
104
+ if (RARRAY_LEN(vkeys) == 1) {
105
+ vvalue = rb_ary_entry(vkeys, 0);
106
+ switch (TYPE(vvalue)){
107
+ case T_STRING:
108
+ case T_FIXNUM:
109
+ break;
110
+ case T_ARRAY:
111
+ vkeys = vvalue;
112
+ break;
113
+ case T_STRUCT: // range is not a T_STRUCT instead of a T_OBJECT in ruby1.9?
114
+ case T_OBJECT:
115
+ vkeys = rb_convert_type(vvalue, T_ARRAY, "Array", "to_a");
116
+ break;
117
+ }
118
+ }
119
+
120
+ Check_Type(vkeys, T_ARRAY);
121
+
122
+ recs = varytomap(vkeys);
123
+ if(!tcrdbget3(db, recs)) return Qnil;
124
+ vhash = maptovhash(recs);
125
+ tcmapdel(recs);
126
+ return vhash;
127
+ }
128
+
129
+ static VALUE cDB_vsiz(VALUE vself, VALUE vkey){
130
+ TCRDB *db = mTokyoTyrant_getdb(vself);
131
+
132
+ vkey = StringValueEx(vkey);
133
+ return INT2NUM(tcrdbvsiz(db, RSTRING_PTR(vkey), RSTRING_LEN(vkey)));
134
+ }
135
+
136
+ static VALUE cDB_fetch(int argc, VALUE *argv, VALUE vself){
137
+ VALUE vkey, vrv, vforce;
138
+ rb_scan_args(argc, argv, "11", &vkey, &vforce);
139
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
140
+ if(vforce == Qnil) vforce = Qfalse;
141
+
142
+ if(vforce != Qfalse || (vrv = cDB_get(vself, vkey)) == Qnil){
143
+ vrv = rb_yield(vkey);
144
+ cDB_put(vself, vkey, vrv);
145
+ }
146
+ return vrv;
147
+ }
148
+
149
+ static VALUE cDB_each(VALUE vself){
150
+ VALUE vrv;
151
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
152
+ TCRDB *db = mTokyoTyrant_getdb(vself);
153
+ vrv = Qnil;
154
+ tcrdbiterinit(db);
155
+ int ksiz;
156
+ char *kbuf;
157
+ while((kbuf = tcrdbiternext(db, &ksiz)) != NULL){
158
+ int vsiz;
159
+ char *vbuf = tcrdbget(db, kbuf, ksiz, &vsiz);
160
+ vrv = rb_yield_values(2, rb_str_new2(kbuf), StringRaw(vbuf, vsiz));
161
+ tcfree(vbuf);
162
+ tcfree(kbuf);
163
+ }
164
+ return vrv;
165
+ }
166
+
167
+ static VALUE cDB_each_value(VALUE vself){
168
+ VALUE vrv;
169
+ if(rb_block_given_p() != Qtrue) rb_raise(rb_eArgError, "no block given");
170
+ TCRDB *db = mTokyoTyrant_getdb(vself);
171
+ vrv = Qnil;
172
+ tcrdbiterinit(db);
173
+ int ksiz;
174
+ char *kbuf;
175
+ while((kbuf = tcrdbiternext(db, &ksiz)) != NULL){
176
+ int vsiz;
177
+ char *vbuf = tcrdbget(db, kbuf, ksiz, &vsiz);
178
+ vrv = rb_yield_values(1, StringRaw(vbuf, vsiz));
179
+ tcfree(vbuf);
180
+ tcfree(kbuf);
181
+ }
182
+ return vrv;
183
+ }
184
+
185
+ static VALUE cDB_values(VALUE vself){
186
+ VALUE vary;
187
+ TCRDB *db = mTokyoTyrant_getdb(vself);
188
+ vary = rb_ary_new2(tcrdbrnum(db));
189
+ tcrdbiterinit(db);
190
+ int ksiz;
191
+ char *kbuf;
192
+ while((kbuf = tcrdbiternext(db, &ksiz)) != NULL){
193
+ int vsiz;
194
+ char *vbuf = tcrdbget(db, kbuf, ksiz, &vsiz);
195
+ rb_ary_push(vary, StringRaw(vbuf, vsiz));
196
+ tcfree(vbuf);
197
+ tcfree(kbuf);
198
+ }
199
+ return vary;
200
+ }
201
+
202
+ void init_db(){
203
+ rb_define_method(cDB, "mput", cDB_mput, 1);
204
+ rb_define_alias(cDB, "lput", "mput"); // Rufus Compat
205
+ rb_define_method(cDB, "put", cDB_put, 2);
206
+ rb_define_alias(cDB, "[]=", "put");
207
+ rb_define_method(cDB, "putkeep", cDB_putkeep, 2);
208
+ rb_define_method(cDB, "putcat", cDB_putcat, 2);
209
+ rb_define_method(cDB, "putshl", cDB_putshl, 3);
210
+ rb_define_method(cDB, "putnr", cDB_putnr, 2);
211
+ rb_define_method(cDB, "get", cDB_get, 1);
212
+ rb_define_alias(cDB, "[]", "get");
213
+ rb_define_method(cDB, "mget", cDB_mget, -1);
214
+ rb_define_alias(cDB, "lget", "mget"); // Rufus Compat
215
+ rb_define_method(cDB, "vsiz", cDB_vsiz, 1);
216
+ /*
217
+ rb_define_method(cDB, "check_value", cDB_check_value, 1);
218
+ rb_define_alias(cDB, "has_value?", "check_value");
219
+ rb_define_alias(cDB, "value?", "check_value");
220
+ */
221
+
222
+ rb_define_method(cDB, "fetch", cDB_fetch, -1);
223
+ rb_define_method(cDB, "each", cDB_each, 0);
224
+ rb_define_alias(cDB, "each_pair", "each");
225
+ rb_define_method(cDB, "each_value", cDB_each_value, 0);
226
+ rb_define_method(cDB, "values", cDB_values, 0);
227
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef RUBY_TOKYOTYRANT_DB
2
+ #define RUBY_TOKYOTYRANT_DB
3
+
4
+ #include <tokyo_tyrant.h>
5
+
6
+ void init_db();
7
+
8
+ #endif