@@ -2848,55 +2848,63 @@ static PyObject* elements_to_dict(PyObject* self, const char* string,
28482848 return result ;
28492849}
28502850
2851+ static int _get_buffer (PyObject * exporter , Py_buffer * view ) {
2852+ if (PyObject_GetBuffer (exporter , view , PyBUF_SIMPLE ) == -1 ) {
2853+ return 0 ;
2854+ }
2855+ if (!PyBuffer_IsContiguous (view , 'C' )) {
2856+ PyErr_SetString (PyExc_ValueError ,
2857+ "must be a contiguous buffer" );
2858+ goto fail ;
2859+ }
2860+ if (!view -> buf || view -> len < 0 ) {
2861+ PyErr_SetString (PyExc_ValueError , "invalid buffer" );
2862+ goto fail ;
2863+ }
2864+ if (view -> itemsize != 1 ) {
2865+ PyErr_SetString (PyExc_ValueError ,
2866+ "buffer data must be ascii or utf8" );
2867+ goto fail ;
2868+ }
2869+ return 1 ;
2870+ fail :
2871+ PyBuffer_Release (view );
2872+ return 0 ;
2873+ }
2874+
28512875static PyObject * _cbson_bson_to_dict (PyObject * self , PyObject * args ) {
28522876 int32_t size ;
28532877 Py_ssize_t total_size ;
28542878 const char * string ;
28552879 PyObject * bson ;
28562880 codec_options_t options ;
2857- PyObject * result ;
2881+ PyObject * result = NULL ;
28582882 PyObject * options_obj ;
2883+ Py_buffer view ;
28592884
28602885 if (! (PyArg_ParseTuple (args , "OO" , & bson , & options_obj ) &&
28612886 convert_codec_options (options_obj , & options ))) {
2862- return NULL ;
2887+ return result ;
28632888 }
28642889
2865- #if PY_MAJOR_VERSION >= 3
2866- if (!PyBytes_Check (bson )) {
2867- PyErr_SetString (PyExc_TypeError , "argument to _bson_to_dict must be a bytes object" );
2868- #else
2869- if (!PyString_Check (bson )) {
2870- PyErr_SetString (PyExc_TypeError , "argument to _bson_to_dict must be a string" );
2871- #endif
2890+ if (!_get_buffer (bson , & view )) {
28722891 destroy_codec_options (& options );
2873- return NULL ;
2892+ return result ;
28742893 }
2875- #if PY_MAJOR_VERSION >= 3
2876- total_size = PyBytes_Size (bson );
2877- #else
2878- total_size = PyString_Size (bson );
2879- #endif
2894+
2895+ total_size = view .len ;
2896+
28802897 if (total_size < BSON_MIN_SIZE ) {
28812898 PyObject * InvalidBSON = _error ("InvalidBSON" );
28822899 if (InvalidBSON ) {
28832900 PyErr_SetString (InvalidBSON ,
28842901 "not enough data for a BSON document" );
28852902 Py_DECREF (InvalidBSON );
28862903 }
2887- destroy_codec_options (& options );
2888- return NULL ;
2904+ goto done ;;
28892905 }
28902906
2891- #if PY_MAJOR_VERSION >= 3
2892- string = PyBytes_AsString (bson );
2893- #else
2894- string = PyString_AsString (bson );
2895- #endif
2896- if (!string ) {
2897- destroy_codec_options (& options );
2898- return NULL ;
2899- }
2907+ string = (char * )view .buf ;
29002908
29012909 memcpy (& size , string , 4 );
29022910 size = (int32_t )BSON_UINT32_FROM_LE (size );
@@ -2906,8 +2914,7 @@ static PyObject* _cbson_bson_to_dict(PyObject* self, PyObject* args) {
29062914 PyErr_SetString (InvalidBSON , "invalid message size" );
29072915 Py_DECREF (InvalidBSON );
29082916 }
2909- destroy_codec_options (& options );
2910- return NULL ;
2917+ goto done ;
29112918 }
29122919
29132920 if (total_size < size || total_size > BSON_MAX_SIZE ) {
@@ -2916,8 +2923,7 @@ static PyObject* _cbson_bson_to_dict(PyObject* self, PyObject* args) {
29162923 PyErr_SetString (InvalidBSON , "objsize too large" );
29172924 Py_DECREF (InvalidBSON );
29182925 }
2919- destroy_codec_options (& options );
2920- return NULL ;
2926+ goto done ;
29212927 }
29222928
29232929 if (size != total_size || string [size - 1 ]) {
@@ -2926,18 +2932,20 @@ static PyObject* _cbson_bson_to_dict(PyObject* self, PyObject* args) {
29262932 PyErr_SetString (InvalidBSON , "bad eoo" );
29272933 Py_DECREF (InvalidBSON );
29282934 }
2929- destroy_codec_options (& options );
2930- return NULL ;
2935+ goto done ;
29312936 }
29322937
29332938 /* No need to decode fields if using RawBSONDocument */
29342939 if (options .is_raw_bson ) {
2935- return PyObject_CallFunction (
2940+ result = PyObject_CallFunction (
29362941 options .document_class , BYTES_FORMAT_STRING "O" , string , size ,
29372942 options_obj );
29382943 }
2939-
2940- result = elements_to_dict (self , string + 4 , (unsigned )size - 5 , & options );
2944+ else {
2945+ result = elements_to_dict (self , string + 4 , (unsigned )size - 5 , & options );
2946+ }
2947+ done :
2948+ PyBuffer_Release (& view );
29412949 destroy_codec_options (& options );
29422950 return result ;
29432951}
@@ -2948,9 +2956,10 @@ static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) {
29482956 const char * string ;
29492957 PyObject * bson ;
29502958 PyObject * dict ;
2951- PyObject * result ;
2959+ PyObject * result = NULL ;
29522960 codec_options_t options ;
29532961 PyObject * options_obj ;
2962+ Py_buffer view ;
29542963
29552964 if (!PyArg_ParseTuple (args , "O|O" , & bson , & options_obj )) {
29562965 return NULL ;
@@ -2963,31 +2972,15 @@ static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) {
29632972 return NULL ;
29642973 }
29652974
2966- #if PY_MAJOR_VERSION >= 3
2967- if (!PyBytes_Check (bson )) {
2968- PyErr_SetString (PyExc_TypeError , "argument to decode_all must be a bytes object" );
2969- #else
2970- if (!PyString_Check (bson )) {
2971- PyErr_SetString (PyExc_TypeError , "argument to decode_all must be a string" );
2972- #endif
2973- destroy_codec_options (& options );
2974- return NULL ;
2975- }
2976- #if PY_MAJOR_VERSION >= 3
2977- total_size = PyBytes_Size (bson );
2978- string = PyBytes_AsString (bson );
2979- #else
2980- total_size = PyString_Size (bson );
2981- string = PyString_AsString (bson );
2982- #endif
2983- if (!string ) {
2975+ if (!_get_buffer (bson , & view )) {
29842976 destroy_codec_options (& options );
29852977 return NULL ;
29862978 }
2979+ total_size = view .len ;
2980+ string = (char * )view .buf ;
29872981
29882982 if (!(result = PyList_New (0 ))) {
2989- destroy_codec_options (& options );
2990- return NULL ;
2983+ goto fail ;
29912984 }
29922985
29932986 while (total_size > 0 ) {
@@ -2998,9 +2991,8 @@ static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) {
29982991 "not enough data for a BSON document" );
29992992 Py_DECREF (InvalidBSON );
30002993 }
3001- destroy_codec_options (& options );
30022994 Py_DECREF (result );
3003- return NULL ;
2995+ goto fail ;
30042996 }
30052997
30062998 memcpy (& size , string , 4 );
@@ -3011,9 +3003,8 @@ static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) {
30113003 PyErr_SetString (InvalidBSON , "invalid message size" );
30123004 Py_DECREF (InvalidBSON );
30133005 }
3014- destroy_codec_options (& options );
30153006 Py_DECREF (result );
3016- return NULL ;
3007+ goto fail ;
30173008 }
30183009
30193010 if (total_size < size ) {
@@ -3022,9 +3013,8 @@ static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) {
30223013 PyErr_SetString (InvalidBSON , "objsize too large" );
30233014 Py_DECREF (InvalidBSON );
30243015 }
3025- destroy_codec_options (& options );
30263016 Py_DECREF (result );
3027- return NULL ;
3017+ goto fail ;
30283018 }
30293019
30303020 if (string [size - 1 ]) {
@@ -3033,9 +3023,8 @@ static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) {
30333023 PyErr_SetString (InvalidBSON , "bad eoo" );
30343024 Py_DECREF (InvalidBSON );
30353025 }
3036- destroy_codec_options (& options );
30373026 Py_DECREF (result );
3038- return NULL ;
3027+ goto fail ;
30393028 }
30403029
30413030 /* No need to decode fields if using RawBSONDocument. */
@@ -3048,20 +3037,22 @@ static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) {
30483037 }
30493038 if (!dict ) {
30503039 Py_DECREF (result );
3051- destroy_codec_options (& options );
3052- return NULL ;
3040+ goto fail ;
30533041 }
30543042 if (PyList_Append (result , dict ) < 0 ) {
30553043 Py_DECREF (dict );
30563044 Py_DECREF (result );
3057- destroy_codec_options (& options );
3058- return NULL ;
3045+ goto fail ;
30593046 }
30603047 Py_DECREF (dict );
30613048 string += size ;
30623049 total_size -= size ;
30633050 }
3064-
3051+ goto done ;
3052+ fail :
3053+ result = NULL ;
3054+ done :
3055+ PyBuffer_Release (& view );
30653056 destroy_codec_options (& options );
30663057 return result ;
30673058}
0 commit comments