huffnpuff 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +158 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/huffnpuff.gemspec +31 -0
- data/lib/huffnpuff.rb +182 -0
- data/lib/huffnpuff/version.rb +3 -0
- metadata +142 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8d53cb2641733aa17816bf18f3482c9917111bcc
|
4
|
+
data.tar.gz: e4af27561bb0efdd23c19a95ba8e20771c79f007
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 43e413245fcea87c5b5cd2078b6a69ce29470beaeba838e907da7658c0c7742878e0194753f48d17b57a04e6ba598f692b349d915934910f313ddfd832e583d2
|
7
|
+
data.tar.gz: 0da34b39907367109459aa7c2e8b6579a20d6bd806e42cc038b00dfa69f58916d4991ea9ba8545084584a08d9241033eca26a8d66a0122a1def0a6ad8eb28f5a
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at bryan@bdlsys.com. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Bryan Colvin
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE 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
|
+
AUTHORS OR COPYRIGHT HOLDERS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
# Huffnpuff
|
2
|
+
|
3
|
+
`Huffnpuff` implements a general purpose Huffman Coding system that uses a construction string which can implement any system.
|
4
|
+
This also includes the `bitfifo` gem which allows variable length bit sequences to address the internal table of the
|
5
|
+
`Huffnpuff` object instance.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'huffnpuff'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install huffnpuff
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Huffman coding systems are widely use on compression engines such as MPEG and PKZIP.
|
26
|
+
The theory suggests that symbols that repeat can be represented by fewer bits if we sacrifice rare symbols with larger bit sequences.
|
27
|
+
If you look at the game of Scrabble, some letters have higher points than others because they don't appear as often.
|
28
|
+
Morse Code uses variable length dits and dahs to represent letters, but is not a valid Huffman system as you need gaps between letters
|
29
|
+
to separate them. A valid Huffman system allows for a stream of data to be able to deterministically separate each token (group of bits).
|
30
|
+
Below is an example of a valid system:
|
31
|
+
|
32
|
+
```
|
33
|
+
0 # 0
|
34
|
+
1000 # 1
|
35
|
+
1001 # 2
|
36
|
+
1010 # 3
|
37
|
+
1011 # 4
|
38
|
+
11000 # 5
|
39
|
+
11001 # 6
|
40
|
+
11010 # 7
|
41
|
+
11011 # 8
|
42
|
+
111 # 9
|
43
|
+
```
|
44
|
+
|
45
|
+
The above system has an order of 10, meaning it can represent or index 10 items.
|
46
|
+
This system can be represented by the the string: `"0:10xx:110xx:111"`.
|
47
|
+
The string represents 4 bins where each bin is separated by a colon.
|
48
|
+
The bin's preamble is defined as the sequence of bits before an `'x'` is encountered.
|
49
|
+
It is the preamble that makes it possible to separate tokens.
|
50
|
+
A valid string may only include the following characters: `'0', '1', 'x', ':'`.
|
51
|
+
The character `'x'` may only appear after the preamble; also, `'1'` or `'0'` may not appear after `'x'`.
|
52
|
+
The character `'x'` represents two possible bit values of `'0'` and `'1'`.
|
53
|
+
Consecutive `'xx'` means there are 4 possible values: `'00'`, `'01'`, `'10'`, `'11'`.
|
54
|
+
Each consecutive `'x'` doubles the possible values.
|
55
|
+
In order for a system to be valid, a preamble may not overlap another preamble.
|
56
|
+
For example, the string `"0:10xxx:101xx"` is invalid because the bit sequence `'10101'`
|
57
|
+
would be found in more than one bin.
|
58
|
+
|
59
|
+
Coming up with a system can be tricky. The best way to come up with a system is to create a histogram of your data set,
|
60
|
+
then sort it in descending order. An evenly distributed histogram means that Huffman encoding will not be effective.
|
61
|
+
If there are large differences, then Huffman encoding will be very effective.
|
62
|
+
The `Huffnpuff` gem has a utility method that can generate the system string needed to create a system.
|
63
|
+
This is best seen by example as follows:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
require 'huffnpuff'
|
67
|
+
|
68
|
+
hist = [200,50,35,27,22,15,13,12,9,8,8,8,8,8,7,6,5,5,4,4,4,3,3,3,3,3,2,2,2,1,1,1,1,1,1,1,1]
|
69
|
+
tight = Huffnpuff.get_system_string_from_histogram(hist, 0.20)
|
70
|
+
medium = Huffnpuff.get_system_string_from_histogram(hist, 0.50)
|
71
|
+
loose = Huffnpuff.get_system_string_from_histogram(hist, 0.75)
|
72
|
+
|
73
|
+
# tight == "0x:10xxxx:1110xx:110xxxx"
|
74
|
+
# medium == "0:10xx:11110:110xx:1110xxxx:111110xx:1111110xxx"
|
75
|
+
# loose == "0:10:110x:1110:1111110:11110xx:111110xxx:11111110xx:111111110xx:1111111110xx:11111111110xxx"
|
76
|
+
```
|
77
|
+
|
78
|
+
The first parameter is our histogram array sorted in descending order.
|
79
|
+
The second parameter is the grouping factor which ranges from 0.1 to 0.9 inclusively.
|
80
|
+
The size of the array is equal to the number of elements we wish to represent with a Huffman code.
|
81
|
+
The first element of the `hist` array is the most likely to occur token, and is encoded first at the beginning of our system string.
|
82
|
+
Note that a system string need not to have its bins numerically sorted.
|
83
|
+
The algorithm sorts based on the length of bits needed for the bin.
|
84
|
+
A `Huffnpuff` object has an internal lookup table which maps the tokens to an entry in the table.
|
85
|
+
This is best seen by example as follows:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
bits = Bitfifo.new
|
89
|
+
lut = ['Apple', 'Banana', 'Cherry', 'Dog', 'Elephant', 'Fortune', 'Grape']
|
90
|
+
huff = Huffnpuff.new(loose, bits, lut)
|
91
|
+
huff.push 'House' # or lut.push 'House' ... same thing
|
92
|
+
|
93
|
+
# prime the pump
|
94
|
+
bits.put 0, 1 # bin 0
|
95
|
+
bits.put 0b10, 2 # bin 1
|
96
|
+
bits.put 0b1100, 4 # bin 2 x==0
|
97
|
+
bits.put 0b1101, 4 # bin 2 x==1
|
98
|
+
bits.put 0b1110, 4 # bin 3
|
99
|
+
bits.put 0b1111110, 7 # bin 4
|
100
|
+
bits.put 0b1111000, 7 # bin 5 xx==00
|
101
|
+
bits.put 0b1111001, 7 # bin 5 xx==01
|
102
|
+
|
103
|
+
bits.size # 36 ... number of bits in bitfifo
|
104
|
+
|
105
|
+
# binary representation of bits in fifo
|
106
|
+
bits.to_i.to_s(2) # "10110011011110111111011110001111001"
|
107
|
+
|
108
|
+
# now get the data
|
109
|
+
huff.get # 'Apple'
|
110
|
+
huff.get # 'Banana'
|
111
|
+
huff.get # 'Cherry'
|
112
|
+
huff.get # 'Dog'
|
113
|
+
huff.get # 'Elephant'
|
114
|
+
huff.get # 'Fortune'
|
115
|
+
huff.get # 'Grape'
|
116
|
+
huff.get # 'House'
|
117
|
+
huff.get # nil, >>> no address found in Bitfifo 'bits'
|
118
|
+
bits.put 0b1100, 4 # random access
|
119
|
+
huff.get # 'Cherry'
|
120
|
+
```
|
121
|
+
|
122
|
+
Huffnpuff has the following methods:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
# class methods:
|
126
|
+
# Huffnpuff.histogram_array_valid?(ary) ... ensures histogram descending integers
|
127
|
+
# Huffnpuff.validate_system_string(str) ... checks for syntax errors on system string
|
128
|
+
# Huffnpuff.get_system_string_from_histogram(ary, rat = 0.61) ... creates system string 0.1 <= rat <= 0.9
|
129
|
+
# Huffnpuff.new(sys_string, bitfifo, array=[]) ... creates new object
|
130
|
+
|
131
|
+
# class constants:
|
132
|
+
# Huffnpuff::CMP ... proc used to sort bins
|
133
|
+
|
134
|
+
# instance methods:
|
135
|
+
# huff.min ... returns minimum number of bits needed to access data
|
136
|
+
# huff.max ... returns maximum number of bits needed to access data
|
137
|
+
# huff.size ... returns maximum number of addresses that may be used to look up data
|
138
|
+
# huff.sys ... returns system string
|
139
|
+
# huff.systemize!(sys) ... recreates system from system string, or replace existing system
|
140
|
+
# huff.push ... adds data to internal lookup table, raises error if no room is available
|
141
|
+
# huff.push_each ... adds elements of array or characters of a string to lookup table
|
142
|
+
# huff.get ... returns data indexed by external bitfifo
|
143
|
+
```
|
144
|
+
|
145
|
+
## Development
|
146
|
+
|
147
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
148
|
+
|
149
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
150
|
+
|
151
|
+
## Contributing
|
152
|
+
|
153
|
+
I need to control this for the time being.
|
154
|
+
|
155
|
+
## License
|
156
|
+
|
157
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
158
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "huffnpuff"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/huffnpuff.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'huffnpuff/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "huffnpuff"
|
8
|
+
spec.version = Huffnpuff::VERSION
|
9
|
+
spec.authors = ["Bryan Colvin"]
|
10
|
+
spec.email = ["bryan@bdlsys.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Huffman encoding system}
|
13
|
+
spec.description = %q{Huffnpuff implements a general purpose Huffman Coding system that uses a construction string which can implement any system.
|
14
|
+
This also includes the bitfifo gem which allows variable length bit sequences to address the internal table of the
|
15
|
+
Huffnpuff object instance. Huffman coding is essential for compression techniques such as MPEG, and PKZIP.
|
16
|
+
}
|
17
|
+
spec.license = "MIT"
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_runtime_dependency 'bitfifo', '~> 0.2', '>= 0.2.1'
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
29
|
+
spec.add_development_dependency 'byebug', '~> 5.0', '>= 5.0.0'
|
30
|
+
|
31
|
+
end
|
data/lib/huffnpuff.rb
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
require "huffnpuff/version"
|
2
|
+
require "bitfifo"
|
3
|
+
|
4
|
+
class Huffnpuff
|
5
|
+
def self.histogram_array_valid?(ary)
|
6
|
+
return false if ary.empty?
|
7
|
+
ary.each do |elm|
|
8
|
+
return false unless elm.kind_of? Integer
|
9
|
+
return false if elm <= 0
|
10
|
+
end
|
11
|
+
return false unless ary == ary.sort.reverse
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.validate_system_string(str)
|
16
|
+
ary = str.split(':')
|
17
|
+
raise "singular bin not valid" if 1==ary.count
|
18
|
+
ary.each do |bin|
|
19
|
+
raise "empty bin definition" if bin.empty?
|
20
|
+
raise "preamble missing: must start with 1 or 0" if bin[0]=='x'
|
21
|
+
xmode = false
|
22
|
+
bin.each_char do |ch|
|
23
|
+
if xmode
|
24
|
+
raise "illegal char following 'x': ['#{ch}']" unless 'x'==ch
|
25
|
+
else
|
26
|
+
if ch=='x'
|
27
|
+
xmode = true
|
28
|
+
elsif ch=='0'
|
29
|
+
elsif ch=='1'
|
30
|
+
else
|
31
|
+
raise "invalid symbol #{ch}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
CMP = lambda { |a,b| a.length <=> b.length }
|
40
|
+
|
41
|
+
def self.get_system_string_from_histogram(ary, rat = 0.61)
|
42
|
+
raise "histogram array must be reverse sorted with values >= 1" unless histogram_array_valid?(ary)
|
43
|
+
raise "parameter 2 must be between 0.2 and 0.8" unless ((rat >= 0.1) && (rat <= 0.9))
|
44
|
+
sys = []
|
45
|
+
top = (rat * 4096.0).to_i
|
46
|
+
n = ary.count - 1
|
47
|
+
tar = (ary[0] * top) >> 12
|
48
|
+
cnt = 1
|
49
|
+
n.times do |idx|
|
50
|
+
if ary[idx+1] <= tar
|
51
|
+
sys.push cnt
|
52
|
+
cnt = 1
|
53
|
+
tar = (ary[idx+1] * top) >> 12
|
54
|
+
else
|
55
|
+
cnt += 1
|
56
|
+
end
|
57
|
+
end
|
58
|
+
sys.push cnt
|
59
|
+
ary = []
|
60
|
+
borrow = 0
|
61
|
+
sys.each do |num|
|
62
|
+
num -= borrow
|
63
|
+
bin_size = 1 << (num-1).bit_length
|
64
|
+
ary.push bin_size
|
65
|
+
borrow = bin_size - num
|
66
|
+
end
|
67
|
+
pre = ""
|
68
|
+
if ary.count==1 # don't bother ... all same
|
69
|
+
return "x" * (ary.first.bit_length - 1)
|
70
|
+
end
|
71
|
+
sys = []
|
72
|
+
ary.each do |num|
|
73
|
+
str = pre + "0" + "x" * (num.bit_length-1)
|
74
|
+
pre += "1"
|
75
|
+
sys.push str
|
76
|
+
end
|
77
|
+
sys.sort! &CMP
|
78
|
+
sys.join(':')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
class Huffnpuff
|
84
|
+
def initialize(sys, fifo, dat = [])
|
85
|
+
@data = dat
|
86
|
+
@fifo = fifo
|
87
|
+
@ary = []
|
88
|
+
systemize!(sys)
|
89
|
+
end
|
90
|
+
def min
|
91
|
+
@min
|
92
|
+
end
|
93
|
+
def max
|
94
|
+
@max
|
95
|
+
end
|
96
|
+
def size
|
97
|
+
@size
|
98
|
+
end
|
99
|
+
|
100
|
+
def sys()
|
101
|
+
@sys
|
102
|
+
end
|
103
|
+
|
104
|
+
def systemize!(sys)
|
105
|
+
if sys.kind_of? String
|
106
|
+
@sys = sys
|
107
|
+
ary = sys.split(':')
|
108
|
+
elsif sys.kind_of? Array
|
109
|
+
ary = sys
|
110
|
+
@sys = ary.join(':')
|
111
|
+
else
|
112
|
+
raise "imcompatible type first parameter"
|
113
|
+
end
|
114
|
+
self.class.validate_system_string(@sys)
|
115
|
+
off = 0
|
116
|
+
@min = 2 ** 10000
|
117
|
+
@max = 0
|
118
|
+
ary.each do |ii|
|
119
|
+
pos = ii.index('x')
|
120
|
+
if pos.nil?
|
121
|
+
@ary.push [ii,0, off]
|
122
|
+
off += 1
|
123
|
+
sz = ii.length
|
124
|
+
@min = sz < @min ? sz : @min
|
125
|
+
@max = sz > @max ? sz : @max
|
126
|
+
else
|
127
|
+
xcount = ii.length - pos
|
128
|
+
@ary.push [ii[(0..(pos-1))],xcount,off]
|
129
|
+
off += 2 ** xcount
|
130
|
+
sz = xcount + ii[(0..(pos-1))].length
|
131
|
+
@min = sz < @min ? sz : @min
|
132
|
+
@max = sz > @max ? sz : @max
|
133
|
+
end
|
134
|
+
end
|
135
|
+
@size = off
|
136
|
+
end
|
137
|
+
|
138
|
+
def push(item)
|
139
|
+
raise "can't excede system size of #{@size}" if @data.size >= @size
|
140
|
+
@data.push item
|
141
|
+
end
|
142
|
+
|
143
|
+
def push_each(item)
|
144
|
+
if item.respond_to? :each
|
145
|
+
item.each do |elm|
|
146
|
+
push elm
|
147
|
+
end
|
148
|
+
elsif item.respond_to? :each_char
|
149
|
+
item.each_char do |ch|
|
150
|
+
push ch
|
151
|
+
end
|
152
|
+
else # punt
|
153
|
+
push item
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# ok, we have a problem ... the MSB is the preamble
|
158
|
+
|
159
|
+
def get
|
160
|
+
idx = 0
|
161
|
+
@ary.each do |ii|
|
162
|
+
pre = @fifo.get(ii.first.length) # not enough bits to address data
|
163
|
+
return nil if pre.nil?
|
164
|
+
if(pre==ii.first.to_i(2))
|
165
|
+
if(0==ii[1]) # only one, no x's
|
166
|
+
return @data[ii[2]]
|
167
|
+
else
|
168
|
+
off = @fifo.get(ii[1])
|
169
|
+
if off.nil?
|
170
|
+
@fifo.unget(ii[1]+ii.first.length) # not enough bits to address data
|
171
|
+
return nil
|
172
|
+
end
|
173
|
+
return @data[off + ii[2]]
|
174
|
+
end
|
175
|
+
else # put back to try another system
|
176
|
+
@fifo.unget(ii.first.length)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
return nil
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
metadata
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: huffnpuff
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bryan Colvin
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-01-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bitfifo
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.2'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.2.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.2'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.2.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: bundler
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.11'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.11'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '10.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '10.0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rspec
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '3.0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: byebug
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '5.0'
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 5.0.0
|
85
|
+
type: :development
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '5.0'
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 5.0.0
|
95
|
+
description: |
|
96
|
+
Huffnpuff implements a general purpose Huffman Coding system that uses a construction string which can implement any system.
|
97
|
+
This also includes the bitfifo gem which allows variable length bit sequences to address the internal table of the
|
98
|
+
Huffnpuff object instance. Huffman coding is essential for compression techniques such as MPEG, and PKZIP.
|
99
|
+
email:
|
100
|
+
- bryan@bdlsys.com
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- ".gitignore"
|
106
|
+
- ".rspec"
|
107
|
+
- ".travis.yml"
|
108
|
+
- CODE_OF_CONDUCT.md
|
109
|
+
- Gemfile
|
110
|
+
- LICENSE.txt
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- bin/console
|
114
|
+
- bin/setup
|
115
|
+
- huffnpuff.gemspec
|
116
|
+
- lib/huffnpuff.rb
|
117
|
+
- lib/huffnpuff/version.rb
|
118
|
+
homepage:
|
119
|
+
licenses:
|
120
|
+
- MIT
|
121
|
+
metadata: {}
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubyforge_project:
|
138
|
+
rubygems_version: 2.5.1
|
139
|
+
signing_key:
|
140
|
+
specification_version: 4
|
141
|
+
summary: Huffman encoding system
|
142
|
+
test_files: []
|