@@ -83,10 +83,13 @@ public function pack($signature, ...$params): Generator
8383 }
8484
8585 //structure buffer
86- $ len = mb_strlen ($ output , '8bit ' );
87- for ($ i = 0 ; $ i < $ len ; $ i += 65535 ) {
88- $ chunk = mb_substr ($ output , $ i , 65535 , '8bit ' );
89- yield pack ('n ' , mb_strlen ($ chunk , '8bit ' )) . $ chunk ;
86+ $ totalLength = mb_strlen ($ output , '8bit ' );
87+ $ offset = 0 ;
88+ while ($ offset < $ totalLength ) {
89+ $ chunk = mb_strcut ($ output , $ offset , 65535 , '8bit ' );
90+ $ chunkLength = mb_strlen ($ chunk , '8bit ' );
91+ $ offset += $ chunkLength ;
92+ yield pack ('n ' , $ chunkLength ) . $ chunk ;
9093 }
9194
9295 yield chr (0x00 ) . chr (0x00 );
@@ -99,33 +102,33 @@ public function pack($signature, ...$params): Generator
99102 */
100103 private function p ($ param ): string
101104 {
102- $ output = '' ;
103- if (is_int ($ param )) {
104- $ output .= $ this ->packInteger ($ param );
105- } elseif (is_float ($ param )) {
106- $ output .= $ this ->packFloat ($ param );
107- } elseif (is_null ($ param )) {
108- $ output .= chr (0xC0 );
109- } elseif (is_bool ($ param )) {
110- $ output .= chr ($ param ? 0xC3 : 0xC2 );
111- } elseif (is_string ($ param )) {
112- $ output .= $ this ->packString ($ param );
113- } elseif ($ param instanceof IStructure) {
114- $ output .= $ this ->packStructure ($ param );
115- } elseif (is_array ($ param )) {
116- $ keys = array_keys ($ param );
117- if (count ($ param ) == 0 || count (array_filter ($ keys , 'is_int ' )) == count ($ keys )) {
118- $ output .= $ this ->packList ($ param );
119- } else {
120- $ output .= $ this ->packMap ($ param );
121- }
122- } elseif (is_object ($ param )) {
123- $ output .= $ this ->packMap ((array )$ param );
124- } else {
125- throw new PackException ('Not recognized type of parameter ' );
105+ switch (gettype ($ param )) {
106+ case 'integer ' :
107+ return $ this ->packInteger ($ param );
108+ case 'double ' :
109+ return $ this ->packFloat ($ param );
110+ case 'boolean ' :
111+ return chr ($ param ? 0xC3 : 0xC2 );
112+ case 'NULL ' :
113+ return chr (0xC0 );
114+ case 'string ' :
115+ return $ this ->packString ($ param );
116+ case 'array ' :
117+ if ($ param === array_values ($ param )) {
118+ return $ this ->packList ($ param );
119+ } else {
120+ return $ this ->packMap ($ param );
121+ }
122+ case 'object ' :
123+ if ($ param instanceof IStructure) {
124+ return $ this ->packStructure ($ param );
125+ } else {
126+ return $ this ->packMap ((array )$ param );
127+ }
128+
129+ default :
130+ throw new PackException ('Not recognized type of parameter ' );
126131 }
127-
128- return $ output ;
129132 }
130133
131134 /**
@@ -135,22 +138,19 @@ private function p($param): string
135138 */
136139 private function packString (string $ str ): string
137140 {
138- $ output = '' ;
139141 $ length = mb_strlen ($ str , '8bit ' );
140142
141143 if ($ length < self ::SMALL ) { //TINY_STRING
142- $ output .= pack ('C ' , 0b10000000 | $ length ) . $ str ;
144+ return pack ('C ' , 0b10000000 | $ length ) . $ str ;
143145 } elseif ($ length < self ::MEDIUM ) { //STRING_8
144- $ output .= chr (0xD0 ) . pack ('C ' , $ length ) . $ str ;
146+ return chr (0xD0 ) . pack ('C ' , $ length ) . $ str ;
145147 } elseif ($ length < self ::LARGE ) { //STRING_16
146- $ output .= chr (0xD1 ) . pack ('n ' , $ length ) . $ str ;
148+ return chr (0xD1 ) . pack ('n ' , $ length ) . $ str ;
147149 } elseif ($ length < self ::HUGE ) { //STRING_32
148- $ output .= chr (0xD2 ) . pack ('N ' , $ length ) . $ str ;
150+ return chr (0xD2 ) . pack ('N ' , $ length ) . $ str ;
149151 } else {
150152 throw new PackException ('String too long ' );
151153 }
152-
153- return $ output ;
154154 }
155155
156156 /**
@@ -169,31 +169,27 @@ private function packFloat(float $value): string
169169 */
170170 private function packInteger (int $ value ): string
171171 {
172- $ output = '' ;
173-
174172 if ($ value >= 0 && $ value <= 127 ) { //+TINY_INT
175173 $ packed = pack ('C ' , 0b00000000 | $ value );
176- $ output .= $ this ->littleEndian ? strrev ($ packed ) : $ packed ;
174+ return $ this ->littleEndian ? strrev ($ packed ) : $ packed ;
177175 } elseif ($ value >= -16 && $ value < 0 ) { //-TINY_INT
178176 $ packed = pack ('c ' , 0b11110000 | $ value );
179- $ output .= $ this ->littleEndian ? strrev ($ packed ) : $ packed ;
177+ return $ this ->littleEndian ? strrev ($ packed ) : $ packed ;
180178 } elseif ($ value >= -128 && $ value <= -17 ) { //INT_8
181179 $ packed = pack ('c ' , $ value );
182- $ output .= chr (0xC8 ) . ($ this ->littleEndian ? strrev ($ packed ) : $ packed );
180+ return chr (0xC8 ) . ($ this ->littleEndian ? strrev ($ packed ) : $ packed );
183181 } elseif (($ value >= 128 && $ value <= 32767 ) || ($ value >= -32768 && $ value <= -129 )) { //INT_16
184182 $ packed = pack ('s ' , $ value );
185- $ output .= chr (0xC9 ) . ($ this ->littleEndian ? strrev ($ packed ) : $ packed );
183+ return chr (0xC9 ) . ($ this ->littleEndian ? strrev ($ packed ) : $ packed );
186184 } elseif (($ value >= 32768 && $ value <= 2147483647 ) || ($ value >= -2147483648 && $ value <= -32769 )) { //INT_32
187185 $ packed = pack ('l ' , $ value );
188- $ output .= chr (0xCA ) . ($ this ->littleEndian ? strrev ($ packed ) : $ packed );
186+ return chr (0xCA ) . ($ this ->littleEndian ? strrev ($ packed ) : $ packed );
189187 } elseif (($ value >= 2147483648 && $ value <= 9223372036854775807 ) || ($ value >= -9223372036854775808 && $ value <= -2147483649 )) { //INT_64
190188 $ packed = pack ('q ' , $ value );
191- $ output .= chr (0xCB ) . ($ this ->littleEndian ? strrev ($ packed ) : $ packed );
189+ return chr (0xCB ) . ($ this ->littleEndian ? strrev ($ packed ) : $ packed );
192190 } else {
193191 throw new PackException ('Integer out of range ' );
194192 }
195-
196- return $ output ;
197193 }
198194
199195 /**
@@ -262,11 +258,11 @@ private function packList(array $arr): string
262258 */
263259 private function packStructure (IStructure $ structure ): string
264260 {
265- if (!array_key_exists (get_class ($ structure ), $ this ->structuresLt )) {
261+ $ arr = $ this ->structuresLt [get_class ($ structure )] ?? null ;
262+ if ($ arr === null ) {
266263 throw new PackException ('Provided structure as parameter is not supported ' );
267264 }
268265
269- $ arr = $ this ->structuresLt [get_class ($ structure )];
270266 $ signature = chr (array_shift ($ arr ));
271267 $ output = pack ('C ' , 0b10110000 | count ($ arr )) . $ signature ;
272268 foreach ($ arr as $ structureMethod => $ packerMethod ) {
0 commit comments