11
11
12
12
namespace Symfony \Component \VarDumper \Cloner ;
13
13
14
+ use Symfony \Component \VarDumper \Dumper \DumperInternalsInterface ;
15
+ use Symfony \Component \VarDumper \Dumper \Cursor ;
16
+
14
17
/**
15
18
* @author Nicolas Grekas <p@tchwork.com>
16
19
*/
@@ -30,4 +33,169 @@ public function getRawData()
30
33
{
31
34
return $ this ->data ;
32
35
}
36
+
37
+ /**
38
+ * Dumps data with a DumperInternalsInterface dumper.
39
+ */
40
+ public function dump (DumperInternalsInterface $ dumper )
41
+ {
42
+ $ refs = array (0 );
43
+ $ this ->dumpItem ($ dumper , new Cursor , $ refs , $ this ->data [0 ][0 ]);
44
+ }
45
+
46
+ /**
47
+ * Breadth-first dumping of items.
48
+ *
49
+ * @param DumperInternalsInterface $dumper The dumper being used for dumping.
50
+ * @param Cursor $cursor A cursor used for tracking dumper state position.
51
+ * @param array &$refs A map of all references discovered while dumping.
52
+ * @param mixed $item A stub stdClass or the original value being dumped.
53
+ */
54
+ private function dumpItem ($ dumper , $ cursor , &$ refs , $ item )
55
+ {
56
+ $ cursor ->refIndex = $ cursor ->refTo = $ cursor ->refIsHard = false ;
57
+
58
+ if ($ item instanceof \stdClass) {
59
+ if (property_exists ($ item , 'val ' )) {
60
+ if (isset ($ item ->ref )) {
61
+ if (isset ($ refs [$ r = $ item ->ref ])) {
62
+ $ cursor ->refTo = $ refs [$ r ];
63
+ $ cursor ->refIsHard = true ;
64
+ } else {
65
+ $ cursor ->refIndex = $ refs [$ r ] = ++$ refs [0 ];
66
+ }
67
+ }
68
+ $ item = $ item ->val ;
69
+ }
70
+ if (isset ($ item ->ref )) {
71
+ if (isset ($ refs [$ r = $ item ->ref ])) {
72
+ if (false === $ cursor ->refTo ) {
73
+ $ cursor ->refTo = $ refs [$ r ];
74
+ $ cursor ->refIsHard = isset ($ item ->count );
75
+ }
76
+ } elseif (false !== $ cursor ->refIndex ) {
77
+ $ refs [$ r ] = $ cursor ->refIndex ;
78
+ } else {
79
+ $ cursor ->refIndex = $ refs [$ r ] = ++$ refs [0 ];
80
+ }
81
+ }
82
+ $ cut = isset ($ item ->cut ) ? $ item ->cut : 0 ;
83
+
84
+ if (isset ($ item ->pos ) && false === $ cursor ->refTo ) {
85
+ $ children = $ this ->data [$ item ->pos ];
86
+
87
+ if ($ cursor ->stop ) {
88
+ if ($ cut >= 0 ) {
89
+ $ cut += count ($ children );
90
+ }
91
+ $ children = array ();
92
+ }
93
+ } else {
94
+ $ children = array ();
95
+ }
96
+ switch (true ) {
97
+ case isset ($ item ->bin ):
98
+ $ dumper ->dumpString ($ cursor , $ item ->bin , true , $ cut );
99
+
100
+ return ;
101
+
102
+ case isset ($ item ->str ):
103
+ $ dumper ->dumpString ($ cursor , $ item ->str , false , $ cut );
104
+
105
+ return ;
106
+
107
+ case isset ($ item ->count ):
108
+ $ dumper ->enterArray ($ cursor , $ item ->count , !empty ($ item ->indexed ), (bool ) $ children );
109
+ $ cut = $ this ->dumpChildren ($ dumper , $ cursor , $ refs , $ children , $ cut , empty ($ item ->indexed ) ? $ cursor ::HASH_ASSOC : $ cursor ::HASH_INDEXED );
110
+ $ dumper ->leaveArray ($ cursor , $ item ->count , !empty ($ item ->indexed ), (bool ) $ children , $ cut );
111
+
112
+ return ;
113
+
114
+ case isset ($ item ->class ):
115
+ $ dumper ->enterObject ($ cursor , $ item ->class , (bool ) $ children );
116
+ $ cut = $ this ->dumpChildren ($ dumper , $ cursor , $ refs , $ children , $ cut , $ cursor ::HASH_OBJECT );
117
+ $ dumper ->leaveObject ($ cursor , $ item ->class , (bool ) $ children , $ cut );
118
+
119
+ return ;
120
+
121
+ case isset ($ item ->res ):
122
+ $ dumper ->enterResource ($ cursor , $ item ->res , (bool ) $ children );
123
+ $ cut = $ this ->dumpChildren ($ dumper , $ cursor , $ refs , $ children , $ cut , $ cursor ::HASH_RESOURCE );
124
+ $ dumper ->leaveResource ($ cursor , $ item ->res , (bool ) $ children , $ cut );
125
+
126
+ return ;
127
+ }
128
+ }
129
+
130
+ if ('array ' === $ type = gettype ($ item )) {
131
+ $ dumper ->enterArray ($ cursor , 0 , true , 0 , 0 );
132
+ $ dumper ->leaveArray ($ cursor , 0 , true , 0 , 0 );
133
+ } else {
134
+ $ dumper ->dumpScalar ($ cursor , $ type , $ item );
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Dumps children of hash structures.
140
+ *
141
+ * @param DumperInternalsInterface $dumper
142
+ * @param Cursor $parentCursor The cursor of the parent hash.
143
+ * @param array &$refs A map of all references discovered while dumping.
144
+ * @param array $children The children to dump.
145
+ * @param int $hashCut The number of items removed from the original hash.
146
+ * @param int $hashType A Cursor::HASH_* const.
147
+ *
148
+ * @return int The final number of removed items.
149
+ */
150
+ private function dumpChildren ($ dumper , $ parentCursor , &$ refs , $ children , $ hashCut , $ hashType )
151
+ {
152
+ if ($ children ) {
153
+ $ cursor = clone $ parentCursor ;
154
+ ++$ cursor ->depth ;
155
+ $ cursor ->hashType = $ hashType ;
156
+ $ cursor ->hashIndex = 0 ;
157
+ $ cursor ->hashLength = count ($ children );
158
+ $ cursor ->hashCut = $ hashCut ;
159
+ foreach ($ children as $ cursor ->hashKey => $ child ) {
160
+ $ this ->dumpItem ($ dumper , $ cursor , $ refs , $ child );
161
+ ++$ cursor ->hashIndex ;
162
+ if ($ cursor ->stop ) {
163
+ $ parentCursor ->stop = true ;
164
+
165
+ return $ hashCut >= 0 ? $ hashCut + $ children - $ cursor ->hashIndex : $ hashCut ;
166
+ }
167
+ }
168
+ }
169
+
170
+ return $ hashCut ;
171
+ }
172
+
173
+ /**
174
+ * Portable variant of utf8_encode()
175
+ *
176
+ * @param string $s
177
+ *
178
+ * @return string
179
+ *
180
+ * @internal
181
+ */
182
+ public static function utf8Encode ($ s )
183
+ {
184
+ if (function_exists ('iconv ' )) {
185
+ return iconv ('CP1252 ' , 'UTF-8 ' , $ s );
186
+ } else {
187
+ $ s .= $ s ;
188
+ $ len = strlen ($ s );
189
+
190
+ for ($ i = $ len >> 1 , $ j = 0 ; $ i < $ len ; ++$ i , ++$ j ) {
191
+ switch (true ) {
192
+ case $ s [$ i ] < "\x80" : $ s [$ j ] = $ s [$ i ]; break ;
193
+ case $ s [$ i ] < "\xC0" : $ s [$ j ] = "\xC2" ; $ s [++$ j ] = $ s [$ i ]; break ;
194
+ default : $ s [$ j ] = "\xC3" ; $ s [++$ j ] = chr (ord ($ s [$ i ]) - 64 ); break ;
195
+ }
196
+ }
197
+
198
+ return substr ($ s , 0 , $ j );
199
+ }
200
+ }
33
201
}
0 commit comments