Class: Flt::Bytes

Inherits:
String
  • Object
show all
Defined in:
lib/float-formats/bytes.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bytes) ⇒ Bytes

Returns a new instance of Bytes.



105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/float-formats/bytes.rb', line 105

def initialize(bytes)
  case bytes
    when Bytes
      @bytes = bytes.to_s
    when Array
      @bytes = bytes.pack("C*")
    else
      @bytes = bytes.to_str
  end
  @bytes.force_encoding("BINARY") if @bytes.respond_to?(:force_encoding)
  super @bytes
end

Class Method Details

.from_bitfields(lens, fields, byte_endianness = :little_endian, bits_little_endian = false) ⇒ Object

pack fixed-width bit-fields as integers into a byte string



292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/float-formats/bytes.rb', line 292

def Bytes.from_bitfields(lens,fields,byte_endianness=:little_endian, bits_little_endian=false)
  i = 0
  lens = lens.reverse
  fields = fields.reverse

  bits = 0

  (0...lens.size).each do |j|
    i <<= lens[j]
    i |= fields[j]
    bits += lens[j]
  end
  from_i i,(bits+7)/8,byte_endianness, bits_little_endian
end

.from_bits(bits, byte_endianness = :little_endian, bits_little_endian = false, nbits = nil) ⇒ Object



313
314
315
316
# File 'lib/float-formats/bytes.rb', line 313

def Bytes.from_bits(bits,byte_endianness=:little_endian, bits_little_endian=false,nbits=nil)
  nbits ||= (bits.size+7)/8
  from_i bits.to_i, nbits, byte_endianness, bits_little_endian
end

.from_hex(hex) ⇒ Object

generate a byte string from an hex representation



168
169
170
# File 'lib/float-formats/bytes.rb', line 168

def Bytes.from_hex(hex)
  Bytes.new [hex.tr(' ','')].pack('H*')
end

.from_i(i, len = 0, byte_endianness = :little_endian, bits_little_endian = false) ⇒ Object

Convert an integer to a byte string



265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/float-formats/bytes.rb', line 265

def Bytes.from_i(i, len=0, byte_endianness=:little_endian, bits_little_endian=false)
  return nil if i<0
  bytes = Bytes.new("")
  while i>0
    b = (i&0xFF)
    bytes << b
    i >>= 8
  end
  bytes << 0 while bytes.size<len
  bytes.reverse_byte_bits! if bits_little_endian
  bytes.convert_endianness!(:little_endian, byte_endianness)
  bytes
end

Instance Method Details

#+(b) ⇒ Object



149
150
151
# File 'lib/float-formats/bytes.rb', line 149

def +(b)
  Bytes.new(to_str + b.to_str)
end

#[](*params) ⇒ Object



128
129
130
131
132
133
134
# File 'lib/float-formats/bytes.rb', line 128

def [](*params)
  if params.size == 1 && !params.first.kind_of?(Range)
    _get_str(params.first).ord # bytes.to_a[params.first]
  else
    Bytes.new(_get_str(*params))
  end
end

#[]=(i, v) ⇒ Object



135
136
137
# File 'lib/float-formats/bytes.rb', line 135

def []=(i,v)
  _set_str i, v.chr(Encoding::BINARY)
end

#_get_strObject



126
127
128
129
130
131
132
# File 'lib/float-formats/bytes.rb', line 126

def [](*params)
  if params.size == 1 && !params.first.kind_of?(Range)
    _get_str(params.first).ord # bytes.to_a[params.first]
  else
    Bytes.new(_get_str(*params))
  end
end

#_set_strObject



127
# File 'lib/float-formats/bytes.rb', line 127

alias _set_str []=

#convert_endianness(from_endianness, to_endianness) ⇒ Object



243
244
245
# File 'lib/float-formats/bytes.rb', line 243

def convert_endianness(from_endianness, to_endianness)
  dup.convert_endianness!(from_endianness, to_endianness)
end

#convert_endianness!(from_endianness, to_endianness) ⇒ Object

Supported endianness modes for byte strings are:

:little_endian

(Intel order): least significant bytes come first.

:big_endian

(Network order): most significant bytes come first.

:little_big_endian or :middle_endian

(PDP-11 order): each pair of bytes (16-bit word) has the bytes in little endian order, but the words are stored in big endian order (we assume the number of bytes is even).

Note that the :big_little_endian order which would logically complete the set is not currently supported as it has no known uses.



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/float-formats/bytes.rb', line 224

