user202987
user202987

Reputation: 1246

JavaScript - Negative byte from integer

I transmit a byte that's always less than 127 with a 1 bit flag to the client by ORing the byte with 0x80.

On the client side, in JavaScript, I have an Array() of numbers representing the bytes of the message (yes it's probably dumb but I haven't figured out typed arrays yet).

Everything works fine until I hit a number with the highest bit of the lowest byte set.

Number:    0011 0101
  flag:    1000 0000
           ---------
           1011 0101


Stored as
integer in   ???
JavaScript

How can I retrieve the original byte (with the highest bit set to 0), plus the flag (denoted by the value of the highest bit)?

EXAMPLE:

(server)
byte x = 90
x | 0x80
> -38

(client - JavaScript)
var x = -38
x ^ 0x80
> -166

How do I get 90 back?

EDIT - I discovered this was due to another bug in my code... I wasn't going crazy with the encoding... sorry all...

Upvotes: 1

Views: 1837

Answers (3)

Aadit M Shah
Aadit M Shah

Reputation: 74204

Try the following in JavaScript:

var received = -38;
var adjusted = received & 0xFF; // 218
var original = adjusted ^ 0x80; // 90

That should solve your problem.

Explanation: All numbers in JavaScript stored in the double-precision floating point format:

Bitwise operators however can't deal with floating point numbers. Hence they convert their operands into 32-bit signed integers. [source]

-38 = 11111111 11111111 11111111 11011010

Hence if you do -38 ^ 0x80 you get the wrong answer as only the 8th bit from the right is set to 0. You need to first limit -38 to 8-bits before xoring it with 0x80. Only the least significant byte (i.e. 11011010) is needed. Hence we do -38 & 0xFF to get the least significant byte.

Now that you have the correct byte you may simply xor it with 0x80.

TLDR: Use byte & 0xFF ^ 0x80.

Upvotes: 1

freefaller
freefaller

Reputation: 19953

I'm not seeing a problem.

Here is some code I've written to test, with JSFiddle live demo

var val = 57;
var flag = 1;

var valWithFlag = val | (flag ? 0x80 : 0);
var newVal = (valWithFlag & 0x7F);
var newValFlag = (valWithFlag & 0x80 ? 1 : 0);

alert("Val: " + val.toString() + "\n" + 
      "Flag: " + flag.toString() + "\n" +
      "Val With Flag: " + valWithFlag.toString() + "\n" + 
      "New Val Without Flag: " + newVal.toString() + "\n" + 
      "New Val Flag: " + newValFlag.toString() + "\n");

It is giving the desired results...

Val: 57
Flag: 1
Val With Flag: 185
New Val Without Flag: 57
New Val Flag: 1

UPDATE based on extra details provided by the OP

I think this is probably due to integers in javascript being held either as 32 or 64 bit values... so when you pass through -38 to javascript it isn't being held in the same way as the single byte on your server.

You need to convert that -38 into an 8-byte...

var val = -38;
var jsVal = (val & 0xFF);

Which should give you your 90 value to work with. Here is an updated JSFiddle

Upvotes: 0

ZER0
ZER0

Reputation: 25322

Not sure I understand the question, but I will give a shot: you have just to XORing the 0x80:

var received = 181; // 10110101
var num = received ^ 0x80;

console.log(num); // 53, 00110101

If you have a different result, probably there is something different in your code – if you run the code above, should give the expected result.

Upvotes: 0

Related Questions