1
1
#include <assert.h>
2
- #include <stdio.h>
3
2
#include <stddef.h>
3
+ #include <stdio.h>
4
4
#include <stdlib.h>
5
5
#include <string.h>
6
6
#define PY_SSIZE_T_CLEAN 1
18
18
#define PY_GET_TYPE (Obj ) ((Obj)->ob_type)
19
19
#endif
20
20
21
+ static const char kErrorAttr [] = "error" ;
22
+ #if PY_MAJOR_VERSION >= 3
23
+ static const char kModuleAttr [] = "_module" ;
24
+ #else
21
25
static PyObject * BrotliError ;
26
+ #endif
22
27
23
28
static const char kInvalidBufferError [] =
24
29
"brotli: data must be a C-contiguous buffer" ;
@@ -195,8 +200,33 @@ PyDoc_STRVAR(brotli_doc,
195
200
"Implementation module for the Brotli library." );
196
201
/* clang-format on */
197
202
198
- static void set_brotli_exception (const char * msg ) {
203
+ /*
204
+ Sets an exception with the given message.
205
+
206
+ `context` could be a module, a module type, or an instance of a module type.
207
+ */
208
+ static void set_brotli_exception (PyObject * context , const char * msg ) {
209
+ #if PY_MAJOR_VERSION >= 3
210
+ PyObject * error = NULL ;
211
+ assert (context != NULL );
212
+
213
+ if (PyModule_Check (context )) {
214
+ error = PyObject_GetAttrString (context , kErrorAttr );
215
+ } else {
216
+ PyObject * type =
217
+ PyType_Check (context ) ? context : (PyObject * )PY_GET_TYPE (context );
218
+ PyObject * module = PyObject_GetAttrString (type , kModuleAttr );
219
+ if (!module ) return ; /* AttributeError raised. */
220
+ error = PyObject_GetAttrString (module , kErrorAttr );
221
+ Py_DECREF (module );
222
+ }
223
+
224
+ if (error == NULL ) return ; /* AttributeError raised. */
225
+ PyErr_SetString (error , msg );
226
+ Py_DECREF (error );
227
+ #else
199
228
PyErr_SetString (BrotliError , msg );
229
+ #endif
200
230
}
201
231
202
232
/*
@@ -316,7 +346,7 @@ static PyObject* Buffer_Finish(Buffer* buffer) {
316
346
317
347
result = PyBytes_FromStringAndSize (NULL , len );
318
348
if (result == NULL ) {
319
- PyErr_Clear (); /* OOM exception will be raised by callers. */
349
+ PyErr_Clear (); /* OOM exception will be raised by callers. */
320
350
return NULL ;
321
351
}
322
352
if (len == 0 ) return result ;
@@ -354,7 +384,7 @@ static PyObject* brotli_Compressor_new(PyTypeObject* type, PyObject* args,
354
384
self -> processing = 0 ;
355
385
self -> enc = BrotliEncoderCreateInstance (0 , 0 , 0 );
356
386
if (self -> enc == NULL ) {
357
- set_brotli_exception (kCompressCreateError );
387
+ set_brotli_exception (( PyObject * ) type , kCompressCreateError );
358
388
PY_GET_TYPE (self )-> tp_free ((PyObject * )self );
359
389
return NULL ;
360
390
}
@@ -386,30 +416,30 @@ static int brotli_Compressor_init(PyBrotli_Compressor* self, PyObject* args,
386
416
if ((mode == 0 ) || (mode == 1 ) || (mode == 2 )) {
387
417
BrotliEncoderSetParameter (self -> enc , BROTLI_PARAM_MODE , (uint32_t )mode );
388
418
} else {
389
- set_brotli_exception (kInvalidModeError );
419
+ set_brotli_exception (( PyObject * ) self , kInvalidModeError );
390
420
self -> healthy = 0 ;
391
421
return -1 ;
392
422
}
393
423
if (quality <= 11 ) {
394
424
BrotliEncoderSetParameter (self -> enc , BROTLI_PARAM_QUALITY ,
395
425
(uint32_t )quality );
396
426
} else {
397
- set_brotli_exception (kInvalidQualityError );
427
+ set_brotli_exception (( PyObject * ) self , kInvalidQualityError );
398
428
self -> healthy = 0 ;
399
429
return -1 ;
400
430
}
401
431
if ((10 <= lgwin ) && (lgwin <= 24 )) {
402
432
BrotliEncoderSetParameter (self -> enc , BROTLI_PARAM_LGWIN , (uint32_t )lgwin );
403
433
} else {
404
- set_brotli_exception (kInvalidLgwinError );
434
+ set_brotli_exception (( PyObject * ) self , kInvalidLgwinError );
405
435
self -> healthy = 0 ;
406
436
return -1 ;
407
437
}
408
438
if ((lgblock == 0 ) || ((16 <= lgblock ) && (lgblock <= 24 ))) {
409
439
BrotliEncoderSetParameter (self -> enc , BROTLI_PARAM_LGBLOCK ,
410
440
(uint32_t )lgblock );
411
441
} else {
412
- set_brotli_exception (kInvalidLgblockError );
442
+ set_brotli_exception (( PyObject * ) self , kInvalidLgblockError );
413
443
self -> healthy = 0 ;
414
444
return -1 ;
415
445
}
@@ -470,8 +500,8 @@ static PyObject* compress_stream(PyBrotli_Compressor* self,
470
500
if (ok ) {
471
501
ret = Buffer_Finish (& buffer );
472
502
if (ret == NULL ) oom = 1 ;
473
- } else { /* Not ok */
474
- set_brotli_exception (kCompressError );
503
+ } else { /* Not ok */
504
+ set_brotli_exception (( PyObject * ) self , kCompressError );
475
505
}
476
506
477
507
error :
@@ -495,11 +525,11 @@ static PyObject* brotli_Compressor_process(PyBrotli_Compressor* self,
495
525
Py_buffer input ;
496
526
497
527
if (self -> healthy == 0 ) {
498
- set_brotli_exception (kCompressUnhealthyError );
528
+ set_brotli_exception (( PyObject * ) self , kCompressUnhealthyError );
499
529
return NULL ;
500
530
}
501
531
if (self -> processing != 0 ) {
502
- set_brotli_exception (kCompressConcurrentError );
532
+ set_brotli_exception (( PyObject * ) self , kCompressConcurrentError );
503
533
return NULL ;
504
534
}
505
535
@@ -522,11 +552,11 @@ static PyObject* brotli_Compressor_flush(PyBrotli_Compressor* self) {
522
552
PyObject * ret = NULL ;
523
553
524
554
if (self -> healthy == 0 ) {
525
- set_brotli_exception (kCompressUnhealthyError );
555
+ set_brotli_exception (( PyObject * ) self , kCompressUnhealthyError );
526
556
return NULL ;
527
557
}
528
558
if (self -> processing != 0 ) {
529
- set_brotli_exception (kCompressConcurrentError );
559
+ set_brotli_exception (( PyObject * ) self , kCompressConcurrentError );
530
560
return NULL ;
531
561
}
532
562
@@ -540,11 +570,11 @@ static PyObject* brotli_Compressor_finish(PyBrotli_Compressor* self) {
540
570
PyObject * ret = NULL ;
541
571
542
572
if (self -> healthy == 0 ) {
543
- set_brotli_exception (kCompressUnhealthyError );
573
+ set_brotli_exception (( PyObject * ) self , kCompressUnhealthyError );
544
574
return NULL ;
545
575
}
546
576
if (self -> processing != 0 ) {
547
- set_brotli_exception (kCompressConcurrentError );
577
+ set_brotli_exception (( PyObject * ) self , kCompressConcurrentError );
548
578
return NULL ;
549
579
}
550
580
@@ -578,7 +608,7 @@ static PyObject* brotli_Decompressor_new(PyTypeObject* type, PyObject* args,
578
608
579
609
self -> dec = BrotliDecoderCreateInstance (0 , 0 , 0 );
580
610
if (self -> dec == NULL ) {
581
- set_brotli_exception (kDecompressCreateError );
611
+ set_brotli_exception (( PyObject * ) type , kDecompressCreateError );
582
612
PY_GET_TYPE (self )-> tp_free ((PyObject * )self );
583
613
return NULL ;
584
614
}
@@ -633,11 +663,11 @@ static PyObject* brotli_Decompressor_process(PyBrotli_Decompressor* self,
633
663
int oom = 0 ;
634
664
635
665
if (self -> healthy == 0 ) {
636
- set_brotli_exception (kDecompressUnhealthyError );
666
+ set_brotli_exception (( PyObject * ) self , kDecompressUnhealthyError );
637
667
return NULL ;
638
668
}
639
669
if (self -> processing != 0 ) {
640
- set_brotli_exception (kDecompressConcurrentError );
670
+ set_brotli_exception (( PyObject * ) self , kDecompressConcurrentError );
641
671
return NULL ;
642
672
}
643
673
@@ -654,7 +684,7 @@ static PyObject* brotli_Decompressor_process(PyBrotli_Decompressor* self,
654
684
655
685
if (self -> unconsumed_data_length > 0 ) {
656
686
if (input .len > 0 ) {
657
- set_brotli_exception (kDecompressSinkError );
687
+ set_brotli_exception (( PyObject * ) self , kDecompressSinkError );
658
688
goto finally ;
659
689
}
660
690
next_in = self -> unconsumed_data ;
@@ -693,7 +723,7 @@ static PyObject* brotli_Decompressor_process(PyBrotli_Decompressor* self,
693
723
if (oom ) {
694
724
goto finally ;
695
725
} else if (result == BROTLI_DECODER_RESULT_ERROR ) {
696
- set_brotli_exception (kDecompressError );
726
+ set_brotli_exception (( PyObject * ) self , kDecompressError );
697
727
goto finally ;
698
728
}
699
729
@@ -712,7 +742,7 @@ static PyObject* brotli_Decompressor_process(PyBrotli_Decompressor* self,
712
742
713
743
if ((result == BROTLI_DECODER_RESULT_SUCCESS ) && (avail_in > 0 )) {
714
744
/* TODO(eustas): Add API to ignore / fetch unused "tail"? */
715
- set_brotli_exception (kDecompressError );
745
+ set_brotli_exception (( PyObject * ) self , kDecompressError );
716
746
goto finally ;
717
747
}
718
748
@@ -742,11 +772,11 @@ static PyObject* brotli_Decompressor_process(PyBrotli_Decompressor* self,
742
772
743
773
static PyObject * brotli_Decompressor_is_finished (PyBrotli_Decompressor * self ) {
744
774
if (self -> healthy == 0 ) {
745
- set_brotli_exception (kDecompressUnhealthyError );
775
+ set_brotli_exception (( PyObject * ) self , kDecompressUnhealthyError );
746
776
return NULL ;
747
777
}
748
778
if (self -> processing != 0 ) {
749
- set_brotli_exception (kDecompressConcurrentError );
779
+ set_brotli_exception (( PyObject * ) self , kDecompressConcurrentError );
750
780
return NULL ;
751
781
}
752
782
if (BrotliDecoderIsFinished (self -> dec )) {
@@ -759,11 +789,11 @@ static PyObject* brotli_Decompressor_is_finished(PyBrotli_Decompressor* self) {
759
789
static PyObject * brotli_Decompressor_can_accept_more_data (
760
790
PyBrotli_Decompressor * self ) {
761
791
if (self -> healthy == 0 ) {
762
- set_brotli_exception (kDecompressUnhealthyError );
792
+ set_brotli_exception (( PyObject * ) self , kDecompressUnhealthyError );
763
793
return NULL ;
764
794
}
765
795
if (self -> processing != 0 ) {
766
- set_brotli_exception (kDecompressConcurrentError );
796
+ set_brotli_exception (( PyObject * ) self , kDecompressConcurrentError );
767
797
return NULL ;
768
798
}
769
799
if (self -> unconsumed_data_length > 0 ) {
@@ -832,7 +862,7 @@ static PyObject* brotli_decompress(PyObject* self, PyObject* args,
832
862
if (oom ) {
833
863
goto finally ;
834
864
} else if (result != BROTLI_DECODER_RESULT_SUCCESS || available_in > 0 ) {
835
- set_brotli_exception (kDecompressError );
865
+ set_brotli_exception (( PyObject * ) self , kDecompressError );
836
866
goto finally ;
837
867
}
838
868
@@ -849,6 +879,8 @@ static PyObject* brotli_decompress(PyObject* self, PyObject* args,
849
879
850
880
/* Module definition */
851
881
882
+ static int init_brotli_mod (PyObject * m );
883
+
852
884
static PyMethodDef brotli_methods [] = {
853
885
{"decompress" , (PyCFunction )brotli_decompress , METH_VARARGS | METH_KEYWORDS ,
854
886
brotli_decompress__doc__ },
@@ -877,16 +909,29 @@ static PyMethodDef brotli_Decompressor_methods[] = {
877
909
878
910
#if PY_MAJOR_VERSION >= 3
879
911
912
+ #if PY_MINOR_VERSION >= 5
913
+ static PyModuleDef_Slot brotli_mod_slots [] = {
914
+ {Py_mod_exec , init_brotli_mod },
915
+ #if PY_MINOR_VERSION >= 12
916
+ {Py_mod_multiple_interpreters , Py_MOD_PER_INTERPRETER_GIL_SUPPORTED },
917
+ #endif
918
+ {0 , NULL }};
919
+ #endif
920
+
880
921
static struct PyModuleDef brotli_module = {
881
922
PyModuleDef_HEAD_INIT ,
882
923
"_brotli" , /* m_name */
883
924
brotli_doc , /* m_doc */
884
925
0 , /* m_size */
885
926
brotli_methods , /* m_methods */
886
- NULL , /* m_reload */
887
- NULL , /* m_traverse */
888
- NULL , /* m_clear */
889
- NULL /* m_free */
927
+ #if PY_MINOR_VERSION >= 5
928
+ brotli_mod_slots , /* m_slots */
929
+ #else
930
+ NULL , /* m_reload */
931
+ #endif
932
+ NULL , /* m_traverse */
933
+ NULL , /* m_clear */
934
+ NULL /* m_free */
890
935
};
891
936
892
937
static PyType_Slot brotli_Compressor_slots [] = {
@@ -915,6 +960,8 @@ static PyType_Spec brotli_Decompressor_spec = {
915
960
"brotli.Decompressor" , sizeof (PyBrotli_Decompressor ), 0 ,
916
961
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , brotli_Decompressor_slots };
917
962
963
+ PyMODINIT_FUNC PyInit__brotli (void ) { return PyModuleDef_Init (& brotli_module ); }
964
+
918
965
#else
919
966
920
967
static PyTypeObject brotli_CompressorType = {
@@ -999,18 +1046,11 @@ static PyTypeObject brotli_DecompressorType = {
999
1046
brotli_Decompressor_new , /* tp_new */
1000
1047
};
1001
1048
1002
- #endif
1049
+ PyMODINIT_FUNC init_brotli (void ) {
1050
+ PyObject * m = Py_InitModule3 ("_brotli" , brotli_methods , brotli_doc );
1051
+ (void )init_brotli_mod (m );
1052
+ }
1003
1053
1004
- #if PY_MAJOR_VERSION >= 3
1005
- #define INIT_BROTLI PyInit__brotli
1006
- #define CREATE_BROTLI PyModule_Create(&brotli_module)
1007
- #define RETURN_BROTLI return m
1008
- #define RETURN_NULL return NULL
1009
- #else
1010
- #define INIT_BROTLI init_brotli
1011
- #define CREATE_BROTLI Py_InitModule3("_brotli", brotli_methods, brotli_doc)
1012
- #define RETURN_BROTLI return
1013
- #define RETURN_NULL return
1014
1054
#endif
1015
1055
1016
1056
/* Emulates PyModule_AddObject */
@@ -1027,8 +1067,7 @@ static int RegisterObject(PyObject* mod, const char* name, PyObject* value) {
1027
1067
#endif
1028
1068
}
1029
1069
1030
- PyMODINIT_FUNC INIT_BROTLI (void ) {
1031
- PyObject * m = CREATE_BROTLI ;
1070
+ static int init_brotli_mod (PyObject * m ) {
1032
1071
PyObject * error_type = NULL ;
1033
1072
PyObject * compressor_type = NULL ;
1034
1073
PyObject * decompressor_type = NULL ;
@@ -1039,27 +1078,35 @@ PyMODINIT_FUNC INIT_BROTLI(void) {
1039
1078
brotli_error_doc , NULL , NULL );
1040
1079
if (error_type == NULL ) goto error ;
1041
1080
1042
- if (RegisterObject (m , "error" , error_type ) < 0 ) goto error ;
1081
+ if (RegisterObject (m , kErrorAttr , error_type ) < 0 ) goto error ;
1082
+ #if PY_MAJOR_VERSION < 3
1043
1083
/* Assumption: pointer is used only while module is alive and well. */
1044
1084
BrotliError = error_type ;
1085
+ #endif
1045
1086
error_type = NULL ;
1046
1087
1047
1088
#if PY_MAJOR_VERSION >= 3
1048
1089
compressor_type = PyType_FromSpec (& brotli_Compressor_spec );
1049
1090
decompressor_type = PyType_FromSpec (& brotli_Decompressor_spec );
1050
1091
#else
1051
- compressor_type = & brotli_CompressorType ;
1092
+ compressor_type = ( PyObject * ) & brotli_CompressorType ;
1052
1093
Py_INCREF (compressor_type );
1053
- decompressor_type = & brotli_DecompressorType ;
1094
+ decompressor_type = ( PyObject * ) & brotli_DecompressorType ;
1054
1095
Py_INCREF (decompressor_type );
1055
1096
#endif
1056
1097
if (compressor_type == NULL ) goto error ;
1057
1098
if (PyType_Ready ((PyTypeObject * )compressor_type ) < 0 ) goto error ;
1099
+ #if PY_MAJOR_VERSION >= 3
1100
+ if (PyObject_SetAttrString (compressor_type , kModuleAttr , m ) < 0 ) goto error ;
1101
+ #endif
1058
1102
if (RegisterObject (m , "Compressor" , compressor_type ) < 0 ) goto error ;
1059
1103
compressor_type = NULL ;
1060
1104
1061
1105
if (decompressor_type == NULL ) goto error ;
1062
1106
if (PyType_Ready ((PyTypeObject * )decompressor_type ) < 0 ) goto error ;
1107
+ #if PY_MAJOR_VERSION >= 3
1108
+ if (PyObject_SetAttrString (decompressor_type , kModuleAttr , m ) < 0 ) goto error ;
1109
+ #endif
1063
1110
if (RegisterObject (m , "Decompressor" , decompressor_type ) < 0 ) goto error ;
1064
1111
decompressor_type = NULL ;
1065
1112
@@ -1073,7 +1120,7 @@ PyMODINIT_FUNC INIT_BROTLI(void) {
1073
1120
(decoderVersion >> 12 ) & 0xFFF , decoderVersion & 0xFFF );
1074
1121
PyModule_AddStringConstant (m , "__version__" , version );
1075
1122
1076
- RETURN_BROTLI ;
1123
+ return 0 ;
1077
1124
1078
1125
error :
1079
1126
if (m != NULL ) {
@@ -1092,5 +1139,5 @@ PyMODINIT_FUNC INIT_BROTLI(void) {
1092
1139
Py_DECREF (decompressor_type );
1093
1140
decompressor_type = NULL ;
1094
1141
}
1095
- RETURN_NULL ;
1142
+ return -1 ;
1096
1143
}
0 commit comments