1<?php
2/**
3 * This file is part of FPDI
4 *
5 * @package   setasign\Fpdi
6 * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
7 * @license   http://opensource.org/licenses/mit-license The MIT License
8 */
9
10namespace setasign\Fpdi\PdfParser\CrossReference;
11
12use setasign\Fpdi\PdfParser\PdfParser;
13use setasign\Fpdi\PdfParser\Type\PdfDictionary;
14use setasign\Fpdi\PdfParser\Type\PdfToken;
15use setasign\Fpdi\PdfParser\Type\PdfTypeException;
16
17/**
18 * Abstract class for cross-reference reader classes.
19 *
20 * @package setasign\Fpdi\PdfParser\CrossReference
21 */
22abstract class AbstractReader
23{
24    /**
25     * @var PdfParser
26     */
27    protected $parser;
28
29    /**
30     * @var PdfDictionary
31     */
32    protected $trailer;
33
34    /**
35     * AbstractReader constructor.
36     *
37     * @param PdfParser $parser
38     * @throws CrossReferenceException
39     * @throws PdfTypeException
40     */
41    public function __construct(PdfParser $parser)
42    {
43        $this->parser = $parser;
44        $this->readTrailer();
45    }
46
47    /**
48     * Get the trailer dictionary.
49     *
50     * @return PdfDictionary
51     */
52    public function getTrailer()
53    {
54        return $this->trailer;
55    }
56
57    /**
58     * Read the trailer dictionary.
59     *
60     * @throws CrossReferenceException
61     * @throws PdfTypeException
62     */
63    protected function readTrailer()
64    {
65        try {
66            $trailerKeyword = $this->parser->readValue(null, PdfToken::class);
67            if ($trailerKeyword->value !== 'trailer') {
68                throw new CrossReferenceException(
69                    \sprintf(
70                        'Unexpected end of cross reference. "trailer"-keyword expected, got: %s.',
71                        $trailerKeyword->value
72                    ),
73                    CrossReferenceException::UNEXPECTED_END
74                );
75            }
76        } catch (PdfTypeException $e) {
77            throw new CrossReferenceException(
78                'Unexpected end of cross reference. "trailer"-keyword expected, got an invalid object type.',
79                CrossReferenceException::UNEXPECTED_END,
80                $e
81            );
82        }
83
84        try {
85            $trailer = $this->parser->readValue(null, PdfDictionary::class);
86        } catch (PdfTypeException $e) {
87            throw new CrossReferenceException(
88                'Unexpected end of cross reference. Trailer not found.',
89                CrossReferenceException::UNEXPECTED_END,
90                $e
91            );
92        }
93
94        $this->trailer = $trailer;
95    }
96}
97