1 : <?php
2 :
3 : /**
4 : * \Midi\Parsing\Parser
5 : *
6 : * @package Midi
7 : * @subpackage Parsing
8 : * @copyright © 2009 Tommy Montgomery <http://phpmidiparser.com/>
9 : * @since 1.0
10 : */
11 :
12 : namespace Midi\Parsing;
13 :
14 : use \Midi\Util\Util;
15 : use \SplFileObject;
16 :
17 : /**
18 : * Base parsing class
19 : *
20 : * @package Midi
21 : * @subpackage Parsing
22 : * @since 1.0
23 : */
24 : abstract class Parser {
25 :
26 : /**
27 : * The current state of the parser
28 : *
29 : * @var int
30 : * @see ParseState
31 : */
32 : private $state;
33 :
34 : /**
35 : * The file to parse
36 : *
37 : * @var SplFileObject
38 : */
39 : protected $file;
40 :
41 : /**
42 : * Constructor
43 : *
44 : * @since 1.0
45 : */
46 : public function __construct() {
47 65 : $this->file = null;
48 65 : $this->state = ParseState::EOF;
49 65 : }
50 :
51 : /**
52 : * Creates a file object suitable for {@link load()}
53 : *
54 : * @since 1.0
55 : *
56 : * @param string $file
57 : * @return SplFileObject
58 : */
59 : public function createFileObject($file) {
60 1 : return new SplFileObject($file, 'rb');
61 : }
62 :
63 : /**
64 : * Loads a file to be parsed
65 : *
66 : * @since 1.0
67 : * @uses createFileObject()
68 : * @uses afterLoad()
69 : *
70 : * @param string|SplFileObject $file A file path, or an SplFileObject opened in "rb" mode
71 : */
72 : public function load($file) {
73 2 : if (!($file instanceof SplFileObject)) {
74 1 : $file = $this->createFileObject($file);
75 1 : }
76 :
77 2 : $this->file = $file;
78 2 : $this->afterLoad();
79 2 : }
80 :
81 : /**
82 : * Sets the buffer stream to read from
83 : *
84 : * @since 1.0
85 : * @uses afterSetFile()
86 : *
87 : * @param SplFileObject $file
88 : */
89 : public function setFile(SplFileObject $file) {
90 10 : $this->file = $file;
91 10 : $this->afterSetFile();
92 10 : }
93 :
94 : /**
95 : * Gets the current parse state
96 : *
97 : * The default is {@link ParseState::EOF}.
98 : *
99 : * @since 1.0
100 : *
101 : * @return int One of the {@link ParseState} constants
102 : */
103 : public function getState() {
104 6 : return $this->state;
105 : }
106 :
107 : /**
108 : * Sets the current parse state
109 : *
110 : * @since 1.0
111 : *
112 : * @param int $state See {@link ParseState}
113 : */
114 : protected function setState($state) {
115 29 : $this->state = $state;
116 29 : }
117 :
118 : /**
119 : * Reads $count bytes from the buffer stream
120 : *
121 : * @since 1.0
122 : *
123 : * @param int $count
124 : * @param bool $throwOnEof Whether to throw a {@link ParseException} if EOF is encountered
125 : * @throws {@link ParseException}
126 : * @return binary
127 : */
128 : protected function read($count, $throwOnEof = false) {
129 3 : $data = null;
130 3 : while ($this->file->valid() && $count--) {
131 3 : $data .= $this->file->fgetc();
132 3 : }
133 :
134 3 : if ($count > 0 && $throwOnEof) {
135 1 : throw new ParseException('Unexpected EOF');
136 : }
137 :
138 2 : return $data;
139 : }
140 :
141 : /**
142 : * Reads a delta time from the buffer stream
143 : *
144 : * @since 1.0
145 : * @uses read()
146 : * @uses Util::unpack()
147 : * @uses Util::getTicksFromDeltaByteSequence()
148 : *
149 : * @return int The number of clock ticks in the delta time
150 : */
151 : protected function getDelta() {
152 1 : $byte = $this->read(1, true);
153 1 : $value = Util::unpack($byte);
154 1 : $delta = '';
155 1 : while ($this->file->valid() && $value[0] > 0x7F) {
156 1 : $delta .= $byte;
157 1 : $byte = $this->read(1);
158 1 : $value = Util::unpack($byte);
159 1 : }
160 :
161 1 : if ($byte !== null) {
162 1 : $delta .= $byte;
163 1 : }
164 :
165 1 : return Util::getTicksFromDeltaByteSequence($delta);
166 : }
167 :
168 : /**
169 : * Called after {@link load()}
170 : *
171 : * @since 1.0
172 : */
173 : protected function afterLoad() {
174 :
175 1 : }
176 :
177 : /**
178 : * Called after {@link setFile()}
179 : *
180 : * @since 1.0
181 : */
182 : protected function afterSetFile() {
183 :
184 9 : }
185 :
186 : /**
187 : * Parses the buffer stream and returns the next chunk
188 : *
189 : * @since 1.0
190 : *
191 : * @return Chunk
192 : */
193 : public abstract function parse();
194 :
195 : }
196 :
|