This RFC is to discuss the addition of 2 new operators to the core, a logical left shift and a logical right shift.
The currently implemented left and right shift operators (<< and >> respectively) perform arithmetic shifts. I am proposing the introduction of a pair of logical shift operators which perform their operations on arbitrary length strings.
The problem can be seen by trying to shift -1 (0xFFFFFFFF on 32 bit, 0xFFFFFFFFFFFFFFFF on 64 bit). If we try -1 >> 1, we get back -1 again. This is due to the shift being arithmetic. If we try -1 >> 2, we will still get -1.
Additionally, the current shifts only work on strings when the string is parsable as a number. So “2” >> 1 yields 1 instead of the expected logical value of 0x19.
At present, if you want to do a logical shift on a string, you need to iterate over the string and apply the shift to each part of it (where the part is less than 4 bytes long, to prevent issues on 32 bit systems). For example:
For example, to implement a logical left shift currently requires something like this (this example could be optimized, but the basics of it are there):
$mask = (0xff << (8 - $bits)) & 0xff;
$state = 0;
$length = strlen($data);
for ($i = $length - 1; $i >= 0; $i--) {
$tmp = ord($data[$i]);
$result .= chr(($tmp << $bits) | $state);
$state = ($tmp & $mask) >> (8 - $bits);
}
return strrev($result);
Other bitwise operators do operate properly on strings (such as XOR - ^, AND - & and OR - |). So it would be complete to add support for shifting strings.
I propose the addition of two new operators which will perform a logical shift. The selection of the operators is a little bit more difficult as <<< is already taken by heredoc. Perhaps something like b<<...
Example:
$foo = “a long string” {operator} 1;
Would yield a string with the following bits:
0xc240d8dedcce40e6e8e4d2dcce
- Added note about <<< being used by heredoc already.