critbit 0.5.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +23 -0
- data/README.md +153 -0
- data/Rakefile +46 -0
- data/config.rb +173 -0
- data/lib/critbit.rb +726 -0
- data/lib/env.rb +12 -0
- data/target/critbit.jar +0 -0
- data/test/crit.rb +6 -0
- data/test/test_critbit.rb +451 -0
- data/version.rb +2 -0
- metadata +121 -0
data/lib/env.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'java'
|
2
|
+
require_relative '../config.rb'
|
3
|
+
|
4
|
+
$CLASSPATH << "#{File.dirname(__FILE__)}/../vendor/"
|
5
|
+
|
6
|
+
Dir["#{File.dirname(__FILE__)}/../vendor/*.jar"].each do |jar|
|
7
|
+
require jar
|
8
|
+
end
|
9
|
+
|
10
|
+
Dir["#{File.dirname(__FILE__)}/../target/*.jar"].each do |jar|
|
11
|
+
require jar
|
12
|
+
end
|
data/target/critbit.jar
ADDED
Binary file
|
data/test/crit.rb
ADDED
@@ -0,0 +1,451 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
##########################################################################################
|
4
|
+
# Copyright © 2013 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
|
5
|
+
# and distribute this software and its documentation for educational, research, and
|
6
|
+
# not-for-profit purposes, without fee and without a signed licensing agreement, is hereby
|
7
|
+
# granted, provided that the above copyright notice, this paragraph and the following two
|
8
|
+
# paragraphs appear in all copies, modifications, and distributions. Contact Rodrigo
|
9
|
+
# Botafogo - rodrigo.a.botafogo@gmail.com for commercial licensing opportunities.
|
10
|
+
#
|
11
|
+
# IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
12
|
+
# INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
|
13
|
+
# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
|
14
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
15
|
+
#
|
16
|
+
# RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
17
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
18
|
+
# SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
19
|
+
# RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
|
20
|
+
# OR MODIFICATIONS.
|
21
|
+
##########################################################################################
|
22
|
+
|
23
|
+
require 'rubygems'
|
24
|
+
require 'test/unit'
|
25
|
+
require 'shoulda'
|
26
|
+
|
27
|
+
require_relative '../config'
|
28
|
+
|
29
|
+
require 'critbit'
|
30
|
+
|
31
|
+
class CritbitTest < Test::Unit::TestCase
|
32
|
+
|
33
|
+
context "Critbit test" do
|
34
|
+
|
35
|
+
setup do
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
#-------------------------------------------------------------------------------------
|
40
|
+
#
|
41
|
+
#-------------------------------------------------------------------------------------
|
42
|
+
|
43
|
+
should "create Critbit from array notation" do
|
44
|
+
|
45
|
+
# Associates "a" to 1, "b" to 2, etc...
|
46
|
+
crit = Critbit["a", 1, "b", 2, "c", 3, "d", 4]
|
47
|
+
|
48
|
+
# Critbit will have the same contente as the given hash
|
49
|
+
crit2 = Critbit["a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5]
|
50
|
+
|
51
|
+
# Create a Cribit from another Critbit, this will do a copy
|
52
|
+
crit3 = Critbit[crit]
|
53
|
+
|
54
|
+
# Uses the given associations
|
55
|
+
crit4 = Critbit[[["a", 1], ["b", 2], ["c", 3], ["d", 4], ["e", 5], ["f", 6]]]
|
56
|
+
|
57
|
+
# This is an error... ["f"] is an illegal argumento to a Critbit
|
58
|
+
assert_raise ( RuntimeError ) { Critbit[[["a", 1], ["b", 2], ["c", 3], ["d", 4],
|
59
|
+
["e", 5], ["f"]]] }
|
60
|
+
# This is an error, since there are only 3 elements on the given array.
|
61
|
+
assert_raise ( RuntimeError ) { Critbit["a", 1, 2] }
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
#-------------------------------------------------------------------------------------
|
66
|
+
#
|
67
|
+
#-------------------------------------------------------------------------------------
|
68
|
+
|
69
|
+
should "delete_if block is true" do
|
70
|
+
|
71
|
+
crit = Critbit.new
|
72
|
+
|
73
|
+
# crit is space efficient and stores prefixes only once and can be used to
|
74
|
+
# find only strings that match a certain prefix
|
75
|
+
items = ["u", "un", "unine", "uni", "unindd", "unj", "unim", "unin", "unio",
|
76
|
+
"uninde", "uninc", "unind", "unh", "unindf",
|
77
|
+
"unindew", "unindex", "unindey", "a", "z"]
|
78
|
+
|
79
|
+
# add items to the container
|
80
|
+
items.each do |item|
|
81
|
+
crit[item] = item
|
82
|
+
end
|
83
|
+
|
84
|
+
# remove all elements with key > "unind"
|
85
|
+
crit.delete_if { |key, val| key > "unind" }
|
86
|
+
|
87
|
+
# those are the elements left
|
88
|
+
ok = ["u", "un", "uni", "unim", "unin", "unind", "unh", "a"]
|
89
|
+
|
90
|
+
ok.each do |item|
|
91
|
+
assert_equal(true, crit.has_key?(item))
|
92
|
+
end
|
93
|
+
|
94
|
+
# add the items to the container again
|
95
|
+
items.each do |item|
|
96
|
+
crit[item] = item
|
97
|
+
end
|
98
|
+
|
99
|
+
crit.delete_if { |key, val| val > "unind" }
|
100
|
+
ok.each do |item|
|
101
|
+
assert_equal(true, crit.has_key?(item))
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
#-------------------------------------------------------------------------------------
|
107
|
+
#
|
108
|
+
#-------------------------------------------------------------------------------------
|
109
|
+
|
110
|
+
should "keep_if block is true" do
|
111
|
+
|
112
|
+
crit = Critbit.new
|
113
|
+
|
114
|
+
# crit is space efficient and stores prefixes only once and can be used to
|
115
|
+
# find only strings that match a certain prefix
|
116
|
+
items = ["u", "un", "unine", "uni", "unindd", "unj", "unim", "unin", "unio",
|
117
|
+
"uninde", "uninc", "unind", "unh", "unindf",
|
118
|
+
"unindew", "unindex", "unindey", "a", "z"]
|
119
|
+
|
120
|
+
# add items to the container
|
121
|
+
items.each do |item|
|
122
|
+
crit[item] = item
|
123
|
+
end
|
124
|
+
|
125
|
+
# remove all elements with key > "unind"
|
126
|
+
crit.keep_if { |key, val| key > "unind" }
|
127
|
+
|
128
|
+
# those are the elements left
|
129
|
+
ok = ["unindd", "uninde", "unindf", "unine", "unio", "unindew", "unindex", "unj",
|
130
|
+
"unindey", "z" ]
|
131
|
+
|
132
|
+
ok.each do |item|
|
133
|
+
assert_equal(true, crit.has_key?(item))
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
#-------------------------------------------------------------------------------------
|
139
|
+
#
|
140
|
+
#-------------------------------------------------------------------------------------
|
141
|
+
|
142
|
+
should "return enumerator from each without block" do
|
143
|
+
|
144
|
+
crit = Critbit.new
|
145
|
+
|
146
|
+
# crit is space efficient and stores prefixes only once and can be used to
|
147
|
+
# find only strings that match a certain prefix
|
148
|
+
items = ["u", "un", "unine", "uni", "unindd", "unj", "unim", "unin", "unio",
|
149
|
+
"uninde", "uninc", "unind", "unh", "unindf",
|
150
|
+
"unindew", "unindex", "unindey", "a", "z"]
|
151
|
+
|
152
|
+
# add items to the container
|
153
|
+
items.each do |item|
|
154
|
+
crit[item] = item
|
155
|
+
end
|
156
|
+
|
157
|
+
# Enumerator
|
158
|
+
e = crit.each
|
159
|
+
assert_equal("a", e.next[0])
|
160
|
+
assert_equal("u", e.next[0])
|
161
|
+
|
162
|
+
# Enumerator with prefix
|
163
|
+
e = crit.each("unind")
|
164
|
+
assert_equal("unind", e.next[0])
|
165
|
+
assert_equal("unindd", e.next[0])
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
#-------------------------------------------------------------------------------------
|
170
|
+
#
|
171
|
+
#-------------------------------------------------------------------------------------
|
172
|
+
|
173
|
+
should "merge critbits" do
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
h1 = Critbit["a" => 100, "b" => 200]
|
178
|
+
h2 = Critbit["b" => 254, "c" => 300]
|
179
|
+
h3 = Critbit["b" => 100, "d" => 1001, "e" => 398]
|
180
|
+
|
181
|
+
n = h1.merge(h2) #=> {"a"=>100, "b"=>254, "c"=>300}
|
182
|
+
n = h1.merge(h2){|key, oldval, newval| newval - oldval} #=> {"a"=>100, "b"=>54, "c"=>300}
|
183
|
+
|
184
|
+
h1.merge!(h2)
|
185
|
+
p h1
|
186
|
+
p h1.rassoc(254)
|
187
|
+
p h1.rassoc(300)
|
188
|
+
p h1.rassoc(1000)
|
189
|
+
|
190
|
+
h1.merge!(h2) { |key, oldval, newval| newval - oldval }
|
191
|
+
p h1
|
192
|
+
|
193
|
+
# put_all is similar to merge, but should be significantly faster than merge for
|
194
|
+
# larger critbits and it does not allow any control for duplicate keys. If there
|
195
|
+
# are duplicate keys, then the value of the second critbit will be kept.
|
196
|
+
h1.put_all(h3)
|
197
|
+
p h1
|
198
|
+
|
199
|
+
p h1.remove("a")
|
200
|
+
p h1.remove("z")
|
201
|
+
p h1
|
202
|
+
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
#-------------------------------------------------------------------------------------
|
207
|
+
#
|
208
|
+
#-------------------------------------------------------------------------------------
|
209
|
+
|
210
|
+
should "create critbit with default values" do
|
211
|
+
|
212
|
+
# Create a new Critbit with a default_proc. Default proc is called whenever a
|
213
|
+
# key is searched and not found in the Critbit. In this example, if we try to
|
214
|
+
# access a non-existing key, the key will be added with value NaN (not a number)
|
215
|
+
# Default_proc accepts three arguments: critbit (the container), key, value
|
216
|
+
|
217
|
+
crit = Critbit.new { |h, k, val| h[k] = 0.0/0.0 }
|
218
|
+
assert_equal(0, crit.size)
|
219
|
+
|
220
|
+
# Since there is a default_proc, this will be called whenever the key is not present
|
221
|
+
# in the container. "null" is not a key, checking for crit["null"] will add the key
|
222
|
+
# with the default NaN (0.0/0.0) value.
|
223
|
+
assert_equal(true, crit["null"].nan?)
|
224
|
+
|
225
|
+
# The size of the repository is now 1 since the key "null" was added.
|
226
|
+
assert_equal(1, crit.size)
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
#-------------------------------------------------------------------------------------
|
231
|
+
#
|
232
|
+
#-------------------------------------------------------------------------------------
|
233
|
+
|
234
|
+
should "use Critbit as Hash" do
|
235
|
+
|
236
|
+
crit = Critbit.new
|
237
|
+
|
238
|
+
# add some key, value pairs to crit
|
239
|
+
crit["hello"] = 0
|
240
|
+
crit["there"] = 1
|
241
|
+
crit["essa"] = 10
|
242
|
+
crit["Essa é uma frase para armazenar"] = 100
|
243
|
+
assert_equal(4, crit.size)
|
244
|
+
assert_equal(0, crit["hello"])
|
245
|
+
assert_equal(1, crit["there"])
|
246
|
+
assert_equal(100, crit["Essa é uma frase para armazenar"])
|
247
|
+
|
248
|
+
# fetch the key from crit
|
249
|
+
assert_equal(0, crit.fetch("hello"))
|
250
|
+
|
251
|
+
# remove a key, value pair from crit. Given the key it will return the value and
|
252
|
+
# remove the entry
|
253
|
+
assert_equal(0, crit.delete("hello"))
|
254
|
+
assert_equal(3, crit.size)
|
255
|
+
assert_equal(nil, crit["hello"])
|
256
|
+
crit.delete("not there") { |k| p "#{k} is not there" }
|
257
|
+
|
258
|
+
assert_raise ( KeyError ) { crit.fetch("hello") }
|
259
|
+
assert_equal("NotFound", crit.fetch("hello", "NotFound"))
|
260
|
+
|
261
|
+
# crit also accepts complex objects
|
262
|
+
crit["works?"] = [10, 20, 30]
|
263
|
+
assert_equal([10, 20, 30], crit["works?"])
|
264
|
+
assert_equal(["works?", [10, 20, 30]], crit.assoc("works?"))
|
265
|
+
|
266
|
+
# check if keys are stored in crit
|
267
|
+
assert_equal(true, crit.has_key?("there"))
|
268
|
+
assert_equal(false, crit.has_key?("Not there"))
|
269
|
+
|
270
|
+
# crit stores data in sorted order, so we can call min and max on crit
|
271
|
+
assert_equal(["Essa é uma frase para armazenar", 100], crit.min)
|
272
|
+
assert_equal(["works?", [10, 20, 30]], crit.max)
|
273
|
+
|
274
|
+
# crit also allows for checking value containment
|
275
|
+
assert_equal(true, crit.has_value?(100))
|
276
|
+
assert_equal(true, crit.has_value?([10, 20, 30]))
|
277
|
+
assert_equal(false, crit.has_value?("hello"))
|
278
|
+
|
279
|
+
# Critbit implements the each method, so all methods from Enumerable can be called
|
280
|
+
assert_equal([["Essa \u00E9 uma frase para armazenar", 100], ["essa", 10],
|
281
|
+
["there", 1], ["works?", [10, 20, 30]]], crit.entries)
|
282
|
+
|
283
|
+
# it is possible to change a value for a given key
|
284
|
+
crit["essa"] = 20
|
285
|
+
assert_equal([["Essa \u00E9 uma frase para armazenar", 100], ["essa", 20],
|
286
|
+
["there", 1], ["works?", [10, 20, 30]]], crit.entries)
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
#-------------------------------------------------------------------------------------
|
291
|
+
#
|
292
|
+
#-------------------------------------------------------------------------------------
|
293
|
+
|
294
|
+
should "use each with prefix" do
|
295
|
+
|
296
|
+
crit = Critbit.new
|
297
|
+
|
298
|
+
# crit is space efficient and stores prefixes only once and can be used to
|
299
|
+
# find only strings that match a certain prefix
|
300
|
+
items = ["u", "un", "unh", "uni", "unj", "unim", "unin", "unio",
|
301
|
+
"uninc", "unind", "unine", "unindd", "uninde", "unindf",
|
302
|
+
"unindew", "unindex", "unindey", "a", "z"]
|
303
|
+
|
304
|
+
# add items to the container
|
305
|
+
items.each do |item|
|
306
|
+
crit[item] = item
|
307
|
+
end
|
308
|
+
|
309
|
+
|
310
|
+
# Does each for all elements in the container
|
311
|
+
print "["
|
312
|
+
crit.each do |key, value|
|
313
|
+
print "[#{key}, #{value}] "
|
314
|
+
end
|
315
|
+
print "]"
|
316
|
+
|
317
|
+
p ""
|
318
|
+
# Does each for all elements in the critbit
|
319
|
+
print "["
|
320
|
+
crit.each("unin") do |key, value|
|
321
|
+
print "[#{key}, #{value}] "
|
322
|
+
end
|
323
|
+
print "]"
|
324
|
+
|
325
|
+
p ""
|
326
|
+
crit.prefix = "unin"
|
327
|
+
# Does each for all elements in the critbit
|
328
|
+
print "["
|
329
|
+
crit.each do |key, value|
|
330
|
+
print "[#{key}, #{value}] "
|
331
|
+
end
|
332
|
+
print "]"
|
333
|
+
|
334
|
+
|
335
|
+
# Does each for all elements in the container
|
336
|
+
crit.each do |key, value|
|
337
|
+
assert_equal(value, crit[key])
|
338
|
+
end
|
339
|
+
|
340
|
+
# Each can also filter by prefix. Let's try prefix unin
|
341
|
+
pre = ["unin", "uninc", "unind", "unine", "unindd", "uninde", "unindf",
|
342
|
+
"unindew", "unindex", "unindey"]
|
343
|
+
crit.each("unin") do |key, value|
|
344
|
+
assert_equal(true, pre.include?(key))
|
345
|
+
end
|
346
|
+
|
347
|
+
# Those are not prefixed by unin
|
348
|
+
flse = ["u", "un", "unh", "uni", "unj", "unim", "unio", "a", "z"]
|
349
|
+
crit.each_pair("unin") do |key, value|
|
350
|
+
assert_equal(false, flse.include?(key))
|
351
|
+
end
|
352
|
+
|
353
|
+
# Using unind as prefix...
|
354
|
+
pre = ["unind", "unindd", "uninde", "unindf", "unindew", "unindex", "unindey"]
|
355
|
+
crit.each("unind") do |key, value|
|
356
|
+
assert_equal(true, pre.include?(key))
|
357
|
+
end
|
358
|
+
|
359
|
+
# sets the crit prefix. From now on, only keys with prefix "unin" will be retrieved
|
360
|
+
# even when the prefix is not part of the parameter list as above
|
361
|
+
crit.prefix = "unin"
|
362
|
+
|
363
|
+
# all unin prefix should be retrieved
|
364
|
+
pre = ["unin", "uninc", "unind", "unine", "unindd", "uninde", "unindf",
|
365
|
+
"unindew", "unindex", "unindey"]
|
366
|
+
crit.each do |key, value|
|
367
|
+
assert_equal(true, pre.include?(key))
|
368
|
+
end
|
369
|
+
|
370
|
+
# all keys that do not have a unin prefix are not retrieved
|
371
|
+
flse = ["u", "un", "unh", "uni", "unj", "unim", "unio", "a", "z"]
|
372
|
+
crit.each do |key, value|
|
373
|
+
assert_equal(false, flse.include?(key))
|
374
|
+
end
|
375
|
+
|
376
|
+
assert_equal([["unin", "unin"], ["uninc", "uninc"], ["unind", "unind"],
|
377
|
+
["unindd", "unindd"], ["uninde", "uninde"], ["unindew", "unindew"],
|
378
|
+
["unindex", "unindex"], ["unindey", "unindey"], ["unindf", "unindf"],
|
379
|
+
["unine", "unine"]], crit.entries)
|
380
|
+
|
381
|
+
=begin
|
382
|
+
p crit.keys
|
383
|
+
p crit.values
|
384
|
+
p crit.values("unin")
|
385
|
+
crit.clear
|
386
|
+
p crit.values
|
387
|
+
=end
|
388
|
+
|
389
|
+
end
|
390
|
+
|
391
|
+
#-------------------------------------------------------------------------------------
|
392
|
+
#
|
393
|
+
#-------------------------------------------------------------------------------------
|
394
|
+
|
395
|
+
should "compare two critbits" do
|
396
|
+
|
397
|
+
crit = Critbit.new
|
398
|
+
|
399
|
+
# crit is space efficient and stores prefixes only once and can be used to
|
400
|
+
# find only strings that match a certain prefix
|
401
|
+
items = ["u", "un", "unh", "uni", "unj", "unim", "unin", "unio",
|
402
|
+
"uninc", "unind", "unine", "unindd", "uninde", "unindf",
|
403
|
+
"unindew", "unindex", "unindey", "a", "z"]
|
404
|
+
|
405
|
+
# add items to the container
|
406
|
+
items.each do |item|
|
407
|
+
crit[item] = item
|
408
|
+
end
|
409
|
+
|
410
|
+
# Create a second critbit with the same content as crit
|
411
|
+
crit2 = Critbit[crit]
|
412
|
+
# they have the same elements
|
413
|
+
assert_equal(true, crit.eql?(crit2))
|
414
|
+
|
415
|
+
# If the prefix is set on a critbit, only keys with the given prefix will be
|
416
|
+
# checkd and eql? will return false
|
417
|
+
crit.prefix = "u"
|
418
|
+
assert_equal(false, crit.eql?(crit2))
|
419
|
+
|
420
|
+
# again both crit and crit2 are equal
|
421
|
+
crit2.prefix = "u"
|
422
|
+
assert_equal(true, crit.eql?(crit2))
|
423
|
+
|
424
|
+
# remove the crit prefix
|
425
|
+
crit.prefix = nil
|
426
|
+
|
427
|
+
# create crit3 that is different from crit
|
428
|
+
crit3 = Critbit.new
|
429
|
+
it2 = ["u", "un", "unh", "uni", "unj", "unim", "unin", "unio",
|
430
|
+
"uninc", "unind", "unine", "unindd", "uninde", "unindf",
|
431
|
+
"unindew", "unindex", "unindey"]
|
432
|
+
|
433
|
+
# add items to the container
|
434
|
+
it2.each do |item|
|
435
|
+
crit3[item] = item
|
436
|
+
end
|
437
|
+
|
438
|
+
# crit and crit3 are not eql?
|
439
|
+
assert_equal(false, crit.eql?(crit2))
|
440
|
+
assert_equal(false, crit2.eql?(crit))
|
441
|
+
|
442
|
+
# but crit3 is a subset of crit with only prefix "u", so now crit and crit3
|
443
|
+
# are eql?
|
444
|
+
crit.prefix = "u"
|
445
|
+
assert_equal(true, crit.eql?(crit3))
|
446
|
+
|
447
|
+
end
|
448
|
+
|
449
|
+
end
|
450
|
+
|
451
|
+
end
|