rufus-tokyo 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,322 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #++
23
+ #
24
+
25
+ #
26
+ # "made in Japan"
27
+ #
28
+ # jmettraux@gmail.com
29
+ #
30
+
31
+ require 'rufus/tokyo/hmethods'
32
+ require 'rufus/tokyo/cabinet/lib'
33
+
34
+
35
+ module Rufus::Tokyo
36
+
37
+ #
38
+ # A Tokyo Cabinet in-memory (tcutil.h) map
39
+ #
40
+ # http://tokyocabinet.sourceforge.net/spex-en.html#tcutilapi
41
+ #
42
+ class Map
43
+ include CabinetLibMixin
44
+ include HashMethods
45
+ include Enumerable
46
+
47
+ #
48
+ # Creates an empty instance of a Tokyo Cabinet in-memory map
49
+ #
50
+ # (It's OK to pass the pointer of a C map directly, this is in fact
51
+ # used in rufus/tokyo/table when retrieving entries)
52
+ #
53
+ def initialize (pointer = nil)
54
+ @map = pointer || lib.tcmapnew
55
+ end
56
+
57
+ #
58
+ # Inserts key/value pair
59
+ #
60
+ def []= (k, v)
61
+ lib.tcmapput2(m, k, v)
62
+ v
63
+ end
64
+
65
+ #
66
+ # Deletes an entry
67
+ #
68
+ def delete (k)
69
+ v = self[k]
70
+ return nil unless v
71
+ (lib.tcmapout2(m, k) == 1) || raise("failed to remove key '#{k}'")
72
+ v
73
+ end
74
+
75
+ #
76
+ # Empties the map
77
+ #
78
+ def clear
79
+ lib.tcmapclear(m)
80
+ end
81
+
82
+ #
83
+ # (the actual #[] method is provided by HashMethods)
84
+ #
85
+ def get (k)
86
+ m; lib.tcmapget2(m, k) rescue nil
87
+ end
88
+ protected :get
89
+
90
+ #
91
+ # Returns an array of all the keys in the map
92
+ #
93
+ def keys
94
+ a = []
95
+ lib.tcmapiterinit(m)
96
+ while (k = (lib.tcmapiternext2(m) rescue nil)); a << k; end
97
+ a
98
+ end
99
+
100
+ #
101
+ # Returns the count of entries in the map
102
+ #
103
+ def size
104
+ lib.tcmaprnum(m)
105
+ end
106
+
107
+ alias :length :size
108
+
109
+ #
110
+ # Frees the map (nukes it from memory)
111
+ #
112
+ def free
113
+ lib.tcmapdel(@map)
114
+ @map = nil
115
+ end
116
+
117
+ alias :destroy :free
118
+ alias :close :free
119
+
120
+ #
121
+ # Returns the pointer to the underlying Tokyo Cabinet map
122
+ #
123
+ def pointer
124
+ @map || raise('map got freed, cannot use anymore')
125
+ end
126
+
127
+ alias :m :pointer
128
+
129
+ #
130
+ # Turns a given Tokyo map structure into a Ruby Hash. By default
131
+ # (free = true) will dispose of the map before replying with the Ruby Hash.
132
+ #
133
+ def self.to_h (map_pointer, free = true)
134
+ m = self.new(map_pointer)
135
+ h = m.to_h
136
+ m.free if free
137
+ h
138
+ end
139
+
140
+ #
141
+ # Turns a Ruby hash into a Tokyo Cabinet Map and returns it
142
+ #
143
+ def self.from_h (h)
144
+ h.inject(Map.new) { |m, (k, v)| m[k] = v; m }
145
+ end
146
+ end
147
+
148
+ #
149
+ # A Tokyo Cabinet in-memory (tcutil.h) list
150
+ #
151
+ # http://tokyocabinet.sourceforge.net/spex-en.html#tcutilapi
152
+ #
153
+ class List
154
+ include CabinetLibMixin
155
+ include Enumerable
156
+
157
+ #
158
+ # Creates a new Tokyo Cabinet list.
159
+ #
160
+ # (by passing a list pointer, one can wrap an existing list pointer
161
+ # into a handy instance of this class)
162
+ #
163
+ def initialize (list_pointer = nil)
164
+ @list = list_pointer || lib.tclistnew
165
+ end
166
+
167
+ def << (s)
168
+ #raise 'cannot insert nils into Tokyo Cabinet lists' unless s
169
+ lib.tclistpush2(@list, s)
170
+ self
171
+ end
172
+
173
+ #
174
+ # Pushes an argument or a list of arguments to this list
175
+ #
176
+ def push (*args)
177
+ args.each { |a| self << a }
178
+ end
179
+
180
+ #
181
+ # Pops the last element in the list
182
+ #
183
+ def pop
184
+ lib.tclistpop2(@list) rescue nil
185
+ end
186
+
187
+ #
188
+ # Removes and returns the first element in a list
189
+ #
190
+ def shift
191
+ lib.tclistshift2(@list) rescue nil
192
+ end
193
+
194
+ #
195
+ # Inserts a string at the beginning of the list
196
+ #
197
+ def unshift (s)
198
+ lib.tclistunshift2(@list, s)
199
+ self
200
+ end
201
+
202
+ def []= (a, b, c=nil)
203
+
204
+ i, s = c.nil? ? [ a, b ] : [ [a, b], c ]
205
+
206
+ range = if i.is_a?(Range)
207
+ i
208
+ elsif i.is_a?(Array)
209
+ start, count = i
210
+ (start..start + count - 1)
211
+ else
212
+ [ i ]
213
+ end
214
+
215
+ range = norm(range)
216
+
217
+ values = s.is_a?(Array) ? s : [ s ]
218
+ # not "values = Array(s)"
219
+
220
+ range.each_with_index do |offset, index|
221
+ val = values[index]
222
+ if val
223
+ lib.tclistover2(@list, offset, val)
224
+ else
225
+ lib.tclistremove2(@list, values.size)
226
+ end
227
+ end
228
+
229
+ self
230
+ end
231
+
232
+ #
233
+ # Removes the value at a given index and returns the value
234
+ # (returns nil if no value available)
235
+ #
236
+ def delete_at (i)
237
+ lib.tclistremove2(@list, i)
238
+ end
239
+
240
+ def delete_if
241
+ # TODO
242
+ end
243
+
244
+ def slice
245
+ # TODO
246
+ end
247
+ def slice!
248
+ # TODO
249
+ end
250
+
251
+ #
252
+ # Returns the size of this Tokyo Cabinet list
253
+ #
254
+ def size
255
+ lib.tclistnum(@list)
256
+ end
257
+
258
+ alias :length :size
259
+
260
+ #
261
+ # The equivalent of Ruby Array#[]
262
+ #
263
+ def [] (i, count=nil)
264
+
265
+ return nil if (count != nil) && count < 1
266
+
267
+ len = self.size
268
+
269
+ range = if count.nil?
270
+ i.is_a?(Range) ? i : [i]
271
+ else
272
+ (i..i + count - 1)
273
+ end
274
+
275
+ r = norm(range).collect { |i| lib.tclistval2(@list, i) rescue nil }
276
+
277
+ range.first == range.last ? r.first : r
278
+ end
279
+
280
+ def clear
281
+ lib.tclistclear(@list)
282
+ end
283
+
284
+ def each
285
+ (0..self.size - 1).each { |i| yield self[i] }
286
+ end
287
+
288
+ #
289
+ # Turns this Tokyo Cabinet list into a Ruby array
290
+ #
291
+ def to_a
292
+ self.collect { |e| e }
293
+ end
294
+
295
+ #
296
+ # Closes (frees) this list
297
+ #
298
+ def close
299
+ lib.tclistdel(@list)
300
+ @list = nil
301
+ end
302
+
303
+ alias :free :close
304
+ alias :destroy :close
305
+
306
+ protected
307
+
308
+ #
309
+ # Makes sure this offset/range fits the size of the list
310
+ #
311
+ def norm (i)
312
+ l = self.length
313
+ case i
314
+ when Range then ((i.first % l)..(i.last % l))
315
+ when Array then [ i.first % l ]
316
+ else i % l
317
+ end
318
+ end
319
+
320
+ end
321
+ end
322
+
@@ -0,0 +1,71 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #++
23
+ #
24
+
25
+ #
26
+ # "made in Japan"
27
+ #
28
+ # jmettraux@gmail.com
29
+ #
30
+
31
+ require 'rufus/tokyo/base'
32
+
33
+
34
+ module Rufus::Tokyo
35
+
36
+ #
37
+ # The libtokyodystopia.so methods get bound to this module
38
+ #
39
+ module DystopiaLib #:nodoc#
40
+ extend FFI::Library
41
+
42
+ Rufus::Tokyo.generate_lib_mixin(self)
43
+ # module Rufus::Tokyo::DystopiaLibMixin
44
+
45
+ #
46
+ # find Tokyo Dystopia lib
47
+
48
+ paths = Array(ENV['TOKYO_DYSTOPIA_LIB'] || %w{
49
+ /opt/local/lib/libtokyodystopia.dylib
50
+ /usr/local/lib/libtokyodystopia.dylib
51
+ /usr/local/lib/libtokyodystopia.so
52
+ })
53
+
54
+ ffi_lib(paths.find { |path| File.exist?(path) })
55
+
56
+ #
57
+ # tcwdb functions
58
+ #
59
+ # http://tokyocabinet.sourceforge.net/dystopiadoc/#tcwdbapi
60
+
61
+ attach_function :tcwdbnew, [], :pointer
62
+
63
+ attach_function :tcwdbopen, [ :pointer, :string, :int ], :int
64
+ attach_function :tcwdbclose, [ :pointer ], :int
65
+
66
+ attach_function :tcwdbecode, [ :pointer ], :int
67
+
68
+ attach_function :tcwdbput2, [ :pointer, :int64, :string, :string ], :pointer
69
+ end
70
+ end
71
+
@@ -0,0 +1,87 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2009, John Mettraux, jmettraux@gmail.com
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+ #++
23
+ #
24
+
25
+ #
26
+ # "made in Japan"
27
+ #
28
+ # jmettraux@gmail.com
29
+ #
30
+
31
+ require 'rufus/tokyo/dystopia/lib'
32
+
33
+
34
+ module Rufus::Tokyo
35
+
36
+ class DystopianError < RuntimeError
37
+ def new (error_code)
38
+ super("tokyo dystopia error #{error_code}")
39
+ end
40
+ end
41
+
42
+ #
43
+ # Tokyo Dystopia words database.
44
+ #
45
+ # http://tokyocabinet.sourceforge.net/dystopiadoc/
46
+ #
47
+ class Words
48
+ include DystopiaLibMixin
49
+
50
+ #
51
+ # TODO : continue me
52
+ #
53
+
54
+ #
55
+ # Opens/create a Tokyo Dystopia words database.
56
+ #
57
+ def initialize (path, opts={})
58
+
59
+ # tcwdb.h :
60
+ #
61
+ # enum { /* enumeration for open modes */
62
+ # WDBOREADER = 1 << 0, /* open as a reader */
63
+ # WDBOWRITER = 1 << 1, /* open as a writer */
64
+ # WDBOCREAT = 1 << 2, /* writer creating */
65
+ # WDBOTRUNC = 1 << 3, /* writer truncating */
66
+ # WDBONOLCK = 1 << 4, /* open without locking */
67
+ # WDBOLCKNB = 1 << 5 /* lock without blocking */
68
+ # };
69
+
70
+ mode = 0
71
+
72
+ @db = lib.tcwdbnew
73
+
74
+ (lib.tcwdbopen(@db, path, mode) == 1) || raise_error
75
+ end
76
+
77
+ protected
78
+
79
+ #
80
+ # Raises a dystopian error (asks the db which one)
81
+ #
82
+ def raise_error
83
+ raise DystopianError.new(lib.tcwdbecode(@db))
84
+ end
85
+ end
86
+ end
87
+