Skip to content

Commit 71446a2

Browse files
committed
static table + php script for generation
1 parent 18fe1fe commit 71446a2

5 files changed

Lines changed: 78 additions & 16 deletions

File tree

‎ext/json/gen_json_escape_table.php‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env php
2+
<?php
3+
/**
4+
* Generates php_json_escape_table.h. This file is not necessary to build
5+
* PHP -- it's only necessary to regenerate php_json_escape_table.h if the
6+
* set of bytes php_json_escape_string() must escape ever changes.
7+
*
8+
* Usage: php gen_json_escape_table.php
9+
*/
10+
11+
function is_dirty(int $b): bool {
12+
// Control characters (< 0x20), non-ASCII bytes (>= 0x80, which need
13+
// UTF-8 decoding), and the ASCII specials " \ / < > & '.
14+
return $b < 0x20 || $b >= 0x80
15+
|| $b === 0x22 // "
16+
|| $b === 0x5c // backslash
17+
|| $b === 0x2f // /
18+
|| $b === 0x3c // <
19+
|| $b === 0x3e // >
20+
|| $b === 0x26 // &
21+
|| $b === 0x27; // '
22+
}
23+
24+
$result = <<<'HEADER'
25+
/* This file was generated by ext/json/gen_json_escape_table.php.
26+
*
27+
* DO NOT EDIT THIS FILE!
28+
*
29+
* Classifies which bytes php_json_escape_string() must escape: control
30+
* characters (< 0x20), non-ASCII bytes (>= 0x80, which need UTF-8
31+
* decoding), and the ASCII specials " \ / < > & '.
32+
*/
33+
34+
static const bool php_json_escape_dirty_table[256] = {
35+
36+
HEADER;
37+
38+
for ($row = 0; $row < 16; $row++) {
39+
$values = [];
40+
for ($col = 0; $col < 16; $col++) {
41+
$b = $row * 16 + $col;
42+
$values[] = is_dirty($b) ? '1' : '0';
43+
}
44+
$result .= "\t" . implode(', ', $values) . ",\n";
45+
}
46+
47+
$result .= "};\n";
48+
49+
file_put_contents(__DIR__ . '/php_json_escape_table.h', $result);
50+
echo "Generated php_json_escape_table.h\n";

‎ext/json/json.c‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ static PHP_MINIT_FUNCTION(json)
4949

5050
register_json_symbols(module_number);
5151

52-
php_json_escape_dirty_table_init();
53-
5452
return SUCCESS;
5553
}
5654
/* }}} */

‎ext/json/json_encoder.c‎

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "zend_smart_str.h"
2323
#include "php_json.h"
2424
#include "php_json_encoder.h"
25+
#include "php_json_escape_table.h"
2526
#include "zend_portability.h"
2627
#include <zend_exceptions.h>
2728
#include "zend_enum.h"
@@ -30,18 +31,6 @@
3031

3132
static const char digits[] = "0123456789abcdef";
3233

33-
static uint8_t php_json_escape_dirty_table[256];
34-
35-
void php_json_escape_dirty_table_init(void)
36-
{
37-
for (int b = 0; b < 256; b++) {
38-
php_json_escape_dirty_table[b] =
39-
b < 0x20 || b >= 0x80
40-
|| b == '"' || b == '\\' || b == '/'
41-
|| b == '<' || b == '>' || b == '&' || b == '\'';
42-
}
43-
}
44-
4534
static zend_always_inline bool php_json_check_stack_limit(void)
4635
{
4736
#ifdef ZEND_CHECK_STACK_LIMIT

‎ext/json/php_json_encoder.h‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,4 @@ zend_result php_json_encode_zval(smart_str *buf, zval *val, int options, php_jso
3535

3636
zend_result php_json_escape_string(smart_str *buf, const char *s, size_t len, int options, php_json_encoder *encoder);
3737

38-
void php_json_escape_dirty_table_init(void);
39-
4038
#endif /* PHP_JSON_ENCODER_H */

‎ext/json/php_json_escape_table.h‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* This file was generated by ext/json/gen_json_escape_table.php.
2+
*
3+
* DO NOT EDIT THIS FILE!
4+
*
5+
* Classifies which bytes php_json_escape_string() must escape: control
6+
* characters (< 0x20), non-ASCII bytes (>= 0x80, which need UTF-8
7+
* decoding), and the ASCII specials " \ / < > & '.
8+
*/
9+
10+
static const bool php_json_escape_dirty_table[256] = {
11+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
12+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
13+
0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1,
14+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
15+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
17+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
19+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
20+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
21+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
22+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
23+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
24+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
25+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
26+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
27+
};

0 commit comments

Comments
 (0)