libcdb-ruby 0.1.1-x86-mswin32-60 → 0.2.0.1-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6074688885d1a8387c93170def13c8d31f2e4d99
4
- data.tar.gz: 137d2dd3eb3bf13bfcf8793f1cd3a46b5881ad78
3
+ metadata.gz: af653f457cbf0eef5806e5553b7de67bcbd7fbfb
4
+ data.tar.gz: f1615af88ae6ee51a117a9878a3e4548fb660a11
5
5
  SHA512:
6
- metadata.gz: b2b973e0f2453c770a035ccaf70f10d464f9a30aef2c234039f77d2cd3e296a81780e9a043c3dec1a7d9f25fbc19e4747accc8d8317fadf7cf6ba590e5452605
7
- data.tar.gz: 7ea1869fc6f4c95bfcde170b6c52322642bc3e312cc8e1ec5a1bbc35e0565766d02d2bcf0eb3c8e757aef510972d59169b3815ae2c5530fad263c23cce3e896d
6
+ metadata.gz: 0f6a130ba9a58902957bc1053f123719d053632916d96814e2046bc509b5aaabdbc295bf248d7ca352bfff921cd79fc965e56b76a388a0349fcbcb68d82972b3
7
+ data.tar.gz: 7db9e49e9f839d9d49917f1e7308ad6d54eef348212a4f93fa7095f67bc9990b07047ea580c8c4246decedf55fe44e4cdb2465a7dbc948812487e3ee6c66e577
data/ChangeLog CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  = Revision history for libcdb-ruby
4
4
 
5
+ == 0.2.0 [2014-12-05]
6
+
7
+ * Added encoding support to LibCDB::CDB::Reader.
8
+ * Added LibCDB::CDB.load and LibCDB::CDB.load_file to create a database from a
9
+ dump.
10
+ * Added LibCDB::CDB.stats and LibCDB::CDB.print_stats to collect stats from a
11
+ database.
12
+ * Fixed that LibCDB::CDB::Reader#each_key and LibCDB::CDB::Reader#each_value
13
+ would not return an enumerator when no block was given.
14
+
5
15
  == 0.1.1 [2014-04-25]
6
16
 
7
17
  * <b>Dropped support for Ruby 1.9.2.</b>
data/README CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  == VERSION
4
4
 
5
- This documentation refers to libcdb-ruby version 0.1.1
5
+ This documentation refers to libcdb-ruby version 0.2.0
6
6
 
7
7
 
8
8
  == DESCRIPTION
@@ -74,7 +74,7 @@ creating and reading {constant databases}[http://cr.yp.to/cdb.html].
74
74
  == SUPPORTED PLATFORMS
75
75
 
76
76
  Linux:: MRI 1.9.3, 2.0 & 2.1 (Tested on 64-bit Ubuntu GNU/Linux
77
- with 1.9.3p488, 2.0.0p377 and 2.1.2p77)
77
+ with 1.9.3p550, 2.0.0p594 and 2.1.5p273)
78
78
  Windows:: MRI 1.9.3 (Tested on 32-bit Windows XP with 1.9.3p194)
79
79
 
80
80
 
@@ -82,7 +82,7 @@ Windows:: MRI 1.9.3 (Tested on 32-bit Windows XP with 1.9.3p194)
82
82
 
83
83
  CDB:: http://cr.yp.to/cdb.html
84
84
  TinyCDB:: http://www.corpit.ru/mjt/tinycdb.html
85
- Documentation:: https://blackwinter.github.io/libcdb-ruby/
85
+ Documentation:: https://blackwinter.github.com/libcdb-ruby
86
86
  Source code:: https://github.com/blackwinter/libcdb-ruby
87
87
  RubyGem:: https://rubygems.org/gems/libcdb-ruby
88
88
  Travis CI:: https://travis-ci.org/blackwinter/libcdb-ruby
