more_core_extensions 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -0
- data/lib/more_core_extensions/core_ext/array/duplicates.rb +9 -7
- data/lib/more_core_extensions/core_ext/array/inclusions.rb +29 -27
- data/lib/more_core_extensions/core_ext/array/random.rb +16 -14
- data/lib/more_core_extensions/core_ext/array/stretch.rb +38 -36
- data/lib/more_core_extensions/core_ext/array/tableize.rb +75 -73
- data/lib/more_core_extensions/core_ext/hash/deletes.rb +14 -12
- data/lib/more_core_extensions/core_ext/hash/nested.rb +46 -44
- data/lib/more_core_extensions/core_ext/string/formats.rb +33 -31
- data/lib/more_core_extensions/core_ext/string/hex_dump.rb +48 -46
- data/lib/more_core_extensions/version.rb +1 -1
- data/more_core_extensions.gemspec +1 -1
- metadata +9 -9
data/README.md
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
MoreCoreExtensions are a set of core extensions beyond those provided by ActiveSupport.
|
4
4
|
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/more_core_extensions.png)](http://badge.fury.io/rb/more_core_extensions)
|
5
6
|
[![Build Status](https://travis-ci.org/ManageIQ/more_core_extensions.png?branch=master)](https://travis-ci.org/ManageIQ/more_core_extensions)
|
6
7
|
[![Code Climate](https://codeclimate.com/github/ManageIQ/more_core_extensions.png)](https://codeclimate.com/github/ManageIQ/more_core_extensions)
|
7
8
|
[![Coverage Status](https://coveralls.io/repos/ManageIQ/more_core_extensions/badge.png)](https://coveralls.io/r/ManageIQ/more_core_extensions)
|
@@ -1,10 +1,12 @@
|
|
1
|
-
module MoreCoreExtensions
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
module MoreCoreExtensions
|
2
|
+
module ArrayDuplicates
|
3
|
+
#
|
4
|
+
# Returns an Array of the duplicates found.
|
5
|
+
#
|
6
|
+
# [1, 2, 3, 4, 2, 4].duplicates #=> [2, 4]
|
7
|
+
def duplicates
|
8
|
+
self.inject(Hash.new(0)) { |h, v| h[v] += 1; h }.reject { |k, v| v == 1 }.keys
|
9
|
+
end
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
@@ -1,32 +1,34 @@
|
|
1
|
-
module MoreCoreExtensions
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
module MoreCoreExtensions
|
2
|
+
module ArrayInclusions
|
3
|
+
#
|
4
|
+
# Returns whether the Array contains any of the items.
|
5
|
+
#
|
6
|
+
# [1, 2, 3].include_any?(1, 2) #=> true
|
7
|
+
# [1, 2, 3].include_any?(1, 4) #=> true
|
8
|
+
# [1, 2, 3].include_any?(4, 5) #=> false
|
9
|
+
def include_any?(*items)
|
10
|
+
!(self & items).empty?
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
#
|
14
|
+
# Returns whether the Array contains none of the items.
|
15
|
+
#
|
16
|
+
# [1, 2, 3].include_none?(1, 2) #=> false
|
17
|
+
# [1, 2, 3].include_none?(1, 4) #=> false
|
18
|
+
# [1, 2, 3].include_none?(4, 5) #=> true
|
19
|
+
def include_none?(*items)
|
20
|
+
(self & items).empty?
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
#
|
24
|
+
# Returns whether the Array contains all of the items.
|
25
|
+
#
|
26
|
+
# [1, 2, 3].include_all?(1, 2) #=> true
|
27
|
+
# [1, 2, 3].include_all?(1, 4) #=> false
|
28
|
+
# [1, 2, 3].include_all?(4, 5) #=> false
|
29
|
+
def include_all?(*items)
|
30
|
+
(items - self).empty?
|
31
|
+
end
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
@@ -1,18 +1,20 @@
|
|
1
|
-
module MoreCoreExtensions
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
1
|
+
module MoreCoreExtensions
|
2
|
+
module ArrayRandom
|
3
|
+
#
|
4
|
+
# Picks a valid index randomly
|
5
|
+
#
|
6
|
+
# [1, 2, 3, 4, 2, 4].random_index #=> random number between 0..5
|
7
|
+
def random_index
|
8
|
+
rand(self.size)
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
#
|
12
|
+
# Picks an element randomly
|
13
|
+
#
|
14
|
+
# [1, 2, 3, 4, 2, 4].random_element #=> any randomly selected element in Array
|
15
|
+
def random_element
|
16
|
+
self[self.random_index]
|
17
|
+
end
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
@@ -1,47 +1,49 @@
|
|
1
|
-
module MoreCoreExtensions
|
2
|
-
module
|
3
|
-
|
1
|
+
module MoreCoreExtensions
|
2
|
+
module ArrayStretch
|
3
|
+
module ClassMethods
|
4
|
+
# Stretch all argument Arrays to make them the same size.
|
5
|
+
#
|
6
|
+
# Array.stretch([1, 2], [3, 4], [5, 6, 7]) #=> [[1, 2, nil], [3, 4, nil], [5, 6, 7]]
|
7
|
+
def stretch(*arys)
|
8
|
+
self.stretch!(*arys.collect { |a| a.dup })
|
9
|
+
end
|
10
|
+
|
11
|
+
# Stretch all argument Arrays to make them the same size. Modifies the arguments in place.
|
12
|
+
#
|
13
|
+
# Array.stretch!([1, 2], [3, 4], [5, 6, 7]) #=> [[1, 2, nil], [3, 4, nil], [5, 6, 7]]
|
14
|
+
def stretch!(*arys)
|
15
|
+
max_size = arys.collect { |a| a.length }.max
|
16
|
+
arys.each { |a| a[max_size - 1] = nil unless a.length == max_size }
|
17
|
+
return *arys
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Stretch receiver to be the same size as the longest argument Array.
|
4
22
|
#
|
5
|
-
#
|
23
|
+
# [1, 2].stretch([3, 4], [5, 6, 7]) #=> [1, 2, nil]
|
6
24
|
def stretch(*arys)
|
7
|
-
self.stretch!(*arys
|
25
|
+
self.dup.stretch!(*arys)
|
8
26
|
end
|
9
27
|
|
10
|
-
# Stretch
|
28
|
+
# Stretch receiver to be the same size as the longest argument Array. Modifies the receiver in place.
|
11
29
|
#
|
12
|
-
#
|
30
|
+
# [1, 2].stretch!([3, 4], [5, 6, 7]) #=> [1, 2, nil]
|
13
31
|
def stretch!(*arys)
|
14
|
-
max_size = arys.collect { |a| a.length }.max
|
15
|
-
|
16
|
-
return
|
32
|
+
max_size = (arys + [self]).collect { |a| a.length }.max
|
33
|
+
self[max_size - 1] = nil unless self.length == max_size
|
34
|
+
return self
|
17
35
|
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Stretch receiver to be the same size as the longest argument Array.
|
21
|
-
#
|
22
|
-
# [1, 2].stretch([3, 4], [5, 6, 7]) #=> [1, 2, nil]
|
23
|
-
def stretch(*arys)
|
24
|
-
self.dup.stretch!(*arys)
|
25
|
-
end
|
26
|
-
|
27
|
-
# Stretch receiver to be the same size as the longest argument Array. Modifies the receiver in place.
|
28
|
-
#
|
29
|
-
# [1, 2].stretch!([3, 4], [5, 6, 7]) #=> [1, 2, nil]
|
30
|
-
def stretch!(*arys)
|
31
|
-
max_size = (arys + [self]).collect { |a| a.length }.max
|
32
|
-
self[max_size - 1] = nil unless self.length == max_size
|
33
|
-
return self
|
34
|
-
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
37
|
+
# Zip arguments stretching the receiver if necessary. Ruby's +zip+ method
|
38
|
+
# will only zip up to the number of the receiver's elements if the receiver
|
39
|
+
# is shorter than the argument Arrays. This method will zip nils instead of
|
40
|
+
# stopping.
|
41
|
+
#
|
42
|
+
# [1, 2].zip([3, 4], [5, 6, 7]) #=> [[1, 3, 5], [2, 4, 6]]
|
43
|
+
# [1, 2].zip_stretched([3, 4], [5, 6, 7]) #=> [[1, 3, 5], [2, 4, 6], [nil, nil, 7]
|
44
|
+
def zip_stretched(*arys)
|
45
|
+
self.stretch(*arys).zip(*arys)
|
46
|
+
end
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
@@ -1,88 +1,90 @@
|
|
1
|
-
module MoreCoreExtensions
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
1
|
+
module MoreCoreExtensions
|
2
|
+
module ArrayTableize
|
3
|
+
# Create a string representation of _self_ in a tabular format if self is an
|
4
|
+
# Array of Arrays or an Array of Hashes.
|
5
|
+
#
|
6
|
+
# If an Array of Hashes is passed, the headers are assumed from the keys in
|
7
|
+
# the first element of the Array, and the header option is ignored. Also,
|
8
|
+
# the headers are sorted, unless overridden with options.
|
9
|
+
#
|
10
|
+
# General options:
|
11
|
+
# ::max_width: Maximum column width, in order to limit wide columns.
|
12
|
+
#
|
13
|
+
# Options with Array of Arrays:
|
14
|
+
# ::header: Whether or not the first row of data is a header row. Default is
|
15
|
+
# true.
|
16
|
+
#
|
17
|
+
# Options with Array of Hashes:
|
18
|
+
# ::columns: An Array of keys that define the order of all columns.
|
19
|
+
# ::leading_columns: An Array of keys that should be moved to the left side
|
20
|
+
# of the table. This option is ignored if columns option
|
21
|
+
# is passed.
|
22
|
+
# ::trailing_columns: An Array of keys that should be moved to the right side
|
23
|
+
# of the table. This option is ignored if columns option
|
24
|
+
# is passed.
|
25
|
+
#
|
26
|
+
# [["Col1", "Col2"], ["Val1", "Val2"], ["Value3", "Value4"]].tableize #=>
|
27
|
+
#
|
28
|
+
# Col1 | Col2
|
29
|
+
# --------+--------
|
30
|
+
# Val1 | Val2
|
31
|
+
# Value3 | Value4
|
32
|
+
#
|
33
|
+
def tableize(options = {})
|
34
|
+
case self.first
|
35
|
+
when Array; tableize_arrays(options)
|
36
|
+
when Hash; tableize_hashes(options)
|
37
|
+
else raise "must be an Array of Arrays or Array of Hashes"
|
38
|
+
end
|
37
39
|
end
|
38
|
-
end
|
39
40
|
|
40
|
-
|
41
|
+
private
|
41
42
|
|
42
|
-
|
43
|
-
|
43
|
+
def tableize_arrays(options)
|
44
|
+
options[:header] = true unless options.has_key?(:header)
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
widths = []
|
47
|
+
justifications = []
|
48
|
+
self.each do |row|
|
49
|
+
row.each_with_index do |field, field_i|
|
50
|
+
widths[field_i] = [widths[field_i].to_i, field.to_s.length].max
|
51
|
+
widths[field_i] = [options[:max_width], widths[field_i].to_i].min if options[:max_width]
|
51
52
|
|
52
|
-
|
53
|
+
justifications[field_i] = field.kind_of?(Numeric) ? "" : "-"
|
54
|
+
end
|
53
55
|
end
|
54
|
-
end
|
55
56
|
|
56
|
-
|
57
|
+
header_separator = widths.collect { |w| "-" * (w + 2) }.join("+")
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
59
|
+
table = []
|
60
|
+
self.each_with_index do |row, row_i|
|
61
|
+
r = []
|
62
|
+
row.each_with_index do |field, field_i|
|
63
|
+
r << sprintf("%0#{justifications[field_i]}#{widths[field_i]}s", field.to_s.gsub(/\n|\r/, '').slice(0, widths[field_i]))
|
64
|
+
end
|
65
|
+
r = " #{r.join(' | ')} ".rstrip
|
65
66
|
|
66
|
-
|
67
|
-
|
67
|
+
table << r
|
68
|
+
table << header_separator if row_i == 0 && options[:header]
|
69
|
+
end
|
70
|
+
table.join("\n") << "\n"
|
68
71
|
end
|
69
|
-
table.join("\n") << "\n"
|
70
|
-
end
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
73
|
+
def tableize_hashes(options)
|
74
|
+
if options[:columns]
|
75
|
+
keys = options[:columns]
|
76
|
+
elsif options[:leading_columns] || options[:trailing_columns]
|
77
|
+
keys = self.first.keys.sort_by(&:to_s)
|
78
|
+
options[:leading_columns].reverse.each { |h| keys.unshift(keys.delete(h)) } if options[:leading_columns]
|
79
|
+
options[:trailing_columns].each { |h| keys.push(keys.delete(h)) } if options[:trailing_columns]
|
80
|
+
else
|
81
|
+
keys = self.first.keys.sort_by(&:to_s)
|
82
|
+
end
|
82
83
|
|
83
|
-
|
84
|
-
|
85
|
-
|
84
|
+
options = options.dup
|
85
|
+
options[:header] = true
|
86
|
+
self.collect { |h| h.values_at(*keys) }.unshift(keys).tableize(options)
|
87
|
+
end
|
86
88
|
end
|
87
89
|
end
|
88
90
|
|
@@ -1,18 +1,20 @@
|
|
1
1
|
require 'active_support/core_ext/object/blank'
|
2
2
|
|
3
|
-
module MoreCoreExtensions
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
module MoreCoreExtensions
|
4
|
+
module HashDeletes
|
5
|
+
# Deletes all keys where the value is nil
|
6
|
+
#
|
7
|
+
# {:a => 1, :b => [], :c => nil}.delete_nils # => {:a => 1, :b => []}
|
8
|
+
def delete_nils
|
9
|
+
delete_if { |k, v| v.nil? }
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
# Deletes all keys where the value is blank
|
13
|
+
#
|
14
|
+
# {:a => 1, :b => [], :c => nil}.delete_blanks # => {:a => 1}
|
15
|
+
def delete_blanks
|
16
|
+
delete_if { |k, v| v.blank? }
|
17
|
+
end
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
@@ -1,54 +1,56 @@
|
|
1
|
-
module MoreCoreExtensions
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
module MoreCoreExtensions
|
2
|
+
module HashNested
|
3
|
+
def fetch_path(*args)
|
4
|
+
args = args.first if args.length == 1 && args.first.kind_of?(Array)
|
5
|
+
raise ArgumentError, "must pass at least one key" if args.empty?
|
6
|
+
|
7
|
+
child = self[args.first]
|
8
|
+
return child if args.length == 1
|
9
|
+
return nil unless child.kind_of?(Hash)
|
10
|
+
return child.fetch_path(args[1..-1])
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
def has_key_path?(*args)
|
14
|
+
args = args.first if args.length == 1 && args.first.kind_of?(Array)
|
15
|
+
raise ArgumentError, "must pass at least one key" if args.empty?
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
key = args.first
|
18
|
+
has_child = self.has_key?(key)
|
19
|
+
return has_child if args.length == 1
|
19
20
|
|
20
|
-
child = self[key]
|
21
|
-
return false unless child.kind_of?(Hash)
|
22
|
-
return child.has_key_path?(args[1..-1])
|
23
|
-
end
|
24
|
-
alias include_path? has_key_path?
|
25
|
-
alias key_path? has_key_path?
|
26
|
-
alias member_path? has_key_path?
|
27
|
-
|
28
|
-
def store_path(*args)
|
29
|
-
raise ArgumentError, "must pass at least one key, and a value" if args.length < 2
|
30
|
-
value = args.pop
|
31
|
-
args = args.first if args.length == 1 && args.first.kind_of?(Array)
|
32
|
-
|
33
|
-
key = args.first
|
34
|
-
if args.length == 1
|
35
|
-
self[key] = value
|
36
|
-
else
|
37
21
|
child = self[key]
|
38
|
-
|
39
|
-
child.
|
22
|
+
return false unless child.kind_of?(Hash)
|
23
|
+
return child.has_key_path?(args[1..-1])
|
24
|
+
end
|
25
|
+
alias include_path? has_key_path?
|
26
|
+
alias key_path? has_key_path?
|
27
|
+
alias member_path? has_key_path?
|
28
|
+
|
29
|
+
def store_path(*args)
|
30
|
+
raise ArgumentError, "must pass at least one key, and a value" if args.length < 2
|
31
|
+
value = args.pop
|
32
|
+
args = args.first if args.length == 1 && args.first.kind_of?(Array)
|
33
|
+
|
34
|
+
key = args.first
|
35
|
+
if args.length == 1
|
36
|
+
self[key] = value
|
37
|
+
else
|
38
|
+
child = self[key]
|
39
|
+
child = self[key] = {} unless child.kind_of?(Hash)
|
40
|
+
child.store_path(args[1..-1], value)
|
41
|
+
end
|
40
42
|
end
|
41
|
-
end
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
def delete_path(*args)
|
45
|
+
args = args.first if args.length == 1 && args.first.kind_of?(Array)
|
46
|
+
raise ArgumentError, "must pass at least one key" if args.empty?
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
key = args.first
|
49
|
+
if args.length == 1 || !(child = self[key]).kind_of?(Hash)
|
50
|
+
self.delete(key)
|
51
|
+
else
|
52
|
+
child.delete_path(args[1..-1])
|
53
|
+
end
|
52
54
|
end
|
53
55
|
end
|
54
56
|
end
|
@@ -1,40 +1,42 @@
|
|
1
|
-
module MoreCoreExtensions
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module MoreCoreExtensions
|
2
|
+
module StringFormats
|
3
|
+
# From: Regular Expression Cookbook: 4.1 Validate Email Addresses
|
4
|
+
RE_EMAIL = %r{\A[\w!#$\%&'*+/=?`\{|\}~^-]+(?:\.[\w!#$\%&'*+/=?`\{|\}~^-]+)*@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}\Z}i
|
5
|
+
def email?
|
6
|
+
!!(self =~ RE_EMAIL)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
# From: Regular Expression Cookbook: 7.15 Validating Domain Names
|
10
|
+
RE_DOMAINNAME = %r{^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$}i
|
11
|
+
def domain_name?
|
12
|
+
!!(self =~ RE_DOMAINNAME)
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
# From: Regular Expression Cookbook: 7.16 Matching IPv4 Addresses
|
16
|
+
RE_IPV4 = %r{^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$}
|
17
|
+
def ipv4?
|
18
|
+
!!(self =~ RE_IPV4)
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
# From: Regular Expression Cookbook: 7.17 Matching IPv6 Addresses
|
22
|
+
RE_IPV6 = %r{^(?:(?:(?:[A-F0-9]{1,4}:){6}|(?=(?:[A-F0-9]{0,4}:){0,6}(?:[0-9]{1,3}\.){3}[0-9]{1,3}$)(([0-9A-F]{1,4}:){0,5}|:)((:[0-9A-F]{1,4}){1,5}:|:))(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4}|(?=(?:[A-F0-9]{0,4}:){0,7}[A-F0-9]{0,4}$)(([0-9A-F]{1,4}:){1,7}|:)((:[0-9A-F]{1,4}){1,7}|:))$}i
|
23
|
+
def ipv6?
|
24
|
+
!!(self =~ RE_IPV6)
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
def ipaddress?
|
28
|
+
ipv4? || ipv6?
|
29
|
+
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
RE_INTEGER = %r{^[0-9]+$}
|
32
|
+
def integer?
|
33
|
+
!!(self =~ RE_INTEGER)
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
RE_GUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
|
37
|
+
def guid?
|
38
|
+
!!(self =~ RE_GUID)
|
39
|
+
end
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
@@ -1,54 +1,56 @@
|
|
1
|
-
module MoreCoreExtensions
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
obj
|
40
|
-
|
1
|
+
module MoreCoreExtensions
|
2
|
+
module StringHexDump
|
3
|
+
# Dumps the string in a hex editor style format. Options include:
|
4
|
+
#
|
5
|
+
# :grouping:: The number of bytes in a line. Default is 16.
|
6
|
+
# :newline:: Whether or not to add a \n after each line. Default is true.
|
7
|
+
# :start_pos:: The number at which byte counts will start. Default is 0.
|
8
|
+
# :obj:: Used in conjunction with _:meth_ to send each line to an object
|
9
|
+
# instead of returning as a string.
|
10
|
+
# :meth:: Used in conjunction with _:obj_ to send each line to an object
|
11
|
+
# instead of returning as a string.
|
12
|
+
def hex_dump(*opts)
|
13
|
+
opts = opts[0] if opts.empty? || (opts.length == 1 && opts[0].kind_of?(Hash))
|
14
|
+
raise ArgumentError, "opts must be a Hash" unless opts.nil? || opts.kind_of?(Hash)
|
15
|
+
|
16
|
+
opts = {:grouping => 16, :newline => true, :start_pos => 0}.merge!(opts || {})
|
17
|
+
obj, meth, grouping, newline, pos = opts.values_at(:obj, :meth, :grouping, :newline, :start_pos)
|
18
|
+
raise ArgumentError, "obj and meth must both be set, or both not set" if (obj.nil? && !meth.nil?) || (!obj.nil? && meth.nil?)
|
19
|
+
|
20
|
+
row_format = "0x%08x #{"%02x " * grouping} "
|
21
|
+
|
22
|
+
i = 0
|
23
|
+
last_i = self.length - 1
|
24
|
+
|
25
|
+
ret = ''
|
26
|
+
row_vals = []
|
27
|
+
row_chars = ''
|
28
|
+
|
29
|
+
self.each_byte do |c|
|
30
|
+
row_vals << c
|
31
|
+
row_chars << (c < 0x20 || (c >= 0x7F && c < 0xA0) ? '.' : c.chr)
|
32
|
+
|
33
|
+
if (i + 1) % grouping == 0 || i == last_i
|
34
|
+
row_format = "0x%08x #{"%02x " * row_vals.length}#{" " * (grouping - row_vals.length)} " if i == last_i
|
35
|
+
|
36
|
+
row_vals.unshift(pos)
|
37
|
+
ret << (row_format % row_vals) << row_chars
|
38
|
+
ret << "\n" if newline
|
39
|
+
if obj
|
40
|
+
obj.send(meth, ret)
|
41
|
+
ret.replace('')
|
42
|
+
end
|
43
|
+
|
44
|
+
pos += grouping
|
45
|
+
row_vals.clear
|
46
|
+
row_chars = ''
|
41
47
|
end
|
42
48
|
|
43
|
-
|
44
|
-
row_vals.clear
|
45
|
-
row_chars = ''
|
49
|
+
i += 1
|
46
50
|
end
|
47
51
|
|
48
|
-
|
52
|
+
return ret
|
49
53
|
end
|
50
|
-
|
51
|
-
return ret
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: more_core_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -80,17 +80,17 @@ dependencies:
|
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
81
81
|
none: false
|
82
82
|
requirements:
|
83
|
-
- -
|
83
|
+
- - ~>
|
84
84
|
- !ruby/object:Gem::Version
|
85
|
-
version:
|
85
|
+
version: 3.2.13
|
86
86
|
type: :runtime
|
87
87
|
prerelease: false
|
88
88
|
version_requirements: !ruby/object:Gem::Requirement
|
89
89
|
none: false
|
90
90
|
requirements:
|
91
|
-
- -
|
91
|
+
- - ~>
|
92
92
|
- !ruby/object:Gem::Version
|
93
|
-
version:
|
93
|
+
version: 3.2.13
|
94
94
|
description: MoreCoreExtensions are a set of core extensions beyond those provided
|
95
95
|
by ActiveSupport.
|
96
96
|
email:
|
@@ -146,7 +146,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
146
146
|
version: '0'
|
147
147
|
segments:
|
148
148
|
- 0
|
149
|
-
hash:
|
149
|
+
hash: -2540507193161773470
|
150
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
151
|
none: false
|
152
152
|
requirements:
|
@@ -155,10 +155,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
155
|
version: '0'
|
156
156
|
segments:
|
157
157
|
- 0
|
158
|
-
hash:
|
158
|
+
hash: -2540507193161773470
|
159
159
|
requirements: []
|
160
160
|
rubyforge_project:
|
161
|
-
rubygems_version: 1.8.
|
161
|
+
rubygems_version: 1.8.25
|
162
162
|
signing_key:
|
163
163
|
specification_version: 3
|
164
164
|
summary: MoreCoreExtensions are a set of core extensions beyond those provided by
|