more_core_extensions 1.0.0 → 1.0.1
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.
- 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
|
+
[](http://badge.fury.io/rb/more_core_extensions)
|
5
6
|
[](https://travis-ci.org/ManageIQ/more_core_extensions)
|
6
7
|
[](https://codeclimate.com/github/ManageIQ/more_core_extensions)
|
7
8
|
[](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
|