bit-packer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ gem "lookup-hash", ">= 0.2.0"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "bundler", "~> 1.0.0"
10
+ gem "jeweler", "~> 1.5.2"
11
+ gem "riot", ">= 0.12.1"
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ hash-utils (0.11.0)
6
+ jeweler (1.5.2)
7
+ bundler (~> 1.0.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ lookup-hash (0.2.0)
11
+ hash-utils (>= 0.11.0)
12
+ rake (0.8.7)
13
+ riot (0.12.1)
14
+ rr
15
+ term-ansicolor
16
+ rr (1.0.2)
17
+ term-ansicolor (1.0.5)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ bundler (~> 1.0.0)
24
+ jeweler (~> 1.5.2)
25
+ lookup-hash (>= 0.2.0)
26
+ riot (>= 0.12.1)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Martin Kozák
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ BitPacker
2
+ =========
3
+
4
+ **bit-packer** provides easy declarative way of analyzing the packed bit
5
+ arrays. See an example:
6
+
7
+ require "bit-packer"
8
+
9
+ bp = BitPacker::new(7) do
10
+ number (:alfa) {2} # length of the entry in bits in block
11
+ boolean :beta
12
+ end
13
+
14
+ p bp.data
15
+ # will print out #<struct alfa=3, beta=true>
16
+
17
+ You can both read from data struct and write to it:
18
+
19
+ bp.data.boolean = false
20
+ bp.data.number = 2
21
+
22
+ p bp.to_i
23
+ # will print out 4
24
+
25
+ Contributing
26
+ ------------
27
+
28
+ 1. Fork it.
29
+ 2. Create a branch (`git checkout -b 20101220-my-change`).
30
+ 3. Commit your changes (`git commit -am "Added something"`).
31
+ 4. Push to the branch (`git push origin 20101220-my-change`).
32
+ 5. Create an [Issue][2] with a link to your branch.
33
+ 6. Enjoy a refreshing Diet Coke and wait.
34
+
35
+ Copyright
36
+ ---------
37
+
38
+ Copyright &copy; 2011 [Martin Kozák][3]. See `LICENSE.txt` for
39
+ further details.
40
+
41
+ [2]: http://github.com/martinkozak/bit-packer/issues
42
+ [3]: http://www.martinkozak.net/
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'bundler'
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+ require 'rake'
12
+
13
+ require 'jeweler'
14
+ Jeweler::Tasks.new do |gem|
15
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
16
+ gem.name = "bit-packer"
17
+ gem.homepage = "http://github.com/martinkozak/bit-packer"
18
+ gem.license = "MIT"
19
+ gem.summary = 'Provides easy declarative way of analyzing the packed bit arrays.'
20
+ gem.email = "martinkozak@martinkozak.net"
21
+ gem.authors = ["Martin Kozák"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rake/rdoctask'
30
+ Rake::RDocTask.new do |rdoc|
31
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
32
+
33
+ rdoc.rdoc_dir = 'rdoc'
34
+ rdoc.title = "hash-utils #{version}"
35
+ rdoc.rdoc_files.include('README*')
36
+ rdoc.rdoc_files.include('lib/**/*.rb')
37
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,57 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{bit-packer}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Martin Kozák"]
12
+ s.date = %q{2011-03-02}
13
+ s.email = %q{martinkozak@martinkozak.net}
14
+ s.extra_rdoc_files = [
15
+ "LICENSE.txt",
16
+ "README.md"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "LICENSE.txt",
23
+ "README.md",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "bit-packer.gemspec",
27
+ "lib/bit-packer.rb",
28
+ "test"
29
+ ]
30
+ s.homepage = %q{http://github.com/martinkozak/bit-packer}
31
+ s.licenses = ["MIT"]
32
+ s.require_paths = ["lib"]
33
+ s.rubygems_version = %q{1.5.3}
34
+ s.summary = %q{Provides easy declarative way of analyzing the packed bit arrays.}
35
+
36
+ if s.respond_to? :specification_version then
37
+ s.specification_version = 3
38
+
39
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
40
+ s.add_runtime_dependency(%q<lookup-hash>, [">= 0.2.0"])
41
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
42
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
43
+ s.add_development_dependency(%q<riot>, [">= 0.12.1"])
44
+ else
45
+ s.add_dependency(%q<lookup-hash>, [">= 0.2.0"])
46
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
47
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
48
+ s.add_dependency(%q<riot>, [">= 0.12.1"])
49
+ end
50
+ else
51
+ s.add_dependency(%q<lookup-hash>, [">= 0.2.0"])
52
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
53
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
54
+ s.add_dependency(%q<riot>, [">= 0.12.1"])
55
+ end
56
+ end
57
+
data/lib/bit-packer.rb ADDED
@@ -0,0 +1,242 @@
1
+ # encoding: utf-8
2
+ # (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
3
+
4
+ require "lookup-hash/frozen"
5
+
6
+ class BitPacker
7
+
8
+ ##
9
+ # Holds types index.
10
+ #
11
+
12
+ TYPES = Frozen::LookupHash[
13
+ :number,
14
+ :boolean
15
+ ]
16
+
17
+ ##
18
+ # Indicates size of one byte.
19
+ #
20
+
21
+ BYTESIZE = 8
22
+
23
+ ##
24
+ # Holds resultant data structure.
25
+ #
26
+
27
+ @struct
28
+
29
+ ##
30
+ # Holds type stack.
31
+ #
32
+
33
+ @stack
34
+
35
+ ##
36
+ # Holds data.
37
+ #
38
+
39
+ @data
40
+
41
+ ##
42
+ # Holds raw data.
43
+ # @return [Integer] raw (original) integer data
44
+ #
45
+
46
+ attr_reader :raw
47
+ @raw
48
+
49
+ ##
50
+ # Holds total length.
51
+ #
52
+ # @return [Integer] total length of the packed data according
53
+ # to declaration
54
+ #
55
+
56
+ attr_reader :length
57
+ @length
58
+
59
+ ##
60
+ # Constructor.
61
+ #
62
+ # @param [Integer] data raw integer for unpack
63
+ # @param [Proc] block block with declaration
64
+ # @see #declare
65
+ #
66
+
67
+ def initialize(data = nil, &block)
68
+ @stack = [ ]
69
+ @length = 0
70
+ self.declare(&block)
71
+
72
+ if not data.nil?
73
+ self << data
74
+ end
75
+ end
76
+
77
+ ##
78
+ # Receives declaration.
79
+ #
80
+ # Adds declaration of bit array items. Can be call multiple times.
81
+ # New delcarations are joind to end of the array.
82
+ #
83
+ # @example
84
+ # packer.declare do
85
+ # number (:number) {2}
86
+ # boolean :boolean
87
+ # end
88
+ #
89
+ # @param [Proc] block block with declaration
90
+ # @see TYPES
91
+ #
92
+
93
+ def declare(&block)
94
+ self.instance_eval(&block)
95
+ end
96
+
97
+ ##
98
+ # Handles missing methods as declarations.
99
+ #
100
+ # @param [Symbol] name data type of the entry
101
+ # @param [Array] args first argument is expected to be name
102
+ # @param [Proc] block block which returns length of the entry in bits
103
+ # @return [Integer] new length of the packed data
104
+ # @see #declare
105
+ #
106
+
107
+ def method_missing(name, *args, &block)
108
+ if not self.class::TYPES.include? name
109
+ raise Exception::new("Invalid type/method specified: '" << name.to_s << "'.")
110
+ end
111
+
112
+ if not block.nil?
113
+ length = block.call()
114
+ else
115
+ length = 1
116
+ end
117
+
118
+ self.add(args.first, name, length)
119
+ end
120
+
121
+ ##
122
+ # Adds declaration.
123
+ #
124
+ # @param [Symbol] name name of the entry
125
+ # @param [Symbol] type type of the entry
126
+ # @param [Integer] length length of the entry in bits
127
+ # @return [Integer] new length of the packed data
128
+ #
129
+
130
+ def add(name, type, length = 1)
131
+ @stack << [name, type, @length, length]
132
+ @struct = nil
133
+ @length += length
134
+ end
135
+
136
+ ##
137
+ # Fills by input data.
138
+ # @param [Integer] value raw integer data for unpack
139
+ #
140
+
141
+ def <<(value)
142
+ if not value.kind_of? Integer
143
+ raise Exception::new("Integer is expected for BitPacker.")
144
+ end
145
+
146
+ @raw = value
147
+ @data = nil
148
+ end
149
+
150
+ ##
151
+ # Returns structure analyze.
152
+ # @return [Class] struct with the packed data
153
+ #
154
+
155
+ def data
156
+ if @data.nil?
157
+ values = [ ]
158
+
159
+ @stack.each do |name, type, position, length|
160
+ rel_pos = @length - position - length
161
+ value = @raw & __mask(rel_pos, length)
162
+
163
+ case type
164
+ when :boolean
165
+ values << (value > 0)
166
+ when :number
167
+ values << (value >> rel_pos)
168
+ end
169
+ end
170
+
171
+ @data = __struct::new(*values)
172
+ end
173
+
174
+ return @data
175
+ end
176
+
177
+ ##
178
+ # Converts to integer.
179
+ # @return [Integer] resultant integer according to current data state
180
+ #
181
+
182
+ def to_i
183
+ result = 0
184
+ @stack.each do |name, type, position, length|
185
+ rel_pos = @length - position - length
186
+ value = self.data[name]
187
+
188
+ case type
189
+ when :boolean
190
+ mask = __mask(rel_pos, length)
191
+ if value === true
192
+ result |= mask
193
+ else
194
+ result &= ~mask
195
+ end
196
+ when :number
197
+ value &= __mask(0, length)
198
+ value = value << rel_pos
199
+ result |= value
200
+ end
201
+ end
202
+
203
+ return result
204
+ end
205
+
206
+ alias :to_int :to_i
207
+
208
+
209
+ protected
210
+
211
+ ##
212
+ # Generates mask.
213
+ #
214
+
215
+ def __mask(position, length = 1)
216
+
217
+ # length of mask
218
+ mask = 0
219
+ length.times do |i|
220
+ mask += 2 ** i
221
+ end
222
+
223
+ # position of mask
224
+ mask = mask << position
225
+
226
+ return mask
227
+ end
228
+
229
+ ##
230
+ # Returns data struct.
231
+ #
232
+
233
+ def __struct
234
+ if @struct.nil?
235
+ members = @stack.map { |i| i[0] }
236
+ @struct = Struct::new(*members)
237
+ end
238
+
239
+ return @struct
240
+ end
241
+
242
+ end
data/test ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+ # (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
4
+
5
+ $:.push("./lib")
6
+ require "bit-packer"
7
+ require "riot"
8
+
9
+ context "BitPacker" do
10
+ setup do
11
+ BitPacker::new(7) do
12
+ number (:number) {2}
13
+ boolean :boolean
14
+ end
15
+ end
16
+
17
+ asserts("correct unpacking") do
18
+ (topic.data.boolean == true) and (topic.data.number == 3)
19
+ end
20
+ asserts("correct packing") do
21
+ topic.data.boolean = false
22
+ topic.data.number = 2
23
+ topic.to_i == 4
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bit-packer
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - "Martin Koz\xC3\xA1k"
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-03-02 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: lookup-hash
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.2.0
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: 1.0.0
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: jeweler
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.5.2
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: riot
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 0.12.1
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: *id004
60
+ description:
61
+ email: martinkozak@martinkozak.net
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files:
67
+ - LICENSE.txt
68
+ - README.md
69
+ files:
70
+ - .document
71
+ - Gemfile
72
+ - Gemfile.lock
73
+ - LICENSE.txt
74
+ - README.md
75
+ - Rakefile
76
+ - VERSION
77
+ - bit-packer.gemspec
78
+ - lib/bit-packer.rb
79
+ - test
80
+ has_rdoc: true
81
+ homepage: http://github.com/martinkozak/bit-packer
82
+ licenses:
83
+ - MIT
84
+ post_install_message:
85
+ rdoc_options: []
86
+
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: -1036686220775041030
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: "0"
104
+ requirements: []
105
+
106
+ rubyforge_project:
107
+ rubygems_version: 1.5.3
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Provides easy declarative way of analyzing the packed bit arrays.
111
+ test_files: []
112
+