55namespace Yiisoft \Db \Pgsql ;
66
77use function in_array ;
8- use function strlen ;
98
109/**
1110 * Array representation to PHP array parser for PostgreSQL Server.
1211 */
1312final class ArrayParser
1413{
15- /**
16- * @var string Character used in an array.
17- */
18- private string $ delimiter = ', ' ;
19-
2014 /**
2115 * Convert an array from PostgresSQL to PHP.
2216 *
2317 * @param string|null $value String to convert.
2418 */
2519 public function parse (string |null $ value ): array |null
2620 {
27- if ($ value === null ) {
28- return null ;
29- }
30-
31- if ($ value === '{} ' ) {
32- return [];
33- }
34-
35- return $ this ->parseArray ($ value );
21+ return $ value !== null
22+ ? $ this ->parseArray ($ value )
23+ : null ;
3624 }
3725
3826 /**
@@ -43,33 +31,23 @@ public function parse(string|null $value): array|null
4331 */
4432 private function parseArray (string $ value , int &$ i = 0 ): array
4533 {
46- $ result = [];
47- $ len = strlen ($ value );
34+ if ($ value [++$ i ] === '} ' ) {
35+ ++$ i ;
36+ return [];
37+ }
4838
49- for (++$ i ; $ i < $ len ; ++$ i ) {
50- switch ($ value [$ i ]) {
51- case '{ ' :
52- $ result [] = $ this ->parseArray ($ value , $ i );
53- break ;
54- case '} ' :
55- break 2 ;
56- case $ this ->delimiter :
57- /** `{}` case */
58- if (empty ($ result )) {
59- $ result [] = null ;
60- }
39+ for ($ result = [];; ++$ i ) {
40+ $ result [] = match ($ value [$ i ]) {
41+ '{ ' => $ this ->parseArray ($ value , $ i ),
42+ ', ' , '} ' => null ,
43+ default => $ this ->parseString ($ value , $ i ),
44+ };
6145
62- /** `{,}` case */
63- if (in_array ($ value [$ i + 1 ], [$ this ->delimiter , '} ' ], true )) {
64- $ result [] = null ;
65- }
66- break ;
67- default :
68- $ result [] = $ this ->parseString ($ value , $ i );
46+ if ($ value [$ i ] === '} ' ) {
47+ ++$ i ;
48+ return $ result ;
6949 }
7050 }
71-
72- return $ result ;
7351 }
7452
7553 /**
@@ -80,27 +58,41 @@ private function parseArray(string $value, int &$i = 0): array
8058 */
8159 private function parseString (string $ value , int &$ i ): string |null
8260 {
83- $ isQuoted = $ value [$ i ] === '" ' ;
84- $ stringEndChars = $ isQuoted ? [ ' " ' ] : [ $ this ->delimiter , ' } ' ];
85- $ result = '' ;
86- $ len = strlen ( $ value );
61+ return $ value [$ i ] === '" '
62+ ? $ this ->parseQuotedString ( $ value , $ i )
63+ : $ this -> parseUnquotedString ( $ value , $ i ) ;
64+ }
8765
88- for ($ i += $ isQuoted ? 1 : 0 ; $ i < $ len ; ++$ i ) {
89- if (in_array ($ value [$ i ], ['\\' , '" ' ], true ) && in_array ($ value [$ i + 1 ], [$ value [$ i ], '" ' ], true )) {
66+ /**
67+ * Parses quoted string.
68+ */
69+ private function parseQuotedString (string $ value , int &$ i ): string
70+ {
71+ for ($ result = '' , ++$ i ;; ++$ i ) {
72+ if ($ value [$ i ] === '\\' ) {
73+ ++$ i ;
74+ } elseif ($ value [$ i ] === '" ' ) {
9075 ++$ i ;
91- } elseif (in_array ($ value [$ i ], $ stringEndChars , true )) {
92- break ;
76+ return $ result ;
9377 }
9478
9579 $ result .= $ value [$ i ];
9680 }
81+ }
9782
98- $ i -= $ isQuoted ? 0 : 1 ;
83+ /**
84+ * Parses unquoted string.
85+ */
86+ private function parseUnquotedString (string $ value , int &$ i ): string |null
87+ {
88+ for ($ result = '' ;; ++$ i ) {
89+ if (in_array ($ value [$ i ], [', ' , '} ' ], true )) {
90+ return $ result !== 'NULL '
91+ ? $ result
92+ : null ;
93+ }
9994
100- if (!$ isQuoted && $ result === 'NULL ' ) {
101- $ result = null ;
95+ $ result .= $ value [$ i ];
10296 }
103-
104- return $ result ;
10597 }
10698}
0 commit comments