2828#else
2929#include <sys/param.h>
3030#endif
31- #include "pack.h"
3231#ifdef HAVE_PWD_H
3332#ifdef PHP_WIN32
3433#include "win32/pwd.h"
5049 } \
5150 outputpos += (a)*(b);
5251
52+ typedef enum {
53+ PHP_LITTLE_ENDIAN ,
54+ PHP_BIG_ENDIAN ,
55+ } php_pack_endianness ;
56+
5357#ifdef WORDS_BIGENDIAN
54- #define MACHINE_LITTLE_ENDIAN 0
58+ # define MACHINE_LITTLE_ENDIAN 0
59+ # define PHP_MACHINE_ENDIAN PHP_BIG_ENDIAN
5560#else
56- #define MACHINE_LITTLE_ENDIAN 1
61+ # define MACHINE_LITTLE_ENDIAN 1
62+ # define PHP_MACHINE_ENDIAN PHP_LITTLE_ENDIAN
63+ #endif
64+
65+ #ifdef ZEND_ENABLE_ZVAL_LONG64
66+ # define PHP_LONG_BSWAP (u ) ZEND_BYTES_SWAP64(u)
67+ #else
68+ # define PHP_LONG_BSWAP (u ) ZEND_BYTES_SWAP32(u)
5769#endif
5870
5971typedef ZEND_SET_ALIGNED (1 , uint16_t unaligned_uint16_t ) ;
@@ -62,40 +74,19 @@ typedef ZEND_SET_ALIGNED(1, uint64_t unaligned_uint64_t);
6274typedef ZEND_SET_ALIGNED (1 , unsigned int unaligned_uint ) ;
6375typedef ZEND_SET_ALIGNED (1 , int unaligned_int ) ;
6476
65- /* Mapping of byte from char (8bit) to long for machine endian */
66- static int byte_map [1 ];
67-
68- /* Mappings of bytes from int (machine dependent) to int for machine endian */
69- static int int_map [sizeof (int )];
70-
71- /* Mappings of bytes from shorts (16bit) for all endian environments */
72- static int machine_endian_short_map [2 ];
73- static int big_endian_short_map [2 ];
74- static int little_endian_short_map [2 ];
75-
76- /* Mappings of bytes from longs (32bit) for all endian environments */
77- static int machine_endian_long_map [4 ];
78- static int big_endian_long_map [4 ];
79- static int little_endian_long_map [4 ];
80-
81- #if SIZEOF_ZEND_LONG > 4
82- /* Mappings of bytes from quads (64bit) for all endian environments */
83- static int machine_endian_longlong_map [8 ];
84- static int big_endian_longlong_map [8 ];
85- static int little_endian_longlong_map [8 ];
86- #endif
87-
8877/* {{{ php_pack */
89- static void php_pack (zval * val , size_t size , int * map , char * output )
78+ static void php_pack (const zval * val , size_t size , php_pack_endianness endianness , char * output )
9079{
91- size_t i ;
92- char * v ;
80+ zend_ulong zl = zval_get_long (val );
9381
94- convert_to_long (val );
95- v = (char * ) & Z_LVAL_P (val );
82+ const char * v = (const char * ) & zl ;
83+ if ((endianness == PHP_LITTLE_ENDIAN ) != MACHINE_LITTLE_ENDIAN ) {
84+ zl = PHP_LONG_BSWAP (zl );
85+ v += sizeof (zend_long ) - size ;
86+ }
9687
97- for ( i = 0 ; i < size ; i ++ ) {
98- * output ++ = v [ map [ i ]] ;
88+ while ( size -- > 0 ) {
89+ * output ++ = * v ++ ;
9990 }
10091}
10192/* }}} */
@@ -529,7 +520,7 @@ PHP_FUNCTION(pack)
529520 case 'c' :
530521 case 'C' :
531522 while (arg -- > 0 ) {
532- php_pack (& argv [currentarg ++ ], 1 , byte_map , & ZSTR_VAL (output )[outputpos ]);
523+ php_pack (& argv [currentarg ++ ], 1 , PHP_MACHINE_ENDIAN , & ZSTR_VAL (output )[outputpos ]);
533524 outputpos ++ ;
534525 }
535526 break ;
@@ -538,16 +529,16 @@ PHP_FUNCTION(pack)
538529 case 'S' :
539530 case 'n' :
540531 case 'v' : {
541- int * map = machine_endian_short_map ;
532+ php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
542533
543534 if (code == 'n' ) {
544- map = big_endian_short_map ;
535+ endianness = PHP_BIG_ENDIAN ;
545536 } else if (code == 'v' ) {
546- map = little_endian_short_map ;
537+ endianness = PHP_LITTLE_ENDIAN ;
547538 }
548539
549540 while (arg -- > 0 ) {
550- php_pack (& argv [currentarg ++ ], 2 , map , & ZSTR_VAL (output )[outputpos ]);
541+ php_pack (& argv [currentarg ++ ], 2 , endianness , & ZSTR_VAL (output )[outputpos ]);
551542 outputpos += 2 ;
552543 }
553544 break ;
@@ -556,7 +547,7 @@ PHP_FUNCTION(pack)
556547 case 'i' :
557548 case 'I' :
558549 while (arg -- > 0 ) {
559- php_pack (& argv [currentarg ++ ], sizeof (int ), int_map , & ZSTR_VAL (output )[outputpos ]);
550+ php_pack (& argv [currentarg ++ ], sizeof (int ), PHP_MACHINE_ENDIAN , & ZSTR_VAL (output )[outputpos ]);
560551 outputpos += sizeof (int );
561552 }
562553 break ;
@@ -565,16 +556,16 @@ PHP_FUNCTION(pack)
565556 case 'L' :
566557 case 'N' :
567558 case 'V' : {
568- int * map = machine_endian_long_map ;
559+ php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
569560
570561 if (code == 'N' ) {
571- map = big_endian_long_map ;
562+ endianness = PHP_BIG_ENDIAN ;
572563 } else if (code == 'V' ) {
573- map = little_endian_long_map ;
564+ endianness = PHP_LITTLE_ENDIAN ;
574565 }
575566
576567 while (arg -- > 0 ) {
577- php_pack (& argv [currentarg ++ ], 4 , map , & ZSTR_VAL (output )[outputpos ]);
568+ php_pack (& argv [currentarg ++ ], 4 , endianness , & ZSTR_VAL (output )[outputpos ]);
578569 outputpos += 4 ;
579570 }
580571 break ;
@@ -585,16 +576,16 @@ PHP_FUNCTION(pack)
585576 case 'Q' :
586577 case 'J' :
587578 case 'P' : {
588- int * map = machine_endian_longlong_map ;
579+ php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
589580
590581 if (code == 'J' ) {
591- map = big_endian_longlong_map ;
582+ endianness = PHP_BIG_ENDIAN ;
592583 } else if (code == 'P' ) {
593- map = little_endian_longlong_map ;
584+ endianness = PHP_LITTLE_ENDIAN ;
594585 }
595586
596587 while (arg -- > 0 ) {
597- php_pack (& argv [currentarg ++ ], 8 , map , & ZSTR_VAL (output )[outputpos ]);
588+ php_pack (& argv [currentarg ++ ], 8 , endianness , & ZSTR_VAL (output )[outputpos ]);
598589 outputpos += 8 ;
599590 }
600591 break ;
@@ -1199,127 +1190,3 @@ PHP_FUNCTION(unpack)
11991190 }
12001191}
12011192/* }}} */
1202-
1203- /* {{{ PHP_MINIT_FUNCTION */
1204- PHP_MINIT_FUNCTION (pack )
1205- {
1206- int i ;
1207-
1208- if (MACHINE_LITTLE_ENDIAN ) {
1209- /* Where to get lo to hi bytes from */
1210- byte_map [0 ] = 0 ;
1211-
1212- for (i = 0 ; i < (int )sizeof (int ); i ++ ) {
1213- int_map [i ] = i ;
1214- }
1215-
1216- machine_endian_short_map [0 ] = 0 ;
1217- machine_endian_short_map [1 ] = 1 ;
1218- big_endian_short_map [0 ] = 1 ;
1219- big_endian_short_map [1 ] = 0 ;
1220- little_endian_short_map [0 ] = 0 ;
1221- little_endian_short_map [1 ] = 1 ;
1222-
1223- machine_endian_long_map [0 ] = 0 ;
1224- machine_endian_long_map [1 ] = 1 ;
1225- machine_endian_long_map [2 ] = 2 ;
1226- machine_endian_long_map [3 ] = 3 ;
1227- big_endian_long_map [0 ] = 3 ;
1228- big_endian_long_map [1 ] = 2 ;
1229- big_endian_long_map [2 ] = 1 ;
1230- big_endian_long_map [3 ] = 0 ;
1231- little_endian_long_map [0 ] = 0 ;
1232- little_endian_long_map [1 ] = 1 ;
1233- little_endian_long_map [2 ] = 2 ;
1234- little_endian_long_map [3 ] = 3 ;
1235-
1236- #if SIZEOF_ZEND_LONG > 4
1237- machine_endian_longlong_map [0 ] = 0 ;
1238- machine_endian_longlong_map [1 ] = 1 ;
1239- machine_endian_longlong_map [2 ] = 2 ;
1240- machine_endian_longlong_map [3 ] = 3 ;
1241- machine_endian_longlong_map [4 ] = 4 ;
1242- machine_endian_longlong_map [5 ] = 5 ;
1243- machine_endian_longlong_map [6 ] = 6 ;
1244- machine_endian_longlong_map [7 ] = 7 ;
1245- big_endian_longlong_map [0 ] = 7 ;
1246- big_endian_longlong_map [1 ] = 6 ;
1247- big_endian_longlong_map [2 ] = 5 ;
1248- big_endian_longlong_map [3 ] = 4 ;
1249- big_endian_longlong_map [4 ] = 3 ;
1250- big_endian_longlong_map [5 ] = 2 ;
1251- big_endian_longlong_map [6 ] = 1 ;
1252- big_endian_longlong_map [7 ] = 0 ;
1253- little_endian_longlong_map [0 ] = 0 ;
1254- little_endian_longlong_map [1 ] = 1 ;
1255- little_endian_longlong_map [2 ] = 2 ;
1256- little_endian_longlong_map [3 ] = 3 ;
1257- little_endian_longlong_map [4 ] = 4 ;
1258- little_endian_longlong_map [5 ] = 5 ;
1259- little_endian_longlong_map [6 ] = 6 ;
1260- little_endian_longlong_map [7 ] = 7 ;
1261- #endif
1262- }
1263- else {
1264- zval val ;
1265- int size = sizeof (Z_LVAL (val ));
1266- Z_LVAL (val )= 0 ; /*silence a warning*/
1267-
1268- /* Where to get hi to lo bytes from */
1269- byte_map [0 ] = size - 1 ;
1270-
1271- for (i = 0 ; i < (int )sizeof (int ); i ++ ) {
1272- int_map [i ] = size - (sizeof (int ) - i );
1273- }
1274-
1275- machine_endian_short_map [0 ] = size - 2 ;
1276- machine_endian_short_map [1 ] = size - 1 ;
1277- big_endian_short_map [0 ] = size - 2 ;
1278- big_endian_short_map [1 ] = size - 1 ;
1279- little_endian_short_map [0 ] = size - 1 ;
1280- little_endian_short_map [1 ] = size - 2 ;
1281-
1282- machine_endian_long_map [0 ] = size - 4 ;
1283- machine_endian_long_map [1 ] = size - 3 ;
1284- machine_endian_long_map [2 ] = size - 2 ;
1285- machine_endian_long_map [3 ] = size - 1 ;
1286- big_endian_long_map [0 ] = size - 4 ;
1287- big_endian_long_map [1 ] = size - 3 ;
1288- big_endian_long_map [2 ] = size - 2 ;
1289- big_endian_long_map [3 ] = size - 1 ;
1290- little_endian_long_map [0 ] = size - 1 ;
1291- little_endian_long_map [1 ] = size - 2 ;
1292- little_endian_long_map [2 ] = size - 3 ;
1293- little_endian_long_map [3 ] = size - 4 ;
1294-
1295- #if SIZEOF_ZEND_LONG > 4
1296- machine_endian_longlong_map [0 ] = size - 8 ;
1297- machine_endian_longlong_map [1 ] = size - 7 ;
1298- machine_endian_longlong_map [2 ] = size - 6 ;
1299- machine_endian_longlong_map [3 ] = size - 5 ;
1300- machine_endian_longlong_map [4 ] = size - 4 ;
1301- machine_endian_longlong_map [5 ] = size - 3 ;
1302- machine_endian_longlong_map [6 ] = size - 2 ;
1303- machine_endian_longlong_map [7 ] = size - 1 ;
1304- big_endian_longlong_map [0 ] = size - 8 ;
1305- big_endian_longlong_map [1 ] = size - 7 ;
1306- big_endian_longlong_map [2 ] = size - 6 ;
1307- big_endian_longlong_map [3 ] = size - 5 ;
1308- big_endian_longlong_map [4 ] = size - 4 ;
1309- big_endian_longlong_map [5 ] = size - 3 ;
1310- big_endian_longlong_map [6 ] = size - 2 ;
1311- big_endian_longlong_map [7 ] = size - 1 ;
1312- little_endian_longlong_map [0 ] = size - 1 ;
1313- little_endian_longlong_map [1 ] = size - 2 ;
1314- little_endian_longlong_map [2 ] = size - 3 ;
1315- little_endian_longlong_map [3 ] = size - 4 ;
1316- little_endian_longlong_map [4 ] = size - 5 ;
1317- little_endian_longlong_map [5 ] = size - 6 ;
1318- little_endian_longlong_map [6 ] = size - 7 ;
1319- little_endian_longlong_map [7 ] = size - 8 ;
1320- #endif
1321- }
1322-
1323- return SUCCESS ;
1324- }
1325- /* }}} */
0 commit comments