Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.

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

   1  <?php
   2  
   3  /**
   4   * SCSSPHP
   5   *
   6   * @copyright 2012-2020 Leaf Corcoran
   7   *
   8   * @license http://opensource.org/licenses/MIT MIT
   9   *
  10   * @link http://scssphp.github.io/scssphp
  11   */
  12  
  13  namespace ScssPhp\ScssPhp\SourceMap;
  14  
  15  /**
  16   * Base 64 VLQ
  17   *
  18   * Based on the Base 64 VLQ implementation in Closure Compiler:
  19   * https://github.com/google/closure-compiler/blob/master/src/com/google/debugging/sourcemap/Base64VLQ.java
  20   *
  21   * Copyright 2011 The Closure Compiler Authors.
  22   *
  23   * Licensed under the Apache License, Version 2.0 (the "License");
  24   * you may not use this file except in compliance with the License.
  25   * You may obtain a copy of the License at
  26   *
  27   *     http://www.apache.org/licenses/LICENSE-2.0
  28   *
  29   * Unless required by applicable law or agreed to in writing, software
  30   * distributed under the License is distributed on an "AS IS" BASIS,
  31   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  32   * See the License for the specific language governing permissions and
  33   * limitations under the License.
  34   *
  35   * @author John Lenz <johnlenz@google.com>
  36   * @author Anthon Pang <anthon.pang@gmail.com>
  37   */
  38  class Base64VLQ
  39  {
  40      // A Base64 VLQ digit can represent 5 bits, so it is base-32.
  41      const VLQ_BASE_SHIFT = 5;
  42  
  43      // A mask of bits for a VLQ digit (11111), 31 decimal.
  44      const VLQ_BASE_MASK = 31;
  45  
  46      // The continuation bit is the 6th bit.
  47      const VLQ_CONTINUATION_BIT = 32;
  48  
  49      /**
  50       * Returns the VLQ encoded value.
  51       *
  52       * @param integer $value
  53       *
  54       * @return string
  55       */
  56      public static function encode($value)
  57      {
  58          $encoded = '';
  59          $vlq = self::toVLQSigned($value);
  60  
  61          do {
  62              $digit = $vlq & self::VLQ_BASE_MASK;
  63  
  64              //$vlq >>>= self::VLQ_BASE_SHIFT; // unsigned right shift
  65              $vlq = (($vlq >> 1) & PHP_INT_MAX) >> (self::VLQ_BASE_SHIFT - 1);
  66  
  67              if ($vlq > 0) {
  68                  $digit |= self::VLQ_CONTINUATION_BIT;
  69              }
  70  
  71              $encoded .= Base64::encode($digit);
  72          } while ($vlq > 0);
  73  
  74          return $encoded;
  75      }
  76  
  77      /**
  78       * Decodes VLQValue.
  79       *
  80       * @param string $str
  81       * @param integer $index
  82       *
  83       * @return integer
  84       */
  85      public static function decode($str, &$index)
  86      {
  87          $result = 0;
  88          $shift = 0;
  89  
  90          do {
  91              $c = $str[$index++];
  92              $digit = Base64::decode($c);
  93              $continuation = ($digit & self::VLQ_CONTINUATION_BIT) != 0;
  94              $digit &= self::VLQ_BASE_MASK;
  95              $result = $result + ($digit << $shift);
  96              $shift = $shift + self::VLQ_BASE_SHIFT;
  97          } while ($continuation);
  98  
  99          return self::fromVLQSigned($result);
 100      }
 101  
 102      /**
 103       * Converts from a two-complement value to a value where the sign bit is
 104       * is placed in the least significant bit.  For example, as decimals:
 105       *   1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
 106       *   2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
 107       *
 108       * @param integer $value
 109       *
 110       * @return integer
 111       */
 112      private static function toVLQSigned($value)
 113      {
 114          if ($value < 0) {
 115              return ((-$value) << 1) + 1;
 116          }
 117  
 118          return ($value << 1) + 0;
 119      }
 120  
 121      /**
 122       * Converts to a two-complement value from a value where the sign bit is
 123       * is placed in the least significant bit.  For example, as decimals:
 124       *   2 (10 binary) becomes 1, 3 (11 binary) becomes -1
 125       *   4 (100 binary) becomes 2, 5 (101 binary) becomes -2
 126       *
 127       * @param integer $value
 128       *
 129       * @return integer
 130       */
 131      private static function fromVLQSigned($value)
 132      {
 133          $negate = ($value & 1) === 1;
 134  
 135          //$value >>>= 1; // unsigned right shift
 136          $value = ($value >> 1) & PHP_INT_MAX;
 137  
 138          if (! $negate) {
 139              return $value;
 140          }
 141  
 142          // We need to OR 0x80000000 here to ensure the 32nd bit (the sign bit) is
 143          // always set for negative numbers. If `value` were 1, (meaning `negate` is
 144          // true and all other bits were zeros), `value` would now be 0. -0 is just
 145          // 0, and doesn't flip the 32nd bit as intended. All positive numbers will
 146          // successfully flip the 32nd bit without issue, so it's a noop for them.
 147          return -$value | 0x80000000;
 148      }
 149  }