Class: Erlang::Bitstring

Inherits:
Object
  • Object
show all
Defined in:
lib/erlang/bitstring.rb

Overview

A Bitstring is a series of bits.

Creating Bitstrings

Erlang::Bitstirng["test", bits: 7]
# => Erlang::Bitstring[116, 101, 115, 4, bits: 3]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#bits::Integer (readonly)

Return the bits for this Bitstring

Returns:

  • (::Integer)


19
20
21
# File 'lib/erlang/bitstring.rb', line 19

def bits
  @bits
end

#data::String (readonly)

Return the data for this Bitstring

Returns:

  • (::String)


15
16
17
# File 'lib/erlang/bitstring.rb', line 15

def data
  @data
end

Class Method Details

.[](*data, bits: 8) ⇒ Bitstring, Binary

Create a new Bitstring populated with the given data and bits.

Parameters:

  • data (::String, Symbol, ::Enumerable, Integer)

    The content of the Binary

  • bits (Integer) (defaults to: 8)

    The number of bits to keep on the last byte

Returns:

Raises:

  • (ArgumentError)

    if data cannot be coerced to be a ::String or bits is not between 1 and 8



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/erlang/bitstring.rb', line 27

def [](*data, bits: 8)
  return EmptyBinary if data.empty?
  raise ArgumentError, 'bits must be an Integer' if not bits.is_a?(::Integer)
  raise ArgumentError, 'bits must be between 1 and 8' if bits < 1 or bits > 8
  binary = Erlang.iolist_to_binary(data)
  if bits == 8 or binary.empty?
    return binary
  else
    return new(binary, bits)
  end
end

.compare(a, b) ⇒ -1, ...

Compares a and b and returns whether they are less than, equal to, or greater than each other.

Parameters:

Returns:

  • (-1, 0, 1)

Raises:

  • (ArgumentError)

    if a or b is not a Bitstring or Binary



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/erlang/bitstring.rb', line 50

def compare(a, b)
  raise ArgumentError, "'a' must be of Erlang::Binary or Erlang::Bitstring type" if not a.kind_of?(Erlang::Binary) and not a.kind_of?(Erlang::Bitstring)
  raise ArgumentError, "'b' must be of Erlang::Binary or Erlang::Bitstring type" if not b.kind_of?(Erlang::Binary) and not b.kind_of?(Erlang::Bitstring)
  c = a.bitsize <=> b.bitsize
  return a.data <=> b.data if c == 0
  c = 0
  i = 0
  abytes = a.bytesize
  bbytes = b.bytesize
  abytes -= 1 if a.bits != 8
  bbytes -= 1 if b.bits != 8
  while c == 0 and i < abytes and i < bbytes
    c = a.data.getbyte(i) <=> b.data.getbyte(i)
    i += 1
  end
  if c == 0
    if (a.bits != 8 and i == abytes and i < bbytes) or (b.bits != 8 and i == bbytes and i < abytes) or (a.bits != 8 and b.bits != 8)
      abyte = a.data.getbyte(i)
      bbyte = b.data.getbyte(i)
      askip = 8 - a.bits
      bskip = 8 - b.bits
      i = 0
      loop do
        if i == a.bits and i == b.bits
          c = 0
          break
        elsif i == a.bits
          c = -1
          break
        elsif i == b.bits
          c = 1
          break
        end
        abit = (abyte >> (7 - ((i + askip) & 7))) & 1
        bbit = (bbyte >> (7 - ((i + bskip) & 7))) & 1
        c = abit <=> bbit
        break if c != 0
        i += 1
        break if (i & 7) == 0
      end
    elsif i >= a.bytesize and i < b.bytesize
      c = -1
    elsif i >= b.bytesize and i < a.bytesize
      c = 1
    end
  end
  return c
end

.concat(*iodata) ⇒ Binary, Bitstring

Concatenates list of Binary or Bitstring items into a single Binary or Bitstring.

Examples:

Erlang::Bitstring.concat(Erlang::Bitstring[1, bits: 2], Erlang::Binary[255])
# => Erlang::Bitstring[127, 3, bits: 2]

