[SPIP] ~maj v3.0.14-->v3.0.17
[ptitvelo/web/www.git] / www / plugins-dist / textwheel / lib / yaml / sfYamlInline.php
1 <?php
2
3 /*
4 * This file is part of the symfony package.
5 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11 if (!defined('_ECRIRE_INC_VERSION')) return;
12
13 /**
14 * sfYamlInline implements a YAML parser/dumper for the YAML inline syntax.
15 *
16 * @package symfony
17 * @subpackage yaml
18 * @author Fabien Potencier <fabien.potencier@symfony-project.com>
19 * @version SVN: $Id: sfYamlInline.class.php 16177 2009-03-11 08:32:48Z fabien $
20 */
21 class sfYamlInline
22 {
23 /**
24 * Convert a YAML string to a PHP array.
25 *
26 * @param string $value A YAML string
27 *
28 * @return array A PHP array representing the YAML string
29 */
30 static public function load($value)
31 {
32 $value = trim($value);
33
34 if (0 == strlen($value))
35 {
36 return '';
37 }
38
39 switch ($value[0])
40 {
41 case '[':
42 return self::parseSequence($value);
43 case '{':
44 return self::parseMapping($value);
45 default:
46 return self::parseScalar($value);
47 }
48 }
49
50 /**
51 * Dumps a given PHP variable to a YAML string.
52 *
53 * @param mixed $value The PHP variable to convert
54 *
55 * @return string The YAML string representing the PHP array
56 */
57 static public function dump($value)
58 {
59 $trueValues = '1.1' == sfYaml::getSpecVersion() ? array('true', 'on', '+', 'yes', 'y') : array('true');
60 $falseValues = '1.1' == sfYaml::getSpecVersion() ? array('false', 'off', '-', 'no', 'n') : array('false');
61
62 switch (true)
63 {
64 case is_resource($value):
65 throw new InvalidArgumentException('Unable to dump PHP resources in a YAML file.');
66 case is_object($value):
67 return '!!php/object:'.serialize($value);
68 case is_array($value):
69 return self::dumpArray($value);
70 case null === $value:
71 return 'null';
72 case true === $value:
73 return 'true';
74 case false === $value:
75 return 'false';
76 case ctype_digit($value):
77 return is_string($value) ? "'$value'" : (int) $value;
78 case is_numeric($value):
79 return is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : (is_string($value) ? "'$value'" : $value);
80 case false !== strpos($value, "\n"):
81 return sprintf('"%s"', str_replace(array('"', "\n", "\r"), array('\\"', '\n', '\r'), $value));
82 case preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \#] | \A[ - ? | < > = ! % @ ]/x', $value):
83 return sprintf("'%s'", str_replace('\'', '\'\'', $value));
84 case '' == $value:
85 return "''";
86 case preg_match(self::getTimestampRegex(), $value):
87 return "'$value'";
88 case in_array(strtolower($value), $trueValues):
89 return "'$value'";
90 case in_array(strtolower($value), $falseValues):
91 return "'$value'";
92 case in_array(strtolower($value), array('null', '~')):
93 return "'$value'";
94 default:
95 return $value;
96 }
97 }
98
99 /**
100 * Dumps a PHP array to a YAML string.
101 *
102 * @param array $value The PHP array to dump
103 *
104 * @return string The YAML string representing the PHP array
105 */
106 static protected function dumpArray($value)
107 {
108 // array
109 $keys = array_keys($value);
110 if (
111 (1 == count($keys) && '0' == $keys[0])
112 ||
113 (count($keys) > 1 && array_reduce($keys, create_function('$v,$w', 'return (integer) $v + $w;'), 0) == count($keys) * (count($keys) - 1) / 2))
114 {
115 $output = array();
116 foreach ($value as $val)
117 {
118 $output[] = self::dump($val);
119 }
120
121 return sprintf('[%s]', implode(', ', $output));
122 }
123
124 // mapping
125 $output = array();
126 foreach ($value as $key => $val)
127 {
128 $output[] = sprintf('%s: %s', self::dump($key), self::dump($val));
129 }
130
131 return sprintf('{ %s }', implode(', ', $output));
132 }
133
134 /**
135 * Parses a scalar to a YAML string.
136 *
137 * @param scalar $scalar
138 * @param string $delimiters
139 * @param array $stringDelimiter
140 * @param integer $i
141 * @param boolean $evaluate
142 *
143 * @return string A YAML string
144 */
145 static public function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true)
146 {
147 if (in_array($scalar[$i], $stringDelimiters))
148 {
149 // quoted scalar
150 $output = self::parseQuotedScalar($scalar, $i);
151
152 // skip next delimiter
153 ++$i;
154 }
155 else
156 {
157 // "normal" string
158 if (!$delimiters)
159 {
160 $output = substr($scalar, $i);
161 $i += strlen($output);
162
163 // remove comments
164 if (false !== $strpos = strpos($output, ' #'))
165 {
166 $output = rtrim(substr($output, 0, $strpos));
167 }
168 }
169 else if (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match))
170 {
171 $output = $match[1];
172 $i += strlen($output);
173 }
174 else
175 {
176 throw new InvalidArgumentException(sprintf('Malformed inline YAML string (%s).', $scalar));
177 }
178
179 $output = $evaluate ? self::evaluateScalar($output) : $output;
180 }
181
182 return $output;
183 }
184
185 /**
186 * Parses a quoted scalar to YAML.
187 *
188 * @param string $scalar
189 * @param integer $i
190 *
191 * @return string A YAML string
192 */
193 static protected function parseQuotedScalar($scalar, &$i)
194 {
195 $delimiter = $scalar[$i];
196 ++$i;
197 $buffer = '';
198 $len = strlen($scalar);
199 $escaped = '"' == $delimiter ? '\\"' : "''";
200
201 while ($i < $len)
202 {
203 if (isset($scalar[$i + 1]) && $escaped == $scalar[$i].$scalar[$i + 1])
204 {
205 $buffer .= $delimiter;
206 ++$i;
207 }
208 else if ($delimiter == $scalar[$i])
209 {
210 break;
211 }
212 else
213 {
214 $buffer .= $scalar[$i];
215 }
216
217 ++$i;
218 }
219
220 if ('"' == $delimiter)
221 {
222 // evaluate the string
223 $buffer = str_replace(array('\\n', '\\r'), array("\n", "\r"), $buffer);
224 if (strpos($buffer,'\\x')!==false){
225 $buffer = preg_replace_callback(',\\\\x([0-9a-f]+),', create_function('$m', 'return chr(hexdec($m[1]));'), $buffer);
226 }
227 }
228
229 return $buffer;
230 }
231
232 /**
233 * Parses a sequence to a YAML string.
234 *
235 * @param string $sequence
236 * @param integer $i
237 *
238 * @return string A YAML string
239 */
240 static protected function parseSequence($sequence, &$i = 0)
241 {
242 $output = array();
243 $len = strlen($sequence);
244 $i += 1;
245
246 // [foo, bar, ...]
247 while ($i < $len)
248 {
249 switch ($sequence[$i])
250 {
251 case '[':
252 // nested sequence
253 $output[] = self::parseSequence($sequence, $i);
254 break;
255 case '{':
256 // nested mapping
257 $output[] = self::parseMapping($sequence, $i);
258 break;
259 case ']':
260 return $output;
261 case ',':
262 case ' ':
263 break;
264 default:
265 $isQuoted = in_array($sequence[$i], array('"', "'"));
266 $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i);
267
268 if (!$isQuoted && false !== strpos($value, ': '))
269 {
270 // embedded mapping?
271 try
272 {
273 $value = self::parseMapping('{'.$value.'}');
274 }
275 catch (InvalidArgumentException $e)
276 {
277 // no, it's not
278 }
279 }
280
281 $output[] = $value;
282
283 --$i;
284 }
285
286 ++$i;
287 }
288
289 throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $sequence));
290 }
291
292 /**
293 * Parses a mapping to a YAML string.
294 *
295 * @param string $mapping
296 * @param integer $i
297 *
298 * @return string A YAML string
299 */
300 static protected function parseMapping($mapping, &$i = 0)
301 {
302 $output = array();
303 $len = strlen($mapping);
304 $i += 1;
305
306 // {foo: bar, bar:foo, ...}
307 while ($i < $len)
308 {
309 switch ($mapping[$i])
310 {
311 case ' ':
312 case ',':
313 ++$i;
314 continue 2;
315 case '}':
316 return $output;
317 }
318
319 // key
320 $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);
321
322 // value
323 $done = false;
324 while ($i < $len)
325 {
326 switch ($mapping[$i])
327 {
328 case '[':
329 // nested sequence
330 $output[$key] = self::parseSequence($mapping, $i);
331 $done = true;
332 break;
333 case '{':
334 // nested mapping
335 $output[$key] = self::parseMapping($mapping, $i);
336 $done = true;
337 break;
338 case ':':
339 case ' ':
340 break;
341 default:
342 $output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i);
343 $done = true;
344 --$i;
345 }
346
347 ++$i;
348
349 if ($done)
350 {
351 continue 2;
352 }
353 }
354 }
355
356 throw new InvalidArgumentException(sprintf('Malformed inline YAML string %s', $mapping));
357 }
358
359 /**
360 * Evaluates scalars and replaces magic values.
361 *
362 * @param string $scalar
363 *
364 * @return string A YAML string
365 */
366 static protected function evaluateScalar($scalar)
367 {
368 $scalar = trim($scalar);
369
370 $trueValues = '1.1' == sfYaml::getSpecVersion() ? array('true', 'on', '+', 'yes', 'y') : array('true');
371 $falseValues = '1.1' == sfYaml::getSpecVersion() ? array('false', 'off', '-', 'no', 'n') : array('false');
372
373 switch (true)
374 {
375 case 'null' == strtolower($scalar):
376 case '' == $scalar:
377 case '~' == $scalar:
378 return null;
379 case 0 === strpos($scalar, '!str'):
380 return (string) substr($scalar, 5);
381 case 0 === strpos($scalar, '! '):
382 return intval(self::parseScalar(substr($scalar, 2)));
383 case 0 === strpos($scalar, '!!php/object:'):
384 return unserialize(substr($scalar, 13));
385 case ctype_digit($scalar):
386 $raw = $scalar;
387 $cast = intval($scalar);
388 return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
389 case in_array(strtolower($scalar), $trueValues):
390 return true;
391 case in_array(strtolower($scalar), $falseValues):
392 return false;
393 case is_numeric($scalar):
394 return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
395 case 0 == strcasecmp($scalar, '.inf'):
396 case 0 == strcasecmp($scalar, '.NaN'):
397 return -log(0);
398 case 0 == strcasecmp($scalar, '-.inf'):
399 return log(0);
400 case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
401 return floatval(str_replace(',', '', $scalar));
402 case preg_match(self::getTimestampRegex(), $scalar):
403 return strtotime($scalar);
404 default:
405 return (string) $scalar;
406 }
407 }
408
409 static protected function getTimestampRegex()
410 {
411 return <<<EOF
412 ~^
413 (?P<year>[0-9][0-9][0-9][0-9])
414 -(?P<month>[0-9][0-9]?)
415 -(?P<day>[0-9][0-9]?)
416 (?:(?:[Tt]|[ \t]+)
417 (?P<hour>[0-9][0-9]?)
418 :(?P<minute>[0-9][0-9])
419 :(?P<second>[0-9][0-9])
420 (?:\.(?P<fraction>[0-9]*))?
421 (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
422 (?::(?P<tz_minute>[0-9][0-9]))?))?)?
423 $~x
424 EOF;
425 }
426 }