sanderjd-bitfields 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/README +0 -0
  2. data/Rakefile +38 -0
  3. data/demo.rb +46 -0
  4. data/lib/bitfields.rb +89 -0
  5. data/lib/bits.rb +60 -0
  6. metadata +57 -0
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ begin
2
+ require 'rubygems'
3
+ rescue Exception
4
+ puts 'RubyGems is not installed. See http://www.rubygems.org/read/chapter/3 for instructions.'
5
+ end
6
+
7
+ begin
8
+ require 'spec/rake/spectask'
9
+
10
+ Spec::Rake::SpecTask.new do |t|
11
+ t.spec_opts = ['-c']
12
+ t.libs << 'lib'
13
+ t.spec_files = FileList['spec/**/*_spec.rb']
14
+ t.rcov = true
15
+ end
16
+ rescue Exception
17
+ puts 'RSpec not available. Install it with: sudo gem install rspec'
18
+ end
19
+
20
+ begin
21
+ require 'jeweler'
22
+ Jeweler::Tasks.new do |s|
23
+ s.name = "bitfields"
24
+ s.summary = "Simple named bit fields"
25
+ s.description = "A very simple library for building binary data by declaring named bit fields"
26
+ s.email = 'sanderjd@gmail.com'
27
+ s.homepage = 'http://github.com/sanderjd/bitfields'
28
+ s.authors = ['James Sanders']
29
+ s.has_rdoc = true
30
+ s.files = ["README",
31
+ "Rakefile",
32
+ "demo.rb",
33
+ "lib/bitfields.rb",
34
+ "lib/bits.rb"]
35
+ end
36
+ rescue LoadError
37
+ puts 'Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com'
38
+ end
data/demo.rb ADDED
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/lib/bitfields'
2
+
3
+ # Make a template
4
+ BitFields.template :demo do |m|
5
+ m.bits :beginning, :length => 10, :value => 0b1010101010
6
+ m.bits :middle, :length => 5
7
+ m.bits :end, :length => 10, :value => 1
8
+ end
9
+
10
+ # Create an object with that template
11
+ message = BitFields.create(:demo)
12
+
13
+ # 1010101010000000000000001
14
+ puts message.bit_string
15
+
16
+ # Create an object with that template and give it parameters
17
+ message = BitFields.create(:demo, :middle => 0b11111)
18
+
19
+ # 1010101010111110000000001
20
+ puts message.bit_string
21
+ # 1557c01
22
+ puts message.hex_string
23
+ # 125276001
24
+ puts message.oct_string
25
+ # 22379521
26
+ puts message.integer
27
+
28
+ # Compose another message using this object as one of its fields
29
+ new_message = BitFields.compose do |m|
30
+ m.bits :before, :length => 1, :value => 1
31
+ m.add :demo__message, message
32
+ m.bits :after, :length => 1, :value => 0
33
+ end
34
+
35
+ # 110101010101111100000000010
36
+ puts new_message.bit_string
37
+
38
+ # Compose another message without creating the original message
39
+ newer_message = BitFields.compose do |m|
40
+ m.bits :before, :length => 1, :value => 1
41
+ m.bring :demo, :middle => 0
42
+ m.bits :after, :length => 1, :value => 0
43
+ end
44
+
45
+ # 110101010100000000000000010
46
+ puts newer_message.bit_string
data/lib/bitfields.rb ADDED
@@ -0,0 +1,89 @@
1
+ require File.dirname(__FILE__) + '/bits'
2
+
3
+ class BitFields
4
+
5
+ # Class methods
6
+
7
+ def self.template(template_name, &block)
8
+ template_name = symbol_if_string(template_name)
9
+ templates[template_name] = self.new
10
+ yield templates[template_name]
11
+ nil
12
+ end
13
+
14
+ def self.create(template_name, params = {})
15
+ template_name = symbol_if_string(template_name)
16
+ params.each_pair { | field_name, value | templates[template_name][field_name] = value }
17
+ templates[template_name]
18
+ end
19
+
20
+ def self.compose(&block)
21
+ composition = self.new
22
+ yield composition
23
+ composition
24
+ end
25
+
26
+ # Object methods
27
+
28
+ def integer; get_bits.integer end
29
+ def bit_string; get_bits.bit_string end
30
+ def hex_string; get_bits.hex_string end
31
+ def oct_string; get_bits.oct_string end
32
+
33
+ def add(field_name, object)
34
+ field_name = BitFields.symbol_if_string(field_name)
35
+ field_names << field_name
36
+ field_values << object.get_bits
37
+ end
38
+
39
+ def bring(template_name, params = {})
40
+ name = BitFields.symbol_if_string(name)
41
+ object = BitFields.create(name, params)
42
+ field_names << template_name
43
+ field_values << object.get_bits
44
+ end
45
+
46
+ def bits(field_name, params = {})
47
+ field_name = BitFields.symbol_if_string(field_name)
48
+ value = params.key?(:value) ? params[:value] : 0
49
+ length = params.key?(:length) ? params[:length] : 0
50
+ field_names << field_name
51
+ field_values << Bits.new(value, length)
52
+ end
53
+
54
+ def get_bits
55
+ field_values.inject(nil) do |final, value|
56
+ final ? final + value : value
57
+ end
58
+ end
59
+
60
+ def [](field_name)
61
+ field_name = BitFields.symbol_if_string(field_name)
62
+ field_values[field_names.index(field_name)] if field_names.index(field_name)
63
+ end
64
+
65
+ def []=(field_name, value)
66
+ self[field_name].set(value) if self[field_name]
67
+ end
68
+
69
+ def field_names
70
+ @field_names ||= Array.new
71
+ end
72
+
73
+ def field_values
74
+ @field_values ||= Array.new
75
+ end
76
+
77
+ private
78
+
79
+ def self.templates
80
+ @@templates ||= Hash.new
81
+ end
82
+
83
+ # Helpers
84
+
85
+ def self.symbol_if_string(name)
86
+ name.kind_of?(String) ? name.to_sym : name
87
+ end
88
+ end
89
+
data/lib/bits.rb ADDED
@@ -0,0 +1,60 @@
1
+ # Bits provides an easy way to store and access sequences of bits,
2
+ # allowing input and output in multiple formats
3
+
4
+ class Bits
5
+
6
+ # +bits+:: The bit field to store
7
+ # +length+:: Length of the bit field - default to calculated length, 0-pad on
8
+ # MSB
9
+
10
+ def initialize(bits, length = 0)
11
+ @length = length
12
+ @bits = bit_string_from_input(bits, length)
13
+ end
14
+
15
+ def +(bits)
16
+ Bits.new("0b#{@bits}" + bit_string_from_input(bits))
17
+ end
18
+
19
+ def bit_string
20
+ @bits
21
+ end
22
+
23
+ def hex_string
24
+ @bits.to_i(2).to_s(16)
25
+ end
26
+
27
+ def oct_string
28
+ @bits.to_i(2).to_s(8)
29
+ end
30
+
31
+ def integer
32
+ @bits.to_i(2)
33
+ end
34
+
35
+ def set(bits)
36
+ @bits = bit_string_from_input(bits, @length)
37
+ end
38
+
39
+ protected
40
+
41
+ attr_reader :bits
42
+
43
+ private
44
+
45
+ def bit_string_from_input(bits, length = 0)
46
+ case bits
47
+ when Integer, Fixnum, Bignum
48
+ "%0#{length}b" % bits
49
+ when String
50
+ "%0#{length}b" % Integer(bits)
51
+ when Bits
52
+ bits.bits
53
+ when BitFields
54
+ bits.get_bits.bits
55
+ else
56
+ warn "Unsupported data #{bits} (#{bits.class}) - defaulting to #{length} length zero field"
57
+ "%0#{length}b" % 0
58
+ end
59
+ end
60
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sanderjd-bitfields
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - James Sanders
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-22 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A very simple library for building binary data by declaring named bit fields
17
+ email: sanderjd@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README
26
+ - Rakefile
27
+ - demo.rb
28
+ - lib/bitfields.rb
29
+ - lib/bits.rb
30
+ has_rdoc: true
31
+ homepage: http://github.com/sanderjd/bitfields
32
+ post_install_message:
33
+ rdoc_options: []
34
+
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project:
52
+ rubygems_version: 1.2.0
53
+ signing_key:
54
+ specification_version: 2
55
+ summary: Simple named bit fields
56
+ test_files: []
57
+