Parameters:

Returns:



107
108
109
# File 'lib/erlang/bitstring.rb', line 107

def concat(*iodata)
  return iodata.reduce(Erlang::EmptyBinary) { |acc, item| acc.concat(item) }
end

.emptyObject



39
40
41
# File 'lib/erlang/bitstring.rb', line 39

def empty
  return Erlang::EmptyBinary
end

Instance Method Details

#at(position) ⇒ Object Also known as: []

Raises:

  • (NotImplementedError)


135
136
137
# File 'lib/erlang/bitstring.rb', line 135

def at(position)
  raise NotImplementedError
end

#bitsizeInteger

Returns the number of bits in this Bitstring.

Returns:

  • (Integer)

    the number of bits in this Bitstring



141
142
143
# File 'lib/erlang/bitstring.rb', line 141

def bitsize
  return @bitsize
end

#bitslice(index) ⇒ Integer? #bitslice(index, length) ⇒ Bitstring, Binary #bitslice(index..end) ⇒ Bitstring, Binary

Return specific objects from the Bitstring. All overloads return nil if the starting index is out of range.

Overloads:

  • #bitslice(index) ⇒ Integer?

    Returns a single bit at the given index. If index is negative, count backwards from the end.

    Examples:

    b = Erlang::Bitstring[2, bits: 2]
    b.bitslice(0)  # => 1
    b.bitslice(1)  # => 0
    b.bitslice(-1) # => 0
    b.bitslice(2)  # => nil

    Parameters:

    • index (Integer)

      The index to retrieve. May be negative.

    Returns:

    • (Integer, nil)
  • #bitslice(index, length) ⇒ Bitstring, Binary

    Return a bitstring starting at index and continuing for length bits or until the end of the Bitstring, whichever occurs first.

    Examples:

    b = Erlang::Bitstring[1, 117, bits: 7]
    b.bitslice(0, 11) # => Erlang::Bitstring[1, 7, bits: 3]
    b.bitslice(11, 4) # => Erlang::Bitstring[5, bits: 4]
    b.bitslice(16, 1) # => nil

    Parameters:

    • start (Integer)

      The index to start retrieving bits from. May be negative.

    • length (Integer)

      The number of bits to retrieve.

    Returns:

  • #bitslice(index..end) ⇒ Bitstring, Binary

    Return a bitstring starting at index and continuing to index end or the end of the Bitstring, whichever occurs first.

    Examples:

    b = Erlang::Bitstring[1, 117, bits: 7]
    b.bitslice(0...11)  # => Erlang::Bitstring[1, 7, bits: 3]
    b.bitslice(11...15) # => Erlang::Bitstring[5, bits: 4]
    b.bitslice(16..-1)  # => nil

    Parameters:

    • range (Range)

      The range of bits to retrieve.

    Returns:

See Also:



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/erlang/bitstring.rb', line 191

def bitslice(arg, length = (missing_length = true))
  if missing_length
    if arg.is_a?(Range)
      from, to = arg.begin, arg.end
      from += bitsize if from < 0
      return nil if from < 0
      to   += bitsize if to < 0
      to   += 1       if !arg.exclude_end?
      length = to - from
      length = 0 if length < 0
      length = bitsize - from if (from + length) > bitsize
      return nil if length < 0
      l8 = length.div(8)
      l1 = length % 8
      pad = 8 - l1
      enum = each_bit
      skip = from
      enum = enum.drop_while {
        if skip > 0
          skip -= 1
          next true
        else
          next false
        end
      }
      head = enum.take(length)
      if l1 == 0
        return Erlang::Binary[[head.join].pack(BIT_PACK)]
      else
        tail = head[-l1..-1]
        head = head[0...-l1]
        tail = ([0] * pad).concat(tail)
        return Erlang::Bitstring[[[head.join, tail.join].join].pack(BIT_PACK), bits: l1]
      end
    else
      arg += bitsize if arg < 0
      return nil if arg < 0
      return nil if arg >= bitsize
      a8 = arg.div(8)
      a1 = arg % 8
      byte = @data.getbyte(a8)
      return nil if byte.nil?
      return (byte >> ((@bits - a1 - 1) & 7)) & 1
    end
  else
    return nil if length < 0
    arg += bitsize if arg < 0
    return nil if arg < 0
    length = bitsize - arg if (arg + length) > bitsize
    return nil if length < 0
    l8 = length.div(8)
    l1 = length % 8
    pad = 8 - l1
    enum = each_bit
    skip = arg
    enum = enum.drop_while {
      if skip > 0
        skip -= 1
        next true
      else
        next false
      end
    }
    head = enum.take(length)
    if l1 == 0
      return Erlang::Binary[[head.join].pack(BIT_PACK)]
    else
      tail = head[-l1..-1]
      head = head[0...-l1]
      tail = ([0] * pad).concat(tail)
      return Erlang::Bitstring[[[head.join, tail.join].join].pack(BIT_PACK), bits: l1]
    end
  end
