Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
/**
4
 * This file is part of FPDI
5
 *
6
 * @package   setasign\Fpdi
7
 * @copyright Copyright (c) 2023 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
}