Class: Fields::SignedField

Inherits:
Field show all
Defined in:
lib/fields.rb

Overview

HexstringField

Instance Attribute Summary

Attributes inherited from Field

#bitstring, #default_value, #desc, #endianness, #length, #length_type, #name, #type

Instance Method Summary collapse

Methods inherited from Field

#parse_buffer, #parse_buffer_lazy, #parse_buffer_strict, #randomize!, #set_raw, #set_value, #to_s

Constructor Details

#initialize(*args) ⇒ SignedField

Returns a new instance of SignedField.



226
227
228
229
# File 'lib/fields.rb', line 226

def initialize *args
    @length_type="fixed"
    super
end

Instance Method Details

#get_valueObject



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/fields.rb', line 252

def get_value
    tempstring=@bitstring
    if self.endianness==:little
        if tempstring.length > 8 && tempstring.length % 8 ==0
            tempstring=tempstring.scan(/.{8}/).reverse.join
        end
    end
    if tempstring.slice(0,1)=="1" #sign bit set
        0-(("1"+"0"*@length).to_i(2)-tempstring.to_i(2))
    elsif  @bitstring.slice(0,1)=="0"
        tempstring.to_i(2)
    else	
        raise RuntimeError, "SignedField: Ouch, internal contents screwed somehow."
    end
end

#input_to_bitstring(value) ⇒ Object



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/fields.rb', line 231

def input_to_bitstring( value )
    unless value.kind_of? Integer
        raise ArgumentError, "SignedField (#{@name}): attempted to assign non-integer"
    end
    if value < 0 and value.to_s(2).length > @length
        # int.to_s(2) will return "-1001001" etc for negative numbers in binary, so this length check will work.
        raise ArgumentError, "SignedField (#{@name}): negative value too long for field length"
    end
    if value > 0 and value.to_s(2).length > @length-1 # positive integers shouldn't overflow the sign bit
        raise ArgumentError, "SignedField (#{@name}): positive value too long for field length"
    end
    unpadded=value <= 0 ? (("1"+"0"*@length).to_i(2)-value.abs).to_s(2) : value.to_s(2)
    value="0"*(@length-unpadded.length)+unpadded # left pad with zeroes to full length
    if self.endianness==:little
        if value.length > 8 && value.length % 8==0
            value=value.scan(/.{8}/).reverse.join
        end
    end
    value
end