tduehr-libmatty 0.9.0

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,16 @@
1
+ class Range
2
+ module RangeExtensions
3
+ # again, surprised this isn't in the library
4
+ def each_backwards
5
+ max.to_i.downto(min) {|i| yield i}
6
+ end
7
+
8
+ # Take a random number out of a range
9
+ #
10
+ def choice
11
+ rand(self.last - self.first) + self.first
12
+ end
13
+ alias_method :choose, :choice
14
+ end
15
+ include RangeExtensions
16
+ end
@@ -0,0 +1,20 @@
1
+ class Socket
2
+ module SocketExtensions
3
+ module ClassMethods
4
+ def addr(host, port=nil)
5
+ if not port
6
+ raise "bad!" if not host =~ /(.*):(.*)/
7
+ host = $1
8
+ port = $2
9
+ end
10
+ port = port.to_i
11
+ Socket.pack_sockaddr_in(port, host)
12
+ end
13
+ end
14
+
15
+ def self.included(klass)
16
+ klass.extend(ClassMethods)
17
+ end
18
+ end
19
+ include SocketExtensions
20
+ end
@@ -0,0 +1,450 @@
1
+ class String
2
+ module StringExtensions
3
+
4
+ if String.instance_methods.include? :toutf16
5
+ alias_method :to_utf16, :toutf16
6
+ else
7
+ # Convert a string to "Unicode", ie, the way Win32 expects it, including
8
+ # trailing NUL.
9
+ def to_utf16
10
+ require 'iconv'
11
+ Iconv.iconv("utf-16LE", "utf-8", self).first + "\x00\x00"
12
+ end
13
+ alias_method :toutf16, :to_utf16
14
+ end
15
+
16
+ if String.instance_methods.include? :toutf8
17
+ # purely for old code using this library that may otherwise still work in 1.9
18
+ alias_method :to_utf8, :toutf8
19
+ alias_method :to_ascii, :toutf8
20
+ alias_method :from_utf16, :toutf8
21
+ else
22
+ # Convert a "Unicode" (Win32-style) string back to native Ruby UTF-8;
23
+ # get rid of any trailing NUL.
24
+ def from_utf16
25
+ require 'iconv'
26
+ ret = Iconv.iconv("utf-8", "utf-16le", self).first
27
+ if ret[-1] == 0
28
+ ret = ret[0..-2]
29
+ end
30
+ end
31
+ alias_method :to_utf8, :from_utf16
32
+ alias_method :to_ascii, :from_utf16
33
+ alias_method :toutf8, :from_utf16
34
+ end
35
+
36
+ # Convenience for parsing UNICODE strings from a buffer
37
+ # Assumes last char ends in 00, which is not always true but works in English
38
+ def from_utf16_buffer
39
+ self[0..index("\0\0\0")+2].from_utf16
40
+ end
41
+
42
+ # Sometimes string buffers passed through Win32 interfaces come with
43
+ # garbage after the trailing NUL; this method gets rid of that, like
44
+ # String#trim
45
+ def asciiz
46
+ begin
47
+ self[0..self.index("\x00")-1]
48
+ rescue
49
+ self
50
+ end
51
+ end
52
+
53
+ def asciiz!
54
+ replace asciiz
55
+ end
56
+
57
+ # shortcut for hex sanity with regex
58
+ # remember kids, always pratice safe hex
59
+ def is_hex? ; (self =~ /^[a-f0-9]+$/i)? true : false ; end
60
+
61
+ # My entry into the hexdump race. Outputs canonical hexdump, uses
62
+ # StringIO for speed, could be cleaned up with "ljust", and should
63
+ # probably use table lookup instead of to_s(16) method calls.
64
+ def hexdump(capture=false)
65
+ require 'stringio'
66
+ sio = StringIO.new
67
+ rem = size - 1
68
+ off = 0
69
+
70
+ while rem > 0
71
+ pbuf = ""
72
+ pad = (15 - rem) if rem < 16
73
+ pad ||= 0
74
+
75
+ sio.write(("0" * (8 - (x = off.to_s(16)).size)) + x + " ")
76
+
77
+ 0.upto(15-pad) do |i|
78
+ c = self[off]
79
+ x = c.to_s(16)
80
+ sio.write(("0" * (2 - x.size)) + x + " ")
81
+ if c.printable?
82
+ pbuf << c
83
+ else
84
+ pbuf << "."
85
+ end
86
+ off += 1
87
+ rem -= 1
88
+ sio.write(" ") if i == 7
89
+ end
90
+
91
+ sio.write("-- " * pad) if pad > 0
92
+ sio.write(" |#{ pbuf }|\n")
93
+ end
94
+
95
+ sio.rewind()
96
+ if capture
97
+ sio.read()
98
+ else
99
+ puts sio.read()
100
+ end
101
+ end
102
+
103
+ # convert a string to its idiomatic ruby class name
104
+ def class_name
105
+ r = ""
106
+ up = true
107
+ each_byte do |c|
108
+ if c == 95
109
+ if up
110
+ r << "::"
111
+ else
112
+ up = true
113
+ end
114
+ else
115
+ m = up ? :upcase : :to_s
116
+ r << (c.chr.send(m))
117
+ up = false
118
+ end
119
+ end
120
+ r
121
+ end
122
+
123
+ if not String.instance_methods.include?(:starts_with?)
124
+ # Insane that this isn't in the library by default.
125
+ # 1.9 does so we don't add it then
126
+ def starts_with? x
127
+ self[0..x.size-1] == x
128
+ end
129
+ end
130
+
131
+ if not String.instance_methods.include?(:starts_with?)
132
+ def ends_with? x
133
+ self[-(x.size)..-1] == x
134
+ end
135
+ end
136
+
137
+ # Cribbed from Ero Carrera's pefile; a relatively expensive entropy
138
+ # function, gives a float result of random-bits-per-byte.
139
+ def entropy
140
+ e = 0
141
+ 0.upto(255) do |i|
142
+ x = count(i.chr)/size.to_f
143
+ if x > 0
144
+ e += - x * Math.log2(x)
145
+ end
146
+ end
147
+
148
+ return e
149
+ end
150
+
151
+ # The driver function for String#strings below; really, this will
152
+ # run on any Enumerable that contains Fixnums.
153
+ def nextstring(opts={})
154
+ off = opts[:offset] || 0
155
+ sz = opts[:minimum] || 7
156
+ u = opts[:unicode] || false
157
+ l = size
158
+ i = off
159
+ while i < l
160
+ if self[i].printable?
161
+ start = i
162
+ cnt = 1
163
+ i += 1
164
+ lastu = false
165
+ while i < l
166
+ if self[i].printable?
167
+ lastu = false
168
+ cnt += 1
169
+ i += 1
170
+ elsif u and self[i] == 0 and not lastu
171
+ lastu = true
172
+ i += 1
173
+ else
174
+ break
175
+ end
176
+ end
177
+
178
+ return([start, i - start]) if cnt >= sz
179
+ else
180
+ i += 1
181
+ end
182
+ end
183
+
184
+ return false, false
185
+ end
186
+
187
+ # A la Unix strings(1). With a block, yields offset, string length,
188
+ # and contents. Otherwise returns a list. Accepts options:
189
+ # :unicode: superficial but effective Win32 Unicode support, skips NULs
190
+ # :minimum: minimum length of returned strings, ala strings -10
191
+ def strings(opts={})
192
+ ret = []
193
+ opts[:offset] ||= 0
194
+ while 1
195
+ off, size = nextstring(opts)
196
+ break if not off
197
+ opts[:offset] += (off + size)
198
+ if block_given?
199
+ yield off, size, self[off,size]
200
+ else
201
+ ret << [off, size, self[off,size]]
202
+ end
203
+ end
204
+ ret
205
+ end
206
+
207
+ # A hacked up adler16 checksum, a la Andrew Tridgell. This is probably
208
+ # even slower than Ruby's native CRC support. A weak, trivial checksum,
209
+ # part of rsync.
210
+ def adler
211
+ a, b = 0, 0
212
+ 0.upto(size-1) {|i| a += self[i]}
213
+ a %= 65536
214
+ 0.upto(size-1) {|i| b += ((size-i)+1) * self[i]}
215
+ b %= 65536
216
+ return (a|(b<<16))
217
+ end
218
+
219
+ # Convert binary strings back to integers
220
+ def to_l32; unpack("L").first; end
221
+ def to_b32; unpack("N").first; end
222
+ def to_l16; unpack("v").first; end
223
+ def to_b16; unpack("n").first; end
224
+ def to_u8; self[0]; end
225
+ def shift_l32; shift(4).to_l32; end
226
+ def shift_b32; shift(4).to_b32; end
227
+ def shift_l16; shift(2).to_l16; end
228
+ def shift_b16; shift(2).to_b16; end
229
+ def shift_u8; shift(1).to_u8; end
230
+
231
+ # oh, it's exactly what it sounds like.
232
+ def method_name
233
+ r = ""
234
+ scoped = false
235
+ each_byte do |c|
236
+ if c == 58
237
+ if not scoped
238
+ r << "_"
239
+ scoped = true
240
+ else
241
+ scoped = false
242
+ end
243
+ else
244
+ if r.size == 0
245
+ r << c.chr.downcase
246
+ else
247
+ if c.upper?
248
+ r << "_"
249
+ r << c.chr.downcase
250
+ else
251
+ r << c.chr
252
+ end
253
+ end
254
+ end
255
+ end
256
+ return r
257
+ end
258
+
259
+ # I love you String#ljust
260
+ def pad(size, char="\x00")
261
+ ljust(size, char)
262
+ end
263
+
264
+ # Convert a string into hex characters
265
+ def hexify
266
+ l = []
267
+ each_byte{|b| l << "%02x" % b}
268
+ l.join
269
+ end
270
+
271
+ # convert a string to hex characters in place
272
+ def hexify!
273
+ self.replace hexify
274
+ end
275
+
276
+
277
+ # Convert a string of raw hex characters (no %'s or anything) into binary
278
+ def dehexify
279
+ (ret||="") << (me||=clone).shift(2).to_i(16).chr while not (me||=clone).empty?
280
+ return ret
281
+ end
282
+
283
+ # Convert a string of raw hex characters (no %'s or anything) into binary in place
284
+ def dehexify!
285
+ (ret||="") << (me||=clone).shift(2).to_i(16).chr while not (me||=clone).empty?
286
+ self.replace ret
287
+ end
288
+
289
+ # OR two strings together. Slow. Handles mismatched lengths by zero-extending
290
+ def or(str)
291
+ max = size < str.size ? str.size : size
292
+ ret = ""
293
+ 0.upto(max-1) do |i|
294
+ x = self[i] || 0
295
+ y = str[i] || 0
296
+ ret << (x | y).chr
297
+ end
298
+ return ret
299
+ end
300
+
301
+ # XOR two strings. wrapping around if str is shorter than self.
302
+ def xor(str)
303
+ r = []
304
+ size.times do |i|
305
+ r << (self[i] ^ str[i % str.size]).chr
306
+ end
307
+ return r.join
308
+ end
309
+
310
+ def xor!(str)
311
+ size.times do |i|
312
+ self[i] ^= str[i % str.size]
313
+ end
314
+ end
315
+
316
+ # byte rotation cypher (yes it's been useful)
317
+ def rotate_bytes(k=0)
318
+ r = []
319
+ each_byte do |b|
320
+ r << ((b + k) % 256).chr
321
+ end
322
+ return r.join
323
+ end
324
+
325
+ # Insanely useful shorthand: pop bytes off the front of a string
326
+ def shift(count=1)
327
+ return self if count == 0
328
+ slice! 0..(count-1)
329
+ end
330
+
331
+ def underscore
332
+ first = false
333
+ gsub(/[a-z0-9][A-Z]/) do |m|
334
+ "#{ m[0].chr }_#{ m[1].chr.downcase }"
335
+ end
336
+ end
337
+
338
+ # "foo: bar".shift_tok /:\s*/ => "foo" # leaving "bar"
339
+ def shift_tok(rx)
340
+ src = rx.source if rx.kind_of? Regexp
341
+ rx = Regexp.new "(#{ src })"
342
+ idx = (self =~ rx)
343
+ if idx
344
+ ret = shift(idx)
345
+ shift($1.size)
346
+ return ret
347
+ else
348
+ shift(self.size)
349
+ end
350
+ end
351
+
352
+ # Base64 encode
353
+ def b64(len=nil)
354
+ ret = [self].pack("m").gsub("\n", "")
355
+ if len and Numeric === len
356
+ ret.scan(/.{1,#{len}}/).join("\n") + "\n"
357
+ else
358
+ ret
359
+ end
360
+ end
361
+
362
+ # Base64 decode
363
+ def d64; self.unpack("m")[0]; end
364
+
365
+ # Returns a single null-terminated ascii string from beginning of self.
366
+ # This will return the entire string if no null is encountered.
367
+ #
368
+ # Parameters:
369
+ #
370
+ # off = specify an optional beggining offset
371
+ #
372
+ def cstring(off=0)
373
+ self[ off, self.index("\x00") || self.size ]
374
+ end
375
+
376
+ # returns CRC32 checksum for the string object
377
+ def crc32
378
+ ## pure ruby version. slower, but here for reference (found on some forum)
379
+ # r = 0xFFFFFFFF
380
+ # self.each_byte do |b|
381
+ # r ^= b
382
+ # 8.times do
383
+ # r = (r>>1) ^ (0xEDB88320 * (r & 1))
384
+ # end
385
+ # end
386
+ # r ^ 0xFFFFFFFF
387
+ # # or... we can just use:
388
+ require 'zlib'
389
+ Zlib.crc32 self
390
+ end
391
+
392
+ # TODO: this needs to work differently....
393
+ # # Returns a reference to actual constant for a given name in namespace
394
+ # # can be used to lookup classes from enums and such
395
+ # def const_lookup(ns=Object)
396
+ # if c=ns.constants.select {|n| n == self.class_name } and not c.empty?
397
+ # ns.const_get(c.first)
398
+ # end
399
+ # end
400
+
401
+ # Return a self encapsulated in a StringIO object.
402
+ def to_stringio
403
+ require 'stringio'
404
+ StringIO.new(self)
405
+ end
406
+
407
+ # a pbcopy from irb on any String object
408
+ # yes, we're a mac shop.
409
+ def pbcopy
410
+ IO.popen("pbcopy", "w") {|io| io.write self}
411
+ end if Object::RUBY_PLATFORM =~ /darwin/
412
+
413
+ def md5
414
+ require 'digest/md5'
415
+ Digest::MD5.digest(self).hexify
416
+ end
417
+
418
+ def sha1
419
+ require 'digest/sha1'
420
+ Digest::SHA1.digest(self).hexify
421
+ end
422
+
423
+ def sha256
424
+ require 'digest/sha256'
425
+ Digest::SHA256.digest(self).hexify
426
+ end
427
+
428
+ def sha512
429
+ require 'digest/sha512'
430
+ Digest::SHA512.digest(self).hexify
431
+ end
432
+
433
+ # fast 37 hash of a string, for non-security stuff.
434
+ def hashcode
435
+ return 5381 if not ((l = self.size) and l > 0)
436
+ code = 0
437
+ 0.upto(l-1) do |i|
438
+ code = ((code << 5) - code) + self[i]
439
+ end
440
+ code
441
+ end
442
+
443
+ # Returns a Time object for a string representing seconds since epoch
444
+ # fmt: format to be passed to String#to_i (see String#to_i)
445
+ def time_at(fmt=0)
446
+ Time.at(self.to_i(fmt))
447
+ end
448
+ end
449
+ include StringExtensions
450
+ end