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 byte (boolean) from buffer. */ public function getBool(): bool { return 1 === $this->getByte(); } /** * Get byte (character) from buffer. */ public function getChar(): string { return chr($this->getByte()); } /** * 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; } }