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 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

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