Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

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