PHP Bytes 2 DWord - php

I have an array:
$arr[0] = 95
$arr[1] = 8
$arr[2] = 0
$arr[3] = 0
That are bytes. I need a DWORD.
I tried:
$dword = $arr[0]+$arr[1]*265+$arr[2]*265*265+$arr[3]*265*265*265;
Is that right or am I doing it wrong?

Try:
$dword = (($arr[3] & 0xFF) << 24) | (($arr[2] & 0xFF) << 16) | (($arr[1] & 0xFF) << 8) | ($arr[0] & 0xFF);
It can also be done your way with some corrections:
$dword = $arr[0] + $arr[1]*0x100 + $arr[2]*0x10000 + $arr[3]*0x1000000;
Or using pack/unpack:
$dword = array_shift(unpack("L", pack("CCCC", $arr[0], $arr[1], $arr[2], $arr[3])));

Or try<?php
$arr = array(95,8,0,0);
$bindata = join('', array_map('chr', $arr));
var_dump(unpack('L', $bindata));both (Emil H's and my code) give you 2143 as the result.

Or at the very least use 256 rather than 265.

Your code should work correctly, but you should multiply with 256, not 265. (in 8 bits, there are 2^8 = 256 unique values). It works, because multiplying with 256 is the same as shifting the bits 8 places to the left.
Perhaps you should consider using the bitwise operators instead, to better convey the intent. See http://theopensourcery.com/phplogic.htm

Related

PHP How to take first 2 bits from byte and make new byte

Operations on bits.
How to take 2 bits from byte like this:
take first 2 from 12345678 = 12;
Make new byte = 00000012
For example as asked in discussion by jspit :
$char = 'z'; //is 122, 0111 1010
$b = $char & '?'; // ? is 63, 0011 1111
echo $b; //$b becomes 58 and shows ':'
//if integer used you get:
$b = $char & 63;// 63 is 0011 1111 as '?' but $char is string and you get 0 result:
echo $b; //$b becomes 0 because conversion to integer is used from string and $char becomes 0 and get 0 & 63 = 0, and here is error.
For clearance operation is on bits not on bytes, but bits from bytes.
'string' >> 1 not work, but this is second problem.
Codes of char You can check on my site generating safe readable tokens, with byte template option on. Site is in all available languages.
I think I found good answer here:
how to bitwise shift a string in php?
PS. Sorry I cant vote yours fine answers but I have no points reputation here to do this ;)...
I hope you understand bits can only be 0 or 1, I'm assuming when you say "12345678" you're just using those decimal symbols to represent the positions of each bit. If that is the case, then you're looking for bitwise operators.
More specifically:
$new = $old >> 6;
This bitwise shift operation will shift all bits 6 positions to the right, discarding the 6 bits that were there before.
You can also use an or operation with a bitmask to ensure only 2 bits remain, in case the variable had more than 8 bits set:
$new = ($old >> 6) | 0b00000011;
function highestBitsOfByte(int $byte, int $count = 2):int {
if($count < 0 OR $count > 8) return false; //Error
return ($byte & 0xFF) >> (8-$count);
}
$input = 0b10011110;
$r = highestBitsOfByte($input,2);
echo sprintf('%08b',$r);
The integer number is limited to the lowest 8 bits with & 0xFF. Then the bits are shifted to the right according to the desired length.
example to try: https://3v4l.org/1lAvO
If there is a character as input and the fixed number of 2 bits is required, then this can be used:
$chr = 'z'; //0111 1010
$hBits = ord($chr) >> 6;
echo sprintf('%08b',$hBits); //00000001

Reading the decimal value of little endian in PHP

I'm reading 6 bytes in little endian from a binary file using
$data = fread($fp, 6);
unpack("V", $data);
The result is 1152664389 and in HEX it is 0x44B44345
Now this result is in little endian and has a decimal number. In Delphi, I was able to get the decimal number using this function:
var
myint:integer;
s:single;
begin
myint:= 1152664389; // same as myint:= $44B44345;
s:= PSingle(#myint)^;
and output of s is 1442.102.. This is exactly the number im looking for...
I searched for a way to do it in PHP but I just got lost.
Please help,
Thanks
Okay, I was a bit confused. I wanted to actually retrieve a little endian number from a binary file then convert it to float.
So my steps were:
1) Read bytes and unpack using $number = unpack("V", $data);
2) Convert $number to decimal using dechex.
3) Then use the following function to convert hex to float:
function hexTo32Float($strHex) {
$v = hexdec($strHex);
$x = ($v & ((1 << 23) - 1)) + (1 << 23) * ($v >> 31 | 1);
$exp = ($v >> 23 & 0xFF) - 127;
return $x * pow(2, $exp - 23);
}
Thanks again.

