critbit 0.5.0-java
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.
- 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
|