Skip to content

Commit

Permalink
improve handling of 64 bit values
Browse files Browse the repository at this point in the history
  • Loading branch information
KurtThiemann committed Sep 10, 2021
1 parent 60b5bc6 commit c0cffc1
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 25 deletions.
1 change: 1 addition & 0 deletions seedValueTest
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
��\��$�
36 changes: 36 additions & 0 deletions src/MachineByteOrder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Aternos\Nbt;

class MachineByteOrder
{
protected static ?bool $isLittle = null;

/**
* Test whether the machine byte order is little endian or big endian
*/
protected static function testByteOrder(): void
{
if(is_null(static::$isLittle)) {
static::$isLittle = pack("S", 0x1234) === hex2bin("3412");
}
}

/**
* @return bool
*/
public static function isLittleEndian(): bool
{
static::testByteOrder();
return static::$isLittle;
}

/**
* @return bool
*/
public static function isBigEndian(): bool
{
static::testByteOrder();
return !static::$isLittle;
}
}
17 changes: 4 additions & 13 deletions src/Serializer/BedrockEditionNbtSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Aternos\Nbt\Serializer;

use Aternos\Nbt\IO\Reader\Reader;
use Aternos\Nbt\MachineByteOrder;
use Aternos\Nbt\NbtFormat;
use pocketmine\utils\Binary;

Expand Down Expand Up @@ -101,26 +102,16 @@ public function encodeInt(int $value): string
*/
protected function decodeLong(string $data): int
{
$data = strrev($data);
$firstHalf = Binary::readInt(substr($data, 0, 4));
$secondHalf = Binary::readInt(substr($data, 4));

$negative = boolval($firstHalf & pow(2, 31));

$firstHalf &= (pow(2, 31) - 1);
$result = ($firstHalf << 32) + $secondHalf;

return $negative ? $result*-1 : $result;
return @unpack("q", MachineByteOrder::isBigEndian() ? strrev($data) : $data)[1] ?? 0;
}

/**
* @inheritDoc
*/
public function encodeLong(int $value): string
{
$firstHalf = ($value & 0xFFFFFFFF00000000) >> 32;
$secondHalf = $value & 0xFFFFFFFF;
return strrev(pack('VV', $firstHalf, $secondHalf));
$packed = pack("q", $value);
return MachineByteOrder::isBigEndian() ? strrev($packed) : $packed;
}

/**
Expand Down
16 changes: 4 additions & 12 deletions src/Serializer/JavaEditionNbtSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Aternos\Nbt\Serializer;

use Aternos\Nbt\IO\Reader\Reader;
use Aternos\Nbt\MachineByteOrder;
use Aternos\Nbt\NbtFormat;
use pocketmine\utils\Binary;

Expand Down Expand Up @@ -96,25 +97,16 @@ public function encodeInt(int $value): string
*/
public function decodeLong(string $data): int
{
$firstHalf = Binary::readInt(substr($data, 0, 4));
$secondHalf = Binary::readInt(substr($data, 4));

$negative = boolval($firstHalf & pow(2, 31));

$firstHalf &= (pow(2, 31) - 1);
$result = ($firstHalf << 32) + $secondHalf;

return $negative ? $result*-1 : $result;
return @unpack("q", MachineByteOrder::isLittleEndian() ? strrev($data) : $data)[1] ?? 0;
}

/**
* @inheritDoc
*/
public function encodeLong(int $value): string
{
$firstHalf = ($value & 0xFFFFFFFF00000000) >> 32;
$secondHalf = $value & 0xFFFFFFFF;
return pack('NN', $firstHalf, $secondHalf);
$packed = pack("q", $value);
return MachineByteOrder::isLittleEndian() ? strrev($packed) : $packed;
}

/**
Expand Down

0 comments on commit c0cffc1

Please sign in to comment.