Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 39 and 401]

   1  <?php
   2  
   3  /**
   4   * This file is part of FPDI
   5   *
   6   * @package   setasign\Fpdi
   7   * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
   8   * @license   http://opensource.org/licenses/mit-license The MIT License
   9   */
  10  
  11  namespace setasign\Fpdi\PdfParser;
  12  
  13  /**
  14   * A tokenizer class.
  15   */
  16  class Tokenizer
  17  {
  18      /**
  19       * @var StreamReader
  20       */
  21      protected $streamReader;
  22  
  23      /**
  24       * A token stack.
  25       *
  26       * @var string[]
  27       */
  28      protected $stack = [];
  29  
  30      /**
  31       * Tokenizer constructor.
  32       *
  33       * @param StreamReader $streamReader
  34       */
  35      public function __construct(StreamReader $streamReader)
  36      {
  37          $this->streamReader = $streamReader;
  38      }
  39  
  40      /**
  41       * Get the stream reader instance.
  42       *
  43       * @return StreamReader
  44       */
  45      public function getStreamReader()
  46      {
  47          return $this->streamReader;
  48      }
  49  
  50      /**
  51       * Clear the token stack.
  52       */
  53      public function clearStack()
  54      {
  55          $this->stack = [];
  56      }
  57  
  58      /**
  59       * Push a token onto the stack.
  60       *
  61       * @param string $token
  62       */
  63      public function pushStack($token)
  64      {
  65          $this->stack[] = $token;
  66      }
  67  
  68      /**
  69       * Get next token.
  70       *
  71       * @return bool|string
  72       */
  73      public function getNextToken()
  74      {
  75          $token = \array_pop($this->stack);
  76          if ($token !== null) {
  77              return $token;
  78          }
  79  
  80          if (($byte = $this->streamReader->readByte()) === false) {
  81              return false;
  82          }
  83  
  84          if (\in_array($byte, ["\x20", "\x0A", "\x0D", "\x0C", "\x09", "\x00"], true)) {
  85              if ($this->leapWhiteSpaces() === false) {
  86                  return false;
  87              }
  88              $byte = $this->streamReader->readByte();
  89          }
  90  
  91          switch ($byte) {
  92              case '/':
  93              case '[':
  94              case ']':
  95              case '(':
  96              case ')':
  97              case '{':
  98              case '}':
  99              case '<':
 100              case '>':
 101                  return $byte;
 102              case '%':
 103                  $this->streamReader->readLine();
 104                  return $this->getNextToken();
 105          }
 106  
 107          /* This way is faster than checking single bytes.
 108           */
 109          $bufferOffset = $this->streamReader->getOffset();
 110          do {
 111              $lastBuffer = $this->streamReader->getBuffer(false);
 112              $pos = \strcspn(
 113                  $lastBuffer,
 114                  "\x00\x09\x0A\x0C\x0D\x20()<>[]{}/%",
 115                  $bufferOffset
 116              );
 117          } while (
 118              // Break the loop if a delimiter or white space char is matched
 119              // in the current buffer or increase the buffers length
 120              $lastBuffer !== false &&
 121              (
 122                  $bufferOffset + $pos === \strlen($lastBuffer) &&
 123                  $this->streamReader->increaseLength()
 124              )
 125          );
 126  
 127          $result = \substr($lastBuffer, $bufferOffset - 1, $pos + 1);
 128          $this->streamReader->setOffset($bufferOffset + $pos);
 129  
 130          return $result;
 131      }
 132  
 133      /**
 134       * Leap white spaces.
 135       *
 136       * @return boolean
 137       */
 138      public function leapWhiteSpaces()
 139      {
 140          do {
 141              if (!$this->streamReader->ensureContent()) {
 142                  return false;
 143              }
 144  
 145              $buffer = $this->streamReader->getBuffer(false);
 146              $matches = \strspn($buffer, "\x20\x0A\x0C\x0D\x09\x00", $this->streamReader->getOffset());
 147              if ($matches > 0) {
 148                  $this->streamReader->addOffset($matches);
 149              }
 150          } while ($this->streamReader->getOffset() >= $this->streamReader->getBufferLength());
 151  
 152          return true;
 153      }
 154  }