end

#bytesizeInteger Also known as: size

Returns the number of bytes in this Bitstring.

Returns:

  • (Integer)

    the number of bytes in this Bitstring



267
268
269
# File 'lib/erlang/bitstring.rb', line 267

def bytesize
  return @data.bytesize
end

#concat(*other) ⇒ Binary, Bitstring Also known as: +

Concatenates list of Binary or Bitstring items into a single Binary or Bitstring.

Examples:

Erlang::Bitstring[3, bits: 3].concat(Erlang::Bitstring[1, bits: 5])
# => "a"

Parameters:

Returns:



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/erlang/bitstring.rb', line 280

def concat(*other)
  if other.size == 1 and (other[0].kind_of?(Erlang::Binary) or other[0].kind_of?(Erlang::Bitstring))
    other = other[0]
  else
    other = Erlang::Binary[*other]
  end
  return other if empty?
  return self if other.empty?
  if @bits == 8
    return to_binary.concat(other)
  else
    bits = (@bits + other.bits) % 8
    head = [*each_bit, *other.each_bit]
    if bits == 0
      return Erlang::Binary[[head.join].pack(BIT_PACK)]
    else
      pad  = 8 - bits
      tail = head[-bits..-1]
      head = head[0...-bits]
      tail = ([0] * pad).concat(tail)
      return Erlang::Bitstring[[[head.join, tail.join].join].pack(BIT_PACK), bits: bits]
    end
  end
end

#copy(n = 1) ⇒ Object

Raises:

  • (NotImplementedError)


307
308
309
# File 'lib/erlang/bitstring.rb', line 307

def copy(n = 1)
  raise NotImplementedError
end

#decode_unsigned(endianness = :big) ⇒ Object

Raises:

  • (NotImplementedError)


312
313
314
# File 'lib/erlang/bitstring.rb', line 312

def decode_unsigned(endianness = :big)
  raise NotImplementedError
end

#each_bit {|Integer| ... } ⇒ self

Call the given block once for each bit in the Bitstring, passing each bit from first to last successively to the block. If no block is given, returns an Enumerator.

Yields:

  • (Integer)

Returns:

  • (self)


322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/erlang/bitstring.rb', line 322

def each_bit
  return enum_for(:each_bit) unless block_given?
  index = 0
  headbits = (self.bytesize - 1) * 8
  skipbits = 8 - @bits
  @data.each_byte do |byte|
    loop do
      break if index == @bitsize
      if index >= headbits
        bit = (byte >> (7 - ((index + skipbits) & 7))) & 1
      else
        bit = (byte >> (7 - (index & 7))) & 1
      end
      yield bit
      index += 1
      break if (index & 7) == 0
    end
  end
  return self
end

#each_bitslice(number) {|Binary, Bitstring| ... } ⇒ self, Enumerator

Split the bits in this Bitstring in groups of number bits, and yield each group to the block (as a List). If no block is given, returns an Enumerator.

Examples:

