Class: BinData::Primitive

Inherits:
BasePrimitive show all
Defined in:
lib/bindata/primitive.rb

Overview

A Primitive is a declarative way to define a new BinData data type. The data type must contain a primitive value only, i.e numbers or strings. For new data types that contain multiple values see BinData::Record.

To define a new data type, set fields as if for Record and add a #get and #set method to extract / convert the data between the fields and the #value of the object.

require 'bindata'

class PascalString < BinData::Primitive
  uint8  :len,  :value => lambda { data.length }
  string :data, :read_length => :len

  def get
    self.data
  end

  def set(v)
    self.data = v
  end
end

ps = PascalString.new(:initial_value => "hello")
ps.to_binary_s #=> "\005hello"
ps.read("\003abcde")
ps.value #=> "abc"

# Unsigned 24 bit big endian integer
class Uint24be < BinData::Primitive
  uint8 :byte1
  uint8 :byte2
  uint8 :byte3

  def get
    (self.byte1 << 16) | (self.byte2 << 8) | self.byte3
  end

  def set(v)
    v = 0 if v < 0
    v = 0xffffff if v > 0xffffff

    self.byte1 = (v >> 16) & 0xff
    self.byte2 = (v >>  8) & 0xff
    self.byte3 =  v        & 0xff
  end
end

u24 = Uint24be.new
u24.read("\x12\x34\x56")
"0x%x" % u24.value #=> 0x123456

Parameters

Primitive objects accept all the parameters that BinData::BasePrimitive do.

Instance Attribute Summary

Attributes inherited from Base

#parent

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BasePrimitive

#clear, #clear?, #eql?, #hash, #respond_to?, #value, #value=

Methods inherited from Base

#==, accepted_parameters, #assign, #clear, #clear?, #debug_name, default_parameters, #eval_parameter, #get_parameter, #has_parameter?, #inspect, mandatory_parameters, mutually_exclusive_parameters, #num_bytes, #offset, optional_parameters, #pretty_print, #read, read, #rel_offset, #snapshot, #to_binary_s, #to_s, #write

Constructor Details

#initialize(params = {}, parent = nil) ⇒ Primitive

Returns a new instance of Primitive.



131
132
133
134
135
# File 'lib/bindata/primitive.rb', line 131

def initialize(params = {}, parent = nil)
  super(params, parent)

  @struct = BinData::Struct.new(get_parameter(:struct_params), self)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args, &block) ⇒ Object

:nodoc:



137
138
139
# File 'lib/bindata/primitive.rb', line 137

def method_missing(symbol, *args, &block) #:nodoc:
  @struct.__send__(symbol, *args, &block)
end

Class Method Details

.endian(endian = nil) ⇒ Object



70
71
72
73
74
75
76
77
78
79
# File 'lib/bindata/primitive.rb', line 70

def endian(endian = nil)
  @endian ||= nil
  if [:little, :big].include?(endian)
    @endian = endian
  elsif endian != nil
    raise ArgumentError,
            "unknown value for endian '#{endian}' in #{self}", caller(1)
  end
  @endian
end

.inherited(subclass) ⇒ Object

:nodoc:



65
66
67
68
# File 'lib/bindata/primitive.rb', line 65

def inherited(subclass) #:nodoc:
  # Register the names of all subclasses of this class.
  register(subclass.name, subclass)
end

.method_missing(symbol, *args) ⇒ Object

:nodoc:



81
82
83
84
85
86
87
88
89
# File 'lib/bindata/primitive.rb', line 81

def method_missing(symbol, *args) #:nodoc:
  name, params = args

  type = symbol
  name = name.to_s
  params ||= {}

  append_field(type, name, params)
end

.sanitize_parameters!(params, sanitizer) ⇒ Object

:nodoc:



91
92
93
94
95
96
97
# File 'lib/bindata/primitive.rb', line 91

def sanitize_parameters!(params, sanitizer) #:nodoc:
  struct_params = {}
  struct_params[:fields] = fields
  struct_params[:endian] = endian unless endian.nil?
  
  params[:struct_params] = struct_params
end

Instance Method Details

#debug_name_of(child) ⇒ Object

:nodoc:



141
142
143
# File 'lib/bindata/primitive.rb', line 141

def debug_name_of(child) #:nodoc:
  debug_name + "-internal-"
end

#offset_of(child) ⇒ Object

:nodoc:



145
146
147
# File 'lib/bindata/primitive.rb', line 145

def offset_of(child) #:nodoc:
  @struct.offset_of(child)
end