def convert_endianness!(from_endianness, to_endianness)
  if from_endianness!=to_endianness
    if ([:little_endian,:big_endian]+[from_endianness, to_endianness]).uniq.size==2
      # no middle_endian order
      reverse!
    else
      # from or to is middle_endian
      if [:middle_endian, :little_big_endian].include?(to_endianness)
        # from little_big_endian
        convert_endianness!(from_endianness, :big_endian).reverse_byte_pairs!
      else
        # from little_big_endian
        reverse_byte_pairs!.convert_endianness!(:big_endian, to_endianness)
      end
    end
  end
  self
end

#dupObject



118
119
120
# File 'lib/float-formats/bytes.rb', line 118

def dup
  Bytes.new @bytes.dup
end

#reverse_byte_bitsObject



180
181
182
# File 'lib/float-formats/bytes.rb', line 180

def reverse_byte_bits
  dup.reverse_byte_bits!
end

#reverse_byte_bits!Object

Reverse the order of the bits in each byte.



174
175
176
177
178
# File 'lib/float-formats/bytes.rb', line 174

def reverse_byte_bits!
  @bytes = @bytes.unpack('b*').pack("B*")[0]
  __setobj__ @bytes
  self
end

#reverse_byte_nibblesObject



195
196
197
# File 'lib/float-formats/bytes.rb', line 195

def reverse_byte_nibbles
  dup.reverse_byte_nibbles!
end

#reverse_byte_nibbles!Object

Reverse the order of the nibbles in each byte.



185
186
187
188
189
190
191
192
193
194
# File 'lib/float-formats/bytes.rb', line 185

def reverse_byte_nibbles!
  w = ""
  w.force_encoding("BINARY") if w.respond_to?(:force_encoding)
  @bytes.each_byte do |b|
    w << ((b >> 4)|((b&0xF)<<4))
  end
  @bytes = w
  __setobj__ @bytes
  self
end

#reverse_byte_pairsObject



212
213
214
# File 'lib/float-formats/bytes.rb', line 212

def reverse_byte_pairs
  dup.reverse_byte_pairs!
end

#reverse_byte_pairs!Object

reverse the order of bytes in 16-bit words



200
201
202
203
204
205
206
207
208
209
210
# File 'lib/float-formats/bytes.rb', line 200

def reverse_byte_pairs!
    w = ""
    w.force_encoding("BINARY") if w.respond_to?(:force_encoding)
    (0...@bytes.size).step(2) do |i|
      w << @bytes[i+1]
      w << @bytes[i]
    end
    @bytes = w
    __setobj__ @bytes
    self
end

#sizeObject



123
124
125
# File 'lib/float-formats/bytes.rb', line 123

def size
  bytesize
end

#to_bitfields(lens, byte_endianness = :little_endian, bits_little_endian = false) ⇒ Object

convert a byte string to separate fixed-width bit-fields as integers



280
281
282
283
284
285
286
287
288
289
# File 'lib/float-formats/bytes.rb', line 280

def to_bitfields(lens,byte_endianness=:little_endian, bits_little_endian=false)
  fields = []
  i = to_i(byte_endianness,bits_little_endian)
  for len in lens
    mask = (1<<len)-1
    fields << (i&mask)
    i >>= len
  end
  fields
end

#to_bits(byte_endianness = :little_endian, bits_little_endian = false, nbits = nil) ⇒ Object



307
308
309
310
311
# File 'lib/float-formats/bytes.rb', line 307

def to_bits(byte_endianness=:little_endian, bits_little_endian=false,nbits=nil)
  i = to_i(byte_endianness, bits_little_endian)
  nbits ||= 8*size
  Bits.from_i(i,nbits)
end

#to_hex(sep_bytes = false) ⇒ Object

return an hex representation of a byte string



154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/float-formats/bytes.rb', line 154

def to_hex(sep_bytes=false)
  hx = @bytes.unpack('H*')[0].upcase
  if sep_bytes
    sep = ""
    (0...hx.size).step(2) do |i|
      sep << " " unless i==0
      sep << hx[i,2]
    end
    hx = sep
  end
  hx
end

#to_i(byte_endianness = :little_endian, bits_little_endian = false) ⇒ Object

Convert a byte string to an integer



253
254
255
256
257
258
259
260
261
262
# File 'lib/float-formats/bytes.rb', line 253

def to_i(byte_endianness=:little_endian, bits_little_endian=false)
  i = 0
  bytes = convert_endianness(byte_endianness, :big_endian)
  bytes = bytes.reverse_byte_bits if bits_little_endian
  bytes.each_byte do |b|
    i <<= 8
    i |= b
  end
  i
end