hex_string 1.0.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.
- data/.gitignore +5 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/README.md +46 -0
- data/Rakefile +19 -0
- data/hex_string.gemspec +24 -0
- data/lib/hex_string.rb +43 -0
- data/test/hex_string_test.rb +57 -0
- metadata +140 -0
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown --readme README.md --hide-void-return
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
Description
|
2
|
+
===========
|
3
|
+
HexString provides two String extension methods:
|
4
|
+
|
5
|
+
* `String#to_hex_string` explodes a string of binary data into human-readable hex tuples, and
|
6
|
+
* `String#to_byte_string` converts a string of human-readable hex digits into the corresponding bytes.
|
7
|
+
|
8
|
+
Examples
|
9
|
+
--------
|
10
|
+
|
11
|
+
# Convert data to human-readable hex tuples:
|
12
|
+
>> "hello".to_hex_string
|
13
|
+
=> "68 65 6c 6c 6f"
|
14
|
+
|
15
|
+
# Compact a hex string into its data equivalent:
|
16
|
+
>> "77 6f 72 6c 64".to_byte_string
|
17
|
+
=> "world"
|
18
|
+
|
19
|
+
# (#to_byte_string is space and case-insensitive:)
|
20
|
+
>> "776F726C64".to_byte_string
|
21
|
+
=> "world"
|
22
|
+
|
23
|
+
# Peek at the first 4 bytes of an executable on OS X:
|
24
|
+
>> File.read("/bin/ls")[0..3].to_hex_string
|
25
|
+
=> "ca fe ba be"
|
26
|
+
|
27
|
+
Motivation
|
28
|
+
----------
|
29
|
+
When working with binary message or file formats, we often want to have a peek
|
30
|
+
at some segment of binary data and talk about individual byte values in
|
31
|
+
human-relatable terms.
|
32
|
+
|
33
|
+
This sort of thing comes in handy during testing, debugging and data
|
34
|
+
introspection, especially when it's inconvenient or impractical to capture the
|
35
|
+
desired binary data to file in order to view it with a hex editor or other
|
36
|
+
binary file reader.
|
37
|
+
|
38
|
+
We were inspired to publish this humble Gem after we found ourselves copying it
|
39
|
+
by hand from project to project over the course of several years.
|
40
|
+
|
41
|
+
Authors
|
42
|
+
=======
|
43
|
+
* Micah Alles (alles@atomicobject.com)
|
44
|
+
* David Crosby (crosby@atomicobject.com)
|
45
|
+
* © 2011 [Atomic Object](http://www.atomicobject.com/)
|
46
|
+
* More Atomic Object [open source](http://www.atomicobject.com/pages/Software+Commons) projects
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "bundler"
|
2
|
+
require "rake/testtask"
|
3
|
+
require "rake/clean"
|
4
|
+
require "yard"
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
Rake::TestTask.new do |t|
|
8
|
+
t.test_files = FileList["test/*_test.rb"]
|
9
|
+
end
|
10
|
+
|
11
|
+
YARD::Rake::YardocTask.new do |t|
|
12
|
+
t.files = %w[ lib/hex_string.rb ]
|
13
|
+
end
|
14
|
+
|
15
|
+
CLEAN.include "pkg"
|
16
|
+
CLEAN.include "doc"
|
17
|
+
CLEAN.include ".yardoc"
|
18
|
+
|
19
|
+
task :default => :test
|
data/hex_string.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "hex_string"
|
5
|
+
s.version = "1.0.0"
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.authors = ["David Crosby", "Micah Alles"]
|
8
|
+
s.email = ["crosby@atomicobject.com", "alles@atomicobject.com"]
|
9
|
+
s.homepage = ""
|
10
|
+
s.summary = %q{String extensions to convert binary data to / from human readable hex tuples.}
|
11
|
+
s.description = %q{String extensions to convert binary data to / from human readable hex tuples.}
|
12
|
+
|
13
|
+
s.rubyforge_project = "hex_string"
|
14
|
+
|
15
|
+
s.add_development_dependency("bundler", ">= 1.0.0")
|
16
|
+
s.add_development_dependency("rake", ">= 0.8.0")
|
17
|
+
s.add_development_dependency("yard", "~> 0.6.4")
|
18
|
+
s.add_development_dependency("bluecloth", "~> 2.0.11")
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
end
|
data/lib/hex_string.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# String extensions providing to_hex_string and to_byte_string.
|
2
|
+
# Requiring hex_string will automatically include HexString in the String class.
|
3
|
+
module HexString
|
4
|
+
|
5
|
+
# Convert a human-readable hex string into binary data.
|
6
|
+
#
|
7
|
+
# Assumes the target String is an ASCII, human readable sequence of hexadecimal
|
8
|
+
# tuples depicting a sequence of 8-bit byte values.
|
9
|
+
# Whitespace between tuples is allowed and will be removed before packing.
|
10
|
+
#
|
11
|
+
# Returns a newly created string containing binary data -- the target string will not be modified.
|
12
|
+
#
|
13
|
+
# Eg:
|
14
|
+
# >> "68 65 6c 6c 6f".to\_byte\_string
|
15
|
+
# => "hello"
|
16
|
+
def to_byte_string
|
17
|
+
stripped = self.gsub(/\s+/,'')
|
18
|
+
unless stripped.size % 2 == 0
|
19
|
+
raise "Can't translate a string unless it has an even number of digits"
|
20
|
+
end
|
21
|
+
raise "Can't translate non-hex characters" if stripped =~ /[^0-9A-Fa-f]/
|
22
|
+
[stripped].pack('H*')
|
23
|
+
end
|
24
|
+
|
25
|
+
# Convert binary data into a human-readable hex string.
|
26
|
+
#
|
27
|
+
# Whatever data is contained in the target string will be "exploded" into a sequence of
|
28
|
+
# hexadecimal tuples, one space between each tuple, for ease of debugging and reading.
|
29
|
+
#
|
30
|
+
# Returns a newly created string containing the hex string -- the target binary string will not be modified.
|
31
|
+
#
|
32
|
+
# Eg:
|
33
|
+
# >> "hello world".to\_hex\_string
|
34
|
+
# => "68 65 6c 6c 6f 20 77 6f 72 6c 64"
|
35
|
+
def to_hex_string
|
36
|
+
self.unpack('H*').first.gsub(/(..)/,'\1 ').rstrip
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Include HexString extensions in the String class
|
41
|
+
class String
|
42
|
+
include HexString
|
43
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/hex_string')
|
3
|
+
|
4
|
+
class HexStringTest < Test::Unit::TestCase
|
5
|
+
def self.should(behave,&block)
|
6
|
+
mname = "test_should_#{behave}"
|
7
|
+
if block
|
8
|
+
define_method mname, &block
|
9
|
+
else
|
10
|
+
puts ">>> UNIMPLEMENTED CASE: #{name.sub(/Test$/,'')} should #{behave}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
should "allow human readable hex strings to become actual byte strings" do
|
15
|
+
human = "0102030405060708090a0b0c0d0e0f"
|
16
|
+
expect = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
|
17
|
+
assert_equal expect, human.to_byte_string
|
18
|
+
end
|
19
|
+
|
20
|
+
should "not care about case of a-f or A-F" do
|
21
|
+
human = "aabbccddeeffAABBCCDDEEFF"
|
22
|
+
expect = "\xaa\xbb\xcc\xdd\xee\xff\xaa\xbb\xcc\xdd\xee\xff"
|
23
|
+
assert_equal expect, human.to_byte_string
|
24
|
+
end
|
25
|
+
|
26
|
+
should "ignore whitespace of all kinds" do
|
27
|
+
human = "\t\t\taa \t\t bb c\nc d\tdee ffAABBCCDDEEFF\t \n\r"
|
28
|
+
expect = "\xaa\xbb\xcc\xdd\xee\xff\xaa\xbb\xcc\xdd\xee\xff"
|
29
|
+
assert_equal expect, human.to_byte_string
|
30
|
+
end
|
31
|
+
|
32
|
+
should "reject odd lengths of digits" do
|
33
|
+
human = "abbccddeeffAABBCCDDEEFF"
|
34
|
+
err = assert_raise(RuntimeError) do
|
35
|
+
human.to_byte_string
|
36
|
+
end
|
37
|
+
assert_match(/even/,err.message)
|
38
|
+
assert_match(/digits/,err.message)
|
39
|
+
end
|
40
|
+
|
41
|
+
should "reject non-hex digits" do
|
42
|
+
human = "aabbccddXKeeffAABBCCDDEEFF"
|
43
|
+
err = assert_raise(RuntimeError) do
|
44
|
+
human.to_byte_string
|
45
|
+
end
|
46
|
+
assert_match(/hex/,err.message)
|
47
|
+
end
|
48
|
+
|
49
|
+
should "convert byte strings into human readable hex strings" do
|
50
|
+
assert_equal "68 65 6c 6c 6f", "hello".to_hex_string
|
51
|
+
end
|
52
|
+
|
53
|
+
should "provide empty hex strings when operating on empty strings" do
|
54
|
+
assert_equal "", "".to_hex_string
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hex_string
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- David Crosby
|
14
|
+
- Micah Alles
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2011-07-06 00:00:00 -04:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: bundler
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 23
|
31
|
+
segments:
|
32
|
+
- 1
|
33
|
+
- 0
|
34
|
+
- 0
|
35
|
+
version: 1.0.0
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id001
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: rake
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
hash: 63
|
47
|
+
segments:
|
48
|
+
- 0
|
49
|
+
- 8
|
50
|
+
- 0
|
51
|
+
version: 0.8.0
|
52
|
+
type: :development
|
53
|
+
version_requirements: *id002
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: yard
|
56
|
+
prerelease: false
|
57
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ~>
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 15
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
- 6
|
66
|
+
- 4
|
67
|
+
version: 0.6.4
|
68
|
+
type: :development
|
69
|
+
version_requirements: *id003
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: bluecloth
|
72
|
+
prerelease: false
|
73
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ~>
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 25
|
79
|
+
segments:
|
80
|
+
- 2
|
81
|
+
- 0
|
82
|
+
- 11
|
83
|
+
version: 2.0.11
|
84
|
+
type: :development
|
85
|
+
version_requirements: *id004
|
86
|
+
description: String extensions to convert binary data to / from human readable hex tuples.
|
87
|
+
email:
|
88
|
+
- crosby@atomicobject.com
|
89
|
+
- alles@atomicobject.com
|
90
|
+
executables: []
|
91
|
+
|
92
|
+
extensions: []
|
93
|
+
|
94
|
+
extra_rdoc_files: []
|
95
|
+
|
96
|
+
files:
|
97
|
+
- .gitignore
|
98
|
+
- .yardopts
|
99
|
+
- Gemfile
|
100
|
+
- README.md
|
101
|
+
- Rakefile
|
102
|
+
- hex_string.gemspec
|
103
|
+
- lib/hex_string.rb
|
104
|
+
- test/hex_string_test.rb
|
105
|
+
has_rdoc: true
|
106
|
+
homepage: ""
|
107
|
+
licenses: []
|
108
|
+
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
hash: 3
|
120
|
+
segments:
|
121
|
+
- 0
|
122
|
+
version: "0"
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
hash: 3
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
version: "0"
|
132
|
+
requirements: []
|
133
|
+
|
134
|
+
rubyforge_project: hex_string
|
135
|
+
rubygems_version: 1.3.7
|
136
|
+
signing_key:
|
137
|
+
specification_version: 3
|
138
|
+
summary: String extensions to convert binary data to / from human readable hex tuples.
|
139
|
+
test_files:
|
140
|
+
- test/hex_string_test.rb
|