Skip to content

Commit 8affbed

Browse files
committed
change: brotli.state resource in brotli_compress_{init,add}() to Btorli\Compress\Context class
1 parent 6eb42b8 commit 8affbed

File tree

2 files changed

+158
-29
lines changed

2 files changed

+158
-29
lines changed

brotli.c

Lines changed: 157 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <ext/apcu/apc_serializer.h>
1313
#include <zend_smart_str.h>
1414
#endif
15+
#include <Zend/zend_interfaces.h>
1516
#include "php_brotli.h"
1617

1718
int le_state;
@@ -859,6 +860,93 @@ php_stream_wrapper php_stream_brotli_wrapper = {
859860
0 /* is_url */
860861
};
861862

863+
/* Brotli Compress/UnCompress Context */
864+
#define PHP_BROTLI_CONTEXT_OBJ_INIT_OF_CLASS(ce) \
865+
php_brotli_context *ctx; \
866+
object_init_ex(return_value, ce); \
867+
ctx = php_brotli_context_from_obj(Z_OBJ_P(return_value)); \
868+
ctx->state.encoder = NULL; \
869+
ctx->state.decoder = NULL; \
870+
ctx->available_in = 0; \
871+
ctx->next_in = NULL; \
872+
ctx->available_out = 0; \
873+
ctx->next_out = NULL; \
874+
ctx->output = NULL;
875+
876+
static php_brotli_context *php_brotli_context_from_obj(zend_object *obj)
877+
{
878+
return (php_brotli_context *)
879+
((char *)(obj) - XtOffsetOf(php_brotli_context, std));
880+
}
881+
882+
static void php_brotli_context_free_obj(zend_object *object)
883+
{
884+
php_brotli_context *intern = php_brotli_context_from_obj(object);
885+
php_brotli_context_close(intern);
886+
zend_object_std_dtor(&intern->std);
887+
}
888+
889+
static zend_object *
890+
php_brotli_context_create_object(zend_class_entry *class_type,
891+
zend_object_handlers *handlers)
892+
{
893+
php_brotli_context *intern;
894+
#if PHP_VERSION_ID >= 80000
895+
intern = zend_object_alloc(sizeof(php_brotli_context), class_type);
896+
#else
897+
intern = ecalloc(1,
898+
sizeof(php_brotli_context)
899+
+ zend_object_properties_size(class_type));
900+
#endif
901+
zend_object_std_init(&intern->std, class_type);
902+
object_properties_init(&intern->std, class_type);
903+
intern->std.handlers = handlers;
904+
905+
return &intern->std;
906+
}
907+
908+
/* Brotli Compress Context */
909+
zend_class_entry *php_brotli_compress_context_ce;
910+
static zend_object_handlers php_brotli_compress_context_object_handlers;
911+
912+
static zend_object *
913+
php_brotli_compress_context_create_object(zend_class_entry *class_type)
914+
{
915+
return php_brotli_context_create_object(
916+
class_type,
917+
&php_brotli_compress_context_object_handlers);
918+
}
919+
920+
static zend_function *
921+
php_brotli_compress_context_get_constructor(zend_object *object)
922+
{
923+
zend_throw_error(NULL,
924+
"Cannot directly construct Brotli\\Compress\\Context, "
925+
"use brotli_compress_init() instead");
926+
return NULL;
927+
}
928+
929+
static zend_class_entry *php_brotli_compress_context_register_class(void)
930+
{
931+
zend_class_entry ce, *class_entry;
932+
933+
INIT_NS_CLASS_ENTRY(ce, "Brotli\\Compress", "Context", NULL);
934+
#if PHP_VERSION_ID >= 80000
935+
class_entry = zend_register_internal_class_ex(&ce, NULL);
936+
#if PHP_VERSION_ID >= 80100
937+
class_entry->ce_flags |= ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE;
938+
#else
939+
class_entry->ce_flags |= ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES;
940+
#endif
941+
#else
942+
ce.create_object = php_brotli_compress_context_create_object;
943+
class_entry = zend_register_internal_class(&ce);
944+
class_entry->ce_flags |= ZEND_ACC_FINAL;
945+
#endif
946+
947+
return class_entry;
948+
}
949+
862950
ZEND_MINIT_FUNCTION(brotli)
863951
{
864952
ZEND_INIT_MODULE_GLOBALS(brotli, php_brotli_init_globals, NULL);
@@ -894,6 +982,34 @@ ZEND_MINIT_FUNCTION(brotli)
894982
php_output_handler_conflict_register(ZEND_STRL(PHP_BROTLI_OUTPUT_HANDLER),
895983
php_brotli_output_conflict);
896984

985+
php_brotli_compress_context_ce
986+
= php_brotli_compress_context_register_class();
987+
#if PHP_VERSION_ID >= 80000
988+
php_brotli_compress_context_ce->create_object
989+
= php_brotli_compress_context_create_object;
990+
#if PHP_VERSION_ID >= 80300
991+
php_brotli_compress_context_ce->default_object_handlers
992+
= &php_brotli_compress_context_object_handlers;
993+
#endif
994+
#if PHP_VERSION_ID < 80100
995+
php_brotli_compress_context_ce->serialize = zend_class_serialize_deny;
996+
php_brotli_compress_context_ce->unserialize = zend_class_unserialize_deny;
997+
#endif
998+
#endif
999+
memcpy(&php_brotli_compress_context_object_handlers,
1000+
&std_object_handlers, sizeof(zend_object_handlers));
1001+
php_brotli_compress_context_object_handlers.offset
1002+
= XtOffsetOf(php_brotli_context, std);
1003+
php_brotli_compress_context_object_handlers.free_obj
1004+
= php_brotli_context_free_obj;
1005+
php_brotli_compress_context_object_handlers.get_constructor
1006+
= php_brotli_compress_context_get_constructor;
1007+
php_brotli_compress_context_object_handlers.clone_obj = NULL;
1008+
#if PHP_VERSION_ID >= 80000
1009+
php_brotli_compress_context_object_handlers.compare
1010+
= zend_objects_not_comparable;
1011+
#endif
1012+
8971013
REGISTER_INI_ENTRIES();
8981014

8991015
php_register_url_stream_wrapper(STREAM_NAME,
@@ -1032,45 +1148,56 @@ static ZEND_FUNCTION(brotli_compress_init)
10321148
{
10331149
zend_long quality = BROTLI_DEFAULT_QUALITY;
10341150
zend_long mode = BROTLI_MODE_GENERIC;
1035-
php_brotli_state_context *ctx;
10361151

10371152
ZEND_PARSE_PARAMETERS_START(0, 2)
10381153
Z_PARAM_OPTIONAL
10391154
Z_PARAM_LONG(quality)
10401155
Z_PARAM_LONG(mode)
10411156
ZEND_PARSE_PARAMETERS_END();
10421157

1043-
ctx = php_brotli_state_init();
1158+
PHP_BROTLI_CONTEXT_OBJ_INIT_OF_CLASS(php_brotli_compress_context_ce);
10441159

1045-
if (php_brotli_encoder_create(&ctx->encoder,
1160+
if (php_brotli_encoder_create(&ctx->state.encoder,
10461161
quality, 0, mode) != SUCCESS) {
1162+
zval_ptr_dtor(return_value);
10471163
php_error_docref(NULL, E_WARNING,
10481164
"Brotli incremental compress init failed");
10491165
RETURN_FALSE;
10501166
}
1051-
1052-
RETURN_RES(zend_register_resource(ctx, le_state));
10531167
}
10541168

10551169
static ZEND_FUNCTION(brotli_compress_add)
10561170
{
10571171
zval *res;
1058-
php_brotli_state_context *ctx;
1172+
php_brotli_context *ctx;
10591173
size_t buffer_size, buffer_used;
10601174
zend_long mode = BROTLI_OPERATION_FLUSH;
1175+
#if PHP_VERSION_ID >= 80000
1176+
zend_object *obj;
1177+
#else
1178+
zval *obj;
1179+
#endif
10611180
char *in_buf;
10621181
size_t in_size;
10631182
smart_string out = {0};
10641183

10651184
ZEND_PARSE_PARAMETERS_START(2, 3)
1066-
Z_PARAM_RESOURCE(res)
1185+
#if PHP_VERSION_ID >= 80000
1186+
Z_PARAM_OBJ_OF_CLASS(obj, php_brotli_compress_context_ce)
1187+
#else
1188+
Z_PARAM_OBJECT_OF_CLASS(obj, php_brotli_compress_context_ce)
1189+
#endif
10671190
Z_PARAM_STRING(in_buf, in_size)
10681191
Z_PARAM_OPTIONAL
10691192
Z_PARAM_LONG(mode)
10701193
ZEND_PARSE_PARAMETERS_END();
10711194

1072-
ctx = zend_fetch_resource(Z_RES_P(res), NULL, le_state);
1073-
if (ctx == NULL || ctx->encoder == NULL) {
1195+
#if PHP_VERSION_ID >= 80000
1196+
ctx = php_brotli_context_from_obj(obj);
1197+
#else
1198+
ctx = php_brotli_context_from_obj(Z_OBJ_P(obj));
1199+
#endif
1200+
if (ctx == NULL || ctx->state.encoder == NULL) {
10741201
php_error_docref(NULL, E_WARNING,
10751202
"Brotli incremental compress resource failed");
10761203
RETURN_FALSE;
@@ -1080,20 +1207,21 @@ static ZEND_FUNCTION(brotli_compress_add)
10801207
buffer_size = (buffer_size < 64) ? 64 : buffer_size;
10811208
uint8_t *buffer = (uint8_t *)emalloc(buffer_size);
10821209

1083-
const uint8_t *next_in = in_buf;
1084-
size_t available_in = in_size;
1210+
ctx->next_in = in_buf;
1211+
ctx->available_in = in_size;
10851212

1086-
while (available_in || BrotliEncoderHasMoreOutput(ctx->encoder)) {
1087-
size_t available_out = buffer_size;
1088-
uint8_t *next_out = buffer;
1089-
if (BrotliEncoderCompressStream(ctx->encoder,
1213+
while (ctx->available_in
1214+
|| BrotliEncoderHasMoreOutput(ctx->state.encoder)) {
1215+
ctx->available_out = buffer_size;
1216+
ctx->next_out = buffer;
1217+
if (BrotliEncoderCompressStream(ctx->state.encoder,
10901218
mode,
1091-
&available_in,
1092-
&next_in,
1093-
&available_out,
1094-
&next_out,
1219+
&ctx->available_in,
1220+
&ctx->next_in,
1221+
&ctx->available_out,
1222+
&ctx->next_out,
10951223
0)) {
1096-
buffer_used = (size_t)(next_out - buffer);
1224+
buffer_used = (size_t)(ctx->next_out - buffer);
10971225
if (buffer_used) {
10981226
smart_string_appendl(&out, buffer, buffer_used);
10991227
}
@@ -1107,17 +1235,17 @@ static ZEND_FUNCTION(brotli_compress_add)
11071235
}
11081236

11091237
if (mode == BROTLI_OPERATION_FINISH) {
1110-
while (!BrotliEncoderIsFinished(ctx->encoder)) {
1111-
size_t available_out = buffer_size;
1112-
uint8_t *next_out = buffer;
1113-
if (BrotliEncoderCompressStream(ctx->encoder,
1238+
while (!BrotliEncoderIsFinished(ctx->state.encoder)) {
1239+
ctx->available_out = buffer_size;
1240+
ctx->next_out = buffer;
1241+
if (BrotliEncoderCompressStream(ctx->state.encoder,
11141242
BROTLI_OPERATION_FINISH,
1115-
&available_in,
1116-
&next_in,
1117-
&available_out,
1118-
&next_out,
1243+
&ctx->available_in,
1244+
&ctx->next_in,
1245+
&ctx->available_out,
1246+
&ctx->next_out,
11191247
0)) {
1120-
buffer_used = (size_t)(next_out - buffer);
1248+
buffer_used = (size_t)(ctx->next_out - buffer);
11211249
if (buffer_used) {
11221250
smart_string_appendl(&out, buffer, buffer_used);
11231251
}

php_brotli.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ typedef struct _php_brotli_context {
4040
size_t available_out;
4141
uint8_t *next_out;
4242
uint8_t *output;
43+
zend_object std;
4344
} php_brotli_context;
4445

4546
ZEND_BEGIN_MODULE_GLOBALS(brotli)

0 commit comments

Comments
 (0)