/** * Returns file size by seeking at the end of file * @see http://www.php.net/manual/en/function.filesize.php#79023 * @see http://www.php.net/manual/en/function.filesize.php#102135 * @param string $path Full path to file * @return BigInteger * @throws Exception */ public function getFileSize($path) { // This should work for large files on 64bit platforms and for small files everywhere $fp = fopen($path, "rb"); if (!$fp) { throw new Exception("Cannot open specified file for reading."); } $flockResult = flock($fp, LOCK_SH); $seekResult = fseek($fp, 0, SEEK_END); $position = ftell($fp); flock($fp, LOCK_UN); fclose($fp); // TODO: There is *hope* that ftell() or fseek() fails when file is over 4GB // TODO: This really needs tests, any ideas how to test this in CI? (please let me know) if ($flockResult === false) { throw new Exception("Couldn't get file lock. Operation abandoned."); } if ($seekResult !== 0) { throw new Exception("Seeking to end of file failed"); } if ($position === false) { throw new Exception("Cannot determine position in file. ftell() failed."); } // PHP uses internally (in C) UNSIGNED integer for file size. // PHP uses signed implicitly // convert signed (max val +2^31) -> unsigned integer will extend range for 32-bit to (+2^32) return BigInteger::of(sprintf("%u", $position)); }
/** * {@inheritdoc} */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null) { return null; } return BigInteger::of($value); }
/** * Creates a BigDecimal from an unscaled value and a scale. * * Example: `(12345, 3)` will result in the BigDecimal `12.345`. * * @param BigNumber|number|string $value The unscaled value. Must be convertible to a BigInteger. * @param int $scale The scale of the number, positive or zero. * * @return BigDecimal * * @throws \InvalidArgumentException If the scale is negative. */ public static function ofUnscaledValue($value, $scale = 0) { $scale = (int) $scale; if ($scale < 0) { throw new \InvalidArgumentException('The scale cannot be negative.'); } return new BigDecimal((string) BigInteger::of($value), $scale); }
/** * Returns file size by using Windows COM interface * @inheritdoc * @link http://stackoverflow.com/questions/5501451/php-x86-how-to-get-filesize-of-2gb-file-without-external-program/5502328#5502328 */ public function getFileSize($path) { // Use the Windows COM interface $fsobj = new \COM('Scripting.FileSystemObject'); if (dirname($path) == '.') { $this->path = substr(getcwd(), -1) == DIRECTORY_SEPARATOR ? getcwd() . basename($path) : getcwd() . DIRECTORY_SEPARATOR . basename($path); } $f = $fsobj->GetFile($path); return BigInteger::of($f->Size); }
/** * Convert string into integer * Must be precise number, otherwise you will see and exception. * * @param $valueAsString * @return BigInteger * @throws Exception */ private function convertToInteger($valueAsString) { if (!is_string($valueAsString)) { throw new Exception("Cannot convert to integer. Expected string, but got " . gettype($valueAsString) . "."); } $trimmedInput = trim($valueAsString); try { return BigInteger::of($trimmedInput); } catch (ArithmeticException $e) { throw new Exception("Returned value cannot be converted to an integer.", 0, $e); } }
/** * Returns file size by using CURL extension * @inheritdoc * @link http://www.php.net/manual/en/function.filesize.php#100434 */ public function getFileSize($path) { $ch = curl_init("file://" . rawurlencode($path)); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); $data = curl_exec($ch); curl_close($ch); if ($data !== false && preg_match('/Content-Length: (\\d+)/', $data, $matches)) { return BigInteger::of($matches[1]); } throw new Exception("Curl haven't returned file size."); }
/** * Returns file size by using system shell/cmd commands * @inheritdoc * @link http://stackoverflow.com/questions/5501451/php-x86-how-to-get-filesize-of-2gb-file-without-external-program/5502328#5502328 */ public function getFileSize($path) { $escapedPath = escapeshellarg($path); if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { // Windows // Try using the NT substitution modifier %~z $size = trim(exec("for %F in ({$escapedPath}) do @echo %~zF")); } else { // other OS // If the platform is not Windows, use the stat command (should work for *nix and MacOS) $size = trim(exec("stat -Lc%s {$escapedPath}")); } // If the return is not blank, not zero, and is number if ($size and ctype_digit($size)) { return BigInteger::of($size); } else { throw new Exception("Exec returned invalid value"); } }
function shift_uint(Binary $data) { if (PHP_INT_SIZE === 8) { if ($data->endianness === Binary::BIG_ENDIAN) { return unpack("N", $data->shift(4))[1]; } else { if ($data->endianness === Binary::LITTLE_ENDIAN) { return unpack("V", $data->shift(4))[1]; } } throw new \InvalidArgumentException("Unknown endianness provided"); } else { if (PHP_INT_SIZE === 4) { /* * On 32-bit systems, attempting to store a number of an unsigned 32-bit integer in a standard PHP integer * (which is a signed 32-bit) is impossible. PHP will convert such numbers automatically to a float which is * a behaviour we do not want. * * Therefore, it is necessary to manually gather individual bytes and put them back together to preserve * precision. */ $v = unpack("C4", $data->shift(4)); if ($data->endianness === Binary::LITTLE_ENDIAN) { $v = array_reverse($v); } else { if ($data->endianness === Binary::BIG_ENDIAN) { $v = array_values($v); // Otherwise the array will start at index 1 } else { throw new \InvalidArgumentException("Unknown endianness provided"); } } return BigInteger::of($v[0])->multipliedBy(BigInteger::of(2)->power(56))->plus(BigInteger::of($v[1])->multipliedBy(BigInteger::of(2)->power(48)))->plus(BigInteger::of($v[2])->multipliedBy(BigInteger::of(2)->power(40)))->plus(BigInteger::of($v[3])->multipliedBy(BigInteger::of(2)->power(32)))->plus(BigInteger::of($v[4])->multipliedBy(BigInteger::of(2)->power(24)))->plus(BigInteger::of($v[5])->multipliedBy(BigInteger::of(2)->power(16)))->plus(BigInteger::of($v[6])->multipliedBy(BigInteger::of(2)->power(8)))->plus(BigInteger::of($v[7])); } } throw new \RuntimeException("Unknown system architecture"); }
/** * This method is required by interface Serializable and MUST NOT be accessed directly. * * @internal * * @param string $value * * @return void */ public function unserialize($value) { if ($this->numerator !== null || $this->denominator !== null) { throw new \LogicException('unserialize() is an internal function, it must not be called directly.'); } list($numerator, $denominator) = explode('/', $value); $this->numerator = BigInteger::of($numerator); $this->denominator = BigInteger::of($denominator); }
/** * Returns the greatest common divisor of this number and the given one. * * The GCD is always positive, unless both operands are zero, in which case it is zero. * * @param BigNumber|number|string $that The operand. Must be convertible to an integer number. * * @return BigInteger */ public function gcd($that) { $that = BigInteger::of($that); if ($that->value === '0' && $this->value[0] !== '-') { return $this; } if ($this->value === '0' && $that->value[0] !== '-') { return $that; } $value = Calculator::get()->gcd($this->value, $that->value); return new BigInteger($value); }
public function testSerialize() { $value = '-1234567890987654321012345678909876543210123456789'; $number = BigInteger::of($value); $this->assertBigIntegerEquals($value, unserialize(serialize($number))); }
/** * @return array */ public function providerPlus() { return [['123/456', 1, '579/456'], ['123/456', BigInteger::of(2), '1035/456'], ['123/456', BigRational::nd(2, 3), '1281/1368'], ['234/567', '123/28', '76293/15876'], ['-1234567890123456789/497', '79394345/109859892', '-135629495075630790047217323/54600366324'], ['-1234567890123456789/999', '-98765/43210', '-53345678532234666518925/43166790'], ['123/456789123456789123456789', '-987/654321987654321', '-450850864771369260370369260/298887167199121283949604203169112635269']]; }