]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | <?php |
2 | /* | |
3 | * Licensed to the Apache Software Foundation (ASF) under one | |
4 | * or more contributor license agreements. See the NOTICE file | |
5 | * distributed with this work for additional information | |
6 | * regarding copyright ownership. The ASF licenses this file | |
7 | * to you under the Apache License, Version 2.0 (the | |
8 | * "License"); you may not use this file except in compliance | |
9 | * with the License. You may obtain a copy of the License at | |
10 | * | |
11 | * http://www.apache.org/licenses/LICENSE-2.0 | |
12 | * | |
13 | * Unless required by applicable law or agreed to in writing, | |
14 | * software distributed under the License is distributed on an | |
15 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
16 | * KIND, either express or implied. See the License for the | |
17 | * specific language governing permissions and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @package thrift | |
21 | */ | |
22 | ||
23 | namespace Thrift\Exception; | |
24 | ||
25 | use Thrift\Type\TType; | |
26 | use Thrift\Base\TBase; | |
27 | ||
28 | /** | |
29 | * NOTE(mcslee): This currently contains a ton of duplicated code from TBase | |
30 | * because we need to save CPU cycles and this is not yet in an extension. | |
31 | * Ideally we'd multiply-inherit TException from both Exception and Base, but | |
32 | * that's not possible in PHP and there are no modules either, so for now we | |
33 | * apologetically take a trip to HackTown. | |
34 | * | |
35 | * Can be called with standard Exception constructor (message, code) or with | |
36 | * Thrift Base object constructor (spec, vals). | |
37 | * | |
38 | * @param mixed $p1 Message (string) or type-spec (array) | |
39 | * @param mixed $p2 Code (integer) or values (array) | |
40 | */ | |
41 | class TException extends \Exception | |
42 | { | |
43 | public function __construct($p1 = null, $p2 = 0) | |
44 | { | |
45 | if (is_array($p1) && is_array($p2)) { | |
46 | $spec = $p1; | |
47 | $vals = $p2; | |
48 | foreach ($spec as $fid => $fspec) { | |
49 | $var = $fspec['var']; | |
50 | if (isset($vals[$var])) { | |
51 | $this->$var = $vals[$var]; | |
52 | } | |
53 | } | |
54 | } else { | |
55 | parent::__construct($p1, $p2); | |
56 | } | |
57 | } | |
58 | ||
59 | public static $tmethod = array( | |
60 | TType::BOOL => 'Bool', | |
61 | TType::BYTE => 'Byte', | |
62 | TType::I16 => 'I16', | |
63 | TType::I32 => 'I32', | |
64 | TType::I64 => 'I64', | |
65 | TType::DOUBLE => 'Double', | |
66 | TType::STRING => 'String' | |
67 | ); | |
68 | ||
69 | private function _readMap(&$var, $spec, $input) | |
70 | { | |
71 | $xfer = 0; | |
72 | $ktype = $spec['ktype']; | |
73 | $vtype = $spec['vtype']; | |
74 | $kread = $vread = null; | |
75 | if (isset(TBase::$tmethod[$ktype])) { | |
76 | $kread = 'read' . TBase::$tmethod[$ktype]; | |
77 | } else { | |
78 | $kspec = $spec['key']; | |
79 | } | |
80 | if (isset(TBase::$tmethod[$vtype])) { | |
81 | $vread = 'read' . TBase::$tmethod[$vtype]; | |
82 | } else { | |
83 | $vspec = $spec['val']; | |
84 | } | |
85 | $var = array(); | |
86 | $_ktype = $_vtype = $size = 0; | |
87 | $xfer += $input->readMapBegin($_ktype, $_vtype, $size); | |
88 | for ($i = 0; $i < $size; ++$i) { | |
89 | $key = $val = null; | |
90 | if ($kread !== null) { | |
91 | $xfer += $input->$kread($key); | |
92 | } else { | |
93 | switch ($ktype) { | |
94 | case TType::STRUCT: | |
95 | $class = $kspec['class']; | |
96 | $key = new $class(); | |
97 | $xfer += $key->read($input); | |
98 | break; | |
99 | case TType::MAP: | |
100 | $xfer += $this->_readMap($key, $kspec, $input); | |
101 | break; | |
102 | case TType::LST: | |
103 | $xfer += $this->_readList($key, $kspec, $input, false); | |
104 | break; | |
105 | case TType::SET: | |
106 | $xfer += $this->_readList($key, $kspec, $input, true); | |
107 | break; | |
108 | } | |
109 | } | |
110 | if ($vread !== null) { | |
111 | $xfer += $input->$vread($val); | |
112 | } else { | |
113 | switch ($vtype) { | |
114 | case TType::STRUCT: | |
115 | $class = $vspec['class']; | |
116 | $val = new $class(); | |
117 | $xfer += $val->read($input); | |
118 | break; | |
119 | case TType::MAP: | |
120 | $xfer += $this->_readMap($val, $vspec, $input); | |
121 | break; | |
122 | case TType::LST: | |
123 | $xfer += $this->_readList($val, $vspec, $input, false); | |
124 | break; | |
125 | case TType::SET: | |
126 | $xfer += $this->_readList($val, $vspec, $input, true); | |
127 | break; | |
128 | } | |
129 | } | |
130 | $var[$key] = $val; | |
131 | } | |
132 | $xfer += $input->readMapEnd(); | |
133 | ||
134 | return $xfer; | |
135 | } | |
136 | ||
137 | private function _readList(&$var, $spec, $input, $set = false) | |
138 | { | |
139 | $xfer = 0; | |
140 | $etype = $spec['etype']; | |
141 | $eread = $vread = null; | |
142 | if (isset(TBase::$tmethod[$etype])) { | |
143 | $eread = 'read' . TBase::$tmethod[$etype]; | |
144 | } else { | |
145 | $espec = $spec['elem']; | |
146 | } | |
147 | $var = array(); | |
148 | $_etype = $size = 0; | |
149 | if ($set) { | |
150 | $xfer += $input->readSetBegin($_etype, $size); | |
151 | } else { | |
152 | $xfer += $input->readListBegin($_etype, $size); | |
153 | } | |
154 | for ($i = 0; $i < $size; ++$i) { | |
155 | $elem = null; | |
156 | if ($eread !== null) { | |
157 | $xfer += $input->$eread($elem); | |
158 | } else { | |
159 | $espec = $spec['elem']; | |
160 | switch ($etype) { | |
161 | case TType::STRUCT: | |
162 | $class = $espec['class']; | |
163 | $elem = new $class(); | |
164 | $xfer += $elem->read($input); | |
165 | break; | |
166 | case TType::MAP: | |
167 | $xfer += $this->_readMap($elem, $espec, $input); | |
168 | break; | |
169 | case TType::LST: | |
170 | $xfer += $this->_readList($elem, $espec, $input, false); | |
171 | break; | |
172 | case TType::SET: | |
173 | $xfer += $this->_readList($elem, $espec, $input, true); | |
174 | break; | |
175 | } | |
176 | } | |
177 | if ($set) { | |
178 | $var[$elem] = true; | |
179 | } else { | |
180 | $var [] = $elem; | |
181 | } | |
182 | } | |
183 | if ($set) { | |
184 | $xfer += $input->readSetEnd(); | |
185 | } else { | |
186 | $xfer += $input->readListEnd(); | |
187 | } | |
188 | ||
189 | return $xfer; | |
190 | } | |
191 | ||
192 | protected function _read($class, $spec, $input) | |
193 | { | |
194 | $xfer = 0; | |
195 | $fname = null; | |
196 | $ftype = 0; | |
197 | $fid = 0; | |
198 | $xfer += $input->readStructBegin($fname); | |
199 | while (true) { | |
200 | $xfer += $input->readFieldBegin($fname, $ftype, $fid); | |
201 | if ($ftype == TType::STOP) { | |
202 | break; | |
203 | } | |
204 | if (isset($spec[$fid])) { | |
205 | $fspec = $spec[$fid]; | |
206 | $var = $fspec['var']; | |
207 | if ($ftype == $fspec['type']) { | |
208 | $xfer = 0; | |
209 | if (isset(TBase::$tmethod[$ftype])) { | |
210 | $func = 'read' . TBase::$tmethod[$ftype]; | |
211 | $xfer += $input->$func($this->$var); | |
212 | } else { | |
213 | switch ($ftype) { | |
214 | case TType::STRUCT: | |
215 | $class = $fspec['class']; | |
216 | $this->$var = new $class(); | |
217 | $xfer += $this->$var->read($input); | |
218 | break; | |
219 | case TType::MAP: | |
220 | $xfer += $this->_readMap($this->$var, $fspec, $input); | |
221 | break; | |
222 | case TType::LST: | |
223 | $xfer += $this->_readList($this->$var, $fspec, $input, false); | |
224 | break; | |
225 | case TType::SET: | |
226 | $xfer += $this->_readList($this->$var, $fspec, $input, true); | |
227 | break; | |
228 | } | |
229 | } | |
230 | } else { | |
231 | $xfer += $input->skip($ftype); | |
232 | } | |
233 | } else { | |
234 | $xfer += $input->skip($ftype); | |
235 | } | |
236 | $xfer += $input->readFieldEnd(); | |
237 | } | |
238 | $xfer += $input->readStructEnd(); | |
239 | ||
240 | return $xfer; | |
241 | } | |
242 | ||
243 | private function _writeMap($var, $spec, $output) | |
244 | { | |
245 | $xfer = 0; | |
246 | $ktype = $spec['ktype']; | |
247 | $vtype = $spec['vtype']; | |
248 | $kwrite = $vwrite = null; | |
249 | if (isset(TBase::$tmethod[$ktype])) { | |
250 | $kwrite = 'write' . TBase::$tmethod[$ktype]; | |
251 | } else { | |
252 | $kspec = $spec['key']; | |
253 | } | |
254 | if (isset(TBase::$tmethod[$vtype])) { | |
255 | $vwrite = 'write' . TBase::$tmethod[$vtype]; | |
256 | } else { | |
257 | $vspec = $spec['val']; | |
258 | } | |
259 | $xfer += $output->writeMapBegin($ktype, $vtype, count($var)); | |
260 | foreach ($var as $key => $val) { | |
261 | if (isset($kwrite)) { | |
262 | $xfer += $output->$kwrite($key); | |
263 | } else { | |
264 | switch ($ktype) { | |
265 | case TType::STRUCT: | |
266 | $xfer += $key->write($output); | |
267 | break; | |
268 | case TType::MAP: | |
269 | $xfer += $this->_writeMap($key, $kspec, $output); | |
270 | break; | |
271 | case TType::LST: | |
272 | $xfer += $this->_writeList($key, $kspec, $output, false); | |
273 | break; | |
274 | case TType::SET: | |
275 | $xfer += $this->_writeList($key, $kspec, $output, true); | |
276 | break; | |
277 | } | |
278 | } | |
279 | if (isset($vwrite)) { | |
280 | $xfer += $output->$vwrite($val); | |
281 | } else { | |
282 | switch ($vtype) { | |
283 | case TType::STRUCT: | |
284 | $xfer += $val->write($output); | |
285 | break; | |
286 | case TType::MAP: | |
287 | $xfer += $this->_writeMap($val, $vspec, $output); | |
288 | break; | |
289 | case TType::LST: | |
290 | $xfer += $this->_writeList($val, $vspec, $output, false); | |
291 | break; | |
292 | case TType::SET: | |
293 | $xfer += $this->_writeList($val, $vspec, $output, true); | |
294 | break; | |
295 | } | |
296 | } | |
297 | } | |
298 | $xfer += $output->writeMapEnd(); | |
299 | ||
300 | return $xfer; | |
301 | } | |
302 | ||
303 | private function _writeList($var, $spec, $output, $set = false) | |
304 | { | |
305 | $xfer = 0; | |
306 | $etype = $spec['etype']; | |
307 | $ewrite = null; | |
308 | if (isset(TBase::$tmethod[$etype])) { | |
309 | $ewrite = 'write' . TBase::$tmethod[$etype]; | |
310 | } else { | |
311 | $espec = $spec['elem']; | |
312 | } | |
313 | if ($set) { | |
314 | $xfer += $output->writeSetBegin($etype, count($var)); | |
315 | } else { | |
316 | $xfer += $output->writeListBegin($etype, count($var)); | |
317 | } | |
318 | foreach ($var as $key => $val) { | |
319 | $elem = $set ? $key : $val; | |
320 | if (isset($ewrite)) { | |
321 | $xfer += $output->$ewrite($elem); | |
322 | } else { | |
323 | switch ($etype) { | |
324 | case TType::STRUCT: | |
325 | $xfer += $elem->write($output); | |
326 | break; | |
327 | case TType::MAP: | |
328 | $xfer += $this->_writeMap($elem, $espec, $output); | |
329 | break; | |
330 | case TType::LST: | |
331 | $xfer += $this->_writeList($elem, $espec, $output, false); | |
332 | break; | |
333 | case TType::SET: | |
334 | $xfer += $this->_writeList($elem, $espec, $output, true); | |
335 | break; | |
336 | } | |
337 | } | |
338 | } | |
339 | if ($set) { | |
340 | $xfer += $output->writeSetEnd(); | |
341 | } else { | |
342 | $xfer += $output->writeListEnd(); | |
343 | } | |
344 | ||
345 | return $xfer; | |
346 | } | |
347 | ||
348 | protected function _write($class, $spec, $output) | |
349 | { | |
350 | $xfer = 0; | |
351 | $xfer += $output->writeStructBegin($class); | |
352 | foreach ($spec as $fid => $fspec) { | |
353 | $var = $fspec['var']; | |
354 | if ($this->$var !== null) { | |
355 | $ftype = $fspec['type']; | |
356 | $xfer += $output->writeFieldBegin($var, $ftype, $fid); | |
357 | if (isset(TBase::$tmethod[$ftype])) { | |
358 | $func = 'write' . TBase::$tmethod[$ftype]; | |
359 | $xfer += $output->$func($this->$var); | |
360 | } else { | |
361 | switch ($ftype) { | |
362 | case TType::STRUCT: | |
363 | $xfer += $this->$var->write($output); | |
364 | break; | |
365 | case TType::MAP: | |
366 | $xfer += $this->_writeMap($this->$var, $fspec, $output); | |
367 | break; | |
368 | case TType::LST: | |
369 | $xfer += $this->_writeList($this->$var, $fspec, $output, false); | |
370 | break; | |
371 | case TType::SET: | |
372 | $xfer += $this->_writeList($this->$var, $fspec, $output, true); | |
373 | break; | |
374 | } | |
375 | } | |
376 | $xfer += $output->writeFieldEnd(); | |
377 | } | |
378 | } | |
379 | $xfer += $output->writeFieldStop(); | |
380 | $xfer += $output->writeStructEnd(); | |
381 | ||
382 | return $xfer; | |
383 | } | |
384 | } |