2

I'm writing on a shared codebase, and we have a linting rule for 'no bitwise operations'. However I'm using a short utility function for converting a binary string to an unsigned int 32, big-endian. It works well:

// converts a four-character string into a big endian 32-bit unsigned integer
stringAsUInt32BE(binString) {
  return (binString.charCodeAt(0) << 24) + (binString.charCodeAt(1) << 16) +
    (binString.charCodeAt(2) << 8) + binString.charCodeAt(3);
};

How can I do this without bitwise operations? Thanks!

3
  • 2
    You really should disable such a nonsensical linting rule for that particular function. Commented Jun 8, 2016 at 13:50
  • I assume your function has a bug for input strings whose first character is > \x7F. If you consider that as the desired behavior, please let us know. See stackoverflow.com/a/37705109/1647737 Commented Jun 8, 2016 at 14:39
  • @Bergi Shows us how such rules can have some merit after all Commented Jun 8, 2016 at 15:26

2 Answers 2

2

You can replace << x with * Math.pow(2, x).

The main difference between these two statements is the behavior for very big or negative input x, e.g. bitwise operators turn their operands into two-complement numbers while the other arithmetic operators don't.

// converts a four-character string into a big endian 32-bit unsigned integer
function stringAsUInt32BE(binString) {
  return binString.charCodeAt(0) * 16777216 + binString.charCodeAt(1) * 65536 + binString.charCodeAt(2) * 256 + binString.charCodeAt(3);
}

console.log(stringAsUInt32BE('\xFF\xFF\xFF\xFF')); // 4294967295
console.log(stringAsUInt32BE('\x00\x00\x00\x00')); // 0

Note the behavior for stringAsUInt32BE('\xFF\xFF\xFF\xFF'): Your original function would return -1 which I consider a bug. This is because '\xFF'.charCodeAt(0) << 24 === 255 << 24 exceeds the maximum range Math.pow(2, 32-1)-1 of a two-complement and thus overflows to -16777216. The function given here does not suffer from that conversion issue.

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

1 Comment

It was not intentional that a string with a first character of > \x7F would result in -1. Thanks for the insight!
2

You could use an ArrayBuffer with 2 different views. Write the bytes in using a Uint8Array and read out a value using a DataView specifying big-endianness like this:

stringAsUInt32BE(binString) {
    var buffer = new ArrayBuffer(4);
    var uint8View = new Uint8Array(buffer);
    uint8View[0] = binString.charCodeAt(0);
    uint8View[1] = binString.charCodeAt(1);
    uint8View[2] = binString.charCodeAt(2);
    uint8View[3] = binString.charCodeAt(3);
    return new DataView(buffer).getUint32(0, false); // false for big endian
}

Using bit-manipulation will work better on older browsers when typed arrays aren't supported.

Comments

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.