You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
4.0 KiB
194 lines
4.0 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* @author Pavel Djundik
|
|
*
|
|
* @see https://xpaw.me
|
|
* @see https://github.com/xPaw/PHP-Source-Query
|
|
*
|
|
* @license GNU Lesser General Public License, version 2.1
|
|
*
|
|
* @internal
|
|
*/
|
|
|
|
namespace xPaw\SourceQuery;
|
|
|
|
use xPaw\SourceQuery\Exception\InvalidPacketException;
|
|
|
|
final class Buffer
|
|
{
|
|
/**
|
|
* Buffer.
|
|
*/
|
|
private string $buffer = '';
|
|
|
|
/**
|
|
* Buffer length.
|
|
*/
|
|
private int $length = 0;
|
|
|
|
/**
|
|
* Current position in buffer.
|
|
*/
|
|
private int $position = 0;
|
|
|
|
/**
|
|
* Sets buffer.
|
|
*/
|
|
public function set(string $buffer): void
|
|
{
|
|
$this->buffer = $buffer;
|
|
$this->length = strlen($buffer);
|
|
$this->position = 0;
|
|
}
|
|
|
|
/**
|
|
* Get remaining bytes.
|
|
*
|
|
* @return int Remaining bytes in buffer
|
|
*/
|
|
public function remaining(): int
|
|
{
|
|
return $this->length - $this->position;
|
|
}
|
|
|
|
public function isEmpty(): bool
|
|
{
|
|
return $this->remaining() <= 0;
|
|
}
|
|
|
|
/**
|
|
* Gets data from buffer.
|
|
*
|
|
* @param int $length Bytes to read
|
|
*/
|
|
public function get(int $length = -1): string
|
|
{
|
|
if (0 === $length) {
|
|
return '';
|
|
}
|
|
|
|
$remaining = $this->remaining();
|
|
|
|
if (-1 === $length) {
|
|
$length = $remaining;
|
|
} elseif ($length > $remaining) {
|
|
return '';
|
|
}
|
|
|
|
$data = substr($this->buffer, $this->position, $length);
|
|
|
|
$this->position += $length;
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Get byte from buffer.
|
|
*/
|
|
public function getByte(): int
|
|
{
|
|
return ord($this->get(1));
|
|
}
|
|
|
|
/**
|
|
* Get short from buffer.
|
|
*
|
|
* @throws InvalidPacketException
|
|
*/
|
|
public function getShort(): int
|
|
{
|
|
if ($this->remaining() < 2) {
|
|
throw new InvalidPacketException('Not enough data to unpack a short.', InvalidPacketException::BUFFER_EMPTY);
|
|
}
|
|
|
|
$data = unpack('v', $this->get(2));
|
|
|
|
if (!$data) {
|
|
throw new InvalidPacketException('Empty data from packet.');
|
|
}
|
|
|
|
return (int) $data[1];
|
|
}
|
|
|
|
/**
|
|
* Get long from buffer.
|
|
*
|
|
* @throws InvalidPacketException
|
|
*/
|
|
public function getLong(): int
|
|
{
|
|
if ($this->remaining() < 4) {
|
|
throw new InvalidPacketException('Not enough data to unpack a long.', InvalidPacketException::BUFFER_EMPTY);
|
|
}
|
|
|
|
$data = unpack('l', $this->get(4));
|
|
|
|
if (!$data) {
|
|
throw new InvalidPacketException('Empty data from packet.');
|
|
}
|
|
|
|
return (int) $data[1];
|
|
}
|
|
|
|
/**
|
|
* Get float from buffer.
|
|
*
|
|
* @throws InvalidPacketException
|
|
*/
|
|
public function getFloat(): float
|
|
{
|
|
if ($this->remaining() < 4) {
|
|
throw new InvalidPacketException('Not enough data to unpack a float.', InvalidPacketException::BUFFER_EMPTY);
|
|
}
|
|
|
|
$data = unpack('f', $this->get(4));
|
|
|
|
if (!$data) {
|
|
throw new InvalidPacketException('Empty data from packet.');
|
|
}
|
|
|
|
return (float) $data[1];
|
|
}
|
|
|
|
/**
|
|
* Get unsigned long from buffer.
|
|
*
|
|
* @throws InvalidPacketException
|
|
*/
|
|
public function getUnsignedLong(): int
|
|
{
|
|
if ($this->remaining() < 4) {
|
|
throw new InvalidPacketException('Not enough data to unpack an usigned long.', InvalidPacketException::BUFFER_EMPTY);
|
|
}
|
|
|
|
$data = unpack('V', $this->get(4));
|
|
|
|
if (!$data) {
|
|
throw new InvalidPacketException('Empty data from packet.');
|
|
}
|
|
|
|
return (int) $data[1];
|
|
}
|
|
|
|
/**
|
|
* Read one string from buffer ending with null byte.
|
|
*/
|
|
public function getString(): string
|
|
{
|
|
$zeroBytePosition = strpos($this->buffer, "\0", $this->position);
|
|
|
|
if (false === $zeroBytePosition) {
|
|
return '';
|
|
}
|
|
|
|
$string = $this->get($zeroBytePosition - $this->position);
|
|
|
|
++$this->position;
|
|
|
|
return $string;
|
|
}
|
|
}
|