Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 400 and 403] [Versions 401 and 403]

   1  <?php
   2  
   3  declare(strict_types=1);
   4  
   5  namespace ZipStream;
   6  
   7  use OverflowException;
   8  
   9  class Bigint
  10  {
  11      /**
  12       * @var int[]
  13       */
  14      private $bytes = [0, 0, 0, 0, 0, 0, 0, 0];
  15  
  16      /**
  17       * Initialize the bytes array
  18       *
  19       * @param int $value
  20       */
  21      public function __construct(int $value = 0)
  22      {
  23          $this->fillBytes($value, 0, 8);
  24      }
  25  
  26      /**
  27       * Get an instance
  28       *
  29       * @param int $value
  30       * @return Bigint
  31       */
  32      public static function init(int $value = 0): self
  33      {
  34          return new self($value);
  35      }
  36  
  37      /**
  38       * Fill bytes from low to high
  39       *
  40       * @param int $low
  41       * @param int $high
  42       * @return Bigint
  43       */
  44      public static function fromLowHigh(int $low, int $high): self
  45      {
  46          $bigint = new self();
  47          $bigint->fillBytes($low, 0, 4);
  48          $bigint->fillBytes($high, 4, 4);
  49          return $bigint;
  50      }
  51  
  52      /**
  53       * Get high 32
  54       *
  55       * @return int
  56       */
  57      public function getHigh32(): int
  58      {
  59          return $this->getValue(4, 4);
  60      }
  61  
  62      /**
  63       * Get value from bytes array
  64       *
  65       * @param int $end
  66       * @param int $length
  67       * @return int
  68       */
  69      public function getValue(int $end = 0, int $length = 8): int
  70      {
  71          $result = 0;
  72          for ($i = $end + $length - 1; $i >= $end; $i--) {
  73              $result <<= 8;
  74              $result |= $this->bytes[$i];
  75          }
  76          return $result;
  77      }
  78  
  79      /**
  80       * Get low FF
  81       *
  82       * @param bool $force
  83       * @return float
  84       */
  85      public function getLowFF(bool $force = false): float
  86      {
  87          if ($force || $this->isOver32()) {
  88              return (float)0xFFFFFFFF;
  89          }
  90          return (float)$this->getLow32();
  91      }
  92  
  93      /**
  94       * Check if is over 32
  95       *
  96       * @psalm-suppress ArgumentTypeCoercion
  97       * @param bool $force
  98       * @return bool
  99       */
 100      public function isOver32(bool $force = false): bool
 101      {
 102          // value 0xFFFFFFFF already needs a Zip64 header
 103          return $force ||
 104              max(array_slice($this->bytes, 4, 4)) > 0 ||
 105              min(array_slice($this->bytes, 0, 4)) === 0xFF;
 106      }
 107  
 108      /**
 109       * Get low 32
 110       *
 111       * @return int
 112       */
 113      public function getLow32(): int
 114      {
 115          return $this->getValue(0, 4);
 116      }
 117  
 118      /**
 119       * Get hexadecimal
 120       *
 121       * @return string
 122       */
 123      public function getHex64(): string
 124      {
 125          $result = '0x';
 126          for ($i = 7; $i >= 0; $i--) {
 127              $result .= sprintf('%02X', $this->bytes[$i]);
 128          }
 129          return $result;
 130      }
 131  
 132      /**
 133       * Add
 134       *
 135       * @param Bigint $other
 136       * @return Bigint
 137       */
 138      public function add(self $other): self
 139      {
 140          $result = clone $this;
 141          $overflow = false;
 142          for ($i = 0; $i < 8; $i++) {
 143              $result->bytes[$i] += $other->bytes[$i];
 144              if ($overflow) {
 145                  $result->bytes[$i]++;
 146                  $overflow = false;
 147              }
 148              if ($result->bytes[$i] & 0x100) {
 149                  $overflow = true;
 150                  $result->bytes[$i] &= 0xFF;
 151              }
 152          }
 153          if ($overflow) {
 154              throw new OverflowException();
 155          }
 156          return $result;
 157      }
 158  
 159      /**
 160       * Fill the bytes field with int
 161       *
 162       * @param int $value
 163       * @param int $start
 164       * @param int $count
 165       * @return void
 166       */
 167      protected function fillBytes(int $value, int $start, int $count): void
 168      {
 169          for ($i = 0; $i < $count; $i++) {
 170              $this->bytes[$start + $i] = $i >= PHP_INT_SIZE ? 0 : $value & 0xFF;
 171              $value >>= 8;
 172          }
 173      }
 174  }