reedb 0.10.rc1

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.
@@ -0,0 +1,49 @@
1
+ # ====================================================
2
+ # Copyright 2015 Lonely Robot (see @author)
3
+ # @author: Katharina Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 3
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ # Implements a rather neat and quick heapsort algorithm to sort values for database output.
11
+ #
12
+ class Array
13
+
14
+ # Heapsorts a douplicate instance and leaves the original alone.
15
+ #
16
+ def heapsort
17
+ self.dup.heapsort!
18
+ end
19
+
20
+ # Heapsorts that array instance.
21
+ #
22
+ def heapsort!
23
+ # Heapify the array!
24
+ ((length - 2) / 2).downto(0) {|first| siftdown(first, length - 1)}
25
+
26
+ (length - 1).downto(1) do |last|
27
+ self[last], self[0] = self[0], self[last]
28
+ siftdown(0, last - 1)
29
+ end
30
+ self
31
+ end
32
+
33
+ def siftdown(first, last)
34
+ root = first
35
+ loop do
36
+ child = root * 2 + 1
37
+ break if child > last
38
+ if child + 1 <= last and self[child] < self[child + 1]
39
+ child += 1
40
+ end
41
+ if self[root] < self[child]
42
+ self[root], self[child] = self[child], self[root]
43
+ root = child
44
+ else
45
+ break
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,121 @@
1
+ # ====================================================
2
+ # Copyright 2015 Lonely Robot (see @author)
3
+ # @author: Katharina Sabel | www.2rsoftworks.de
4
+ #
5
+ # Distributed under the GNU Lesser GPL Version 3
6
+ # (See accompanying LICENSE file or get a copy at
7
+ # https://www.gnu.org/licenses/lgpl.html)
8
+ # ====================================================
9
+
10
+ require 'socket'
11
+
12
+ module Reedb
13
+
14
+ class Timestamp
15
+ attr_accessor :utc
16
+ def initialize
17
+ @utc = Time.now.getutc
18
+ end
19
+
20
+ def < x
21
+ return (self.utc < x.utc)
22
+ end
23
+
24
+ def > x
25
+ return (self.utc > x.utc)
26
+ end
27
+
28
+ def == x
29
+ return (self.utc == x.utc)
30
+ end
31
+
32
+ def to_s
33
+ return "#{@utc}"
34
+ end
35
+ end
36
+
37
+ class Utilities
38
+
39
+ # Takes version string and increments it by 1. Does patch-minor and minor-major steps
40
+ # TODO: Replace this with a RegEx to split the version string at the dots, and analise it's sub-elements.
41
+ def self.increment_version(version)
42
+ # <b>DEPRECATED:</b> Please use <tt>Version class</tt> instead.
43
+ warn "[DEPRECIATED] `increment_version` is depreciated. Please use Version class instead."
44
+
45
+ if version?(version) # Checks if it actually is version
46
+ i = version[2].to_i
47
+
48
+ tmp = version
49
+
50
+ if i < 9
51
+ i += 1
52
+ tmp = version[0] + "." + i.to_s
53
+
54
+ elsif i >= 9
55
+ i = version[0].to_i
56
+ i += 1
57
+ tmp = i.to_s + "." + "0".to_s
58
+ end
59
+
60
+ return tmp
61
+ end
62
+ end
63
+
64
+ # Normalises name to have the first letter be capital
65
+ def self.capitalise_first(string)
66
+ string[0].upcase + string.slice(1..-1)
67
+ end
68
+
69
+ #
70
+ # Returns if the provided string is actually a version string.
71
+ #
72
+ #
73
+ # => I love you Ashley, stop looking in my source :')
74
+ # TODO: Use RegEx to scan through ENTIRE string, not just mayor and minor version
75
+ def self.version?(version)
76
+ def is_i?(i)
77
+ i.to_i.to_s == i
78
+ end
79
+ is_i?(version[0]) and is_i?(version[2]) ? true : false
80
+ end
81
+
82
+ # Fix the actual inputs (aka test on virtual machines)
83
+ def self.parse_os
84
+ platform = RUBY_PLATFORM
85
+ if platform.end_with?("linux")
86
+ return :linux
87
+ elsif platform.end_with?("Windows")
88
+ return :win
89
+ elsif platform.end_with?("Mac OS X")
90
+ return :osx
91
+ end
92
+ end
93
+
94
+ def self.parse_host
95
+ return "#{Socket.gethostname}"
96
+ end
97
+
98
+ # Returns user currently logged in. Not sure for what that will be used but hey!
99
+ #
100
+ def self.parse_user
101
+ if parse_os == :win
102
+ return ENV['USERNAME']
103
+ else
104
+ return ENV['USER']
105
+ end
106
+ end
107
+
108
+ def self.get_time(only_date = false)
109
+ time = Time.now
110
+ val_h = "#{time.year}-#{'%02d' % time.month}-#{'%02d' % time.day}"
111
+ val_t = "#{time.hour}:#{'%02d' % time.min}:#{'%02d' % time.sec}"
112
+
113
+ # => TODO: Make this more Ruby-Like
114
+ if only_date
115
+ return "#{val_h}"
116
+ else
117
+ return "[#{val_h} #{val_t}]"
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,375 @@
1
+ #!/usr/bin/env ruby
2
+ ### http://mput.dip.jp/mput/uuid.txt
3
+
4
+ # Copyright(c) 2005 URABE, Shyouhei.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this code, to deal in the code without restriction, including without
8
+ # limitation the rights to use, copy, modify, merge, publish, distribute,
9
+ # sublicense, and/or sell copies of the code, and to permit persons to whom the
10
+ # code is furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the code.
14
+ #
15
+ # THE CODE 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
+ # AUTHOR OR COPYRIGHT HOLDER 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 CODE OR THE USE OR OTHER DEALINGS IN THE
21
+ # CODE.
22
+ #
23
+ # 2009-02-20: Modified by Pablo Lorenzoni <pablo@propus.com.br> to correctly
24
+ # include the version in the raw_bytes.
25
+
26
+
27
+ require 'digest/md5'
28
+ require 'digest/sha1'
29
+ require 'tmpdir'
30
+
31
+ # Pure ruby UUID generator, which is compatible with RFC4122
32
+ UUID = Struct.new :raw_bytes
33
+
34
+ class UUID
35
+ private_class_method :new
36
+
37
+ class << self
38
+ def mask19 v, str # :nodoc
39
+ nstr = str.bytes.to_a
40
+ version = [0, 16, 32, 48, 64, 80][v]
41
+ nstr[6] &= 0b00001111
42
+ nstr[6] |= version
43
+ # nstr[7] &= 0b00001111
44
+ # nstr[7] |= 0b01010000
45
+ nstr[8] &= 0b00111111
46
+ nstr[8] |= 0b10000000
47
+ str = ''
48
+ nstr.each { |s| str << s.chr }
49
+ str
50
+ end
51
+
52
+ def mask18 v, str # :nodoc
53
+ version = [0, 16, 32, 48, 64, 80][v]
54
+ str[6] &= 0b00001111
55
+ str[6] |= version
56
+ # str[7] &= 0b00001111
57
+ # str[7] |= 0b01010000
58
+ str[8] &= 0b00111111
59
+ str[8] |= 0b10000000
60
+ str
61
+ end
62
+
63
+ def mask v, str
64
+ if RUBY_VERSION >= "1.9.0"
65
+ return mask19 v, str
66
+ else
67
+ return mask18 v, str
68
+ end
69
+ end
70
+ private :mask, :mask18, :mask19
71
+
72
+ # UUID generation using SHA1. Recommended over create_md5.
73
+ # Namespace object is another UUID, some of them are pre-defined below.
74
+ def create_sha1 str, namespace
75
+ sha1 = Digest::SHA1.new
76
+ sha1.update namespace.raw_bytes
77
+ sha1.update str
78
+ sum = sha1.digest
79
+ raw = mask 5, sum[0..15]
80
+ ret = new raw
81
+ ret.freeze
82
+ ret
83
+ end
84
+ alias :create_v5 :create_sha1
85
+
86
+ # UUID generation using MD5 (for backward compat.)
87
+ def create_md5 str, namespace
88
+ md5 = Digest::MD5.new
89
+ md5.update namespace.raw_bytes
90
+ md5.update str
91
+ sum = md5.digest
92
+ raw = mask 3, sum[0..16]
93
+ ret = new raw
94
+ ret.freeze
95
+ ret
96
+ end
97
+ alias :create_v3 :create_md5
98
+
99
+ # UUID generation using random-number generator. From it's random
100
+ # nature, there's no warranty that the created ID is really universaly
101
+ # unique.
102
+ def create_random
103
+ rnd = [
104
+ rand(0x100000000),
105
+ rand(0x100000000),
106
+ rand(0x100000000),
107
+ rand(0x100000000),
108
+ ].pack "N4"
109
+ raw = mask 4, rnd
110
+ ret = new raw
111
+ ret.freeze
112
+ ret
113
+ end
114
+ alias :create_v4 :create_random
115
+
116
+ def read_state fp # :nodoc:
117
+ fp.rewind
118
+ Marshal.load fp.read
119
+ end
120
+
121
+ def write_state fp, c, m # :nodoc:
122
+ fp.rewind
123
+ str = Marshal.dump [c, m]
124
+ fp.write str
125
+ end
126
+
127
+ private :read_state, :write_state
128
+ STATE_FILE = 'ruby-uuid'
129
+
130
+ # create the "version 1" UUID with current system clock, current UTC
131
+ # timestamp, and the IEEE 802 address (so-called MAC address).
132
+ #
133
+ # Speed notice: it's slow. It writes some data into hard drive on every
134
+ # invokation. If you want to speed this up, try remounting tmpdir with a
135
+ # memory based filesystem (such as tmpfs). STILL slow? then no way but
136
+ # rewrite it with c :)
137
+ def create clock=nil, time=nil, mac_addr=nil
138
+ c = t = m = nil
139
+ Dir.chdir Dir.tmpdir do
140
+ unless FileTest.exist? STATE_FILE then
141
+ # Generate a pseudo MAC address because we have no pure-ruby way
142
+ # to know the MAC address of the NIC this system uses. Note
143
+ # that cheating with pseudo arresses here is completely legal:
144
+ # see Section 4.5 of RFC4122 for details.
145
+ sha1 = Digest::SHA1.new
146
+ 256.times do
147
+ r = [rand(0x100000000)].pack "N"
148
+ sha1.update r
149
+ end
150
+ str = sha1.digest
151
+ r = rand 14 # 20-6
152
+ node = str[r, 6] || str
153
+ if RUBY_VERSION >= "1.9.0"
154
+ nnode = node.bytes.to_a
155
+ nnode[0] |= 0x01
156
+ node = ''
157
+ nnode.each { |s| node << s.chr }
158
+ else
159
+ node[0] |= 0x01 # multicast bit
160
+ end
161
+ k = rand 0x40000
162
+ open STATE_FILE, 'w' do |fp|
163
+ fp.flock IO::LOCK_EX
164
+ write_state fp, k, node
165
+ fp.chmod 0o777 # must be world writable
166
+ end
167
+ end
168
+ open STATE_FILE, 'r+' do |fp|
169
+ fp.flock IO::LOCK_EX
170
+ c, m = read_state fp
171
+ c = clock % 0x4000 if clock
172
+ m = mac_addr if mac_addr
173
+ t = time
174
+ if t.nil? then
175
+ # UUID epoch is 1582/Oct/15
176
+ tt = Time.now
177
+ t = tt.to_i*10000000 + tt.tv_usec*10 + 0x01B21DD213814000
178
+ end
179
+ c = c.succ # important; increment here
180
+ write_state fp, c, m
181
+ end
182
+ end
183
+
184
+ tl = t & 0xFFFF_FFFF
185
+ tm = t >> 32
186
+ tm = tm & 0xFFFF
187
+ th = t >> 48
188
+ th = th & 0x0FFF
189
+ th = th | 0x1000
190
+ cl = c & 0xFF
191
+ ch = c & 0x3F00
192
+ ch = ch >> 8
193
+ ch = ch | 0x80
194
+ pack tl, tm, th, cl, ch, m
195
+ end
196
+ alias :create_v1 :create
197
+
198
+ # A simple GUID parser: just ignores unknown characters and convert
199
+ # hexadecimal dump into 16-octet object.
200
+ def parse obj
201
+ str = obj.to_s.sub %r/\Aurn:uuid:/, ''
202
+ str.gsub! %r/[^0-9A-Fa-f]/, ''
203
+ raw = str[0..31].lines.to_a.pack 'H*'
204
+ ret = new raw
205
+ ret.freeze
206
+ ret
207
+ end
208
+
209
+ # The 'primitive constructor' of this class
210
+ # Note UUID.pack(uuid.unpack) == uuid
211
+ def pack tl, tm, th, ch, cl, n
212
+ raw = [tl, tm, th, ch, cl, n].pack "NnnCCa6"
213
+ ret = new raw
214
+ ret.freeze
215
+ ret
216
+ end
217
+ end
218
+
219
+ # The 'primitive deconstructor', or the dual to pack.
220
+ # Note UUID.pack(uuid.unpack) == uuid
221
+ def unpack
222
+ raw_bytes.unpack "NnnCCa6"
223
+ end
224
+
225
+ # Generate the string representation (a.k.a GUID) of this UUID
226
+ def to_s
227
+ a = unpack
228
+ tmp = a[-1].unpack 'C*'
229
+ a[-1] = sprintf '%02x%02x%02x%02x%02x%02x', *tmp
230
+ "%08x-%04x-%04x-%02x%02x-%s" % a
231
+ end
232
+ alias guid to_s
233
+
234
+ # Convert into a RFC4122-comforming URN representation
235
+ def to_uri
236
+ "urn:uuid:" + self.to_s
237
+ end
238
+ alias urn to_uri
239
+
240
+ # Convert into 128-bit unsigned integer
241
+ # Typically a Bignum instance, but can be a Fixnum.
242
+ def to_int
243
+ tmp = self.raw_bytes.unpack "C*"
244
+ tmp.inject do |r, i|
245
+ r * 256 | i
246
+ end
247
+ end
248
+ alias to_i to_int
249
+
250
+ # Gets the version of this UUID
251
+ # returns nil if bad version
252
+ def version
253
+ a = unpack
254
+ v = (a[2] & 0xF000).to_s(16)[0].chr.to_i
255
+ return v if (1..5).include? v
256
+ return nil
257
+ end
258
+
259
+ # Two UUIDs are said to be equal if and only if their (byte-order
260
+ # canonicalized) integer representations are equivallent. Refer RFC4122 for
261
+ # details.
262
+ def == other
263
+ to_i == other.to_i
264
+ end
265
+
266
+ include Comparable
267
+ # UUIDs are comparable (don't know what benefits are there, though).
268
+ def <=> other
269
+ to_s <=> other.to_s
270
+ end
271
+
272
+ # Pre-defined UUID Namespaces described in RFC4122 Appendix C.
273
+ NameSpace_DNS = parse "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
274
+ NameSpace_URL = parse "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
275
+ NameSpace_OID = parse "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
276
+ NameSpace_X500 = parse "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
277
+
278
+ # The Nil UUID in RFC4122 Section 4.1.7
279
+ Nil = parse "00000000-0000-0000-0000-000000000000"
280
+ end
281
+
282
+ __END__
283
+
284
+ if __FILE__ == $0 then
285
+ require 'test/unit'
286
+
287
+ class TC_UUID < Test::Unit::TestCase
288
+ def test_v1
289
+ u1 = UUID.create
290
+ u2 = UUID.create
291
+ assert_not_equal u1, u2
292
+ end
293
+
294
+ def test_v1_repeatability
295
+ u1 = UUID.create 1, 2, "345678"
296
+ u2 = UUID.create 1, 2, "345678"
297
+ assert_equal u1, u2
298
+ end
299
+
300
+ def test_v3
301
+ u1 = UUID.create_md5 "foo", UUID::NameSpace_DNS
302
+ u2 = UUID.create_md5 "foo", UUID::NameSpace_DNS
303
+ u3 = UUID.create_md5 "foo", UUID::NameSpace_URL
304
+ assert_equal u1, u2
305
+ assert_not_equal u1, u3
306
+ end
307
+
308
+ def test_v5
309
+ u1 = UUID.create_sha1 "foo", UUID::NameSpace_DNS
310
+ u2 = UUID.create_sha1 "foo", UUID::NameSpace_DNS
311
+ u3 = UUID.create_sha1 "foo", UUID::NameSpace_URL
312
+ assert_equal u1, u2
313
+ assert_not_equal u1, u3
314
+ end
315
+
316
+ def test_v4
317
+ # This test is not perfect, because the random nature of version 4
318
+ # UUID it is not always true that the three objects below really
319
+ # differ. But in real life it's enough to say we're OK when this
320
+ # passes.
321
+ u1 = UUID.create_random
322
+ u2 = UUID.create_random
323
+ u3 = UUID.create_random
324
+ assert_not_equal u1.raw_bytes, u2.raw_bytes
325
+ assert_not_equal u1.raw_bytes, u3.raw_bytes
326
+ assert_not_equal u2.raw_bytes, u3.raw_bytes
327
+ end
328
+
329
+ def test_pack
330
+ u1 = UUID.pack 0x6ba7b810, 0x9dad, 0x11d1, 0x80, 0xb4,
331
+ "\000\300O\3240\310"
332
+ assert_equal UUID::NameSpace_DNS, u1
333
+ end
334
+
335
+ def test_unpack
336
+ tl, tm, th, cl, ch, m = UUID::NameSpace_DNS.unpack
337
+ assert_equal 0x6ba7b810, tl
338
+ assert_equal 0x9dad, tm
339
+ assert_equal 0x11d1, th
340
+ assert_equal 0x80, cl
341
+ assert_equal 0xb4, ch
342
+ assert_equal "\000\300O\3240\310", m
343
+ end
344
+
345
+ def test_parse
346
+ u1 = UUID.pack 0x6ba7b810, 0x9dad, 0x11d1, 0x80, 0xb4,
347
+ "\000\300O\3240\310"
348
+ u2 = UUID.parse "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
349
+ u3 = UUID.parse "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
350
+ assert_equal u1, u2
351
+ assert_equal u1, u3
352
+ end
353
+
354
+ def test_to_s
355
+ u1 = UUID.parse "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
356
+ assert_equal "6ba7b810-9dad-11d1-80b4-00c04fd430c8", u1.to_s
357
+ end
358
+
359
+ def test_to_i
360
+ u1 = UUID.parse "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
361
+ assert_equal 0x6ba7b8109dad11d180b400c04fd430c8, u1.to_i
362
+ end
363
+
364
+ def test_version
365
+ u1 = UUID.create_v1
366
+ assert_equal 1, u1.version
367
+ u3 = UUID.create_v3 "foo", UUID::NameSpace_DNS
368
+ assert_equal 3, u3.version
369
+ u4 = UUID.create_v4
370
+ assert_equal 4, u4.version
371
+ u5 = UUID.create_v5 "foo", UUID::NameSpace_DNS
372
+ assert_equal 5, u5.version
373
+ end
374
+ end
375
+ end