Skip to content

Commit a81d595

Browse files
committed
encoder: Add support for base64url encoding
1 parent 4e82ead commit a81d595

File tree

6 files changed

+41
-9
lines changed

6 files changed

+41
-9
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ $fileContentEncoded = new SimdJsonBase64Encode($fileContent);
136136
simdjson_encode(['image' => $fileContentEncoded]); // returns {"image":"TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu..."}
137137
```
138138

139+
You can also use base64url encoding (RFC 4648 §5) by setting second argument to true: `new SimdJsonBase64Encode($fileContent, true);`
140+
139141
### Encode to stream
140142

141143
For large data sets, simdjson_php provides the `simdjson_encode_to_stream()` function to save data directly to a file or output buffer.

php_simdjson.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -591,23 +591,29 @@ PHP_FUNCTION(simdjson_encode_to_stream) {
591591

592592
PHP_METHOD(SimdJsonBase64Encode, __construct) {
593593
zend_string *binary_string = NULL;
594+
bool base64_url = false;
594595

595-
ZEND_PARSE_PARAMETERS_START(1, 1)
596+
ZEND_PARSE_PARAMETERS_START(1, 2)
596597
Z_PARAM_STR(binary_string)
598+
Z_PARAM_OPTIONAL
599+
Z_PARAM_BOOL(base64_url)
597600
ZEND_PARSE_PARAMETERS_END();
598601

599602
return_value = ZEND_THIS;
600603
ZVAL_STR_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), binary_string);
604+
ZVAL_BOOL(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 1), base64_url);
601605
}
602606

603607
PHP_METHOD(SimdJsonBase64Encode, jsonSerialize) {
604608
ZEND_PARSE_PARAMETERS_NONE();
605609

606-
zend_string *binary_string = Z_STR(Z_OBJ_P(ZEND_THIS)->properties_table[0]);
610+
zend_string *binary_string = Z_STR_P(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0));
611+
bool base64_url = Z_TYPE_INFO_P(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 1)) == IS_TRUE;
612+
auto options = base64_url ? simdutf::base64_url : simdutf::base64_default;
607613

608-
size_t encoded_length = simdutf::base64_length_from_binary(ZSTR_LEN(binary_string));
614+
size_t encoded_length = simdutf::base64_length_from_binary(ZSTR_LEN(binary_string), options);
609615
zend_string *result = zend_string_alloc(encoded_length, 0);
610-
simdutf::binary_to_base64(ZSTR_VAL(binary_string), ZSTR_LEN(binary_string), ZSTR_VAL(result));
616+
simdutf::binary_to_base64(ZSTR_VAL(binary_string), ZSTR_LEN(binary_string), ZSTR_VAL(result), options);
611617
ZSTR_VAL(result)[encoded_length] = '\0';
612618
GC_ADD_FLAGS(result, IS_STR_VALID_UTF8); // base64 encoded string must be always valid UTF-8 string
613619

simdjson.stub.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,11 +364,13 @@ class SimdJsonEncoderException extends SimdJsonException {}
364364
*/
365365
final class SimdJsonBase64Encode implements JsonSerializable {
366366
private string $string;
367+
private bool $base64url = false;
367368

368369
/**
369370
* @param string $string The data to encode.
371+
* @param bool $base64url When true, use base64url encoding (RFC 4648 §5).
370372
*/
371-
public function __construct(string $string) {}
373+
public function __construct(string $string, bool $base64url = false) {}
372374

373375
/**
374376
* @return mixed Base64 encoded string

simdjson_arginfo.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 5b2147fe5e6865e7ab51e22a21cb235aeba0a12e */
2+
* Stub hash: 21c3b21c513b1ce2b8c72912856cd6d7326dbfe5 */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_simdjson_validate, 0, 1, _IS_BOOL, 0)
55
ZEND_ARG_TYPE_INFO(0, json, IS_STRING, 0)
@@ -62,6 +62,7 @@ ZEND_END_ARG_INFO()
6262

6363
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SimdJsonBase64Encode___construct, 0, 0, 1)
6464
ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0)
65+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, base64url, _IS_BOOL, 0, "false")
6566
ZEND_END_ARG_INFO()
6667

6768
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_SimdJsonBase64Encode_jsonSerialize, 0, 0, IS_MIXED, 0)
@@ -216,5 +217,11 @@ static zend_class_entry *register_class_SimdJsonBase64Encode(zend_class_entry *c
216217
zend_declare_typed_property(class_entry, property_string_name, &property_string_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING));
217218
zend_string_release(property_string_name);
218219

220+
zval property_base64url_default_value;
221+
ZVAL_FALSE(&property_base64url_default_value);
222+
zend_string *property_base64url_name = zend_string_init("base64url", sizeof("base64url") - 1, 1);
223+
zend_declare_typed_property(class_entry, property_base64url_name, &property_base64url_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
224+
zend_string_release(property_base64url_name);
225+
219226
return class_entry;
220227
}

src/simdjson_encoder.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -709,14 +709,16 @@ static zend_result simdjson_escape_string(smart_str *buf, zend_string *str, simd
709709
}
710710

711711
static void simdjson_encode_base64_object(smart_str *buf, const zval *val) {
712-
zend_string *binary_string = Z_STR(Z_OBJ_P(val)->properties_table[0]);
712+
zend_string *binary_string = Z_STR_P(OBJ_PROP_NUM(Z_OBJ_P(val), 0));
713+
bool base64_url = Z_TYPE_INFO_P(OBJ_PROP_NUM(Z_OBJ_P(val), 1)) == IS_TRUE;
714+
auto options = base64_url ? simdutf::base64_url : simdutf::base64_default;
713715

714716
// As we are sure that base64 encoded string is always valid UTF-8 and do not contain any char that need to be
715717
// escaped, so we can skip all checks and just directly copy encoded string to output buffer
716-
size_t encoded_length = simdutf::base64_length_from_binary(ZSTR_LEN(binary_string));
718+
size_t encoded_length = simdutf::base64_length_from_binary(ZSTR_LEN(binary_string), options);
717719
char* output = simdjson_smart_str_extend(buf, encoded_length + 2);
718720
*output++ = '"';
719-
simdutf::binary_to_base64(ZSTR_VAL(binary_string), ZSTR_LEN(binary_string), output);
721+
simdutf::binary_to_base64(ZSTR_VAL(binary_string), ZSTR_LEN(binary_string), output, options);
720722
output += encoded_length;
721723
*output = '"';
722724
}

tests/encode/simdjson_base64_encode.phpt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,29 @@
22
Test SimdJsonBase64Encode
33
--FILE--
44
<?php
5+
echo "Base64 encode\n";
56
$base64Encode = new SimdJsonBase64Encode("ahoj");
67
var_dump($base64Encode->jsonSerialize());
78
var_dump((string)$base64Encode);
89
var_dump(json_encode(base64_encode("ahoj")));
910
var_dump(json_encode($base64Encode));
1011
var_dump(simdjson_encode($base64Encode));
12+
echo "Base64 URL encode\n";
13+
$base64Encode = new SimdJsonBase64Encode("ahoj", true);
14+
var_dump($base64Encode->jsonSerialize());
15+
var_dump((string)$base64Encode);
16+
var_dump(json_encode($base64Encode));
17+
var_dump(simdjson_encode($base64Encode));
1118
?>
1219
--EXPECT--
20+
Base64 encode
1321
string(8) "YWhvag=="
1422
string(8) "YWhvag=="
1523
string(10) ""YWhvag==""
1624
string(10) ""YWhvag==""
1725
string(10) ""YWhvag==""
26+
Base64 URL encode
27+
string(6) "YWhvag"
28+
string(6) "YWhvag"
29+
string(8) ""YWhvag""
30+
string(8) ""YWhvag""

0 commit comments

Comments
 (0)