Skip to content

Commit 71d305d

Browse files
committed
Optimize pack()
1 parent 50dc301 commit 71d305d

File tree

4 files changed

+38
-195
lines changed

4 files changed

+38
-195
lines changed

ext/standard/basic_functions.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,6 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */
299299

300300
BASIC_MINIT_SUBMODULE(var)
301301
BASIC_MINIT_SUBMODULE(file)
302-
BASIC_MINIT_SUBMODULE(pack)
303302
BASIC_MINIT_SUBMODULE(browscap)
304303
BASIC_MINIT_SUBMODULE(standard_filters)
305304
BASIC_MINIT_SUBMODULE(user_filters)

ext/standard/pack.c

Lines changed: 38 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
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"
@@ -50,10 +49,23 @@
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

5971
typedef ZEND_SET_ALIGNED(1, uint16_t unaligned_uint16_t);
@@ -62,40 +74,19 @@ typedef ZEND_SET_ALIGNED(1, uint64_t unaligned_uint64_t);
6274
typedef ZEND_SET_ALIGNED(1, unsigned int unaligned_uint);
6375
typedef 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-
/* }}} */

ext/standard/pack.h

Lines changed: 0 additions & 22 deletions
This file was deleted.

ext/standard/php_standard.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include "php_ext_syslog.h"
3030
#include "php_filestat.h"
3131
#include "php_browscap.h"
32-
#include "pack.h"
3332
#include "datetime.h"
3433
#include "url.h"
3534
#include "pageinfo.h"

0 commit comments

Comments
 (0)