@@ -196,6 +196,7 @@ static double php_pack_parse_double(int is_little_endian, void * src)
196
196
/* pack() idea stolen from Perl (implemented formats behave the same as there except J and P)
197
197
* 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, @.
198
198
* 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.
199
200
*/
200
201
/* {{{ Takes one or more arguments and packs them into a binary string according to the format argument */
201
202
PHP_FUNCTION (pack )
@@ -293,6 +294,8 @@ PHP_FUNCTION(pack)
293
294
case 'Q' :
294
295
case 'J' :
295
296
case 'P' :
297
+ case 'j' :
298
+ case 'p' :
296
299
#if SIZEOF_ZEND_LONG < 8
297
300
efree (formatcodes );
298
301
efree (formatargs );
@@ -317,6 +320,10 @@ PHP_FUNCTION(pack)
317
320
case 'd' : /* double */
318
321
case 'e' : /* little endian double */
319
322
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 */
320
327
if (arg < 0 ) {
321
328
arg = num_args - currentarg ;
322
329
}
@@ -373,6 +380,8 @@ PHP_FUNCTION(pack)
373
380
case 'S' :
374
381
case 'n' :
375
382
case 'v' :
383
+ case 'm' : /* little endian signed 2-byte */
384
+ case 'y' : /* big endian signed 2-byte */
376
385
INC_OUTPUTPOS (arg ,2 ) /* 16 bit per arg */
377
386
break ;
378
387
@@ -385,6 +394,8 @@ PHP_FUNCTION(pack)
385
394
case 'L' :
386
395
case 'N' :
387
396
case 'V' :
397
+ case 'M' : /* little endian signed 4-byte */
398
+ case 'Y' : /* big endian signed 4-byte */
388
399
INC_OUTPUTPOS (arg ,4 ) /* 32 bit per arg */
389
400
break ;
390
401
@@ -393,7 +404,9 @@ PHP_FUNCTION(pack)
393
404
case 'Q' :
394
405
case 'J' :
395
406
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 */
397
410
break ;
398
411
#endif
399
412
@@ -508,12 +521,14 @@ PHP_FUNCTION(pack)
508
521
case 's' :
509
522
case 'S' :
510
523
case 'n' :
511
- case 'v' : {
524
+ case 'v' :
525
+ case 'm' :
526
+ case 'y' : {
512
527
php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
513
528
514
- if (code == 'n' ) {
529
+ if (code == 'n' || code == 'y' ) {
515
530
endianness = PHP_BIG_ENDIAN ;
516
- } else if (code == 'v' ) {
531
+ } else if (code == 'v' || code == 'm' ) {
517
532
endianness = PHP_LITTLE_ENDIAN ;
518
533
}
519
534
@@ -535,12 +550,14 @@ PHP_FUNCTION(pack)
535
550
case 'l' :
536
551
case 'L' :
537
552
case 'N' :
538
- case 'V' : {
553
+ case 'V' :
554
+ case 'M' :
555
+ case 'Y' : {
539
556
php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
540
557
541
- if (code == 'N' ) {
558
+ if (code == 'N' || code == 'Y' ) {
542
559
endianness = PHP_BIG_ENDIAN ;
543
- } else if (code == 'V' ) {
560
+ } else if (code == 'V' || code == 'M' ) {
544
561
endianness = PHP_LITTLE_ENDIAN ;
545
562
}
546
563
@@ -555,12 +572,14 @@ PHP_FUNCTION(pack)
555
572
case 'q' :
556
573
case 'Q' :
557
574
case 'J' :
558
- case 'P' : {
575
+ case 'P' :
576
+ case 'j' :
577
+ case 'p' : {
559
578
php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
560
579
561
- if (code == 'J' ) {
580
+ if (code == 'J' || code == 'j' ) {
562
581
endianness = PHP_BIG_ENDIAN ;
563
- } else if (code == 'P' ) {
582
+ } else if (code == 'P' || code == 'p' ) {
564
583
endianness = PHP_LITTLE_ENDIAN ;
565
584
}
566
585
@@ -672,6 +691,7 @@ PHP_FUNCTION(pack)
672
691
* f and d will return doubles.
673
692
* 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, @.
674
693
* 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.
675
695
*/
676
696
/* {{{ Unpack binary string into named array elements according to format argument */
677
697
PHP_FUNCTION (unpack )
@@ -793,6 +813,8 @@ PHP_FUNCTION(unpack)
793
813
case 'S' :
794
814
case 'n' :
795
815
case 'v' :
816
+ case 'm' :
817
+ case 'y' :
796
818
size = 2 ;
797
819
break ;
798
820
@@ -807,6 +829,8 @@ PHP_FUNCTION(unpack)
807
829
case 'L' :
808
830
case 'N' :
809
831
case 'V' :
832
+ case 'M' :
833
+ case 'Y' :
810
834
size = 4 ;
811
835
break ;
812
836
@@ -815,6 +839,8 @@ PHP_FUNCTION(unpack)
815
839
case 'Q' :
816
840
case 'J' :
817
841
case 'P' :
842
+ case 'p' :
843
+ case 'j' :
818
844
#if SIZEOF_ZEND_LONG > 4
819
845
size = 8 ;
820
846
break ;
@@ -1017,6 +1043,18 @@ PHP_FUNCTION(unpack)
1017
1043
break ;
1018
1044
}
1019
1045
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
+
1020
1058
case 'i' : /* signed integer, machine size, machine endian */
1021
1059
case 'I' : { /* unsigned integer, machine size, machine endian */
1022
1060
zend_long v ;
@@ -1051,6 +1089,18 @@ PHP_FUNCTION(unpack)
1051
1089
break ;
1052
1090
}
1053
1091
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
+
1054
1104
#if SIZEOF_ZEND_LONG > 4
1055
1105
case 'q' : /* signed machine endian */
1056
1106
case 'Q' : /* unsigned machine endian */
@@ -1070,6 +1120,18 @@ PHP_FUNCTION(unpack)
1070
1120
ZVAL_LONG (& val , v );
1071
1121
break ;
1072
1122
}
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
+ }
1073
1135
#endif
1074
1136
1075
1137
case 'f' : /* float */
0 commit comments