0

I am trying to translate this simple function from Go to Javascript:

func ShiftLeft(b []byte) []byte {
    l := len(b)
    if l == 0 {
        panic("shiftLeft requires a non-empty buffer.")
    }

    output := make([]byte, l)

    overflow := byte(0)
    for i := int(l - 1); i >= 0; i-- {
        output[i] = b[i] << 1
        output[i] |= overflow
        overflow = (b[i] & 0x80) >> 7
    }

    return output
}

My first attempt was this:

function makeEmpty(size) {


  var result = [];

  for (var i = 0; i < size; i++) {
    result.push(0x00);
  }

  return result;

}

function shiftLeft (b) {

  var len = b.length;

  if (len == 0) {
    throw 'shiftLeft requires a non-empty buffer';
  }

  var output = makeEmpty(len);

  var overflow = 0;

  for (var i = len - 1; i >= 0; i--) {
    output[i] = b[i] << 1;
    output[i] |= overflow;
    overflow = (b[i] & 0x80) >> 7;
  }

  return output;

}

However, this does not work. Given the following test case:

function fromOctal(str) {

  var bytes = [parseInt(str, 2)];

  return bytes;

}

console.log(shiftLeft(fromOctal("10000000"))

The Javascript version returns [256], but the expected result is "00000000" or [0].

What am I getting wrong here? I think it might have to do with endianness, but I have no idea about how to deal with this kind of issue consistently.

1 Answer 1

2

Your mistake appears to be in assuming that the elements of your array are 8-bit integers, but the result of bitwise operators in JavaScript are 32-bit integers and so the most significant bit remains when you do the left shift.

I believe that adding a bit mask by changing:

output[i] = b[i] << 1;

to:

output[i] = (b[i] << 1) & 0xFF;

should fix your issue.

http://jsfiddle.net/MTj63/

As a side note, I think your fromOctal() function should actually be named fromBinary().

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks! Is there a more "consistent" way to deal with these issue? Would it be possible to use TypedArrays across the board?
I don't do all that much work with raw binary data, especially not in JavaScript, so I'm probably not the best person to ask, but I would certainly suggest looking into what ArrayBuffers and Uint8Arrays have to offer, since they are specifically designed for the type of stuff you seem to be doing. html5rocks.com/en/tutorials/webgl/typed_arrays
I doubt using a Uint8Array would help -- IIRC it's converted back to a 32 bit integer when using the bitwise operators (JavaScript doesn't actually have separate number types, it just means that it's internally stored as that type).
@OneKitten I think you're incorrect there. The whole point of the typed arrays is to provide arrays of typed values, and the article points out that "A Typed Array is a slab of memory with a typed view into it". They can't change the behavior of the bitwise operators, but when a value is assigned to the array, the right number of bits will be used. Just try this: var a = new Uint8Array(2); a[0] = 0x88; a[0] = a[0] << 1; console.log(a[0]); and you will find that the value displayed is 16 rather than 272.
@JLRishe: I see your point there (will remove both comments in 5 minutes).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.