Moved binary methods from Utils to Binary

This commit is contained in:
Shoghi Cervantes
2014-04-07 13:54:07 +02:00
parent ac02185ad0
commit c0de004472
25 changed files with 894 additions and 546 deletions

View File

@ -30,10 +30,6 @@ use pocketmine\item\Item;
* Big collection of functions
*/
class Utils{
const BIG_ENDIAN = 0x00;
const LITTLE_ENDIAN = 0x01;
public static $online = true;
public static $ip = false;
@ -201,199 +197,6 @@ class Utils{
return preg_replace('#([^\x20-\x7E])#', '.', $str);
}
/**
* Reads a 3-byte big-endian number
*
* @param $str
*
* @return mixed
*/
public static function readTriad($str){
list(, $unpacked) = @unpack("N", "\x00" . $str);
return $unpacked;
}
/**
* Writes a 3-byte big-endian number
*
* @param $value
*
* @return string
*/
public static function writeTriad($value){
return substr(pack("N", $value), 1);
}
/**
* Writes a coded metadata string
* TODO: Replace and move this to entity
*
* @param $data
*
* @return string
*/
public static function writeMetadata($data){
$m = "";
foreach($data as $bottom => $d){
$m .= chr(($d["type"] << 5) | ($bottom & 0b00011111));
switch($d["type"]){
case 0:
$m .= Utils::writeByte($d["value"]);
break;
case 1:
$m .= Utils::writeLShort($d["value"]);
break;
case 2:
$m .= Utils::writeLInt($d["value"]);
break;
case 3:
$m .= Utils::writeLFloat($d["value"]);
break;
case 4:
$m .= Utils::writeLShort(strlen($d["value"]));
$m .= $data["value"];
break;
case 5:
$m .= Utils::writeLShort($d["value"][0]);
$m .= Utils::writeByte($d["value"][1]);
$m .= Utils::writeLShort($d["value"][2]);
break;
case 6:
for($i = 0; $i < 3; ++$i){
$m .= Utils::writeLInt($d["value"][$i]);
}
break;
}
}
$m .= "\x7f";
return $m;
}
/**
* Writes a Item to binary (short id, byte Count, short Damage)
*
* @param Item $item
*
* @return string
*/
public static function writeSlot(Item $item){
return Utils::writeShort($item->getID()) . chr($item->getCount()) . Utils::writeShort($item->getMetadata());
}
/**
* Reads a binary Item, returns an Item object
*
* @param $ob
*
* @return Item
*/
public static function readSlot($ob){
$id = Utils::readShort($ob->get(2));
$cnt = ord($ob->get(1));
return Item::get(
$id,
Utils::readShort($ob->get(2)),
$cnt
);
}
/**
* Reads a metadata coded string
* TODO: Change
*
* @param $value
* @param bool $types
*
* @return array
*/
public static function readMetadata($value, $types = false){
$offset = 0;
$m = array();
$b = ord($value{$offset});
++$offset;
while($b !== 127 and isset($value{$offset})){
$bottom = $b & 0x1F;
$type = $b >> 5;
switch($type){
case 0:
$r = Utils::readByte($value{$offset});
++$offset;
break;
case 1:
$r = Utils::readLShort(substr($value, $offset, 2));
$offset += 2;
break;
case 2:
$r = Utils::readLInt(substr($value, $offset, 4));
$offset += 4;
break;
case 3:
$r = Utils::readLFloat(substr($value, $offset, 4));
$offset += 4;
break;
case 4:
$len = Utils::readLShort(substr($value, $offset, 2));
$offset += 2;
$r = substr($value, $offset, $len);
$offset += $len;
break;
case 5:
$r = array();
$r[] = Utils::readLShort(substr($value, $offset, 2));
$offset += 2;
$r[] = ord($value{$offset});
++$offset;
$r[] = Utils::readLShort(substr($value, $offset, 2));
$offset += 2;
break;
case 6:
$r = array();
for($i = 0; $i < 3; ++$i){
$r[] = Utils::readLInt(substr($value, $offset, 4));
$offset += 4;
}
break;
}
if($types === true){
$m[$bottom] = array($r, $type);
}else{
$m[$bottom] = $r;
}
$b = ord($value{$offset});
++$offset;
}
return $m;
}
public static function readDataArray($str, $len = 10, &$offset = null){
$data = array();
$offset = 0;
for($i = 1; $i <= $len and isset($str{$offset}); ++$i){
$l = Utils::readTriad(substr($str, $offset, 3));
$offset += 3;
$data[] = substr($str, $offset, $l);
$offset += $l;
}
return $data;
}
public static function writeDataArray($data){
$raw = "";
foreach($data as $v){
$raw .= Utils::writeTriad(strlen($v));
$raw .= $v;
}
return $raw;
}
/**
* This function tries to get all the entropy available in PHP, and distills it to get a good RNG.
*
@ -578,249 +381,4 @@ class Utils{
return $ret;
}
/**
* Reads a byte boolean
*
* @param $b
*
* @return bool
*/
public static function readBool($b){
return Utils::readByte($b, false) === 0 ? false : true;
}
/**
* Writes a byte boolean
*
* @param $b
*
* @return bool|string
*/
public static function writeBool($b){
return Utils::writeByte($b === true ? 1 : 0);
}
/**
* Reads an unsigned/signed byte
*
* @param $c
* @param bool $signed
*
* @return int
*/
public static function readByte($c, $signed = true){
$b = ord($c{0});
if($signed === true and ($b & 0x80) === 0x80){ //calculate Two's complement
$b = -0x80 + ($b & 0x7f);
}
return $b;
}
/**
* Writes an unsigned/signed byte
*
* @param $c
*
* @return bool|string
*/
public static function writeByte($c){
if($c > 0xff){
return false;
}
if($c < 0 and $c >= -0x80){
$c = 0xff + $c + 1;
}
return chr($c);
}
/**
* Reads a 16-bit signed/unsigned big-endian number
*
* @param $str
* @param bool $signed
*
* @return int
*/
public static function readShort($str, $signed = true){
list(, $unpacked) = @unpack("n", $str);
if($unpacked > 0x7fff and $signed === true){
$unpacked -= 0x10000; // Convert unsigned short to signed short
}
return $unpacked;
}
/**
* Writes a 16-bit signed/unsigned big-endian number
*
* @param $value
*
* @return string
*/
public static function writeShort($value){
if($value < 0){
$value += 0x10000;
}
return pack("n", $value);
}
/**
* Reads a 16-bit signed/unsigned little-endian number
*
* @param $str
* @param bool $signed
*
* @return int
*/
public static function readLShort($str, $signed = true){
list(, $unpacked) = @unpack("v", $str);
if($unpacked > 0x7fff and $signed === true){
$unpacked -= 0x10000; // Convert unsigned short to signed short
}
return $unpacked;
}
/**
* Writes a 16-bit signed/unsigned little-endian number
*
* @param $value
*
* @return string
*/
public static function writeLShort($value){
if($value < 0){
$value += 0x10000;
}
return pack("v", $value);
}
public static function readInt($str){
list(, $unpacked) = @unpack("N", $str);
if($unpacked > 2147483647){
$unpacked -= 4294967296;
}
return (int) $unpacked;
}
public static function writeInt($value){
return pack("N", $value);
}
public static function readLInt($str){
list(, $unpacked) = @unpack("V", $str);
if($unpacked >= 2147483648){
$unpacked -= 4294967296;
}
return (int) $unpacked;
}
public static function writeLInt($value){
return pack("V", $value);
}
public static function readFloat($str){
list(, $value) = ENDIANNESS === Utils::BIG_ENDIAN ? @unpack("f", $str) : @unpack("f", strrev($str));
return $value;
}
public static function writeFloat($value){
return ENDIANNESS === Utils::BIG_ENDIAN ? pack("f", $value) : strrev(pack("f", $value));
}
public static function readLFloat($str){
list(, $value) = ENDIANNESS === Utils::BIG_ENDIAN ? @unpack("f", strrev($str)) : @unpack("f", $str);
return $value;
}
public static function writeLFloat($value){
return ENDIANNESS === Utils::BIG_ENDIAN ? strrev(pack("f", $value)) : pack("f", $value);
}
public static function printFloat($value){
return preg_replace("/(\.\d+?)0+$/", "$1", sprintf("%F", $value));
}
public static function readDouble($str){
list(, $value) = ENDIANNESS === Utils::BIG_ENDIAN ? @unpack("d", $str) : @unpack("d", strrev($str));
return $value;
}
public static function writeDouble($value){
return ENDIANNESS === Utils::BIG_ENDIAN ? pack("d", $value) : strrev(pack("d", $value));
}
public static function readLDouble($str){
list(, $value) = ENDIANNESS === Utils::BIG_ENDIAN ? @unpack("d", strrev($str)) : @unpack("d", $str);
return $value;
}
public static function writeLDouble($value){
return ENDIANNESS === Utils::BIG_ENDIAN ? strrev(pack("d", $value)) : pack("d", $value);
}
public static function readLong($x, $signed = true){
$value = "0";
if($signed === true){
$negative = ((ord($x{0}) & 0x80) === 0x80) ? true : false;
if($negative){
$x = ~$x;
}
}else{
$negative = false;
}
for($i = 0; $i < 8; $i += 4){
$value = bcmul($value, "4294967296", 0); //4294967296 == 2^32
$value = bcadd($value, 0x1000000 * ord(@$x{$i}) + ((ord(@$x{$i + 1}) << 16) | (ord(@$x{$i + 2}) << 8) | ord(@$x{$i + 3})), 0);
}
return ($negative === true ? "-" . $value : $value);
}
public static function writeLong($value){
$x = "";
if($value{0} === "-"){
$negative = true;
$value = bcadd($value, "1");
if($value{0} === "-"){
$value = substr($value, 1);
}
}else{
$negative = false;
}
while(bccomp($value, "0", 0) > 0){
$temp = bcmod($value, "16777216");
$x = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $x;
$value = bcdiv($value, "16777216", 0);
}
$x = str_pad(substr($x, 0, 8), 8, "\x00", STR_PAD_LEFT);
if($negative === true){
$x = ~$x;
}
return $x;
}
public static function readLLong($str){
return Utils::readLong(strrev($str));
}
public static function writeLLong($value){
return strrev(Utils::writeLong($value));
}
}
@define("pocketmine\\utils\\ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Utils::BIG_ENDIAN : Utils::LITTLE_ENDIAN));
}