JavaScript equivalent to htonl? - javascript

For an AJAX request, I need to send a magic number as the first four bytes of the request body, most significant byte first, along with several other (non-constant) values in the request body. Is there something equivalent to htonl in JavaScript?
For example, given 0x42656566, I need to produce the string "Beef". Unfortunately, my number is along the lines of 0xc1ba5ba9. When the server reads the request, it is getting the value -1014906182 (instead of -1044751447).

There's no built-in function, but something like this should work:
// Convert an integer to an array of "bytes" in network/big-endian order.
function htonl(n)
{
// Mask off 8 bytes at a time then shift them into place
return [
(n & 0xFF000000) >>> 24,
(n & 0x00FF0000) >>> 16,
(n & 0x0000FF00) >>> 8,
(n & 0x000000FF) >>> 0,
];
}
To get the bytes as a string, just call String.fromCharCode on each byte and concatenate them:
// Convert an integer to a string made up of the bytes in network/big-endian order.
function htonl(n)
{
// Mask off 8 bytes at a time then shift them into place
return String.fromCharCode((n & 0xFF000000) >>> 24) +
String.fromCharCode((n & 0x00FF0000) >>> 16) +
String.fromCharCode((n & 0x0000FF00) >>> 8) +
String.fromCharCode((n & 0x000000FF) >>> 0);
}

Simplified version http://jsfiddle.net/eZsTp/ :
function dot2num(dot) { // the same as ip2long in php
var d = dot.split('.');
return ((+d[0]) << 24) +
((+d[1]) << 16) +
((+d[2]) << 8) +
(+d[3]);
}
function num2array(num) {
return [
(num & 0xFF000000) >>> 24,
(num & 0x00FF0000) >>> 16,
(num & 0x0000FF00) >>> 8,
(num & 0x000000FF)
];
}
function htonl(x)
{
return dot2num(num2array(x).reverse().join('.'));
}
var ipbyte = dot2num('12.34.56.78');
alert(ipbyte);
var inv = htonl(ipbyte);
alert(inv + '=' + num2array(inv).join('.'));

Related

Why use large numbers directly in your code in javascript?

If you look at GA(google analytics), 268435455, 2147483647 will do bit operations with these numbers.
AirBnB Also use these numbers and bitwise operators: 3266489909, 2246822507, 3864292196.
example)
function n(e, t) {
return (65535 & e) * t + (((e >>> 16) * t & 65535) << 16) & 4294967295
}
function r(e) {
for (var t = e.length, r = 3432918353, o = 461845907, i = 0, u = void 0, a = t & -4, c = 0; c < a; c += 4) u = e.charCodeAt(c) | e.charCodeAt(c + 1) << 8 | e.charCodeAt(c + 2) << 16 | e.charCodeAt(c + 3) << 24, u = n(u, r), u = u << 15 | u >>> 17, u = n(u, o), i ^= u, i = i << 13 | i >>> 19, i = 5 * i + 3864292196 | 0;
switch (u = 0, t % 4) {
case 3:
u = e.charCodeAt(a + 2) << 16;
case 2:
u |= e.charCodeAt(a + 1) << 8;
case 1:
u |= e.charCodeAt(a), u = n(u, r), u = u << 15 | u >>> 17, u = n(u, o), i ^= u
}
return i ^= t, i ^= i >>> 16, i = n(i, 2246822507), i ^= i >>> 13, i = n(i, 3266489909), i ^= i >>> 16, i >>> 0
}
I am wondering why it works in this way.
268435455 is an odd composite number. It is composed of six distinct prime numbers multiplied together. It has a total of sixty-four divisors.
Prime factorization of 268435455:
3 × 5 × 29 × 43 × 113 × 127
According to wikipedia, the number 2147483647 is the eighth Mersenne prime, equal to 2^31 − 1. It is one of only four known double Mersenne primes. This is the maximum positive value for a 32-bit signed binary integer in computing. The nice part about the number is that 2,147,483,647 remained the largest known prime until 1867.
Similarly other numbers also have the relevant significance in computing.
The first two numbers are bitwise AND masks. Google Analytics is trying to extract a specific number of bits from a number:
00001111 11111111 11111111 11111111 = 268435455
01111111 11111111 11111111 11111111 = 2147483647
00001111 11100000 00000000 00000000 = 266338304
Essentially, it only wants bits where there is a 1 bit—it wants to ignore the 0 bits.It's part of their domain URL hash code.
Those other numbers are mathematical constants used in the hashing algorithm MurmurHash3. Basically they have been statistically generated to provide improved results in the hash function.
If they are not chosen at random (some constants are simply random primes), they are chosen to satisfy certain mathematical/probabilistic criteria. These numbers are often found by running some sort of simulation. In particular, these numbers appear to be derived from a Simulated annealing algorithm.

