PocketMine-MP  1.4 - API 1.10.0
 All Classes Namespaces Functions Variables Pages
Binary.php
1 <?php
2 
3 /*
4  *
5  * ____ _ _ __ __ _ __ __ ____
6  * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7  * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8  * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9  * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * @author PocketMine Team
17  * @link http://www.pocketmine.net/
18  *
19  *
20 */
21 
25 namespace pocketmine\utils;
26 
31 class Binary{
32  const BIG_ENDIAN = 0x00;
33  const LITTLE_ENDIAN = 0x01;
34 
35 
43  public static function readTriad($str){
44  return unpack("N", "\x00" . $str)[1];
45  }
46 
54  public static function writeTriad($value){
55  return substr(pack("N", $value), 1);
56  }
57 
65  public static function readLTriad($str){
66  return unpack("V", $str . "\x00")[1];
67  }
68 
76  public static function writeLTriad($value){
77  return substr(pack("V", $value), 0, -1);
78  }
79 
88  public static function writeMetadata(array $data){
89  $m = "";
90  foreach($data as $bottom => $d){
91  $m .= chr(($d["type"] << 5) | ($bottom & 0x1F));
92  switch($d["type"]){
93  case 0:
94  $m .= self::writeByte($d["value"]);
95  break;
96  case 1:
97  $m .= self::writeLShort($d["value"]);
98  break;
99  case 2:
100  $m .= self::writeLInt($d["value"]);
101  break;
102  case 3:
103  $m .= self::writeLFloat($d["value"]);
104  break;
105  case 4:
106  $m .= self::writeLShort(strlen($d["value"])) . $d["value"];
107  break;
108  case 5:
109  $m .= self::writeLShort($d["value"][0]);
110  $m .= self::writeByte($d["value"][1]);
111  $m .= self::writeLShort($d["value"][2]);
112  break;
113  case 6:
114  $m .= self::writeLInt($d["value"][0]);
115  $m .= self::writeLInt($d["value"][1]);
116  $m .= self::writeLInt($d["value"][2]);
117  break;
118  }
119  }
120  $m .= "\x7f";
121 
122  return $m;
123  }
124 
134  public static function readMetadata($value, $types = false){
135  $offset = 0;
136  $m = [];
137  $b = ord($value{$offset});
138  ++$offset;
139  while($b !== 127 and isset($value{$offset})){
140  $bottom = $b & 0x1F;
141  $type = $b >> 5;
142  switch($type){
143  case 0:
144  $r = self::readByte($value{$offset});
145  ++$offset;
146  break;
147  case 1:
148  $r = self::readLShort(substr($value, $offset, 2));
149  $offset += 2;
150  break;
151  case 2:
152  $r = self::readLInt(substr($value, $offset, 4));
153  $offset += 4;
154  break;
155  case 3:
156  $r = self::readLFloat(substr($value, $offset, 4));
157  $offset += 4;
158  break;
159  case 4:
160  $len = self::readLShort(substr($value, $offset, 2));
161  $offset += 2;
162  $r = substr($value, $offset, $len);
163  $offset += $len;
164  break;
165  case 5:
166  $r = [];
167  $r[] = self::readLShort(substr($value, $offset, 2));
168  $offset += 2;
169  $r[] = ord($value{$offset});
170  ++$offset;
171  $r[] = self::readLShort(substr($value, $offset, 2));
172  $offset += 2;
173  break;
174  case 6:
175  $r = [];
176  for($i = 0; $i < 3; ++$i){
177  $r[] = self::readLInt(substr($value, $offset, 4));
178  $offset += 4;
179  }
180  break;
181  default:
182  return [];
183 
184  }
185  if($types === true){
186  $m[$bottom] = ["value" => $r, "type" => $type];
187  }else{
188  $m[$bottom] = $r;
189  }
190  $b = ord($value{$offset});
191  ++$offset;
192  }
193 
194  return $m;
195  }
196 
204  public static function readBool($b){
205  return self::readByte($b, false) === 0 ? false : true;
206  }
207 
215  public static function writeBool($b){
216  return self::writeByte($b === true ? 1 : 0);
217  }
218 
227  public static function readByte($c, $signed = true){
228  $b = ord($c{0});
229 
230  if($signed){
231  if(PHP_INT_SIZE === 8){
232  return $b << 56 >> 56;
233  }else{
234  return $b << 24 >> 24;
235  }
236  }else{
237  return $b;
238  }
239  }
240 
248  public static function writeByte($c){
249  return chr($c);
250  }
251 
259  public static function readShort($str){
260  return unpack("n", $str)[1];
261  }
262 
270  public static function readSignedShort($str){
271  if(PHP_INT_SIZE === 8){
272  return unpack("n", $str)[1] << 48 >> 48;
273  }else{
274  return unpack("n", $str)[1] << 16 >> 16;
275  }
276  }
277 
285  public static function writeShort($value){
286  return pack("n", $value);
287  }
288 
296  public static function readLShort($str){
297  return unpack("v", $str)[1];
298  }
299 
307  public static function readSignedLShort($str){
308  if(PHP_INT_SIZE === 8){
309  return unpack("v", $str)[1] << 48 >> 48;
310  }else{
311  return unpack("v", $str)[1] << 16 >> 16;
312  }
313  }
314 
322  public static function writeLShort($value){
323  return pack("v", $value);
324  }
325 
326  public static function readInt($str){
327  if(PHP_INT_SIZE === 8){
328  return unpack("N", $str)[1] << 32 >> 32;
329  }else{
330  return unpack("N", $str)[1];
331  }
332  }
333 
334  public static function writeInt($value){
335  return pack("N", $value);
336  }
337 
338  public static function readLInt($str){
339  if(PHP_INT_SIZE === 8){
340  return unpack("V", $str)[1] << 32 >> 32;
341  }else{
342  return unpack("V", $str)[1];
343  }
344  }
345 
346  public static function writeLInt($value){
347  return pack("V", $value);
348  }
349 
350  public static function readFloat($str){
351  return ENDIANNESS === self::BIG_ENDIAN ? unpack("f", $str)[1] : unpack("f", strrev($str))[1];
352  }
353 
354  public static function writeFloat($value){
355  return ENDIANNESS === self::BIG_ENDIAN ? pack("f", $value) : strrev(pack("f", $value));
356  }
357 
358  public static function readLFloat($str){
359  return ENDIANNESS === self::BIG_ENDIAN ? unpack("f", strrev($str))[1] : unpack("f", $str)[1];
360  }
361 
362  public static function writeLFloat($value){
363  return ENDIANNESS === self::BIG_ENDIAN ? strrev(pack("f", $value)) : pack("f", $value);
364  }
365 
366  public static function printFloat($value){
367  return preg_replace("/(\\.\\d+?)0+$/", "$1", sprintf("%F", $value));
368  }
369 
370  public static function readDouble($str){
371  return ENDIANNESS === self::BIG_ENDIAN ? unpack("d", $str)[1] : unpack("d", strrev($str))[1];
372  }
373 
374  public static function writeDouble($value){
375  return ENDIANNESS === self::BIG_ENDIAN ? pack("d", $value) : strrev(pack("d", $value));
376  }
377 
378  public static function readLDouble($str){
379  return ENDIANNESS === self::BIG_ENDIAN ? unpack("d", strrev($str))[1] : unpack("d", $str)[1];
380  }
381 
382  public static function writeLDouble($value){
383  return ENDIANNESS === self::BIG_ENDIAN ? strrev(pack("d", $value)) : pack("d", $value);
384  }
385 
386  public static function readLong($x){
387  if(PHP_INT_SIZE === 8){
388  $int = unpack("N*", $x);
389  return ($int[1] << 32) | $int[2];
390  }else{
391  $value = "0";
392  for($i = 0; $i < 8; $i += 2){
393  $value = bcmul($value, "65536", 0);
394  $value = bcadd($value, self::readShort(substr($x, $i, 2)), 0);
395  }
396 
397  if(bccomp($value, "9223372036854775807") == 1){
398  $value = bcadd($value, "-18446744073709551616");
399  }
400 
401  return $value;
402  }
403  }
404 
405  public static function writeLong($value){
406  if(PHP_INT_SIZE === 8){
407  return pack("NN", $value >> 32, $value & 0xFFFFFFFF);
408  }else{
409  $x = "";
410 
411  if(bccomp($value, "0") == -1){
412  $value = bcadd($value, "18446744073709551616");
413  }
414 
415  $x .= self::writeShort(bcmod(bcdiv($value, "281474976710656"), "65536"));
416  $x .= self::writeShort(bcmod(bcdiv($value, "4294967296"), "65536"));
417  $x .= self::writeShort(bcmod(bcdiv($value, "65536"), "65536"));
418  $x .= self::writeShort(bcmod($value, "65536"));
419 
420  return $x;
421  }
422  }
423 
424  public static function readLLong($str){
425  return self::readLong(strrev($str));
426  }
427 
428  public static function writeLLong($value){
429  return strrev(self::writeLong($value));
430  }
431 
432 }
static writeBool($b)
Definition: Binary.php:215
static writeTriad($value)
Definition: Binary.php:54
static writeByte($c)
Definition: Binary.php:248
static readByte($c, $signed=true)
Definition: Binary.php:227
static readLTriad($str)
Definition: Binary.php:65
static readSignedShort($str)
Definition: Binary.php:270
static writeShort($value)
Definition: Binary.php:285
static readMetadata($value, $types=false)
Definition: Binary.php:134
static writeLShort($value)
Definition: Binary.php:322
static readShort($str)
Definition: Binary.php:259
static writeMetadata(array $data)
Definition: Binary.php:88
static readTriad($str)
Definition: Binary.php:43
static readSignedLShort($str)
Definition: Binary.php:307
static readBool($b)
Definition: Binary.php:204
static readLShort($str)
Definition: Binary.php:296
static writeLTriad($value)
Definition: Binary.php:76