/** * Reads a token from the context * * @param pdf_context $c * @return mixed */ protected function _readToken($c) { // If there is a token available // on the stack, pop it out and // return it. if (count($c->stack)) { return array_pop($c->stack); } // Strip away any whitespace do { if (!$c->ensureContent()) { return false; } $c->offset += strspn($c->buffer, " \n\f\r\t", $c->offset); } while ($c->offset >= $c->length - 1); // Get the first character in the stream $char = $c->buffer[$c->offset++]; switch ($char) { case '[': case ']': case '(': case ')': // This is either an array or literal string // delimiter, Return it return $char; case '<': case '>': // This could either be a hex string or // dictionary delimiter. Determine the // appropriate case and return the token if ($c->buffer[$c->offset] == $char) { if (!$c->ensureContent()) { return false; } $c->offset++; return $char . $char; } else { return $char; } case '%': // This is a comment - jump over it! $pos = $c->offset; while (1) { $match = preg_match("/(\r\n|\r|\n)/", $c->buffer, $m, PREG_OFFSET_CAPTURE, $pos); if ($match === 0) { if (!$c->increaseLength()) { return false; } else { continue; } } $c->offset = $m[0][1] + strlen($m[0][0]); return $this->_readToken($c); } default: // This is "another" type of token (probably // a dictionary entry or a numeric value) // Find the end and return it. if (!$c->ensureContent()) { return false; } while (1) { // Determine the length of the token $pos = strcspn($c->buffer, " %[]<>()/\n\f\r\t", $c->offset); if ($c->offset + $pos <= $c->length - 1) { break; } else { // If the script reaches this point, // the token may span beyond the end // of the current buffer. Therefore, // we increase the size of the buffer // and try again--just to be safe. $c->increaseLength(); } } $result = substr($c->buffer, $c->offset - 1, $pos + 1); $c->offset += $pos; return $result; } }