How to parse ASCII HEX FLOAT in Javascript for data returned from a serial device

I have a piece of returned code from a (serial) device. I have 4 bytes of information that I need to get a usable, human-readable value from.
I tried a lot of code examples from the Internet, but I can't get a grip on it.
Here is an example of an outcome, but no formula for how to do this in JavaScript:
34 32 33 39 37 30 41 34 Bus voltage-float: A4703942=46.36
// ( so Voltage is 46.36 )
How do I get this from the Hex A4703942 in JavaScript?
I know it has something to do with a float, little or big endian... yes?
Check the below URL
http://babbage.cs.qc.cuny.edu/IEEE-754.old/32bit.html
In the above URL, you enter the string 423970A4, which is the reverse(because of that end-ian stuff) of the your bytes string and click on compute, You will get the 46.36.
The JavaScript found in this URL page's source would help you for this conversion.
To answer my own question more or less :
//extract usable data from the returned Hex
function hex2float(num) {
var sign = (num & 0x80000000) ? -1 : 1;
var exponent = ((num >> 23) & 0xff) - 127;
var mantissa = 1 + ((num & 0x7fffff) / 0x7fffff);
return sign * mantissa * Math.pow(2, exponent);
}
//make it a nice 4 digits number
function roundToTwo(num) {
return +(Math.round(num + "e+2") + "e-2");
}
print or whatever (roundToTwo(hex2float("0x"+<yourhexInput>)));[/CODE]
( sometimes there is the need to flip the bytes/Hex to become the right input )
for example :
function swap32(val) {
return ((val & 0xFF) << 24)
| ((val & 0xFF00) << 8)
| ((val >> 8) & 0xFF00)
| ((val >> 24) & 0xFF);
}

Russian characters converting to binary incorrectly (JavaScript)

I'm writing a program in JavaScript that needs to convert text to 8-bit binary, which I accomplish with a loop that uses "exampleVariable.charCodeAt(i).toString(2)", then appends "0"s to the front until the length of the binary representation of each character is 8 bits. However, when Russian characters are passed into the function, each character is converted to an 11-bit binary representation, when it should actually be 16 bits. For example, "д" converts to 10000110100, when, in actuality, it should convert to "1101000010110100". Any ideas on how to fix this?
It looks like you are trying to get the binary representation of the UTF-8 representation of the character. JavaScript uses UTF-16 internally, so you will have to do some work to do the translation. There are various libraries out there, we'd need to know more about the environment to recommend the right tools. If you wanted to code it up yourself, it would be roughly:
function codepointToUTF_8(code) {
if (code < 0x07f) {
return [code];
} else if (code < 0x800) {
var byte1 = 0xc0 | (code >> 6 );
var byte2 = 0x80 | (code & 0x3f);
return [ byte1, byte2 ];
} else if (code < 0x10000) {
var byte1 = 0xe0 | ( code >> 12 );
var byte2 = 0x80 | ((code >> 6 ) & 0x3f);
var byte3 = 0x80 | ( code & 0x3f);
return [ byte1, byte2, byte3 ];
} else {
var byte1 = 0xf0 | ( code >> 18 );
var byte2 = 0x80 | ((code >> 12) & 0x3f);
var byte3 = 0x80 | ((code >> 6) & 0x3f);
var byte4 = 0x80 | ( code & 0x3f);
return [ byte1, byte2, byte3, byte4 ];
}
}
function strToUTF_8 (str) {
var result = [];
for (var i = 0; i < str.length; i++) {
// NOTE: this will not handle anything beyond the BMP
result.push(codepointToUTF_8(str.charCodeAt(i)));
}
console.log('result = ', result);
return [].concat.apply([], result);
}
function byteToBinary (b) {
var str = b.toString(2);
while (str.length < 8) {
str = '0' + str;
}
return str;
}
function toBinaryUTF_8 (str) {
return strToUTF_8(str).map(byteToBinary).join(' ');
}
console.log("абвгд => '" + toBinaryUTF_8("абвгд") + "'");
When I execute this I get:
абвгд => '11010000 10110000 11010000 10110001 11010000 10110010 11010000 10110011 11010000 10110100'
I haven't tested this thoroughly, but it should handle the Russian characters OK. It produces an array of character codes, which if you translate as you were trying before with 8 binary bits per character, you should be fine.

