12
12
#include <ext/apcu/apc_serializer.h>
13
13
#include <zend_smart_str.h>
14
14
#endif
15
+ #include <Zend/zend_interfaces.h>
15
16
#include "php_brotli.h"
16
17
17
18
int le_state ;
@@ -859,6 +860,93 @@ php_stream_wrapper php_stream_brotli_wrapper = {
859
860
0 /* is_url */
860
861
};
861
862
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
+
862
950
ZEND_MINIT_FUNCTION (brotli )
863
951
{
864
952
ZEND_INIT_MODULE_GLOBALS (brotli , php_brotli_init_globals , NULL );
@@ -894,6 +982,34 @@ ZEND_MINIT_FUNCTION(brotli)
894
982
php_output_handler_conflict_register (ZEND_STRL (PHP_BROTLI_OUTPUT_HANDLER ),
895
983
php_brotli_output_conflict );
896
984
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
+
897
1013
REGISTER_INI_ENTRIES ();
898
1014
899
1015
php_register_url_stream_wrapper (STREAM_NAME ,
@@ -1032,45 +1148,56 @@ static ZEND_FUNCTION(brotli_compress_init)
1032
1148
{
1033
1149
zend_long quality = BROTLI_DEFAULT_QUALITY ;
1034
1150
zend_long mode = BROTLI_MODE_GENERIC ;
1035
- php_brotli_state_context * ctx ;
1036
1151
1037
1152
ZEND_PARSE_PARAMETERS_START (0 , 2 )
1038
1153
Z_PARAM_OPTIONAL
1039
1154
Z_PARAM_LONG (quality )
1040
1155
Z_PARAM_LONG (mode )
1041
1156
ZEND_PARSE_PARAMETERS_END ();
1042
1157
1043
- ctx = php_brotli_state_init ( );
1158
+ PHP_BROTLI_CONTEXT_OBJ_INIT_OF_CLASS ( php_brotli_compress_context_ce );
1044
1159
1045
- if (php_brotli_encoder_create (& ctx -> encoder ,
1160
+ if (php_brotli_encoder_create (& ctx -> state . encoder ,
1046
1161
quality , 0 , mode ) != SUCCESS ) {
1162
+ zval_ptr_dtor (return_value );
1047
1163
php_error_docref (NULL , E_WARNING ,
1048
1164
"Brotli incremental compress init failed" );
1049
1165
RETURN_FALSE ;
1050
1166
}
1051
-
1052
- RETURN_RES (zend_register_resource (ctx , le_state ));
1053
1167
}
1054
1168
1055
1169
static ZEND_FUNCTION (brotli_compress_add )
1056
1170
{
1057
1171
zval * res ;
1058
- php_brotli_state_context * ctx ;
1172
+ php_brotli_context * ctx ;
1059
1173
size_t buffer_size , buffer_used ;
1060
1174
zend_long mode = BROTLI_OPERATION_FLUSH ;
1175
+ #if PHP_VERSION_ID >= 80000
1176
+ zend_object * obj ;
1177
+ #else
1178
+ zval * obj ;
1179
+ #endif
1061
1180
char * in_buf ;
1062
1181
size_t in_size ;
1063
1182
smart_string out = {0 };
1064
1183
1065
1184
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
1067
1190
Z_PARAM_STRING (in_buf , in_size )
1068
1191
Z_PARAM_OPTIONAL
1069
1192
Z_PARAM_LONG (mode )
1070
1193
ZEND_PARSE_PARAMETERS_END ();
1071
1194
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 ) {
1074
1201
php_error_docref (NULL , E_WARNING ,
1075
1202
"Brotli incremental compress resource failed" );
1076
1203
RETURN_FALSE ;
@@ -1080,20 +1207,21 @@ static ZEND_FUNCTION(brotli_compress_add)
1080
1207
buffer_size = (buffer_size < 64 ) ? 64 : buffer_size ;
1081
1208
uint8_t * buffer = (uint8_t * )emalloc (buffer_size );
1082
1209
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 ;
1085
1212
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 ,
1090
1218
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 ,
1095
1223
0 )) {
1096
- buffer_used = (size_t )(next_out - buffer );
1224
+ buffer_used = (size_t )(ctx -> next_out - buffer );
1097
1225
if (buffer_used ) {
1098
1226
smart_string_appendl (& out , buffer , buffer_used );
1099
1227
}
@@ -1107,17 +1235,17 @@ static ZEND_FUNCTION(brotli_compress_add)
1107
1235
}
1108
1236
1109
1237
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 ,
1114
1242
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 ,
1119
1247
0 )) {
1120
- buffer_used = (size_t )(next_out - buffer );
1248
+ buffer_used = (size_t )(ctx -> next_out - buffer );
1121
1249
if (buffer_used ) {
1122
1250
smart_string_appendl (& out , buffer , buffer_used );
1123
1251
}
0 commit comments