@@ -196,6 +196,7 @@ static double php_pack_parse_double(int is_little_endian, void * src)
196196/* pack() idea stolen from Perl (implemented formats behave the same as there except J and P)
197197 * Implemented formats are Z, A, a, h, H, c, C, s, S, i, I, l, L, n, N, q, Q, J, P, f, d, x, X, @.
198198 * Added g, G for little endian float and big endian float, added e, E for little endian double and big endian double.
199+ * Added m, y for little/big endian signed 2-byte, M, Y for little/big endian signed 4-byte, p, j for little/big endian signed 8-byte.
199200 */
200201/* {{{ Takes one or more arguments and packs them into a binary string according to the format argument */
201202PHP_FUNCTION (pack )
@@ -293,6 +294,8 @@ PHP_FUNCTION(pack)
293294 case 'Q' :
294295 case 'J' :
295296 case 'P' :
297+ case 'j' :
298+ case 'p' :
296299#if SIZEOF_ZEND_LONG < 8
297300 efree (formatcodes );
298301 efree (formatargs );
@@ -317,6 +320,10 @@ PHP_FUNCTION(pack)
317320 case 'd' : /* double */
318321 case 'e' : /* little endian double */
319322 case 'E' : /* big endian double */
323+ case 'm' : /* little endian signed 2-byte */
324+ case 'y' : /* big endian signed 2-byte */
325+ case 'M' : /* little endian signed 4-byte */
326+ case 'Y' : /* big endian signed 4-byte */
320327 if (arg < 0 ) {
321328 arg = num_args - currentarg ;
322329 }
@@ -373,6 +380,8 @@ PHP_FUNCTION(pack)
373380 case 'S' :
374381 case 'n' :
375382 case 'v' :
383+ case 'm' : /* little endian signed 2-byte */
384+ case 'y' : /* big endian signed 2-byte */
376385 INC_OUTPUTPOS (arg ,2 ) /* 16 bit per arg */
377386 break ;
378387
@@ -385,6 +394,8 @@ PHP_FUNCTION(pack)
385394 case 'L' :
386395 case 'N' :
387396 case 'V' :
397+ case 'M' : /* little endian signed 4-byte */
398+ case 'Y' : /* big endian signed 4-byte */
388399 INC_OUTPUTPOS (arg ,4 ) /* 32 bit per arg */
389400 break ;
390401
@@ -393,7 +404,9 @@ PHP_FUNCTION(pack)
393404 case 'Q' :
394405 case 'J' :
395406 case 'P' :
396- INC_OUTPUTPOS (arg ,8 ) /* 32 bit per arg */
407+ case 'j' :
408+ case 'p' :
409+ INC_OUTPUTPOS (arg ,8 ) /* 64 bit per arg */
397410 break ;
398411#endif
399412
@@ -508,12 +521,14 @@ PHP_FUNCTION(pack)
508521 case 's' :
509522 case 'S' :
510523 case 'n' :
511- case 'v' : {
524+ case 'v' :
525+ case 'm' :
526+ case 'y' : {
512527 php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
513528
514- if (code == 'n' ) {
529+ if (code == 'n' || code == 'y' ) {
515530 endianness = PHP_BIG_ENDIAN ;
516- } else if (code == 'v' ) {
531+ } else if (code == 'v' || code == 'm' ) {
517532 endianness = PHP_LITTLE_ENDIAN ;
518533 }
519534
@@ -535,12 +550,14 @@ PHP_FUNCTION(pack)
535550 case 'l' :
536551 case 'L' :
537552 case 'N' :
538- case 'V' : {
553+ case 'V' :
554+ case 'M' :
555+ case 'Y' : {
539556 php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
540557
541- if (code == 'N' ) {
558+ if (code == 'N' || code == 'Y' ) {
542559 endianness = PHP_BIG_ENDIAN ;
543- } else if (code == 'V' ) {
560+ } else if (code == 'V' || code == 'M' ) {
544561 endianness = PHP_LITTLE_ENDIAN ;
545562 }
546563
@@ -555,12 +572,14 @@ PHP_FUNCTION(pack)
555572 case 'q' :
556573 case 'Q' :
557574 case 'J' :
558- case 'P' : {
575+ case 'P' :
576+ case 'j' :
577+ case 'p' : {
559578 php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
560579
561- if (code == 'J' ) {
580+ if (code == 'J' || code == 'j' ) {
562581 endianness = PHP_BIG_ENDIAN ;
563- } else if (code == 'P' ) {
582+ } else if (code == 'P' || code == 'p' ) {
564583 endianness = PHP_LITTLE_ENDIAN ;
565584 }
566585
@@ -672,6 +691,7 @@ PHP_FUNCTION(pack)
672691 * f and d will return doubles.
673692 * Implemented formats are Z, A, a, h, H, c, C, s, S, i, I, l, L, n, N, q, Q, J, P, f, d, x, X, @.
674693 * Added g, G for little endian float and big endian float, added e, E for little endian double and big endian double.
694+ * Added m, y for little/big endian signed 2-byte, M, Y for little/big endian signed 4-byte, p, j for little/big endian signed 8-byte.
675695 */
676696/* {{{ Unpack binary string into named array elements according to format argument */
677697PHP_FUNCTION (unpack )
@@ -793,6 +813,8 @@ PHP_FUNCTION(unpack)
793813 case 'S' :
794814 case 'n' :
795815 case 'v' :
816+ case 'm' :
817+ case 'y' :
796818 size = 2 ;
797819 break ;
798820
@@ -807,6 +829,8 @@ PHP_FUNCTION(unpack)
807829 case 'L' :
808830 case 'N' :
809831 case 'V' :
832+ case 'M' :
833+ case 'Y' :
810834 size = 4 ;
811835 break ;
812836
@@ -815,6 +839,8 @@ PHP_FUNCTION(unpack)
815839 case 'Q' :
816840 case 'J' :
817841 case 'P' :
842+ case 'p' :
843+ case 'j' :
818844#if SIZEOF_ZEND_LONG > 4
819845 size = 8 ;
820846 break ;
@@ -1017,6 +1043,18 @@ PHP_FUNCTION(unpack)
10171043 break ;
10181044 }
10191045
1046+ case 'm' : /* signed little endian 2-byte */
1047+ case 'y' : { /* signed big endian 2-byte */
1048+ uint16_t x = * ((unaligned_uint16_t * ) & input [inputpos ]);
1049+
1050+ if ((type == 'y' && MACHINE_LITTLE_ENDIAN ) || (type == 'm' && !MACHINE_LITTLE_ENDIAN )) {
1051+ x = php_pack_reverse_int16 (x );
1052+ }
1053+
1054+ ZVAL_LONG (& val , (int16_t ) x );
1055+ break ;
1056+ }
1057+
10201058 case 'i' : /* signed integer, machine size, machine endian */
10211059 case 'I' : { /* unsigned integer, machine size, machine endian */
10221060 zend_long v ;
@@ -1051,6 +1089,18 @@ PHP_FUNCTION(unpack)
10511089 break ;
10521090 }
10531091
1092+ case 'M' : /* signed little endian 4-byte */
1093+ case 'Y' : { /* signed big endian 4-byte */
1094+ uint32_t x = * ((unaligned_uint32_t * ) & input [inputpos ]);
1095+
1096+ if ((type == 'Y' && MACHINE_LITTLE_ENDIAN ) || (type == 'M' && !MACHINE_LITTLE_ENDIAN )) {
1097+ x = php_pack_reverse_int32 (x );
1098+ }
1099+
1100+ ZVAL_LONG (& val , (int32_t ) x );
1101+ break ;
1102+ }
1103+
10541104#if SIZEOF_ZEND_LONG > 4
10551105 case 'q' : /* signed machine endian */
10561106 case 'Q' : /* unsigned machine endian */
@@ -1070,6 +1120,18 @@ PHP_FUNCTION(unpack)
10701120 ZVAL_LONG (& val , v );
10711121 break ;
10721122 }
1123+
1124+ case 'j' : /* signed big endian */
1125+ case 'p' : { /* signed little endian */
1126+ uint64_t x = * ((unaligned_uint64_t * ) & input [inputpos ]);
1127+
1128+ if ((type == 'j' && MACHINE_LITTLE_ENDIAN ) || (type == 'p' && !MACHINE_LITTLE_ENDIAN )) {
1129+ x = php_pack_reverse_int64 (x );
1130+ }
1131+
1132+ ZVAL_LONG (& val , (int64_t ) x );
1133+ break ;
1134+ }
10731135#endif
10741136
10751137 case 'f' : /* float */
0 commit comments