Jump To …

ByteIterableBase.coffee

fs = require 'fs'
ByteIterable = require('../../ByteIterable.coffee').ByteIterable
ByteIterableUtil = require('./ByteIterableUtil.coffee').ByteIterableUtil

This absract class implements common methods for iterables.

class ByteIterableBase extends ByteIterable

@private

  bytes: undefined

@private

  length: undefined

@private

  @singleBytes: undefined

@private Function that returns array of arrays with single bytes from 0 to 255.

  @SINGLE_BYTES: () ->
    if !ByteIterableBase.singleBytes?
      ByteIterableBase.singleBytes = new Array 256
      for i in [0..ByteIterableBase.singleBytes.length - 1]
        ByteIterableBase.singleBytes[i] = new Buffer([i])
    return ByteIterableBase.singleBytes

Compares two iterables.

@param o the second iterable. @return number (see ByteIterableUtil.compare$ByteIterable$ByteIterable).

  compareTo$ByteIterable$emit: (o) ->
    return ByteIterableUtil.compare$ByteIterable$ByteIterable this, o

Gets iterator.

@return iterator.

  iterator: () ->
    if (@bytes == null)
      return @getIterator()
    bytes = @bytes
    length = @length
    res =
      i: 0
      hasNext: () ->
        return i < length
      next$emit: () ->
        result = bytes[i]
        i += 1
        return result
      skip$int: (len) ->
        result =  Math.min(length - i, len)
        i += result
        return result
    return res

  getBytesUnsafe: () ->
    if (@bytes == undefined)
      @fillBytes()
    return @bytes

  getLength: () ->
    if (@length == undefined)
      @fillBytes()
    return @length

Compares two iterables.

@param obj any object. @return true if objects are equal and false otherwise.

  equals$Object: (obj) ->
    return obj instanceof ByteIterable && @compareTo(obj) == 0

For tests.

@return hascode that contains all the bytes.

  hashCode: () ->
    a = @getBytesUnsafe()
    if !(a?)
      return 0
    result = 1
    length = @getLength()
    for i in [0..length - 1]
      result = 31 * result + a[i]
    return result

  toString: () ->
    a = @getBytesUnsafe()
    if (a == undefined)
      return "null"
    length = @getLength()
    if (length <= 0 || length == undefined)
      return "[]"
    s = '['
    i = 0
    while true
      s += a[i++]
      if i == length
        return s + ']'
      s += ', '

All five functions below fill bytes of the some ByteIterable to this ByteIterable or to LightOutputStream.

  fillBytes: () ->
    @fillBytes$ByteIterator @getIterator()

@param bi ByteIterable that is written to stream. @param output stream.

  @fillBytes$ByteIterable$LightOutputStream: (bi, output) ->
    it = bi.iterator()
    if it.hasNext$emit()
      ByteIterableBase.fillBytes$ByteIterator$LightOutpustStream it, output

@param bi ByteIterator of data that is written to stream. @param output stream.

  @fillBytes$ByteIterator$LightOutputStream: (it, output) ->
    while it.hasNext$emit()
      output.writeFast$int it.next$emit()

@param bi ByteIterator of data that is written to this ByteIterable.

  fillBytes$ByteIterator: (it) ->
    if (!it.hasNext$emit())
      @bytes = ByteIterableBase.EMPTY.getBytesUnsafe()
      @length = 0
    else
      @fillBytes$int$ByteIterator it.next$emit(), it

@param firstByte the first value to be written. @param bi ByteIterator of data that is written to this ByteIterable.

  fillBytes$int$ByteIterator: (firstByte, it) ->
    if !(it.hasNext$emit())
      @bytes = ByteIterableBase.SINGLE_BYTES()[firstByte & 0xff]
      @length = 1
    else
      output = (require './LightOutputStream.coffee').LightOutputStream.create()
      output.writeFast$int firstByte
      ByteIterableBase.fillBytes$ByteIterator$LightOutputStream it, output
      @bytes = output.getBufferBytes()
      @length = output.getBufferLength()

exports.ByteIterableBase = ByteIterableBase