Guidance to understand Base64 encoding algorithm

I found this algorithm on the net but I'm having a bit of trouble understanding exactly how it works. It encodes an Uint8Array to Base64. I would like to understand especially the sections under the comments "Combine the three bytes into a single integer" and "Use bitmasks to extract 6-bit segments from the triplet". I understood the concept of bit shifting used there, but can't understand what's its purpose in those two sections.
function base64ArrayBuffer(bytes) {
var base64 = ''
var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
var byteLength = bytes.byteLength
var byteRemainder = byteLength % 3
var mainLength = byteLength - byteRemainder
var a, b, c, d
var chunk
// Main loop deals with bytes in chunks of 3
for (var i = 0; i < mainLength; i = i + 3) {
// Combine the three bytes into a single integer
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
// Use bitmasks to extract 6-bit segments from the triplet
a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12
c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6
d = chunk & 63 // 63 = 2^6 - 1
// Convert the raw binary segments to the appropriate ASCII encoding
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
}
// Deal with the remaining bytes and padding
if (byteRemainder == 1) {
chunk = bytes[mainLength]
a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2
// Set the 4 least significant bits to zero
b = (chunk & 3) << 4 // 3 = 2^2 - 1
base64 += encodings[a] + encodings[b] + '=='
} else if (byteRemainder == 2) {
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4
// Set the 2 least significant bits to zero
c = (chunk & 15) << 2 // 15 = 2^4 - 1
base64 += encodings[a] + encodings[b] + encodings[c] + '='
}
return base64
}
The first step takes each group of 3 bytes in the input and combines them into a 24-bit number. If we call them x = bytes[i], y = bytes[i+1], and z = bytes[i+2], it uses bit-shifting and bit-OR to create a 24-bit integer whose bits are:
xxxxxxxxyyyyyyyyzzzzzzzz
Then it extracts these bits in groups of 6 to get 4 numbers. The bits of a, b, c, and d correspond this way:
xxxxxxxxyyyyyyyyzzzzzzzz
aaaaaabbbbbbccccccdddddd
Then for each of these 6-bit numbers, it indexes the encodings string to get a corresponding character, and concatenates them into the base64 result string.
At the end there are some special cases to deal with the last 1 or 2 bytes in the input if it wasn't a multiple of 3 bytes long.

Javascript unsigned short to signed short

I have the following code:
var v = [0xFF, 0xFF];
alert((v[0]<<8) | v[1]);
And it alerts 65535 (the max short value).
How can I treat this byte array as a signed short, and get the signed value of this array.
Assuming the higher bit is the sign:
var sign = v[0] & (1 << 7);
var i = ((v[0] & 0x7F) << 8) | v[1];
if (sign) {
i = -i;
}
http://jsfiddle.net/p4TQw/1/
If you use the Two's complement representation:
var i = (((v[0] << 8) | v[1]) << 16) >> 16);
The 16 bits left shift moves all bits to the left; and the arithmetic 16 bits right shift takes care of the sign while shifting. (Javascript uses 32 bits integers for shift operations.)
http://jsfiddle.net/p4TQw/3/

Categories

Resources