Permalink
Browse files

Added documentation

  • Loading branch information...
1 parent c95bebc commit 5a9a200dee19ca8b34511d48c88bab491fffaa8f @mwylde committed Nov 22, 2010
Showing with 52 additions and 13 deletions.
  1. +1 −1 Rakefile
  2. +51 −12 lib/rubybits.rb
View
@@ -15,7 +15,7 @@ Jeweler::Tasks.new do |gem|
gem.name = "rubybits"
gem.homepage = "http://github.com/mwylde/rubybits"
gem.license = "MIT"
- gem.summary = %Q{A library that makes dealing with bit strings and binary formats easier, inspired by Erlang}
+ gem.summary = %Q{A library that makes dealing with bit strings and binary formats easier, inspired by BitStruct}
gem.description = %Q{TODO: longer description of your gem}
gem.email = "mwylde@wesleyan.edu"
gem.authors = ["Micah Wylde"]
View
@@ -1,7 +1,29 @@
+# Provides various utilities for working with binary formats.
module RubyBits
# You can subclass RubyBits::Strcuture to define new binary formats. This
# can be used for lots of purposes: reading binary data, communicating in
# binary formats (like TCP/IP, http, etc).
+ #
+ # @example
+ # class NECProjectorFormat < RubyBits::Structure
+ # unsigned :id1, 1.byte, "Identification data assigned to each command"
+ # unsigned :id2, 1.byte, "Identification data assigned to each command"
+ # unsigned :p_id, 1.byte, "Projector ID"
+ # unsigned :m_code, 4.bits, "Model code for projector"
+ # unsigned :len, 12.bits, "Length of data in bytes"
+ # variable :data, 1.byte, "Packet data", :length => :len
+ # unsigned :checksum,1.byte, "Checksum"
+ #
+ # checksum :checksum do |bytes|
+ # bytes[0..-2].inject{|sum, byte| sum += byte} & 255
+ # end
+ # end
+ #
+ # NECProjectorFormat.parse(buffer)
+ # # => [<NECProjectorFormat>, <NECProjectorFormat>]
+ #
+ # NECProjectorFormat.new(:id1 => 0x44, :id2 => 2, :p_id => 0, :m_code => 0, :len => 5, :data => "hello").to_s.bytes.to_a
+ # # => [0x44, 0x2, 0x05, 0x00, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x5F]
class Structure < Object
class << self
[:unsigned, :signed, :text, :variable].each{|kind|
@@ -10,11 +32,22 @@ class << self
end
}
+ # Sets the checksum field. Setting a checksum field alters the functionality
+ # in several ways: the checksum is automatically calculated and set, and #parse
+ # will only consider a bitstring to be a valid instance of the structure if it
+ # has a checksum appropriate to its data.
+ # @param field [Symbol] the field that contains the checksum data
+ # @yield [bytes] block that should calculate the checksum given bytes, which is
+ # an array of bytes representing the full structure, with the checksum field
+ # set to 0
def checksum field, &block
@_checksum_field = [field, block]
end
+ # A list of the fields in the class
def fields; @_fields; end
+
+ # The checksum field
def checksum_field; @_checksum_field; end
private
@@ -33,6 +66,10 @@ def #{name}
end
end
+ # Creates a new instance of the class. You can pass in field names to initialize to
+ # set their values.
+ # @example
+ # MyStructure.new(:field1 => 44, :field2 => 0x70, :field3 => "hello")
def initialize(values={})
values.each{|key, value|
self.send "#{key}=", value
@@ -66,18 +103,10 @@ def to_s(do_checksum = true)
#puts buffer.collect{|x| "%08b" % x}.inspect
#puts [0b11010001, 0b10101010, 0b11111010, 0b10001110].collect{|x| "%08b" % x}.inspect
- buffer.pack("c*")
-
+ buffer.pack("c*")
end
-
- protected
-
- PACK_MAP = {
- :unsigned => "I",
- :signed => "i"
- }
-
+ # Calculates and sets the checksum bit according to the checksum field defined by #checksum
def calculate_checksum
if self.class.checksum_field
self.send("#{self.class.checksum_field[0]}=", 0)
@@ -87,13 +116,23 @@ def calculate_checksum
end
end
+ protected
+ # Returns the input number with the specified bit set to the specified value
+ # @param byte [Fixnum] Number to be modified
+ # @param bit [Fixnum] Bit number to be set
+ # @param value [Fixnum: {0, 1}] Value to set (either 0 or 1)
+ # @return [Fixnum] byte with bit set to value
def set_bit(byte, bit, value)
#TODO: this can probably be made more efficient
byte & (1<<bit) > 0 == value > 0 ? byte : byte ^ (1<<bit)
end
- def get_bit(byte, bit)
- byte & (1<<bit) > 0 ? 1 : 0
+ # Returns the value at position bit of byte
+ # @param number [Fixnum] Number to be queried
+ # @param bit [Fixnum] bit of interest
+ # @return [Fixnum: {0, 1}] 0 or 1, depending on the value of the bit at position bit of number
+ def get_bit(number, bit)
+ number & (1<<bit) > 0 ? 1 : 0
end
end

0 comments on commit 5a9a200

Please sign in to comment.