mirror of
https://gitlab.com/hashborgir/d2tools.git
synced 2024-11-30 12:36:03 +00:00
361 lines
16 KiB
PHP
361 lines
16 KiB
PHP
<?php
|
|
|
|
require_once './src/D2Functions.php';
|
|
require_once './src/D2BitReader.php';
|
|
|
|
/**
|
|
* A class for reading and manipulating bytes.
|
|
*/
|
|
class D2ByteReader {
|
|
|
|
/**
|
|
* @var string The byte data.
|
|
*/
|
|
private string $data = '';
|
|
|
|
/**
|
|
* @var int The current offset position.
|
|
*/
|
|
private int $offset = 0;
|
|
|
|
/**
|
|
* Constructs a new D2ByteReader instance.
|
|
*
|
|
* @param string $data The byte data to read.
|
|
*/
|
|
public function __construct(string $data) {
|
|
if (!$data) { // Check if the provided data is empty or false
|
|
return false; // Return false if the data is empty or false
|
|
}
|
|
|
|
$this->data = $data; // Assign the provided data to the internal property "data"
|
|
}
|
|
|
|
/**
|
|
* Skips a specified number of bytes.
|
|
*
|
|
* @param int $numBytes The number of bytes to skip.
|
|
* @return bool Returns true on success, false otherwise.
|
|
*/
|
|
public function skip(int $numBytes): bool {
|
|
if ($numBytes < 0 || $numBytes > strlen($this->data)) { // Check if the specified number of bytes is within the valid range
|
|
return false; // Return false if the number of bytes is invalid
|
|
}
|
|
|
|
$this->offset += $numBytes; // Increment the internal offset by the specified number of bytes
|
|
return true; // Return true to indicate a successful skip operation
|
|
}
|
|
|
|
/**
|
|
* Moves the offset position to a specified position.
|
|
*
|
|
* @param int $pos The new offset position.
|
|
* @return bool Returns true if the offset position is valid, false otherwise.
|
|
*/
|
|
public function seek(int $pos): bool {
|
|
if ($pos < 0 || $pos > strlen($this->data)) { // Check if the specified position is within the valid range
|
|
return false; // Return false if the position is invalid
|
|
}
|
|
|
|
$this->offset = $pos; // Set the internal offset to the specified position
|
|
return true; // Return true to indicate a successful seek operation
|
|
}
|
|
|
|
/**
|
|
* Reads a specified number of bytes from the current offset position.
|
|
*
|
|
* @param int $offset The offset position to start reading from.
|
|
* @param int $numBytes The number of bytes to read.
|
|
* @param bool $str Indicates whether to return the result as a string (default) or an array.
|
|
* @return string|array The read bytes.
|
|
*/
|
|
public function read(int $offset, int $numBytes, bool $str = true) {
|
|
$this->seek($offset); // Set the internal offset to the specified position
|
|
$bytes = null; // Initialize a variable to store the read bytes
|
|
// Loop through the specified number of bytes
|
|
for ($i = $this->offset; $i < $this->offset + $numBytes; $i++) {
|
|
// Depending on the $str parameter, concatenate the byte to $bytes as a string or add it to $bytes array
|
|
$str ? $bytes .= $this->data[$i] : $bytes[] = $this->data[$i];
|
|
}
|
|
|
|
return $bytes; // Return the read bytes as either a string or an array
|
|
}
|
|
|
|
/**
|
|
* Reads a specified number of bytes from the current offset position and returns them as a hex string.
|
|
*
|
|
* @param int $offset The offset position to start reading from.
|
|
* @param int $numBytes The number of bytes to read.
|
|
* @param bool $str Indicates whether to return the result as a string (default) or an array.
|
|
* @return string The read bytes as a hex string.
|
|
*/
|
|
public function readh(int $offset, int $numBytes, bool $str = true) {
|
|
$this->seek($offset); // Set the internal offset to the specified position
|
|
$bytes = null; // Initialize a variable to store the read bytes
|
|
// Loop through the specified number of bytes
|
|
for ($i = $this->offset; $i < $this->offset + $numBytes; $i++) {
|
|
// Depending on the $str parameter, concatenate the byte to $bytes as a string or add it to $bytes array
|
|
$str ? $bytes .= $this->data[$i] : $bytes[] = $this->data[$i];
|
|
}
|
|
|
|
return unpack('H*', $bytes)[1]; // Unpack the bytes into a hexadecimal string and return it
|
|
}
|
|
|
|
/**
|
|
* Reads a specified number of bytes from the current offset position and returns them as an array of integers.
|
|
*
|
|
* @param int $offset The offset position to start reading from.
|
|
* @param int $numBytes The number of bytes to read.
|
|
* @param bool $str Indicates whether to return the result as a string (default) or an array.
|
|
* @return array The read bytes as an array of integers.
|
|
*/
|
|
public function readc(int $offset, int $numBytes, bool $str = true) {
|
|
$this->seek($offset); // Set the internal offset to the specified position
|
|
$bytes = null; // Initialize a variable to store the read bytes
|
|
// Loop through the specified number of bytes
|
|
for ($i = $this->offset; $i < $this->offset + $numBytes; $i++) {
|
|
// Depending on the $str parameter, concatenate the byte to $bytes as a string or add it to $bytes array
|
|
$str ? $bytes .= $this->data[$i] : $bytes[] = $this->data[$i];
|
|
}
|
|
|
|
return unpack('C*', $bytes); // Unpack the bytes into an array of unsigned characters
|
|
}
|
|
|
|
/**
|
|
* Rewinds the offset position to the beginning.
|
|
*
|
|
* @return bool Returns true on success.
|
|
*/
|
|
public function rewind(): bool {
|
|
$this->offset = 0; // Set the offset property to 0, indicating the start position
|
|
return true; // Return true to indicate that the rewind operation was successful
|
|
}
|
|
|
|
/**
|
|
* Writes a byte at the specified offset position.
|
|
*
|
|
* @param int $offset The offset position to write the byte.
|
|
* @param int $byte The byte value to write.
|
|
* @return void
|
|
*/
|
|
public function writeByte(int $offset, int $byte) {
|
|
$this->data[$offset] = pack('C', $byte);
|
|
}
|
|
|
|
/**
|
|
* Writes multiple bytes starting from the specified offset position.
|
|
*
|
|
* @param int $offset The offset position to start writing from.
|
|
* @param string $bytes The bytes to write.
|
|
* @return false|void Returns false on failure or void on success.
|
|
*/
|
|
public function writeBytes(int $offset, string $bytes) {
|
|
if ($offset < 0 || $offset > strlen($this->data) || $bytes == '') {
|
|
return false; // Return false if the offset is invalid or the bytes string is empty
|
|
}
|
|
$_bytes = str_split($bytes, 2); // Split the bytes string into an array of two-character chunks
|
|
foreach ($_bytes as $k => $byte) {
|
|
$pos = $offset + $k; // Calculate the position in the data to write the byte
|
|
$this->data[$pos] = pack('H*', $byte); // Pack the hexadecimal byte into binary format and write it at the specified position
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inserts bytes at the specified offset position.
|
|
*
|
|
* @param int $offset The offset position to insert the bytes.
|
|
* @param string $bytes The bytes to insert.
|
|
* @return false|void Returns false on failure or void on success.
|
|
*/
|
|
public function insertBytes(int $offset, string $bytes) {
|
|
if ($offset < 0 || $offset > strlen($this->data) || $bytes == '') {
|
|
return false; // Return false if the offset is invalid or the bytes string is empty
|
|
}
|
|
$data = bin2hex($this->data); // Convert the binary data to a hexadecimal string
|
|
$newData = substr_replace($data, $bytes, $offset, 0); // Insert the new bytes at the specified offset in the hexadecimal string
|
|
$this->data = hex2bin($newData); // Convert the modified hexadecimal string back to binary data and update the 'data' property
|
|
}
|
|
|
|
/**
|
|
* Returns the byte data.
|
|
*
|
|
* @return false|string Returns the byte data on success, or false if no data is set.
|
|
*/
|
|
public function getData() {
|
|
return $this->data ? $this->data : false; // Return the value of the 'data' property if it exists, otherwise return false
|
|
}
|
|
|
|
/**
|
|
* Sets the byte data.
|
|
*
|
|
* @param $data The byte data to set.
|
|
* @return void
|
|
*/
|
|
public function setData($data) {
|
|
$this->data = $data; // Set the value of the 'data' property to the provided data
|
|
}
|
|
|
|
/**
|
|
* Returns the current offset position.
|
|
*
|
|
* @return int The current offset position.
|
|
*/
|
|
public function getOffset(): int {
|
|
return $this->offset; // Return the value of the 'offset' property
|
|
}
|
|
|
|
/**
|
|
* Checks if a string is a valid hexadecimal string.
|
|
*
|
|
* @param string $str The string to check.
|
|
* @return bool Returns true if the string is a valid hexadecimal string, false otherwise.
|
|
*/
|
|
public function isHexString(string $str): bool {
|
|
// Check if the length of the string is even and if all characters are hexadecimal using ctype_xdigit function
|
|
if (strlen($str) % 2 == 0 && ctype_xdigit($str)) {
|
|
return true; // Return true if the string is a valid hexadecimal string
|
|
}
|
|
|
|
return false; // Return false if the string is not a valid hexadecimal string
|
|
}
|
|
|
|
/**
|
|
* Converts input to a string of bits.
|
|
*
|
|
* @param mixed $input The input to convert.
|
|
* @return string The converted string of bits.
|
|
*/
|
|
public function toBits($input): string {
|
|
$output = ''; // Initialize an empty string to store the resulting bits
|
|
// Check if the input is a hexadecimal string
|
|
if ($this->isHexString($input)) {
|
|
// Convert each byte of the hexadecimal string to binary and concatenate the bits to the output
|
|
// Split the hexadecimal string into an array of bytes (2 characters per byte)
|
|
foreach (str_split($input, 2) as $byte) {
|
|
// Convert the byte from hexadecimal to decimal using `hexdec` function,
|
|
// then convert the decimal to binary using `decbin` function,
|
|
// reverse the resulting binary string using `strrev` function,
|
|
// and pad the binary string with leading zeros to make it 8 bits long using `str_pad` function.
|
|
// Finally, concatenate the resulting bits to the output string.
|
|
$output .= (strrev(str_pad(decbin(hexdec($byte)), 8, 0, STR_PAD_LEFT)));
|
|
}
|
|
|
|
return $output; // Return the resulting bits
|
|
} else if (is_string($input)) {
|
|
// Convert each character of the string to binary and concatenate the bits to the output
|
|
// Split the string into an array of characters
|
|
foreach (str_split($input) as $i) {
|
|
// Convert the character to its ASCII value using `ord` function,
|
|
// then convert the ASCII value to binary using `decbin` function,
|
|
// reverse the resulting binary string using `strrev` function,
|
|
// and pad the binary string with leading zeros to make it 8 bits long using `str_pad` function.
|
|
// Finally, concatenate the resulting bits to the output string.
|
|
$output .= strrev(str_pad(decbin(ord($i)), 8, 0, STR_PAD_LEFT));
|
|
}
|
|
|
|
return $output; // Return the resulting bits
|
|
} else if (is_int($input)) {
|
|
// Convert the integer to binary and return the resulting bits
|
|
// Convert the integer to binary using `decbin` function,
|
|
// reverse the resulting binary string using `strrev` function,
|
|
// and pad the binary string with leading zeros to make it 8 bits long using `str_pad` function.
|
|
// Finally, return the resulting bits.
|
|
return strrev(str_pad(decbin($input), 8, 0, STR_PAD_LEFT));
|
|
} else if (is_array($input)) {
|
|
// If the input is an array, recursively call the `toBits` function for each element and concatenate the bits to the output
|
|
// Iterate over each element in the input array
|
|
foreach ($input as $i) {
|
|
// Recursively call the `toBits` function for the current element,
|
|
// and concatenate the resulting bits to the output string.
|
|
$output .= $this->toBits($i);
|
|
}
|
|
|
|
return $output; // Return the resulting bits
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Converts a string of bits to bytes (reversing the bit order).
|
|
*
|
|
* @param string $bits The string of bits to convert.
|
|
* @return string The converted bytes.
|
|
*/
|
|
public function toBytesR(string $bits): string {
|
|
$bytes = ''; // Initialize an empty string to store the resulting bytes
|
|
// Split the bits string into an array of byte-sized chunks (8 bits per chunk)
|
|
foreach (str_split($bits, 8) as $byteString) {
|
|
// Convert each byte-sized chunk from binary to decimal using `bindec` function,
|
|
// then convert the decimal to hexadecimal using `dechex` function,
|
|
// and pad the resulting hexadecimal string with leading zeros to make it 2 characters long using `str_pad` function.
|
|
// Finally, concatenate the resulting byte to the bytes string.
|
|
$bytes .= strtoupper(str_pad(dechex(bindec($byteString)), 2, 0, STR_PAD_LEFT));
|
|
}
|
|
|
|
return $bytes; // Return the resulting bytes
|
|
}
|
|
|
|
/**
|
|
* Converts a string of bits to bytes.
|
|
*
|
|
* @param string $bits The string of bits to convert.
|
|
* @return string The converted bytes.
|
|
*/
|
|
public function toBytes(string $bits): string {
|
|
$bytes = ''; // Initialize an empty string to store the resulting bytes
|
|
// Split the bits string into an array of byte-sized chunks (8 bits per chunk)
|
|
foreach (str_split($bits, 8) as $byteString) {
|
|
// Reverse the order of bits within each byte-sized chunk using `strrev` function,
|
|
// then convert the reversed binary string to decimal using `bindec` function,
|
|
// then convert the decimal to hexadecimal using `dechex` function,
|
|
// and pad the resulting hexadecimal string with leading zeros to make it 2 characters long using `str_pad` function.
|
|
// Finally, concatenate the resulting byte to the bytes string.
|
|
$bytes .= strtoupper(str_pad(dechex(bindec(strrev($byteString))), 2, 0, STR_PAD_LEFT));
|
|
}
|
|
|
|
return $bytes; // Return the resulting bytes
|
|
}
|
|
|
|
/**
|
|
* Converts a string of bits to a hexadecimal string.
|
|
*
|
|
* @param string $bits The string of bits to convert.
|
|
* @return string The converted hexadecimal string.
|
|
*/
|
|
public function bitsToHexString(string $bits): string {
|
|
$bytes = ''; // Initialize an empty string to store the resulting hexadecimal bytes
|
|
// Split the bits string into an array of byte-sized chunks (8 bits per chunk)
|
|
foreach (str_split($bits, 8) as $byte) {
|
|
// Reverse the order of bits within each byte-sized chunk using `strrev` function,
|
|
// then convert the reversed binary string to decimal using `bindec` function,
|
|
// then convert the decimal to hexadecimal using `dechex` function,
|
|
// and pad the resulting hexadecimal string with leading zeros to make it 2 characters long using `str_pad` function.
|
|
// Finally, concatenate the resulting hexadecimal byte to the bytes string.
|
|
$bytes .= (str_pad(dechex(bindec(strrev($byte))), 2, 0, STR_PAD_LEFT));
|
|
}
|
|
|
|
return $bytes; // Return the resulting hexadecimal bytes
|
|
}
|
|
|
|
/**
|
|
* Converts a string of bits to an array of hexadecimal values.
|
|
*
|
|
* @param string $bits The string of bits to convert.
|
|
* @return array The converted array of hexadecimal values.
|
|
*/
|
|
public function bitsToHexArray(string $bits): array {
|
|
$bytes = []; // Initialize an empty array to store the resulting hexadecimal bytes
|
|
// Split the bits string into an array of byte-sized chunks (8 bits per chunk)
|
|
foreach (str_split($bits, 8) as $byte) {
|
|
// Reverse the order of bits within each byte-sized chunk using `strrev` function,
|
|
// then convert the reversed binary string to decimal using `bindec` function,
|
|
// then convert the decimal to hexadecimal using `dechex` function,
|
|
// and pad the resulting hexadecimal string with leading zeros to make it 2 characters long using `str_pad` function.
|
|
// Finally, add the resulting hexadecimal byte to the bytes array.
|
|
$bytes[] = (str_pad(dechex(bindec(strrev($byte))), 2, 0, STR_PAD_LEFT));
|
|
}
|
|
|
|
return $bytes; // Return the resulting array of hexadecimal bytes
|
|
}
|
|
|
|
}
|