b = Erlang::Bitstring[117, bits: 7]
b.each_bitslice(4).to_a # => [Erlang::Bitstring[14, bits: 4], Erlang::Bitstring[5, bits: 3]]

Yields:

Returns:

  • (self, Enumerator)

Raises:

  • (ArgumentError)

See Also:



354
355
356
357
358
359
360
361
362
363
364
365
366
# File 'lib/erlang/bitstring.rb', line 354

def each_bitslice(number)
  return enum_for(:each_bitslice, number) unless block_given?
  raise ArgumentError, 'number must be a positive Integer' if not number.is_a?(::Integer) or number < 1
  slices = bitsize.div(number) + ((bitsize % number == 0) ? 0 : 1)
  index  = 0
  loop do
    break if slices == 0
    yield(bitslice(index * number, number))
    slices -= 1
    index  += 1
  end
  return self
end

#each_byteObject

Raises:

  • (NotImplementedError)


369
370
371
# File 'lib/erlang/bitstring.rb', line 369

def each_byte
  raise NotImplementedError
end

#empty?Boolean

Returns true if this Bitstring is empty.

Returns:

  • (Boolean)


376
377
378
# File 'lib/erlang/bitstring.rb', line 376

def empty?
  return @data.empty?
end

#eql?(other) ⇒ Boolean Also known as: ==

Return true if other has the same type and contents as this Bitstring.

Parameters:

  • other (Object)

    The object to compare with

Returns:

  • (Boolean)


384
385
386
387
388
389
390
391
# File 'lib/erlang/bitstring.rb', line 384

def eql?(other)
  return true if other.equal?(self)
  if instance_of?(other.class)
    return !!(self.class.compare(self, other) == 0)
  else
    return !!(Erlang.compare(other, self) == 0)
  end
end

#erlang_inspect(raw = false) ⇒ ::String

Return the contents of this Bitstring as a Erlang-readable ::String.

Examples:

Erlang::Bitstring["test", bits: 3].erlang_inspect
# => "<<116,101,115,4:3>>"

Returns:

  • (::String)


416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
# File 'lib/erlang/bitstring.rb', line 416

def erlang_inspect(raw = false)
  return Erlang.inspect(Erlang::Binary.new(@data), raw: raw) if @bits == 8
  result = '<<'
  bytes = @data.bytes
  if last = bytes.pop
    result << bytes.join(',')
    result << ',' if not bytes.empty?
    if @bits == 8
      result << "#{last}"
    else
      result << "#{last}:#{@bits}"
    end
  end
  result << '>>'
  return result
end

#firstObject

Raises:

  • (NotImplementedError)


395
396
397
# File 'lib/erlang/bitstring.rb', line 395

def first
  raise NotImplementedError
end

#inspect::String

Returns the nicely formatted version of the Bitstring.

Returns:

  • (::String)

    the nicely formatted version of the Bitstring



434
435
436
# File 'lib/erlang/bitstring.rb', line 434

def inspect
  return "Erlang::Bitstring[#{data.bytes.inspect[1..-2]}, bits: #{bits.inspect}]"
end

#lastObject

Raises:

  • (NotImplementedError)


400
401
402
# File 'lib/erlang/bitstring.rb', line 400

def last
  raise NotImplementedError
end

#part(position, length) ⇒ Object

Raises:

  • (NotImplementedError)


405
406
407
# File 'lib/erlang/bitstring.rb', line 405

def part(position, length)
  raise NotImplementedError
end

#to_binaryBinary

Returns the Binary version of the Bitstring padded with zeroes.

Returns:

  • (Binary)

    the Binary version of the Bitstring padded with zeroes



439
440
441
442
# File 'lib/erlang/bitstring.rb', line 439

def to_binary
  return EmptyBinary if empty?
  return Erlang::Binary[@data]
end

#to_s::String Also known as: to_str

Returns the string version of the Bitstring.

Returns:

  • (::String)

    the string version of the Bitstring



445
446
447
# File 'lib/erlang/bitstring.rb', line 445

def to_s
  return @data
end