How can I do bitwise operation between string and hexadecimal?
I need to use input of string to bitwise OR with hexadecimal and result should be hexadecimal.
First, input is string of time.
So 23:00 would be ["23", "00"].
Then I need it in hexadecimal as it is. For example, 23->0x23, 11->-0x11.
Now, bitwise OR with hexadecimal. But it doesn't give the result I want.
Expected result of (time[0] | 0x80) is 0xA3, where time[0] is 0x23 (0x isn't necessary)
Below is what I coded.
let input = "23:00"
let time = input.split(":"); //--> ["23","00"]
console.log(time[0] | 80); //--> 87
console.log(time[0] | "80"); //--> 87
console.log("0x"+time[0] | 80); //--> 115
console.log("0x"+time[0] | "0x80") //--> 163
you need to use proper radix in string2int2string conversions:
let input = "23:00"
let time = input.split(":"); //--> ["23","00"]
let temp = parseInt(time[0],16) | 0x80;
console.log(temp.toString(10)); // prints 163
console.log(temp.toString(16)); // prints a3
Related
I have several strings like
I need to match the strings that start wih >=100 and <=300 folowed by space and then any string.
The expected result is
I have tried with
[123][0-9][0-9]\s.*
But this matched incorrectly giving 301, 399 and so on. How do I correct it?
If you're absolutely set on a regex solution, try looking for 100 - 299 or 300
const rx = /^([12][0-9]{2}|300)\s./
// | | | | | | |
// | | | | | | Any character
// | | | | | A whitespace character
// | | | | Literal "300"
// | | | or
// | | 0-9 repeated twice
// | "1" or "2"
// Start of string
You can then use this to filter your strings with a test
const strings = [
"99 Apple",
"100 banana",
"101 pears",
"200 wheat",
"220 rice",
"300 corn",
"335 raw maize",
"399 barley",
"400 green beans",
]
const rx = /^([12][0-9]{2}|300)\s./
const filtered = strings.filter(str => rx.test(str))
console.log(filtered)
.as-console-wrapper { max-height: 100% !important; }
That is because in your pattern, it also matches 3xx where x can be any digit and not just 0. If you change your pattern to match 1xx, 2xx and 300 then it will return the result as you intended, i.e.:
/^([12][0-9][0-9]|300)\s.*/g
See example below:
const str = `
99 Apple
100 banana
101 pears
200 wheat
220 rice
300 corn
335 raw maize
399 barley
400 green beans
`;
const matches = str.split('\n').filter(s => s.match(/^([12][0-9][0-9]|300)\s.*/));
console.log(matches);
However, using regex to match numerical values might not be as intuitive than simply extracting any numbers from a string, converting them to a number and then simply using mathematical operations. We can use the unary + operator to convert the matched number-like string as such:
const str = `
99 Apple
100 banana
101 pears
200 wheat
220 rice
300 corn
335 raw maize
399 barley
400 green beans
`;
const entries = str.split('\n').filter(s => {
const match = s.match(/\d+\s/);
return match !== null && +match[0] >= 100 & +match[0] <= 300;
});
console.log(entries);
I am looking at this:
function encodeCodePoint(codePoint) {
if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
return stringFromCharCode(codePoint);
}
var symbol = '';
if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
}
else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
checkScalarValue(codePoint);
symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
symbol += createByte(codePoint, 6);
}
else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
symbol += createByte(codePoint, 12);
symbol += createByte(codePoint, 6);
}
symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
return symbol;
}
which, in JavaScript, seems to be taking advantage of the fact that the numbers in JavaScript are (I think) something around 32-bits long. So it does some bit manipulation which I am unfamiliar with and gets the encoded value. Same with the decode function:
function decodeSymbol() {
var byte1;
var byte2;
var byte3;
var byte4;
var codePoint;
if (byteIndex > byteCount) {
throw Error('Invalid byte index');
}
if (byteIndex == byteCount) {
return false;
}
// Read first byte
byte1 = byteArray[byteIndex] & 0xFF;
byteIndex++;
// 1-byte sequence (no continuation bytes)
if ((byte1 & 0x80) == 0) {
return byte1;
}
// 2-byte sequence
if ((byte1 & 0xE0) == 0xC0) {
byte2 = readContinuationByte();
codePoint = ((byte1 & 0x1F) << 6) | byte2;
if (codePoint >= 0x80) {
return codePoint;
} else {
throw Error('Invalid continuation byte');
}
}
// 3-byte sequence (may include unpaired surrogates)
if ((byte1 & 0xF0) == 0xE0) {
byte2 = readContinuationByte();
byte3 = readContinuationByte();
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
if (codePoint >= 0x0800) {
checkScalarValue(codePoint);
return codePoint;
} else {
throw Error('Invalid continuation byte');
}
}
// 4-byte sequence
if ((byte1 & 0xF8) == 0xF0) {
byte2 = readContinuationByte();
byte3 = readContinuationByte();
byte4 = readContinuationByte();
codePoint = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0C) |
(byte3 << 0x06) | byte4;
if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
return codePoint;
}
}
throw Error('Invalid UTF-8 detected');
}
Basically, I can't quite read this code and can't really tell what's going on. Wondering if one with better bit-manipulation chops or UTF-8 encoding knowledge could describe at a high level what the input and output are from encoding and decoding, and very roughly how it goes from input to output for each. I am trying to build a utf-8 encoder/decoder and don't see exactly how an 8-bit stream is chunked into 1 to 4 byte chunks, partly because the JavaScript 32-bit integer thingy is getting in the way I think. But to me it seems like this is what happens:
Decoding:
We have an 8-bit (1-byte) stream of data.
We get a byte
We check if that byte is within a certain range of some sort (which I don't know)
If it's in some range, then we know an extra byte follows, or something like that.
We then collect all the bytes for the character...
And in the case of JavaScript, convert it to an integer and then String.fromCharCode(integer) sort of thing.
What I'm missing is how exactly it goes from the 1-byte sequence to up to 4 bytes, how does it do that part?
Encoding:
This is language/architecture dependent, since some architectures will have integers be 16, 32, or 64 bits (...I'm guessing...).
In the case of JavaScript, take the 32-ish-bit integer and do some bit-manipulation magic to extract out the 1 to 4 bytes for this character. How does it know how many bytes to receive???
Repeat until you have an array of bytes.
Wondering if one could fill in the gaps in my understanding. I'm not looking for exactly each bit-manipulation step, as there are a lot. I am just looking for the questions which I highlighted in my analysis just above.
JS integers have 32bit binary operators, thus you can safely work with 4 x 8bit (4bytes) in one single number. That's what your decoder receives as a parameter.
UTF-8 encoding is variable in size. If the codepoint would only take 7bits (= ASCII), then it would fit into one byte, that has a leading zero to indicate that it only has one byte:
0XXXXXXXX
Now to check whether the codepoint is only one byte, one could check if there is a bit set somewhere in the upper bytes. That can be done by comparing the codepoint to 0xFFFFF80, which has all bits set excluding the last 8. Thus, if a bitwise and results in something unequal 0, there is a bit set somewhere in the upper bytes.
1111111111111111111110000000 &
0XXXXXXX
= 0
Now if there are more than 7 bits, the first byte contains the number of bytes, all the following bytes contain a 01 sequence at the beginning, for 4 bytes that would be:
11110XXX 10XXXXXX 10XXXXXX 10XXXXXX
Now to get the upper 8 encoded bits here for example, one could rightshift by 18:
1110XXX 10XXXXX
I seem to not be understanding the Uint32Array. According to what I've read about the Uint8Array I could just feed it a number inside an array (Uint8Array([16]) or Uint8Array([96,56])) and the results are exactly that. However, when I try the same thing for a larger number like Uint32Array([21640]), it seems to truncate it. Where 21640 should equal 5488 in hex, I only get 88. How does this actually work?
Edit: Elaborations
I am also attempting to concatenate several ArrayBuffers together. If I'm not mistaken readAsArrayBuffer produces an Uint8Array, and I am trying to append to that some 32-bit numbers using https://gist.github.com/72lions/4528834
There is so much information and examples on Uint8Array and what little there was on Uint32Array makes me think that one of these 32 would store a value as if it was 4 of the 8.
The largest value of an unsigned 8 bit number is 255. Larger numbers will be truncated or rolled over depending on the os/cpu. If you want to convert a 32 bit numbers in an 8 bit array try something like this.
var number = 21640;
var byte1 = 0xff & number;
var byte2 = 0xff & (number >> 8);
var byte3 = 0xff & (number >> 16);
var byte4 = 0xff & (number >> 24);
var arr1 = Uint8Array([byte1,byte2,byte3,byte4]);
Just reverse the order of the bytes when you create the array depending on if you want little or big endian.
Here is a working example showing 5488 in console
var bigNumber = new Uint32Array([21640]);
console.log(bigNumber[0].toString(16));
Since you've added more to the question. If you wanted to convert
var byte1 = 0x88;
var byte2 = 0x54;
var byte3 = 0;
var byte4 = 0;
var bigValue = (byte4 << 24) | (byte3 << 16) | (byte2 << 8) | (byte1);
console.log(bigValue);
Although you will need to factor in Endianness
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...
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.
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.
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
I am receiving and sending a decimal representation of two little endian numbers. I would like to:
shift one variable 8 bits left
OR them
shift a variable number of bits
create 2 8 bit numbers representing the first and second half of the 16 bit number.
javascript (according to https://developer.mozilla.org/en/JavaScript/Reference/Operators/Bitwise_Operators) uses big endian representation when shifting...
endianness is a bit foreign to me (I am only 90 percent sure that my outlined steps are what i want.) so swapping is a bit dizzying. please help! I only really need to know how to swap the order in an efficient manner. (I can only think of using a for loop on a toString() return value)
function swap16(val) {
return ((val & 0xFF) << 8)
| ((val >> 8) & 0xFF);
}
Explanation:
Let's say that val is, for example, 0xAABB.
Mask val to get the LSB by &ing with 0xFF: result is 0xBB.
Shift that result 8 bits to the left: result is 0xBB00.
Shift val 8 bits to the right: result is 0xAA (the LSB has "dropped off" the right-hand side).
Mask that result to get the LSB by &ing with 0xFF: result is 0xAA.
Combine the results from steps 3 and step 5 by |ing them together:
0xBB00 | 0xAA is 0xBBAA.
function swap32(val) {
return ((val & 0xFF) << 24)
| ((val & 0xFF00) << 8)
| ((val >> 8) & 0xFF00)
| ((val >> 24) & 0xFF);
}
Explanation:
Let's say that val is, for example, 0xAABBCCDD.
Mask val to get the LSB by &ing with 0xFF: result is 0xDD.
Shift that result 24 bits to the left: result is 0xDD000000.
Mask val to get the second byte by &ing with 0xFF00: result is 0xCC00.
Shift that result 8 bits to the left: result is 0xCC0000.
Shift val 8 bits to the right: result is 0xAABBCC (the LSB has "dropped off" the right-hand side).
Mask that result to get the second byte by &ing with 0xFF00: result is 0xBB00.
Shift val 24 bits to the right: result is 0xAA (everything except the MSB has "dropped off" the right-hand side).
Mask that result to get the LSB by &ing with 0xFF: result is 0xAA.
Combine the results from steps 3, 5, 7 and 9 by |ing them together:
0xDD000000 | 0xCC0000 | 0xBB00 | 0xAA is 0xDDCCBBAA.
Such function can be used to change endianness in js:
const changeEndianness = (string) => {
const result = [];
let len = string.length - 2;
while (len >= 0) {
result.push(string.substr(len, 2));
len -= 2;
}
return result.join('');
}
changeEndianness('AA00FF1234'); /// '3412FF00AA'
Use the << (bit shift) operator. Ex: 1 << 2 == 4.
I really think that the underlying implementation of JavaScript will use whatever endianess the platform it is running on is using. Since you cannot directly access memory in JavaScript you won't ever have to worry about how numbers are represented physically in memory. Bit shifting integer values always yield the same result no matter the endianess. You only see a difference when looking at individual bytes in memory using pointers.
Here is a oneliner for arrays to swap between big and little endian (and vise versa). The swapping is done using reverse on byte level. I guess for large arrays, it is more efficient than looping over scalar swap function.
function swapbyte(x) {
return new Float64Array(new Int8Array(x.buffer).reverse().buffer).reverse()
}
// Example
buf = new ArrayBuffer(16); // for 2 float64 numbers
enBig = new Float64Array(buf);
enBig[0] = 3.2073756306779606e-192;
enBig[1] = 2.7604354232023903e+199;
enLittle = swapbyte(enBig)
// two famous numbers are revealed
console.log(enLittle)
// Float64Array [ 6.283185307179586, 2.718281828459045 ]
// swapping again yields the original input
console.log(swapbyte(enLittle))
// Float64Array [ 3.2073756306779606e-192, 2.7604354232023903e+199 ]