Abilogos
Abilogos

Reputation: 5030

how to bitwise shift a string in php?

i want to shift a 16-bit variable in Php. but my code is not working. its just shifts the Lowest nibbles of each Byte. and leave The High nibble unchanged. first and third nibble shifts fine. but second and fourth is not.

public static function leftShift2Byte($in){
     $strarr = str_split($in);
     if($strarr[1]>chr(127)){
         $strarr[1] = $strarr[1]<<1;
         $strarr[0] = $strarr[0]<<1;
         $strarr[0]++;
     }else{
         $strarr[1] = $strarr[1]<<1;
         $strarr[0] = $strarr[0]<<1;
     }
     return $strarr[0].$strarr[1];
 } 

Upvotes: 2

Views: 2221

Answers (3)

Bitwise operator << or >> left or right


echo 1010<<2 ;

Upvotes: 0

ob-ivan
ob-ivan

Reputation: 833

Unlike C, dereferencing a string by index in PHP doesn't produce a numeric variable, but a 1-byte string:

$str = 'as';
var_dump($str[0]); 
// prints: string(1) "a"

Strings are not subject to bitwise operations. Or more precisely: they are parsed as integers before performing a bitwise operation. That's why if you pass it a string containing numeric characters, it would appear as 'shifting the lowest nibble', while in reality it does something completely different:

var_dump(leftShift2Byte('01'));
// prints: string(2) "02"
// That is:
// - '0' parsed as integer to 0, shifted 1 bit, got 0, concatenated as '0'
// - '1' parsed as 1, shifted to 2, concatenated as '2'

You have to explicitly cast 1-byte strings to byte codes by calling ord and then back by calling chr:

function leftShift2ByteOrd($in){
    $strarr = str_split($in);
    $numarr = array_map('ord', $strarr);
    $carry = $numarr[1] | 0x80;
    $numarr[1] = $numarr[1] << 1;
    $numarr[0] = $numarr[0] << 1;
    if ($carry) {
        $numarr[0]++;
    }
    return chr($numarr[0]) . chr($numarr[1]);
}

var_dump(leftShift2ByteOrd('01'));
// prints: string(2) "ab"

Upvotes: 1

Abilogos
Abilogos

Reputation: 5030

finnaly i found out that should change the string to The number type in order to shift it. like this one:

public function nextChildCode($childs){
    $mask=bindec('0000000000000001');
    $counter=0;
    $childNum=ord($childs{1})+( ord($childs{0})*256 );
    //$childNum=32767;
    while((($mask & $childNum)!=0)&& $counter<17){
        $mask=$mask<<1;
        $counter++;
    }

    if($counter<16){
        return dechex($counter) ;
    }else{
        return NULL;
    }
}

Upvotes: 0

Related Questions