data/Rakefile CHANGED
@@ -1,19 +1,8 @@
1
- require File.expand_path(%q{../lib/libcdb/version}, __FILE__)
1
+ require_relative 'lib/libcdb/version'
2
2
 
3
3
  begin
4
4
  require 'hen'
5
5
 
6
- cco = []
7
-
8
- if dir = ENV['TINYCDB']
9
- cco << "--with-cdb-include=#{dir}"
10
- cco << "--with-cdb-lib=#{dir}"
11
- end
12
-
13
- if dir = ENV['MINGW32']
14
- cco << %Q{--with-cflags="-I#{dir}/include -L#{dir}/lib"}
15
- end
16
-
17
6
  Hen.lay! {{
18
7
  gem: {
19
8
  name: %q{libcdb-ruby},
@@ -23,7 +12,7 @@ begin
23
12
  email: %q{jens.wille@gmail.com},
24
13
  license: %q{AGPL-3.0},
25
14
  homepage: :blackwinter,
26
- extension: { cross_config_options: cco },
15
+ extension: { with_cross_cdb: lambda { |dir| [dir] } },
27
16
 
28
17
  required_ruby_version: '>= 1.9.3'
29
18
  }
@@ -38,17 +38,23 @@ rcdb_##what##er_alloc(VALUE klass) {\
38
38
  rb_sys_fail(0);\
39
39
  }
40
40
 
41
- #define RCDB_RAISE_ARGS(min, max) \
41
+ #define RCDB_RAISE_ARGS0(min, max, argc) \
42
42
  rb_raise(rb_eArgError,\
43
43
  "wrong number of arguments (%d for " #min "-" #max ")", argc);
44
44
 
45
- #define RCDB_RETURN_ENUMERATOR(self, argc, argv, max) \
45
+ #define RCDB_RAISE_ARGS(min, max) RCDB_RAISE_ARGS0(min, max, argc)
46
+
47
+ #define RCDB_RETURN_ENUMERATOR0(argc, argv, max) \
46
48
  if (argc > max) {\
47
- RCDB_RAISE_ARGS(0, max)\
49
+ RCDB_RAISE_ARGS0(0, max, argc)\
48
50
  }\
49
51
  \
50
52
  RETURN_ENUMERATOR(self, argc, argv)
51
53
 
54
+ #define RCDB_RETURN_ENUMERATOR(max) RCDB_RETURN_ENUMERATOR0(argc, argv, max)
55
+
56
+ #define RCDB_RETURN_ENUMERATOR_NONE RCDB_RETURN_ENUMERATOR0(0, NULL, 0)
57
+
52
58
  #define RCDB_DEFINE_INSPECT(what) \
53
59
  static VALUE \
54
60
  rcdb_##what##er_inspect(VALUE self) {\
@@ -25,6 +25,7 @@ rcdb_reader_closed_p(VALUE self) {
25
25
  static VALUE
26
26
  rcdb_reader_initialize(VALUE self, VALUE io) {
27
27
  RCDB_INITIALIZE(read, READ, cdb, init)
28
+ rb_iv_set(self, "@encoding", rb_enc_default_external());
28
29
  return self;
29
30
  }
30
31
 
@@ -40,22 +41,20 @@ rcdb_reader_iter_push(VALUE val, VALUE ary) {
40
41
  /* Helper method */
41
42
  static VALUE
42
43
  rcdb_reader_iter_aset(VALUE pair, VALUE hash) {
43
- VALUE key = rb_ary_entry(pair, 0), val = rb_ary_entry(pair, 1), old;
44
-
45
- if (!st_lookup(RHASH_TBL(hash), key, 0)) {
46
- rb_hash_aset(hash, key, val);
47
- }
48
- else {
49
- old = rb_hash_aref(hash, key);
50
-
51
- switch (TYPE(old)) {
52
- case T_ARRAY:
53
- rb_ary_push(old, val);
54
- break;
55
- default:
56
- rb_hash_aset(hash, key, rb_ary_new3(2, old, val));
57
- break;
58
- }
44
+ VALUE key = rb_ary_entry(pair, 0);
45
+ VALUE val = rb_ary_entry(pair, 1);
46
+ VALUE old = rb_hash_aref(hash, key);
47
+
48
+ switch (TYPE(old)) {
49
+ case T_NIL:
50
+ rb_hash_aset(hash, key, val);
51
+ break;
52
+ case T_ARRAY:
53
+ rb_ary_push(old, val);
54
+ break;
55
+ default:
56
+ rb_hash_aset(hash, key, rb_ary_new3(2, old, val));
57
+ break;
59
58
  }
60
59
 
61
60
  return Qnil;
@@ -104,9 +103,9 @@ rcdb_reader_dump_pair(VALUE key, VALUE val) {
104
103
  VALUE str = rb_str_new2("");
105
104
 
106
105
  rb_str_cat2(str, "+");
107
- rb_str_append(str, rb_fix2str(LONG2NUM(RSTRING_LEN(key)), 10));
106
+ rb_str_append(str, RCDB_READER_STRING_LEN(key));
108
107
  rb_str_cat2(str, ",");
109
- rb_str_append(str, rb_fix2str(LONG2NUM(RSTRING_LEN(val)), 10));
108
+ rb_str_append(str, RCDB_READER_STRING_LEN(val));
110
109
  rb_str_cat2(str, ":");
111
110
  rb_str_append(str, key);
112
111
  rb_str_cat2(str, "->");
@@ -144,7 +143,7 @@ rcdb_reader_each(int argc, VALUE *argv, VALUE self) {
144
143
  unsigned cdbp;
145
144
  VALUE key;
146
145
 
147
- RCDB_RETURN_ENUMERATOR(self, argc, argv, 1);
146
+ RCDB_RETURN_ENUMERATOR(1);
148
147
  RCDB_READER_GET(self, cdb);
149
148
 
150
149
  if (rb_scan_args(argc, argv, "01", &key) == 1 && !NIL_P(key)) {
@@ -155,7 +154,7 @@ rcdb_reader_each(int argc, VALUE *argv, VALUE self) {
155
154
  }
156
155
 
157
156
  while (cdb_findnext(&cdbf) > 0) {
158
- rb_yield(rcdb_reader_read_data(cdb));
157
+ rb_yield(RCDB_READER_READ(data));
159
158
  }
160
159
  }
161
160
  else {
@@ -163,8 +162,8 @@ rcdb_reader_each(int argc, VALUE *argv, VALUE self) {
163
162
 
164
163
  while (cdb_seqnext(&cdbp, cdb) > 0) {
165
164
  rb_yield(rb_ary_new3(2,
166
- rcdb_reader_read_key(cdb),
167
- rcdb_reader_read_data(cdb)));
165
+ RCDB_READER_READ(key),
166
+ RCDB_READER_READ(data)));
168
167
  }
169
168
  }
170
169
 
@@ -184,9 +183,11 @@ static VALUE
184
183
  rcdb_reader_each_dump(int argc, VALUE *argv, VALUE self) {
185
184
  VALUE key;
186
185
 
187
- RCDB_RETURN_ENUMERATOR(self, argc, argv, 1);
186
+ RCDB_RETURN_ENUMERATOR(1);
188
187
 
189
188
  if (rb_scan_args(argc, argv, "01", &key) == 1 && !NIL_P(key)) {
189
+ StringValue(key);
190
+
190
191
  RCDB_READER_ITERATE0(each, yield_dump2, rb_ary_new3(1, key))
191
192
  }
192
193
  else {
@@ -210,11 +211,12 @@ rcdb_reader_each_key(VALUE self) {
210
211
  unsigned cdbp;
211
212
  VALUE key, hash = rb_hash_new();
212
213
 
214
+ RCDB_RETURN_ENUMERATOR_NONE;
213
215
  RCDB_READER_GET(self, cdb);
214
216
  cdb_seqinit(&cdbp, cdb);
215
217
 
216
218
  while (cdb_seqnext(&cdbp, cdb) > 0) {
217
- if (!st_lookup(RHASH_TBL(hash), key = rcdb_reader_read_key(cdb), 0)) {
219
+ if (NIL_P(rb_hash_lookup(hash, key = RCDB_READER_READ(key)))) {
218
220
  rb_hash_aset(hash, key, Qtrue);
219
221
  rb_yield(key);
220
222
  }
@@ -236,11 +238,12 @@ rcdb_reader_each_value(VALUE self) {
236
238
  struct cdb *cdb = NULL;
237
239
  unsigned cdbp;
238
240
 
241
+ RCDB_RETURN_ENUMERATOR_NONE;
239
242
  RCDB_READER_GET(self, cdb);
240
243
  cdb_seqinit(&cdbp, cdb);
241
244
 
242
245
  while (cdb_seqnext(&cdbp, cdb) > 0) {
243
- rb_yield(rcdb_reader_read_data(cdb));
246
+ rb_yield(RCDB_READER_READ(data));
244
247
  }
245
248
 
246
249
  return self;
@@ -274,7 +277,7 @@ rcdb_reader_fetch_first(VALUE self, VALUE key) {
274
277
  RCDB_READER_GET(self, cdb);
275
278
 
276
279
  if (cdb_find(cdb, RSTRING_PTR(key), RSTRING_LEN(key)) > 0) {
277
- val = rcdb_reader_read_data(cdb);
280
+ val = RCDB_READER_READ(data);
278
281
  }
279
282
 
280
283
  return val;
@@ -307,9 +310,7 @@ rcdb_reader_fetch_last(VALUE self, VALUE key) {
307
310
  }
308
311
 
309
312
  if (pos > 0) {
310
- val = rb_str_buf_new(len);
311
- cdb_read(cdb, RSTRING_PTR(val), len, pos);
312
- rb_str_set_len(val, len);
313
+ RCDB_READER_READ_POS(pos)
313
314
  }
314
315
 
315
316
  return val;
@@ -511,6 +512,8 @@ rcdb_init_reader(void) {
511
512
  rb_define_alloc_func(cCDBReader, rcdb_reader_alloc);
512
513
  rb_include_module(cCDBReader, rb_mEnumerable);
513
514
 
515
+ rb_define_attr(cCDBReader, "encoding", 1, 1);
516
+
514
517
  rb_define_method(cCDBReader, "close", rcdb_reader_close, 0);
515
518
  rb_define_method(cCDBReader, "closed?", rcdb_reader_closed_p, 0);
516
519
  rb_define_method(cCDBReader, "dump", rcdb_reader_dump, 0);
@@ -28,19 +28,28 @@
28
28
 
29
29
  #define RCDB_READER_DEFINE_READ(what) \
30
30
  static VALUE \
31
- rcdb_reader_read_##what(struct cdb *cdb) {\
32
- size_t len;\
33
- VALUE ret;\
31
+ rcdb_reader_read_##what(struct cdb *cdb, VALUE self) {\
32
+ size_t len = cdb_##what##len(cdb);\
33
+ VALUE val;\
34
34
  \
35
- len = cdb_##what##len(cdb);\
36
- ret = rb_str_buf_new(len);\
35
+ RCDB_READER_READ_POS(cdb_##what##pos(cdb))\
37
36
  \
38
- cdb_read(cdb, RSTRING_PTR(ret), len, cdb_##what##pos(cdb));\
39
- rb_str_set_len(ret, len);\
40
- \
41
- return ret;\
37
+ return val;\
42
38
  }
43
39
 
40
+ #define RCDB_READER_READ_POS(pos) \
41
+ val = rb_str_buf_new(len);\
42
+ \
43
+ cdb_read(cdb, RSTRING_PTR(val), len, pos);\
44
+ rb_str_set_len(val, len);\
45
+ \
46
+ rb_funcall(val, rb_intern("force_encoding"), 1, rb_iv_get(self, "@encoding"));
47
+
48
+ #define RCDB_READER_READ(what) rcdb_reader_read_##what(cdb, self)
49
+
50
+ #define RCDB_READER_STRING_LEN(str) \
51
+ rb_funcall(LONG2NUM(RSTRING_LEN(str)), rb_intern("to_s"), 0)
52
+
44
53
  extern VALUE cCDBReader;
45
54
  void rcdb_init_reader(void);
46
55
 
@@ -60,6 +60,8 @@ static void
60
60
  rcdb_writer_put_value(struct cdb_make *cdbm, VALUE key, VALUE val, enum cdb_put_mode mode) {
61
61
  long i;
62
62
 
63
+ StringValue(key);
64
+
63
65
  switch (TYPE(val)) {
64
66
  case T_ARRAY:
65
67
  switch (mode) {
@@ -132,8 +134,7 @@ rcdb_writer_put(int argc, VALUE *argv, VALUE self, enum cdb_put_mode mode) {
132
134
 
133
135
  break;
134
136
  case T_HASH:
135
- val = rb_ary_new();
136
- st_foreach(RHASH_TBL(arg), rcdb_writer_push_pair, val);
137
+ rb_hash_foreach(arg, rcdb_writer_push_pair, val = rb_ary_new());
137
138
 
138
139
  for (i = 0; i < RARRAY_LEN(val); i++) {
139
140
  tmp = rb_ary_entry(val, i);
@@ -1,6 +1,7 @@
1
1
  begin
2
2
  require "libcdb/#{RUBY_VERSION[/\d+.\d+/]}/libcdb_ruby"
3
- rescue LoadError
3
+ rescue LoadError => err
4
+ raise if err.respond_to?(:path) && !err.path
4
5
  require 'libcdb/libcdb_ruby'
5
6
  end
6
7
 
@@ -86,6 +87,116 @@ module LibCDB
86
87
  }
87
88
  end
88
89
 
90
+ # call-seq:
91
+ # CDB.load(path, dump) -> aCDB
92
+ #
93
+ # Opens +path+ for writing and loads +dump+ into the database. +dump+
94
+ # may be a string or an IO object. Returns the (unclosed) CDB object.
95
+ def load(path, dump)
96
+ require 'strscan'
97
+
98
+ s, n, e = nil, 0, lambda { |m| s.eos? ?
99
+ raise("Unexpected end of input (#{m} at #{n}).") :
100
+ raise("#{m} at #{n}:#{s.pos}: #{s.peek(16).inspect}") }
101
+
102
+ cdb = open(path, 'w+')
103
+
104
+ dump.each_line { |line|
105
+ n += 1
106
+
107
+ s = StringScanner.new(line)
108
+
109
+ e['Record identifier expected'] unless s.scan(/\+/)
110
+
111
+ e['Key length expected'] unless s.scan(/\d+/)
112
+ klen = s.matched.to_i
113
+
114
+ e['Length separator expected'] unless s.scan(/,/)
115
+
116
+ e['Value length expected'] unless s.scan(/\d+/)
117
+ vlen = s.matched.to_i
118
+
119
+ e['Key separator expected'] unless s.scan(/:/)
120
+
121
+ key = ''
122
+ klen.times { key << s.get_byte }
123
+
124
+ e['Value separator expected'] unless s.scan(/->/)
125
+
126
+ value = ''
127
+ vlen.times { value << s.get_byte }
128
+
129
+ e['Record terminator expected'] unless s.scan(/\n/)
130
+ e['Unexpected data'] unless s.eos?
131
+
132
+ cdb.store(key, value)
133
+ }
134
+
135
+ cdb
136
+ end
137
+
138
+ # call-seq:
139
+ # CDB.load_file(path, file) -> aCDB
140
+ #
141
+ # Loads the dump at +file+ into the database at +path+ (see #load).
142
+ def load_file(path, file)
143
+ File.open(file, 'rb') { |f| self.load(path, f) }
144
+ end
145
+
146
+ # call-seq:
147
+ # CDB.stats(path) -> aHash
148
+ #
149
+ # Returns a hash with the stats on +path+.
150
+ def stats(path)
151
+ {}.tap { |stats| open(path) { |cdb|
152
+ stats[:records] = cnt = cdb.total
153
+
154
+ stats[:keys] = khash = { min: Float::INFINITY, avg: 0, max: 0 }
155
+ stats[:values] = vhash = khash.dup
156
+
157
+ stats[:hash] = Hash.new(0).update(distances: Hash.new([0, 0]))
158
+
159
+ khash[:min] = vhash[:min] = 0 and break if cnt.zero?
160
+
161
+ ktot, vtot, update = 0, 0, lambda { |h, s| s.bytesize.tap { |l|
162
+ h[:min] = l if l < h[:min]
163
+ h[:max] = l if l > h[:max]
164
+ } }
165
+
166
+ cdb.each_key { |k| ktot += update[khash, k] }
167
+ cdb.each_value { |v| vtot += update[vhash, v] }
168
+
169
+ khash[:avg] = (ktot + cnt / 2) / cnt
170
+ vhash[:avg] = (vtot + cnt / 2) / cnt
171
+
172
+ # TODO: hash table stats
173
+ } }
174
+ end
175
+
176
+ # call-seq:
177
+ # CDB.print_stats(path) -> aHash
178
+ #
179
+ # Prints the #stats on +path+.
180
+ def print_stats(path)
181
+ stats(path).tap { |s|
182
+ r, k, v, h = s.values_at(:records, :keys, :values, :hash)
183
+
184
+ v1, v2 = [:min, :avg, :max], [:tables, :entries, :collisions]
185
+
186
+ puts 'number of records: %d' % r
187
+ puts 'key min/avg/max length: %d/%d/%d' % k.values_at(*v1)
188
+ puts 'val min/avg/max length: %d/%d/%d' % v.values_at(*v1)
189
+ next # TODO: hash table stats
190
+ puts 'hash tables/entries/collisions: %d/%d/%d' % h.values_at(*v2)
191
+ puts 'hash table min/avg/max length: %d/%d/%d' % h.values_at(*v1)
192
+ puts 'hash table distances:'
193
+
194
+ d = h[:distances]
195
+ 0.upto(9) { |i| puts ' d%d: %6d %2d%%' % [i, *d[i]] }
196
+ puts ' >9: %6d %2d%%' % d[-1]
197
+ }
198
+ end
199
+
89
200
  private
90
201
 
91
202
  def _open_args(path, mode)
@@ -145,11 +256,11 @@ module LibCDB
145
256
  end
146
257
 
147
258
  def_delegators :reader, :[], :dump, :each, :each_dump, :each_key,
148
- :each_value, :empty?, :fetch, :fetch_all,
149
- :fetch_first, :fetch_last, :get, :has_key?,
150
- :has_value?, :include?, :key, :key?, :keys,
151
- :length, :member?, :rget, :size, :to_a,
152
- :to_h, :total, :value?, :values, :values_at
259
+ :each_value, :empty?, :encoding, :encoding=,
260
+ :fetch, :fetch_all, :fetch_first, :fetch_last,
261
+ :get, :has_key?, :has_value?, :include?, :key,
262
+ :key?, :keys, :length, :member?, :rget, :size,
263
+ :to_a, :to_h, :total, :value?, :values, :values_at
153
264
 
154
265
  def_delegators :writer, :<<, :[]=, :add, :insert, :replace, :store
155
266