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.



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

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(Encoding::BINARY) if RUBY_VERSION>="1.9.0"
  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



170
171
172
# File 'lib/float-formats/bytes.rb', line 170

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



151
152
153
# File 'lib/float-formats/bytes.rb', line 151

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

#[](*params) ⇒ Object



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

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



137
138
139
# File 'lib/float-formats/bytes.rb', line 137

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

#_get_strObject



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

#_set_strObject



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

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



120
121
122
# File 'lib/float-formats/bytes.rb', line 120

def dup
  Bytes.new @bytes.dup
end

#reverse_byte_bitsObject



182
183
184
# File 'lib/float-formats/bytes.rb', line 182

def reverse_byte_bits
  dup.reverse_byte_bits!
end

#reverse_byte_bits!Object

Reverse the order of the bits in each byte.



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

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

#reverse_byte_nibblesObject



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

def reverse_byte_nibbles
  dup.reverse_byte_nibbles!
end

#reverse_byte_nibbles!Object

Reverse the order of the nibbles in each byte.



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

def reverse_byte_nibbles!
  w = ""
  @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



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

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

#sizeObject



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

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



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

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