jscud / jsBytes

Handy helper functions for working with byte arrays in JavaScript.
1 stars 0 forks source link

Shorts / Longs #1

Open ghost opened 10 years ago

ghost commented 10 years ago

Hey, great effort here! Thank you.

I need to convert bytes created from java which consists of longs, shorts, and integers. Your function works for integers, but how would I go about doing longs and shorts?

Thanks.

ghost commented 10 years ago

I got this for shorts, seems correct?

  jsBytes.littleEndianBytesToSignedShort = function(bytes, opt_startIndex) {
  var index = jsBytes.checkBytesToIntInput(bytes, 2, opt_startIndex);
  value = bytes[index];
  value += bytes[index + 1] << 8;
  return value;
};

But it is my understanding that javascript doesn't support longs. Any way to get it from a byte array? As a string perhaps?

jscud commented 10 years ago

For a short, that would work for positive values but negatives would require some additional logic in the function. Working with 32 bit integers is a bit easier since JavaScript will do the right thing when a bit shift ends up setting the sign bit.

This previous version has some of the logic that would be needed to do the 2's complement for the negative numbers: https://github.com/jscud/jsBytes/commit/3343bb3fb97105af20c413e4dba694c34b55dc8a

Hopefully I can add some functions for 2 byte shorts soon.

Longs are a bit tricky in JavaScript since numbers are represented using 64 bit doubles, so not all 64 bit integer values can be represented in a JavaScript native data type. You could always work with an 8 byte array though it might be a bit cumbersome.

ghost commented 10 years ago

Here's what I'm using for longs:

 jsBytes.littleEndianBytesToBigInteger = function(bytes, opt_startIndex) {
    var index = jsBytes.checkBytesToIntInput(bytes, 8, opt_startIndex);

    var value = new BigInteger("0",10);

    var temp1,temp2;

    for (var i=7; i>=0; i--) {
        temp1 = value.multiply(new BigInteger("256",10));
            temp2 = temp1.add(new BigInteger(bytes[opt_startIndex+i].toString(10),10));
        value = temp2;
    }

    return value;
}

I use only .toString() on that to compare to another string representation of the long.

This uses the libraries found here:

http://www-cs-students.stanford.edu/~tjw/jsbn/

(jsbn.js + jsbn2.js)

Is there an issue with this approach?

jscud commented 10 years ago

I've added some functions for dealing with short ints. The same general pattern should be usable with the BigInteger that you are using I imagine. Looks like the code that you posted wouldn't handle negative values. If that's a concern you could base your solution on the jsBytes.littleEndianBytesToSignedInt16 function. Will need to do further multiplication as you increase the number of bytes to 8. It might help to have an accumulator which grows the multiplier as you look at each byte. The jsBytes.bigEndianBytesToUnsignedInt32 function has an example of what I mean.