source: trunk/common/array_path.php @ 852

Revision 852, 6.1 KB checked in by cdleonard@…, 4 years ago (diff)

svn:eol-style native in trunk. Also svn:executable on all scripts

  • Property svn:eol-style set to native
Line 
1<?php
2
3require_once(IA_ROOT_DIR."common/common.php");
4
5// NOTE: These functions are untested. They will become useful if we
6// send array paths to javascript. Until then it's better to work with
7// exploded array paths.
8
9// Create an array path string from an array of steps (or a single step)
10// Steps can only be strings or ints.
11// Array paths can be queries with <item><path> in javascript.
12// FIXME: properly escape javascript strings.
13// FIXME: array_path_get
14// FIXME: Optimize
15//
16// Examples:
17//      array_path_join('bubbles') == '.bubbles';
18//      array_path_join(2, 'ala bala', gigi) == '[2]['ala bala'].gigi;
19function array_path_join($steps)
20{
21    if (!is_array($steps)) {
22        $steps = array($steps);
23    }
24    $result = '';
25    foreach ($steps as $step) {
26        if (is_string($step)) {
27            if (preg_match('/^[a-z_][a-z0-9_]*$/i', $step)) {
28                $result .= $step;
29            } else {
30                $result .= "['$step']";
31            }
32        } else if (is_int($step)) {
33            $result .= "[$step]";
34        } else {
35            log_error("Invalid array path step $step");
36        }
37    }
38    return $result;
39}
40
41// Split an array path string into an array of steps.
42// It's generally preferable to work with splitted paths.
43// This function is rather heavy.
44function array_path_split($path)
45{
46    if (!is_string($path)) {
47        log_error("Invalid array path: Not a string.");
48    }
49    $result = array();
50    $strlen = $count($path);
51    $pos = 0;
52    while ($path != '') {
53        $step = '';
54
55        // Process .identifier step.
56        $char = $path[$pos];
57        if ($char == '.') {
58            if ($pos + 1 >= $len) {
59                log_error("Invalid array path: Ends with dot.");
60            }
61           
62            // Check first character
63            $char = $path[++$pos];
64            if (($char < 'a' || $char > 'z') &&
65                ($char < 'A' || $char > 'Z') && $char != '_') {
66                log_error("Invalid array path[$pos]: Bad identifier start.");
67            }
68            $step .= $char;
69
70            // Now check the following
71            while (true) {
72                if ($pos + 1 >= $len) {
73                    break;
74                }
75                $char = $path[++$pos];
76                if ($char == '.') {
77                    break;
78                }
79
80                if (($char < 'a' || $char > 'z') &&
81                    ($char < 'A' || $char > 'Z') &&
82                    ($char < '0' || $char > '9') && $char != '_') {
83                    log_error("Invalid array path[$pos]: Bad identifier character.");
84                }
85                $step .= $char;
86            }
87            $result[] = $step;
88            continue;
89        }
90
91        // Process ['string'] or [number] step.
92        if ($char == '[') {
93            // Check character after [
94            if ($pos + 1 >= 2) {
95                log_error('Invalid array path: Ends with [.');
96            }
97            $char = $path[++$pos];
98
99            // Number. FIXME: hex and octal not supported, neither are float. This is OK.
100            if ($char >= '0' && $char <= '9') {
101                $span = strspn($path, '0123456789', $pos);
102                if ($path[$span] != ']') {
103                    log_error("Invalid array path: ] expected");
104                }
105                $result[] = (int)substr($path, $pos, $span);
106                $pos += $span;
107                continue;
108            }
109
110            // Now parse quoted strings
111            if ($char != "'" && $char != '"') {
112                log_error('Invalid array path: Quoted string or number expected in []');
113            }
114            $quote = $char;
115            while (true) {
116                if ($pos + 1 >= $len) {
117                    log_error("Invalid array path: Unterminated [{$quote}string.");
118                }
119                $char = $path[++$pos];
120
121                // Parse escape sequences
122                if ($char == "\\") {
123                    if ($pos + 1 >= $len) {
124                        log_error("Invalid array path: Dangling \\.");
125                    }
126                    $char = $path[++$pos];
127
128                    // Parse javascript escape sequences, as per JS string literal syntax.
129                    static $simple_slash_escapes = array(
130                        "'" => "'", '"' => '"', "\\" => "\\",
131                        "n" => "\n", "r" => "\r",
132                        "t" => "\t", "v" => "\v",
133                        "b" => "\b", "f" => "\f",
134                    );
135                    if (isset($simple_slash_escapes[$char])) {
136                        $step .= $simple_slash_escapes($path[$i + 1]);
137                    } elseif ($char == 'x') {
138                        // Parse \x hex ascii character escapes.
139                        if ($pos + 2 >= $len) {
140                            log_error("Invalid array path: Unterminated \\x sequnce.");
141                        }
142                        $char = $path[++$pos];
143                        $step .= chr(ord($char) - ord('0'));
144                        $char = $path[++$pos];
145                        $step .= chr(ord($char) - ord('0'));
146                    } elseif ($char == 'u') {
147                        log_error("Invalid array path[$pos]: Unicode escape not supported.");
148                    } elseif ($char >= 0 && $char <= 9) {
149                        log_error("Invalid array path[$pos]: Octal escape not supported.");
150                    } else {
151                        log_error("Invalid array path[$pos]: Unrecognized escape sequence.");
152                    }
153                } else if ($char == $quote) {
154                    break;
155                } else if ($char >= 32 && $char < 127) {
156                    // Printable characters
157                    $step .= $char;
158                } else {
159                    log_error("Invalid array path[$pos]: Unprintable character found");
160                }
161            }
162            // If we broke off then we found a properly quoted " or ' string.
163            if ($pos + 1 >= $len || $path[$pos + 1] != ']') {
164                log_error("Invalid array path[$pos]: ] expected");
165            }
166            $result[] = $step;
167        }
168    }
169    return $result;
170}
171
172?>
Note: See TracBrowser for help on using the repository browser.