19
19
#include <stdlib.h>
20
20
#include <errno.h>
21
21
#include <sys/types.h>
22
- #include "pack.h"
23
22
24
23
#define INC_OUTPUTPOS (a ,b ) \
25
24
if ((a) < 0 || ((INT_MAX - outputpos)/((int)b)) < (a)) { \
30
29
} \
31
30
outputpos += (a)*(b);
32
31
32
+ typedef enum {
33
+ PHP_LITTLE_ENDIAN ,
34
+ PHP_BIG_ENDIAN ,
35
+ } php_pack_endianness ;
36
+
33
37
#ifdef WORDS_BIGENDIAN
34
- #define MACHINE_LITTLE_ENDIAN 0
38
+ # define MACHINE_LITTLE_ENDIAN 0
39
+ # define PHP_MACHINE_ENDIAN PHP_BIG_ENDIAN
35
40
#else
36
- #define MACHINE_LITTLE_ENDIAN 1
41
+ # define MACHINE_LITTLE_ENDIAN 1
42
+ # define PHP_MACHINE_ENDIAN PHP_LITTLE_ENDIAN
43
+ #endif
44
+
45
+ #ifdef ZEND_ENABLE_ZVAL_LONG64
46
+ # define PHP_LONG_BSWAP (u ) ZEND_BYTES_SWAP64(u)
47
+ #else
48
+ # define PHP_LONG_BSWAP (u ) ZEND_BYTES_SWAP32(u)
37
49
#endif
38
50
39
51
typedef ZEND_SET_ALIGNED (1 , uint16_t unaligned_uint16_t ) ;
@@ -42,41 +54,23 @@ typedef ZEND_SET_ALIGNED(1, uint64_t unaligned_uint64_t);
42
54
typedef ZEND_SET_ALIGNED (1 , unsigned int unaligned_uint ) ;
43
55
typedef ZEND_SET_ALIGNED (1 , int unaligned_int ) ;
44
56
45
- /* Mapping of byte from char (8bit) to long for machine endian */
46
- static int byte_map [1 ];
47
-
48
- /* Mappings of bytes from int (machine dependent) to int for machine endian */
49
- static int int_map [sizeof (int )];
50
-
51
- /* Mappings of bytes from shorts (16bit) for all endian environments */
52
- static int machine_endian_short_map [2 ];
53
- static int big_endian_short_map [2 ];
54
- static int little_endian_short_map [2 ];
55
-
56
- /* Mappings of bytes from longs (32bit) for all endian environments */
57
- static int machine_endian_long_map [4 ];
58
- static int big_endian_long_map [4 ];
59
- static int little_endian_long_map [4 ];
60
-
61
- #if SIZEOF_ZEND_LONG > 4
62
- /* Mappings of bytes from quads (64bit) for all endian environments */
63
- static int machine_endian_longlong_map [8 ];
64
- static int big_endian_longlong_map [8 ];
65
- static int little_endian_longlong_map [8 ];
66
- #endif
67
-
68
57
/* {{{ php_pack */
69
- static void php_pack (zval * val , size_t size , int * map , char * output )
58
+ static void php_pack (const zval * val , size_t size , php_pack_endianness endianness , char * output )
70
59
{
71
- size_t i ;
72
- char * v ;
73
-
74
- convert_to_long (val );
75
- v = (char * ) & Z_LVAL_P (val );
60
+ zend_ulong zl = zval_get_long (val );
76
61
77
- for (i = 0 ; i < size ; i ++ ) {
78
- * output ++ = v [map [i ]];
62
+ if ((endianness == PHP_LITTLE_ENDIAN ) != MACHINE_LITTLE_ENDIAN ) {
63
+ zl = PHP_LONG_BSWAP (zl );
64
+ #if MACHINE_LITTLE_ENDIAN
65
+ zl >>= (sizeof (zl ) - size ) * 8 ;
66
+ #endif
67
+ } else {
68
+ #if !MACHINE_LITTLE_ENDIAN
69
+ zl <<= (sizeof (zl ) - size ) * 8 ;
70
+ #endif
79
71
}
72
+
73
+ memcpy (output , (const char * ) & zl , size );
80
74
}
81
75
/* }}} */
82
76
@@ -88,10 +82,7 @@ ZEND_ATTRIBUTE_CONST static inline uint16_t php_pack_reverse_int16(uint16_t arg)
88
82
/* {{{ php_pack_reverse_int32 */
89
83
ZEND_ATTRIBUTE_CONST static inline uint32_t php_pack_reverse_int32 (uint32_t arg )
90
84
{
91
- uint32_t result ;
92
- result = ((arg & 0xFF ) << 24 ) | ((arg & 0xFF00 ) << 8 ) | ((arg >> 8 ) & 0xFF00 ) | ((arg >> 24 ) & 0xFF );
93
-
94
- return result ;
85
+ return ZEND_BYTES_SWAP32 (arg );
95
86
}
96
87
/* }}} */
97
88
@@ -509,7 +500,7 @@ PHP_FUNCTION(pack)
509
500
case 'c' :
510
501
case 'C' :
511
502
while (arg -- > 0 ) {
512
- php_pack (& argv [currentarg ++ ], 1 , byte_map , & ZSTR_VAL (output )[outputpos ]);
503
+ php_pack (& argv [currentarg ++ ], 1 , PHP_MACHINE_ENDIAN , & ZSTR_VAL (output )[outputpos ]);
513
504
outputpos ++ ;
514
505
}
515
506
break ;
@@ -518,16 +509,16 @@ PHP_FUNCTION(pack)
518
509
case 'S' :
519
510
case 'n' :
520
511
case 'v' : {
521
- int * map = machine_endian_short_map ;
512
+ php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
522
513
523
514
if (code == 'n' ) {
524
- map = big_endian_short_map ;
515
+ endianness = PHP_BIG_ENDIAN ;
525
516
} else if (code == 'v' ) {
526
- map = little_endian_short_map ;
517
+ endianness = PHP_LITTLE_ENDIAN ;
527
518
}
528
519
529
520
while (arg -- > 0 ) {
530
- php_pack (& argv [currentarg ++ ], 2 , map , & ZSTR_VAL (output )[outputpos ]);
521
+ php_pack (& argv [currentarg ++ ], 2 , endianness , & ZSTR_VAL (output )[outputpos ]);
531
522
outputpos += 2 ;
532
523
}
533
524
break ;
@@ -536,7 +527,7 @@ PHP_FUNCTION(pack)
536
527
case 'i' :
537
528
case 'I' :
538
529
while (arg -- > 0 ) {
539
- php_pack (& argv [currentarg ++ ], sizeof (int ), int_map , & ZSTR_VAL (output )[outputpos ]);
530
+ php_pack (& argv [currentarg ++ ], sizeof (int ), PHP_MACHINE_ENDIAN , & ZSTR_VAL (output )[outputpos ]);
540
531
outputpos += sizeof (int );
541
532
}
542
533
break ;
@@ -545,16 +536,16 @@ PHP_FUNCTION(pack)
545
536
case 'L' :
546
537
case 'N' :
547
538
case 'V' : {
548
- int * map = machine_endian_long_map ;
539
+ php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
549
540
550
541
if (code == 'N' ) {
551
- map = big_endian_long_map ;
542
+ endianness = PHP_BIG_ENDIAN ;
552
543
} else if (code == 'V' ) {
553
- map = little_endian_long_map ;
544
+ endianness = PHP_LITTLE_ENDIAN ;
554
545
}
555
546
556
547
while (arg -- > 0 ) {
557
- php_pack (& argv [currentarg ++ ], 4 , map , & ZSTR_VAL (output )[outputpos ]);
548
+ php_pack (& argv [currentarg ++ ], 4 , endianness , & ZSTR_VAL (output )[outputpos ]);
558
549
outputpos += 4 ;
559
550
}
560
551
break ;
@@ -565,16 +556,16 @@ PHP_FUNCTION(pack)
565
556
case 'Q' :
566
557
case 'J' :
567
558
case 'P' : {
568
- int * map = machine_endian_longlong_map ;
559
+ php_pack_endianness endianness = PHP_MACHINE_ENDIAN ;
569
560
570
561
if (code == 'J' ) {
571
- map = big_endian_longlong_map ;
562
+ endianness = PHP_BIG_ENDIAN ;
572
563
} else if (code == 'P' ) {
573
- map = little_endian_longlong_map ;
564
+ endianness = PHP_LITTLE_ENDIAN ;
574
565
}
575
566
576
567
while (arg -- > 0 ) {
577
- php_pack (& argv [currentarg ++ ], 8 , map , & ZSTR_VAL (output )[outputpos ]);
568
+ php_pack (& argv [currentarg ++ ], 8 , endianness , & ZSTR_VAL (output )[outputpos ]);
578
569
outputpos += 8 ;
579
570
}
580
571
break ;
@@ -1178,127 +1169,3 @@ PHP_FUNCTION(unpack)
1178
1169
}
1179
1170
}
1180
1171
/* }}} */
1181
-
1182
- /* {{{ PHP_MINIT_FUNCTION */
1183
- PHP_MINIT_FUNCTION (pack )
1184
- {
1185
- int i ;
1186
-
1187
- if (MACHINE_LITTLE_ENDIAN ) {
1188
- /* Where to get lo to hi bytes from */
1189
- byte_map [0 ] = 0 ;
1190
-
1191
- for (i = 0 ; i < (int )sizeof (int ); i ++ ) {
1192
- int_map [i ] = i ;
1193
- }
1194
-
1195
- machine_endian_short_map [0 ] = 0 ;
1196
- machine_endian_short_map [1 ] = 1 ;
1197
- big_endian_short_map [0 ] = 1 ;
1198
- big_endian_short_map [1 ] = 0 ;
1199
- little_endian_short_map [0 ] = 0 ;
1200
- little_endian_short_map [1 ] = 1 ;
1201
-
1202
- machine_endian_long_map [0 ] = 0 ;
1203
- machine_endian_long_map [1 ] = 1 ;
1204
- machine_endian_long_map [2 ] = 2 ;
1205
- machine_endian_long_map [3 ] = 3 ;
1206
- big_endian_long_map [0 ] = 3 ;
1207
- big_endian_long_map [1 ] = 2 ;
1208
- big_endian_long_map [2 ] = 1 ;
1209
- big_endian_long_map [3 ] = 0 ;
1210
- little_endian_long_map [0 ] = 0 ;
1211
- little_endian_long_map [1 ] = 1 ;
1212
- little_endian_long_map [2 ] = 2 ;
1213
- little_endian_long_map [3 ] = 3 ;
1214
-
1215
- #if SIZEOF_ZEND_LONG > 4
1216
- machine_endian_longlong_map [0 ] = 0 ;
1217
- machine_endian_longlong_map [1 ] = 1 ;
1218
- machine_endian_longlong_map [2 ] = 2 ;
1219
- machine_endian_longlong_map [3 ] = 3 ;
1220
- machine_endian_longlong_map [4 ] = 4 ;
1221
- machine_endian_longlong_map [5 ] = 5 ;
1222
- machine_endian_longlong_map [6 ] = 6 ;
1223
- machine_endian_longlong_map [7 ] = 7 ;
1224
- big_endian_longlong_map [0 ] = 7 ;
1225
- big_endian_longlong_map [1 ] = 6 ;
1226
- big_endian_longlong_map [2 ] = 5 ;
1227
- big_endian_longlong_map [3 ] = 4 ;
1228
- big_endian_longlong_map [4 ] = 3 ;
1229
- big_endian_longlong_map [5 ] = 2 ;
1230
- big_endian_longlong_map [6 ] = 1 ;
1231
- big_endian_longlong_map [7 ] = 0 ;
1232
- little_endian_longlong_map [0 ] = 0 ;
1233
- little_endian_longlong_map [1 ] = 1 ;
1234
- little_endian_longlong_map [2 ] = 2 ;
1235
- little_endian_longlong_map [3 ] = 3 ;
1236
- little_endian_longlong_map [4 ] = 4 ;
1237
- little_endian_longlong_map [5 ] = 5 ;
1238
- little_endian_longlong_map [6 ] = 6 ;
1239
- little_endian_longlong_map [7 ] = 7 ;
1240
- #endif
1241
- }
1242
- else {
1243
- zval val ;
1244
- int size = sizeof (Z_LVAL (val ));
1245
- Z_LVAL (val )= 0 ; /*silence a warning*/
1246
-
1247
- /* Where to get hi to lo bytes from */
1248
- byte_map [0 ] = size - 1 ;
1249
-
1250
- for (i = 0 ; i < (int )sizeof (int ); i ++ ) {
1251
- int_map [i ] = size - (sizeof (int ) - i );
1252
- }
1253
-
1254
- machine_endian_short_map [0 ] = size - 2 ;
1255
- machine_endian_short_map [1 ] = size - 1 ;
1256
- big_endian_short_map [0 ] = size - 2 ;
1257
- big_endian_short_map [1 ] = size - 1 ;
1258
- little_endian_short_map [0 ] = size - 1 ;
1259
- little_endian_short_map [1 ] = size - 2 ;
1260
-
1261
- machine_endian_long_map [0 ] = size - 4 ;
1262
- machine_endian_long_map [1 ] = size - 3 ;
1263
- machine_endian_long_map [2 ] = size - 2 ;
1264
- machine_endian_long_map [3 ] = size - 1 ;
1265
- big_endian_long_map [0 ] = size - 4 ;
1266
- big_endian_long_map [1 ] = size - 3 ;
1267
- big_endian_long_map [2 ] = size - 2 ;
1268
- big_endian_long_map [3 ] = size - 1 ;
1269
- little_endian_long_map [0 ] = size - 1 ;
1270
- little_endian_long_map [1 ] = size - 2 ;
1271
- little_endian_long_map [2 ] = size - 3 ;
1272
- little_endian_long_map [3 ] = size - 4 ;
1273
-
1274
- #if SIZEOF_ZEND_LONG > 4
1275
- machine_endian_longlong_map [0 ] = size - 8 ;
1276
- machine_endian_longlong_map [1 ] = size - 7 ;
1277
- machine_endian_longlong_map [2 ] = size - 6 ;
1278
- machine_endian_longlong_map [3 ] = size - 5 ;
1279
- machine_endian_longlong_map [4 ] = size - 4 ;
1280
- machine_endian_longlong_map [5 ] = size - 3 ;
1281
- machine_endian_longlong_map [6 ] = size - 2 ;
1282
- machine_endian_longlong_map [7 ] = size - 1 ;
1283
- big_endian_longlong_map [0 ] = size - 8 ;
1284
- big_endian_longlong_map [1 ] = size - 7 ;
1285
- big_endian_longlong_map [2 ] = size - 6 ;
1286
- big_endian_longlong_map [3 ] = size - 5 ;
1287
- big_endian_longlong_map [4 ] = size - 4 ;
1288
- big_endian_longlong_map [5 ] = size - 3 ;
1289
- big_endian_longlong_map [6 ] = size - 2 ;
1290
- big_endian_longlong_map [7 ] = size - 1 ;
1291
- little_endian_longlong_map [0 ] = size - 1 ;
1292
- little_endian_longlong_map [1 ] = size - 2 ;
1293
- little_endian_longlong_map [2 ] = size - 3 ;
1294
- little_endian_longlong_map [3 ] = size - 4 ;
1295
- little_endian_longlong_map [4 ] = size - 5 ;
1296
- little_endian_longlong_map [5 ] = size - 6 ;
1297
- little_endian_longlong_map [6 ] = size - 7 ;
1298
- little_endian_longlong_map [7 ] = size - 8 ;
1299
- #endif
1300
- }
1301
-
1302
- return SUCCESS ;
1303
- }
1304
- /* }}} */
0 commit comments