24bit int in php

Hey all so I've ran into a bit of a problem, from PHP I have to read some data from a binary file where SPACE is of the utmost importance so they've used 24 bit integers in places.
Now for most of the data I can read with unpack however pack/unpack does not support 24 bit int's :s
I thought I could perhaps simple read the data (say for example 000104) as H* and have it read into a var that would be correct.
// example binary data say I had the following 3 bytes in a binary file
// 0x00, 0x01, 0x04
$buffer = unpack("H*", $data);
// this should equate to 260 in base 10 however unpacking as H* will not get
// this value.
// now we can't unpack as N as it requires 0x4 bytes of data and n being a 16 bit int
// is too short.
Has anyone had to deal with this before? Any solutions? advice?
If the file has only 3 bytes as above, the easiest way is padding as #DaveRandom said. But if it's a long file this method becomes inefficient.
In this case you can read each element as a char and a short, after that repack it by bitwise operators.
Or you can read along 12 bytes as 3 longs and then splits it into 4 groups of 3 bytes with bitwise operators. The remaining bytes will be extracted by the above 2 methods. This will be the fastest solution on large data.
unsigned int i, j;
unsigned int dataOut[SIZE];
for (i = 0, j = 0; j < size; i += 4, j += 3)
{
dataOut[i] = dataIn[j] >> 8;
dataOut[i + 1] = ((dataIn[j] & 0xff) << 16) | (dataIn[j + 1] >> 16);
dataOut[i + 2] = ((dataIn[j + 1] & 0xffff) << 8) | (dataIn[j + 2] >> 24);
dataOut[i + 3] = dataIn[j + 2] & 0xffffff;
}
The following question has an example code to unpack a string of 24/48bits too

PHP Bit shifting in code?

Can someone help me understand this ancient code?
$a = 00040000000002;
$n = sscanf($a,"%02x%02x%02x%02x%02x%02x%02x",$r[7],$r[6],$r[5],$r[4],$r[3],$r[2],$r[1]);
$ptemp = $r[1] + (($r[2] & 0x1F) << 8);
$l[$i] = (($r[2] & 0xE0) >> 5) + ($r[3] << 3);
$m[$i] = $r[4] + (($r[5] & 0x03) << 8);
$h[$i] = (($r[5] & 0xFC) >> 2) + (($r[6] & 0x03) << 6);
$dist[$i] = (($r[6] & 0xFC) >> 2) + (($r[7] & 0x0F) << 6);
$fruittoday[$i] = ($r[7] & 0xF0) >> 4;
I understand the sscanf, but I'm not sure what is going on with the & 0x1f << 8, etc.
Any ideas?
They're using Bitwise Operators to check if specific bits are turned on.
In the example you've provided, they're confirming the first 5 bits are 1's then shifting all bits to the left 8 places. (Although it seems like in this case they're starting with 0 (00000000), checking if 0x1F are on (00011111) which would still be 0, then shifting them left 8 places (put in to the 2^8th position)
For reference, I would check out php's manual on bitwise operators. They list some example of what's going on here. If you're really curious, just echo the variables as they are manipulated (or break it out in to separate operations) and then examine them).

bytes convert to float (php)

How can I convert from bytes to float in php? Like in Java
int i = (byte3 & 0xff) << 24 | (byte2 & 0xff) << 16 | (byte1 & 0xff) << 8 | byte0 & 0xff;
Float.intBitsToFloat(i);
There may be a more direct way, but here you go:
<?php
var_dump(unpack('f', pack('i', 1059760811)));
?>
This is, of course, machine dependent, but I don't know of any machine running PHP that doesn't use IEEE 754 floats.
I don't think php has bytes, does it?
When you assign a number to a variable you'll get an variable with a number type
$a = 10; // integer
$f = 1.0; // double
$b = $a + $f; // $b is double
If I'm understanding you correctly, you want to take a raw 32- or 64-bit "integer" value, and force that set of bits to treated as a floating point number instead?
Try the 'pack' and 'unpack' functions

Categories