LCOV - code coverage report
Current view: top level - Python - codecs.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 105 778 13.5 %
Date: 2023-03-20 08:15:36 Functions: 12 50 24.0 %
Branches: 47 448 10.5 %

           Branch data     Line data    Source code
       1                 :            : /* ------------------------------------------------------------------------
       2                 :            : 
       3                 :            :    Python Codec Registry and support functions
       4                 :            : 
       5                 :            : Written by Marc-Andre Lemburg (mal@lemburg.com).
       6                 :            : 
       7                 :            : Copyright (c) Corporation for National Research Initiatives.
       8                 :            : 
       9                 :            :    ------------------------------------------------------------------------ */
      10                 :            : 
      11                 :            : #include "Python.h"
      12                 :            : #include "pycore_call.h"          // _PyObject_CallNoArgs()
      13                 :            : #include "pycore_interp.h"        // PyInterpreterState.codec_search_path
      14                 :            : #include "pycore_pystate.h"       // _PyInterpreterState_GET()
      15                 :            : #include "pycore_ucnhash.h"       // _PyUnicode_Name_CAPI
      16                 :            : #include <ctype.h>
      17                 :            : 
      18                 :            : const char *Py_hexdigits = "0123456789abcdef";
      19                 :            : 
      20                 :            : /* --- Codec Registry ----------------------------------------------------- */
      21                 :            : 
      22                 :            : /* Import the standard encodings package which will register the first
      23                 :            :    codec search function.
      24                 :            : 
      25                 :            :    This is done in a lazy way so that the Unicode implementation does
      26                 :            :    not downgrade startup time of scripts not needing it.
      27                 :            : 
      28                 :            :    ImportErrors are silently ignored by this function. Only one try is
      29                 :            :    made.
      30                 :            : 
      31                 :            : */
      32                 :            : 
      33                 :            : static int _PyCodecRegistry_Init(void); /* Forward */
      34                 :            : 
      35                 :         25 : int PyCodec_Register(PyObject *search_function)
      36                 :            : {
      37                 :         25 :     PyInterpreterState *interp = _PyInterpreterState_GET();
      38   [ -  +  -  - ]:         25 :     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
      39                 :          0 :         goto onError;
      40         [ -  + ]:         25 :     if (search_function == NULL) {
      41                 :          0 :         PyErr_BadArgument();
      42                 :          0 :         goto onError;
      43                 :            :     }
      44         [ -  + ]:         25 :     if (!PyCallable_Check(search_function)) {
      45                 :          0 :         PyErr_SetString(PyExc_TypeError, "argument must be callable");
      46                 :          0 :         goto onError;
      47                 :            :     }
      48                 :         25 :     return PyList_Append(interp->codec_search_path, search_function);
      49                 :            : 
      50                 :          0 :  onError:
      51                 :          0 :     return -1;
      52                 :            : }
      53                 :            : 
      54                 :            : int
      55                 :          0 : PyCodec_Unregister(PyObject *search_function)
      56                 :            : {
      57                 :          0 :     PyInterpreterState *interp = PyInterpreterState_Get();
      58                 :          0 :     PyObject *codec_search_path = interp->codec_search_path;
      59                 :            :     /* Do nothing if codec_search_path is not created yet or was cleared. */
      60         [ #  # ]:          0 :     if (codec_search_path == NULL) {
      61                 :          0 :         return 0;
      62                 :            :     }
      63                 :            : 
      64                 :            :     assert(PyList_CheckExact(codec_search_path));
      65                 :          0 :     Py_ssize_t n = PyList_GET_SIZE(codec_search_path);
      66         [ #  # ]:          0 :     for (Py_ssize_t i = 0; i < n; i++) {
      67                 :          0 :         PyObject *item = PyList_GET_ITEM(codec_search_path, i);
      68         [ #  # ]:          0 :         if (item == search_function) {
      69         [ #  # ]:          0 :             if (interp->codec_search_cache != NULL) {
      70                 :            :                 assert(PyDict_CheckExact(interp->codec_search_cache));
      71                 :          0 :                 PyDict_Clear(interp->codec_search_cache);
      72                 :            :             }
      73                 :          0 :             return PyList_SetSlice(codec_search_path, i, i+1, NULL);
      74                 :            :         }
      75                 :            :     }
      76                 :          0 :     return 0;
      77                 :            : }
      78                 :            : 
      79                 :            : extern int _Py_normalize_encoding(const char *, char *, size_t);
      80                 :            : 
      81                 :            : /* Convert a string to a normalized Python string(decoded from UTF-8): all characters are
      82                 :            :    converted to lower case, spaces and hyphens are replaced with underscores. */
      83                 :            : 
      84                 :            : static
      85                 :        828 : PyObject *normalizestring(const char *string)
      86                 :            : {
      87                 :        828 :     size_t len = strlen(string);
      88                 :            :     char *encoding;
      89                 :            :     PyObject *v;
      90                 :            : 
      91         [ -  + ]:        828 :     if (len > PY_SSIZE_T_MAX) {
      92                 :          0 :         PyErr_SetString(PyExc_OverflowError, "string is too large");
      93                 :          0 :         return NULL;
      94                 :            :     }
      95                 :            : 
      96                 :        828 :     encoding = PyMem_Malloc(len + 1);
      97         [ -  + ]:        828 :     if (encoding == NULL)
      98                 :          0 :         return PyErr_NoMemory();
      99                 :            : 
     100         [ -  + ]:        828 :     if (!_Py_normalize_encoding(string, encoding, len + 1))
     101                 :            :     {
     102                 :          0 :         PyErr_SetString(PyExc_RuntimeError, "_Py_normalize_encoding() failed");
     103                 :          0 :         PyMem_Free(encoding);
     104                 :          0 :         return NULL;
     105                 :            :     }
     106                 :            : 
     107                 :        828 :     v = PyUnicode_FromString(encoding);
     108                 :        828 :     PyMem_Free(encoding);
     109                 :        828 :     return v;
     110                 :            : }
     111                 :            : 
     112                 :            : /* Lookup the given encoding and return a tuple providing the codec
     113                 :            :    facilities.
     114                 :            : 
     115                 :            :    The encoding string is looked up converted to all lower-case
     116                 :            :    characters. This makes encodings looked up through this mechanism
     117                 :            :    effectively case-insensitive.
     118                 :            : 
     119                 :            :    If no codec is found, a LookupError is set and NULL returned.
     120                 :            : 
     121                 :            :    As side effect, this tries to load the encodings package, if not
     122                 :            :    yet done. This is part of the lazy load strategy for the encodings
     123                 :            :    package.
     124                 :            : 
     125                 :            : */
     126                 :            : 
     127                 :        828 : PyObject *_PyCodec_Lookup(const char *encoding)
     128                 :            : {
     129         [ -  + ]:        828 :     if (encoding == NULL) {
     130                 :          0 :         PyErr_BadArgument();
     131                 :          0 :         return NULL;
     132                 :            :     }
     133                 :            : 
     134                 :        828 :     PyInterpreterState *interp = _PyInterpreterState_GET();
     135   [ +  +  -  + ]:        828 :     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) {
     136                 :          0 :         return NULL;
     137                 :            :     }
     138                 :            : 
     139                 :            :     /* Convert the encoding to a normalized Python string: all
     140                 :            :        characters are converted to lower case, spaces and hyphens are
     141                 :            :        replaced with underscores. */
     142                 :        828 :     PyObject *v = normalizestring(encoding);
     143         [ -  + ]:        828 :     if (v == NULL) {
     144                 :          0 :         return NULL;
     145                 :            :     }
     146                 :        828 :     PyUnicode_InternInPlace(&v);
     147                 :            : 
     148                 :            :     /* First, try to lookup the name in the registry dictionary */
     149                 :        828 :     PyObject *result = PyDict_GetItemWithError(interp->codec_search_cache, v);
     150         [ +  + ]:        828 :     if (result != NULL) {
     151                 :        779 :         Py_INCREF(result);
     152                 :        779 :         Py_DECREF(v);
     153                 :        779 :         return result;
     154                 :            :     }
     155         [ -  + ]:         49 :     else if (PyErr_Occurred()) {
     156                 :          0 :         goto onError;
     157                 :            :     }
     158                 :            : 
     159                 :            :     /* Next, scan the search functions in order of registration */
     160                 :         49 :     const Py_ssize_t len = PyList_Size(interp->codec_search_path);
     161         [ -  + ]:         49 :     if (len < 0)
     162                 :          0 :         goto onError;
     163         [ -  + ]:         49 :     if (len == 0) {
     164                 :          0 :         PyErr_SetString(PyExc_LookupError,
     165                 :            :                         "no codec search functions registered: "
     166                 :            :                         "can't find encoding");
     167                 :          0 :         goto onError;
     168                 :            :     }
     169                 :            : 
     170                 :            :     Py_ssize_t i;
     171         [ +  - ]:         49 :     for (i = 0; i < len; i++) {
     172                 :            :         PyObject *func;
     173                 :            : 
     174                 :         49 :         func = PyList_GetItem(interp->codec_search_path, i);
     175         [ -  + ]:         49 :         if (func == NULL)
     176                 :          0 :             goto onError;
     177                 :         49 :         result = PyObject_CallOneArg(func, v);
     178         [ -  + ]:         49 :         if (result == NULL)
     179                 :          0 :             goto onError;
     180         [ -  + ]:         49 :         if (result == Py_None) {
     181                 :          0 :             Py_DECREF(result);
     182                 :          0 :             continue;
     183                 :            :         }
     184   [ +  -  -  + ]:         49 :         if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 4) {
     185                 :          0 :             PyErr_SetString(PyExc_TypeError,
     186                 :            :                             "codec search functions must return 4-tuples");
     187                 :          0 :             Py_DECREF(result);
     188                 :          0 :             goto onError;
     189                 :            :         }
     190                 :         49 :         break;
     191                 :            :     }
     192         [ -  + ]:         49 :     if (i == len) {
     193                 :            :         /* XXX Perhaps we should cache misses too ? */
     194                 :          0 :         PyErr_Format(PyExc_LookupError,
     195                 :            :                      "unknown encoding: %s", encoding);
     196                 :          0 :         goto onError;
     197                 :            :     }
     198                 :            : 
     199                 :            :     /* Cache and return the result */
     200         [ -  + ]:         49 :     if (PyDict_SetItem(interp->codec_search_cache, v, result) < 0) {
     201                 :          0 :         Py_DECREF(result);
     202                 :          0 :         goto onError;
     203                 :            :     }
     204                 :         49 :     Py_DECREF(v);
     205                 :         49 :     return result;
     206                 :            : 
     207                 :          0 :  onError:
     208                 :          0 :     Py_DECREF(v);
     209                 :          0 :     return NULL;
     210                 :            : }
     211                 :            : 
     212                 :            : /* Codec registry encoding check API. */
     213                 :            : 
     214                 :          0 : int PyCodec_KnownEncoding(const char *encoding)
     215                 :            : {
     216                 :            :     PyObject *codecs;
     217                 :            : 
     218                 :          0 :     codecs = _PyCodec_Lookup(encoding);
     219         [ #  # ]:          0 :     if (!codecs) {
     220                 :          0 :         PyErr_Clear();
     221                 :          0 :         return 0;
     222                 :            :     }
     223                 :            :     else {
     224                 :          0 :         Py_DECREF(codecs);
     225                 :          0 :         return 1;
     226                 :            :     }
     227                 :            : }
     228                 :            : 
     229                 :            : static
     230                 :          0 : PyObject *args_tuple(PyObject *object,
     231                 :            :                      const char *errors)
     232                 :            : {
     233                 :            :     PyObject *args;
     234                 :            : 
     235         [ #  # ]:          0 :     args = PyTuple_New(1 + (errors != NULL));
     236         [ #  # ]:          0 :     if (args == NULL)
     237                 :          0 :         return NULL;
     238                 :          0 :     PyTuple_SET_ITEM(args, 0, Py_NewRef(object));
     239         [ #  # ]:          0 :     if (errors) {
     240                 :            :         PyObject *v;
     241                 :            : 
     242                 :          0 :         v = PyUnicode_FromString(errors);
     243         [ #  # ]:          0 :         if (v == NULL) {
     244                 :          0 :             Py_DECREF(args);
     245                 :          0 :             return NULL;
     246                 :            :         }
     247                 :          0 :         PyTuple_SET_ITEM(args, 1, v);
     248                 :            :     }
     249                 :          0 :     return args;
     250                 :            : }
     251                 :            : 
     252                 :            : /* Helper function to get a codec item */
     253                 :            : 
     254                 :            : static
     255                 :          0 : PyObject *codec_getitem(const char *encoding, int index)
     256                 :            : {
     257                 :            :     PyObject *codecs;
     258                 :            :     PyObject *v;
     259                 :            : 
     260                 :          0 :     codecs = _PyCodec_Lookup(encoding);
     261         [ #  # ]:          0 :     if (codecs == NULL)
     262                 :          0 :         return NULL;
     263                 :          0 :     v = PyTuple_GET_ITEM(codecs, index);
     264                 :          0 :     Py_DECREF(codecs);
     265                 :          0 :     return Py_NewRef(v);
     266                 :            : }
     267                 :            : 
     268                 :            : /* Helper functions to create an incremental codec. */
     269                 :            : static
     270                 :        753 : PyObject *codec_makeincrementalcodec(PyObject *codec_info,
     271                 :            :                                      const char *errors,
     272                 :            :                                      const char *attrname)
     273                 :            : {
     274                 :            :     PyObject *ret, *inccodec;
     275                 :            : 
     276                 :        753 :     inccodec = PyObject_GetAttrString(codec_info, attrname);
     277         [ -  + ]:        753 :     if (inccodec == NULL)
     278                 :          0 :         return NULL;
     279         [ +  - ]:        753 :     if (errors)
     280                 :        753 :         ret = PyObject_CallFunction(inccodec, "s", errors);
     281                 :            :     else
     282                 :          0 :         ret = _PyObject_CallNoArgs(inccodec);
     283                 :        753 :     Py_DECREF(inccodec);
     284                 :        753 :     return ret;
     285                 :            : }
     286                 :            : 
     287                 :            : static
     288                 :          0 : PyObject *codec_getincrementalcodec(const char *encoding,
     289                 :            :                                     const char *errors,
     290                 :            :                                     const char *attrname)
     291                 :            : {
     292                 :            :     PyObject *codec_info, *ret;
     293                 :            : 
     294                 :          0 :     codec_info = _PyCodec_Lookup(encoding);
     295         [ #  # ]:          0 :     if (codec_info == NULL)
     296                 :          0 :         return NULL;
     297                 :          0 :     ret = codec_makeincrementalcodec(codec_info, errors, attrname);
     298                 :          0 :     Py_DECREF(codec_info);
     299                 :          0 :     return ret;
     300                 :            : }
     301                 :            : 
     302                 :            : /* Helper function to create a stream codec. */
     303                 :            : 
     304                 :            : static
     305                 :          0 : PyObject *codec_getstreamcodec(const char *encoding,
     306                 :            :                                PyObject *stream,
     307                 :            :                                const char *errors,
     308                 :            :                                const int index)
     309                 :            : {
     310                 :            :     PyObject *codecs, *streamcodec, *codeccls;
     311                 :            : 
     312                 :          0 :     codecs = _PyCodec_Lookup(encoding);
     313         [ #  # ]:          0 :     if (codecs == NULL)
     314                 :          0 :         return NULL;
     315                 :            : 
     316                 :          0 :     codeccls = PyTuple_GET_ITEM(codecs, index);
     317         [ #  # ]:          0 :     if (errors != NULL)
     318                 :          0 :         streamcodec = PyObject_CallFunction(codeccls, "Os", stream, errors);
     319                 :            :     else
     320                 :          0 :         streamcodec = PyObject_CallOneArg(codeccls, stream);
     321                 :          0 :     Py_DECREF(codecs);
     322                 :          0 :     return streamcodec;
     323                 :            : }
     324                 :            : 
     325                 :            : /* Helpers to work with the result of _PyCodec_Lookup
     326                 :            : 
     327                 :            :  */
     328                 :        679 : PyObject *_PyCodecInfo_GetIncrementalDecoder(PyObject *codec_info,
     329                 :            :                                              const char *errors)
     330                 :            : {
     331                 :        679 :     return codec_makeincrementalcodec(codec_info, errors,
     332                 :            :                                       "incrementaldecoder");
     333                 :            : }
     334                 :            : 
     335                 :         74 : PyObject *_PyCodecInfo_GetIncrementalEncoder(PyObject *codec_info,
     336                 :            :                                              const char *errors)
     337                 :            : {
     338                 :         74 :     return codec_makeincrementalcodec(codec_info, errors,
     339                 :            :                                       "incrementalencoder");
     340                 :            : }
     341                 :            : 
     342                 :            : 
     343                 :            : /* Convenience APIs to query the Codec registry.
     344                 :            : 
     345                 :            :    All APIs return a codec object with incremented refcount.
     346                 :            : 
     347                 :            :  */
     348                 :            : 
     349                 :          0 : PyObject *PyCodec_Encoder(const char *encoding)
     350                 :            : {
     351                 :          0 :     return codec_getitem(encoding, 0);
     352                 :            : }
     353                 :            : 
     354                 :          0 : PyObject *PyCodec_Decoder(const char *encoding)
     355                 :            : {
     356                 :          0 :     return codec_getitem(encoding, 1);
     357                 :            : }
     358                 :            : 
     359                 :          0 : PyObject *PyCodec_IncrementalEncoder(const char *encoding,
     360                 :            :                                      const char *errors)
     361                 :            : {
     362                 :          0 :     return codec_getincrementalcodec(encoding, errors, "incrementalencoder");
     363                 :            : }
     364                 :            : 
     365                 :          0 : PyObject *PyCodec_IncrementalDecoder(const char *encoding,
     366                 :            :                                      const char *errors)
     367                 :            : {
     368                 :          0 :     return codec_getincrementalcodec(encoding, errors, "incrementaldecoder");
     369                 :            : }
     370                 :            : 
     371                 :          0 : PyObject *PyCodec_StreamReader(const char *encoding,
     372                 :            :                                PyObject *stream,
     373                 :            :                                const char *errors)
     374                 :            : {
     375                 :          0 :     return codec_getstreamcodec(encoding, stream, errors, 2);
     376                 :            : }
     377                 :            : 
     378                 :          0 : PyObject *PyCodec_StreamWriter(const char *encoding,
     379                 :            :                                PyObject *stream,
     380                 :            :                                const char *errors)
     381                 :            : {
     382                 :          0 :     return codec_getstreamcodec(encoding, stream, errors, 3);
     383                 :            : }
     384                 :            : 
     385                 :            : /* Helper that tries to ensure the reported exception chain indicates the
     386                 :            :  * codec that was invoked to trigger the failure without changing the type
     387                 :            :  * of the exception raised.
     388                 :            :  */
     389                 :            : static void
     390                 :          0 : wrap_codec_error(const char *operation,
     391                 :            :                  const char *encoding)
     392                 :            : {
     393                 :            :     /* TrySetFromCause will replace the active exception with a suitably
     394                 :            :      * updated clone if it can, otherwise it will leave the original
     395                 :            :      * exception alone.
     396                 :            :      */
     397                 :          0 :     _PyErr_TrySetFromCause("%s with '%s' codec failed",
     398                 :            :                            operation, encoding);
     399                 :          0 : }
     400                 :            : 
     401                 :            : /* Encode an object (e.g. a Unicode object) using the given encoding
     402                 :            :    and return the resulting encoded object (usually a Python string).
     403                 :            : 
     404                 :            :    errors is passed to the encoder factory as argument if non-NULL. */
     405                 :            : 
     406                 :            : static PyObject *
     407                 :          0 : _PyCodec_EncodeInternal(PyObject *object,
     408                 :            :                         PyObject *encoder,
     409                 :            :                         const char *encoding,
     410                 :            :                         const char *errors)
     411                 :            : {
     412                 :          0 :     PyObject *args = NULL, *result = NULL;
     413                 :          0 :     PyObject *v = NULL;
     414                 :            : 
     415                 :          0 :     args = args_tuple(object, errors);
     416         [ #  # ]:          0 :     if (args == NULL)
     417                 :          0 :         goto onError;
     418                 :            : 
     419                 :          0 :     result = PyObject_Call(encoder, args, NULL);
     420         [ #  # ]:          0 :     if (result == NULL) {
     421                 :          0 :         wrap_codec_error("encoding", encoding);
     422                 :          0 :         goto onError;
     423                 :            :     }
     424                 :            : 
     425   [ #  #  #  # ]:          0 :     if (!PyTuple_Check(result) ||
     426                 :          0 :         PyTuple_GET_SIZE(result) != 2) {
     427                 :          0 :         PyErr_SetString(PyExc_TypeError,
     428                 :            :                         "encoder must return a tuple (object, integer)");
     429                 :          0 :         goto onError;
     430                 :            :     }
     431                 :          0 :     v = Py_NewRef(PyTuple_GET_ITEM(result,0));
     432                 :            :     /* We don't check or use the second (integer) entry. */
     433                 :            : 
     434                 :          0 :     Py_DECREF(args);
     435                 :          0 :     Py_DECREF(encoder);
     436                 :          0 :     Py_DECREF(result);
     437                 :          0 :     return v;
     438                 :            : 
     439                 :          0 :  onError:
     440                 :          0 :     Py_XDECREF(result);
     441                 :          0 :     Py_XDECREF(args);
     442                 :          0 :     Py_XDECREF(encoder);
     443                 :          0 :     return NULL;
     444                 :            : }
     445                 :            : 
     446                 :            : /* Decode an object (usually a Python string) using the given encoding
     447                 :            :    and return an equivalent object (e.g. a Unicode object).
     448                 :            : 
     449                 :            :    errors is passed to the decoder factory as argument if non-NULL. */
     450                 :            : 
     451                 :            : static PyObject *
     452                 :          0 : _PyCodec_DecodeInternal(PyObject *object,
     453                 :            :                         PyObject *decoder,
     454                 :            :                         const char *encoding,
     455                 :            :                         const char *errors)
     456                 :            : {
     457                 :          0 :     PyObject *args = NULL, *result = NULL;
     458                 :            :     PyObject *v;
     459                 :            : 
     460                 :          0 :     args = args_tuple(object, errors);
     461         [ #  # ]:          0 :     if (args == NULL)
     462                 :          0 :         goto onError;
     463                 :            : 
     464                 :          0 :     result = PyObject_Call(decoder, args, NULL);
     465         [ #  # ]:          0 :     if (result == NULL) {
     466                 :          0 :         wrap_codec_error("decoding", encoding);
     467                 :          0 :         goto onError;
     468                 :            :     }
     469   [ #  #  #  # ]:          0 :     if (!PyTuple_Check(result) ||
     470                 :          0 :         PyTuple_GET_SIZE(result) != 2) {
     471                 :          0 :         PyErr_SetString(PyExc_TypeError,
     472                 :            :                         "decoder must return a tuple (object,integer)");
     473                 :          0 :         goto onError;
     474                 :            :     }
     475                 :          0 :     v = Py_NewRef(PyTuple_GET_ITEM(result,0));
     476                 :            :     /* We don't check or use the second (integer) entry. */
     477                 :            : 
     478                 :          0 :     Py_DECREF(args);
     479                 :          0 :     Py_DECREF(decoder);
     480                 :          0 :     Py_DECREF(result);
     481                 :          0 :     return v;
     482                 :            : 
     483                 :          0 :  onError:
     484                 :          0 :     Py_XDECREF(args);
     485                 :          0 :     Py_XDECREF(decoder);
     486                 :          0 :     Py_XDECREF(result);
     487                 :          0 :     return NULL;
     488                 :            : }
     489                 :            : 
     490                 :            : /* Generic encoding/decoding API */
     491                 :          0 : PyObject *PyCodec_Encode(PyObject *object,
     492                 :            :                          const char *encoding,
     493                 :            :                          const char *errors)
     494                 :            : {
     495                 :            :     PyObject *encoder;
     496                 :            : 
     497                 :          0 :     encoder = PyCodec_Encoder(encoding);
     498         [ #  # ]:          0 :     if (encoder == NULL)
     499                 :          0 :         return NULL;
     500                 :            : 
     501                 :          0 :     return _PyCodec_EncodeInternal(object, encoder, encoding, errors);
     502                 :            : }
     503                 :            : 
     504                 :          0 : PyObject *PyCodec_Decode(PyObject *object,
     505                 :            :                          const char *encoding,
     506                 :            :                          const char *errors)
     507                 :            : {
     508                 :            :     PyObject *decoder;
     509                 :            : 
     510                 :          0 :     decoder = PyCodec_Decoder(encoding);
     511         [ #  # ]:          0 :     if (decoder == NULL)
     512                 :          0 :         return NULL;
     513                 :            : 
     514                 :          0 :     return _PyCodec_DecodeInternal(object, decoder, encoding, errors);
     515                 :            : }
     516                 :            : 
     517                 :            : /* Text encoding/decoding API */
     518                 :        753 : PyObject * _PyCodec_LookupTextEncoding(const char *encoding,
     519                 :            :                                        const char *alternate_command)
     520                 :            : {
     521                 :            :     PyObject *codec;
     522                 :            :     PyObject *attr;
     523                 :            :     int is_text_codec;
     524                 :            : 
     525                 :        753 :     codec = _PyCodec_Lookup(encoding);
     526         [ -  + ]:        753 :     if (codec == NULL)
     527                 :          0 :         return NULL;
     528                 :            : 
     529                 :            :     /* Backwards compatibility: assume any raw tuple describes a text
     530                 :            :      * encoding, and the same for anything lacking the private
     531                 :            :      * attribute.
     532                 :            :      */
     533         [ +  - ]:        753 :     if (!PyTuple_CheckExact(codec)) {
     534         [ -  + ]:        753 :         if (_PyObject_LookupAttr(codec, &_Py_ID(_is_text_encoding), &attr) < 0) {
     535                 :          0 :             Py_DECREF(codec);
     536                 :          0 :             return NULL;
     537                 :            :         }
     538         [ +  - ]:        753 :         if (attr != NULL) {
     539                 :        753 :             is_text_codec = PyObject_IsTrue(attr);
     540                 :        753 :             Py_DECREF(attr);
     541         [ -  + ]:        753 :             if (is_text_codec <= 0) {
     542                 :          0 :                 Py_DECREF(codec);
     543         [ #  # ]:          0 :                 if (!is_text_codec)
     544                 :          0 :                     PyErr_Format(PyExc_LookupError,
     545                 :            :                                  "'%.400s' is not a text encoding; "
     546                 :            :                                  "use %s to handle arbitrary codecs",
     547                 :            :                                  encoding, alternate_command);
     548                 :          0 :                 return NULL;
     549                 :            :             }
     550                 :            :         }
     551                 :            :     }
     552                 :            : 
     553                 :            :     /* This appears to be a valid text encoding */
     554                 :        753 :     return codec;
     555                 :            : }
     556                 :            : 
     557                 :            : 
     558                 :            : static
     559                 :          0 : PyObject *codec_getitem_checked(const char *encoding,
     560                 :            :                                 const char *alternate_command,
     561                 :            :                                 int index)
     562                 :            : {
     563                 :            :     PyObject *codec;
     564                 :            :     PyObject *v;
     565                 :            : 
     566                 :          0 :     codec = _PyCodec_LookupTextEncoding(encoding, alternate_command);
     567         [ #  # ]:          0 :     if (codec == NULL)
     568                 :          0 :         return NULL;
     569                 :            : 
     570                 :          0 :     v = Py_NewRef(PyTuple_GET_ITEM(codec, index));
     571                 :          0 :     Py_DECREF(codec);
     572                 :          0 :     return v;
     573                 :            : }
     574                 :            : 
     575                 :          0 : static PyObject * _PyCodec_TextEncoder(const char *encoding)
     576                 :            : {
     577                 :          0 :     return codec_getitem_checked(encoding, "codecs.encode()", 0);
     578                 :            : }
     579                 :            : 
     580                 :          0 : static PyObject * _PyCodec_TextDecoder(const char *encoding)
     581                 :            : {
     582                 :          0 :     return codec_getitem_checked(encoding, "codecs.decode()", 1);
     583                 :            : }
     584                 :            : 
     585                 :          0 : PyObject *_PyCodec_EncodeText(PyObject *object,
     586                 :            :                               const char *encoding,
     587                 :            :                               const char *errors)
     588                 :            : {
     589                 :            :     PyObject *encoder;
     590                 :            : 
     591                 :          0 :     encoder = _PyCodec_TextEncoder(encoding);
     592         [ #  # ]:          0 :     if (encoder == NULL)
     593                 :          0 :         return NULL;
     594                 :            : 
     595                 :          0 :     return _PyCodec_EncodeInternal(object, encoder, encoding, errors);
     596                 :            : }
     597                 :            : 
     598                 :          0 : PyObject *_PyCodec_DecodeText(PyObject *object,
     599                 :            :                               const char *encoding,
     600                 :            :                               const char *errors)
     601                 :            : {
     602                 :            :     PyObject *decoder;
     603                 :            : 
     604                 :          0 :     decoder = _PyCodec_TextDecoder(encoding);
     605         [ #  # ]:          0 :     if (decoder == NULL)
     606                 :          0 :         return NULL;
     607                 :            : 
     608                 :          0 :     return _PyCodec_DecodeInternal(object, decoder, encoding, errors);
     609                 :            : }
     610                 :            : 
     611                 :            : /* Register the error handling callback function error under the name
     612                 :            :    name. This function will be called by the codec when it encounters
     613                 :            :    an unencodable characters/undecodable bytes and doesn't know the
     614                 :            :    callback name, when name is specified as the error parameter
     615                 :            :    in the call to the encode/decode function.
     616                 :            :    Return 0 on success, -1 on error */
     617                 :        200 : int PyCodec_RegisterError(const char *name, PyObject *error)
     618                 :            : {
     619                 :        200 :     PyInterpreterState *interp = _PyInterpreterState_GET();
     620   [ -  +  -  - ]:        200 :     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
     621                 :          0 :         return -1;
     622         [ -  + ]:        200 :     if (!PyCallable_Check(error)) {
     623                 :          0 :         PyErr_SetString(PyExc_TypeError, "handler must be callable");
     624                 :          0 :         return -1;
     625                 :            :     }
     626                 :        200 :     return PyDict_SetItemString(interp->codec_error_registry,
     627                 :            :                                 name, error);
     628                 :            : }
     629                 :            : 
     630                 :            : /* Lookup the error handling callback function registered under the
     631                 :            :    name error. As a special case NULL can be passed, in which case
     632                 :            :    the error handling callback for strict encoding will be returned. */
     633                 :        152 : PyObject *PyCodec_LookupError(const char *name)
     634                 :            : {
     635                 :        152 :     PyObject *handler = NULL;
     636                 :            : 
     637                 :        152 :     PyInterpreterState *interp = _PyInterpreterState_GET();
     638   [ -  +  -  - ]:        152 :     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
     639                 :          0 :         return NULL;
     640                 :            : 
     641         [ +  + ]:        152 :     if (name==NULL)
     642                 :          2 :         name = "strict";
     643                 :        152 :     handler = _PyDict_GetItemStringWithError(interp->codec_error_registry, name);
     644         [ +  - ]:        152 :     if (handler) {
     645                 :        152 :         Py_INCREF(handler);
     646                 :            :     }
     647         [ #  # ]:          0 :     else if (!PyErr_Occurred()) {
     648                 :          0 :         PyErr_Format(PyExc_LookupError, "unknown error handler name '%.400s'", name);
     649                 :            :     }
     650                 :        152 :     return handler;
     651                 :            : }
     652                 :            : 
     653                 :          0 : static void wrong_exception_type(PyObject *exc)
     654                 :            : {
     655                 :          0 :     PyErr_Format(PyExc_TypeError,
     656                 :            :                  "don't know how to handle %.200s in error callback",
     657                 :          0 :                  Py_TYPE(exc)->tp_name);
     658                 :          0 : }
     659                 :            : 
     660                 :          2 : PyObject *PyCodec_StrictErrors(PyObject *exc)
     661                 :            : {
     662         [ +  - ]:          2 :     if (PyExceptionInstance_Check(exc))
     663                 :          2 :         PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
     664                 :            :     else
     665                 :          0 :         PyErr_SetString(PyExc_TypeError, "codec must pass exception instance");
     666                 :          2 :     return NULL;
     667                 :            : }
     668                 :            : 
     669                 :            : 
     670                 :          0 : PyObject *PyCodec_IgnoreErrors(PyObject *exc)
     671                 :            : {
     672                 :            :     Py_ssize_t end;
     673                 :            : 
     674         [ #  # ]:          0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
     675         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
     676                 :          0 :             return NULL;
     677                 :            :     }
     678         [ #  # ]:          0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
     679         [ #  # ]:          0 :         if (PyUnicodeDecodeError_GetEnd(exc, &end))
     680                 :          0 :             return NULL;
     681                 :            :     }
     682         [ #  # ]:          0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {
     683         [ #  # ]:          0 :         if (PyUnicodeTranslateError_GetEnd(exc, &end))
     684                 :          0 :             return NULL;
     685                 :            :     }
     686                 :            :     else {
     687                 :          0 :         wrong_exception_type(exc);
     688                 :          0 :         return NULL;
     689                 :            :     }
     690                 :          0 :     return Py_BuildValue("(Nn)", PyUnicode_New(0, 0), end);
     691                 :            : }
     692                 :            : 
     693                 :            : 
     694                 :          0 : PyObject *PyCodec_ReplaceErrors(PyObject *exc)
     695                 :            : {
     696                 :            :     Py_ssize_t start, end, i, len;
     697                 :            : 
     698         [ #  # ]:          0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
     699                 :            :         PyObject *res;
     700                 :            :         Py_UCS1 *outp;
     701         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetStart(exc, &start))
     702                 :          0 :             return NULL;
     703         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
     704                 :          0 :             return NULL;
     705                 :          0 :         len = end - start;
     706                 :          0 :         res = PyUnicode_New(len, '?');
     707         [ #  # ]:          0 :         if (res == NULL)
     708                 :          0 :             return NULL;
     709                 :            :         assert(PyUnicode_KIND(res) == PyUnicode_1BYTE_KIND);
     710                 :          0 :         outp = PyUnicode_1BYTE_DATA(res);
     711         [ #  # ]:          0 :         for (i = 0; i < len; ++i)
     712                 :          0 :             outp[i] = '?';
     713                 :            :         assert(_PyUnicode_CheckConsistency(res, 1));
     714                 :          0 :         return Py_BuildValue("(Nn)", res, end);
     715                 :            :     }
     716         [ #  # ]:          0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
     717         [ #  # ]:          0 :         if (PyUnicodeDecodeError_GetEnd(exc, &end))
     718                 :          0 :             return NULL;
     719                 :          0 :         return Py_BuildValue("(Cn)",
     720                 :            :                              (int)Py_UNICODE_REPLACEMENT_CHARACTER,
     721                 :            :                              end);
     722                 :            :     }
     723         [ #  # ]:          0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {
     724                 :            :         PyObject *res;
     725                 :            :         Py_UCS2 *outp;
     726         [ #  # ]:          0 :         if (PyUnicodeTranslateError_GetStart(exc, &start))
     727                 :          0 :             return NULL;
     728         [ #  # ]:          0 :         if (PyUnicodeTranslateError_GetEnd(exc, &end))
     729                 :          0 :             return NULL;
     730                 :          0 :         len = end - start;
     731                 :          0 :         res = PyUnicode_New(len, Py_UNICODE_REPLACEMENT_CHARACTER);
     732         [ #  # ]:          0 :         if (res == NULL)
     733                 :          0 :             return NULL;
     734                 :            :         assert(PyUnicode_KIND(res) == PyUnicode_2BYTE_KIND);
     735                 :          0 :         outp = PyUnicode_2BYTE_DATA(res);
     736         [ #  # ]:          0 :         for (i = 0; i < len; i++)
     737                 :          0 :             outp[i] = Py_UNICODE_REPLACEMENT_CHARACTER;
     738                 :            :         assert(_PyUnicode_CheckConsistency(res, 1));
     739                 :          0 :         return Py_BuildValue("(Nn)", res, end);
     740                 :            :     }
     741                 :            :     else {
     742                 :          0 :         wrong_exception_type(exc);
     743                 :          0 :         return NULL;
     744                 :            :     }
     745                 :            : }
     746                 :            : 
     747                 :          0 : PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc)
     748                 :            : {
     749         [ #  # ]:          0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
     750                 :            :         PyObject *restuple;
     751                 :            :         PyObject *object;
     752                 :            :         Py_ssize_t i;
     753                 :            :         Py_ssize_t start;
     754                 :            :         Py_ssize_t end;
     755                 :            :         PyObject *res;
     756                 :            :         Py_UCS1 *outp;
     757                 :            :         Py_ssize_t ressize;
     758                 :            :         Py_UCS4 ch;
     759         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetStart(exc, &start))
     760                 :          0 :             return NULL;
     761         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
     762                 :          0 :             return NULL;
     763         [ #  # ]:          0 :         if (!(object = PyUnicodeEncodeError_GetObject(exc)))
     764                 :          0 :             return NULL;
     765         [ #  # ]:          0 :         if (end - start > PY_SSIZE_T_MAX / (2+7+1))
     766                 :          0 :             end = start + PY_SSIZE_T_MAX / (2+7+1);
     767         [ #  # ]:          0 :         for (i = start, ressize = 0; i < end; ++i) {
     768                 :            :             /* object is guaranteed to be "ready" */
     769                 :          0 :             ch = PyUnicode_READ_CHAR(object, i);
     770         [ #  # ]:          0 :             if (ch<10)
     771                 :          0 :                 ressize += 2+1+1;
     772         [ #  # ]:          0 :             else if (ch<100)
     773                 :          0 :                 ressize += 2+2+1;
     774         [ #  # ]:          0 :             else if (ch<1000)
     775                 :          0 :                 ressize += 2+3+1;
     776         [ #  # ]:          0 :             else if (ch<10000)
     777                 :          0 :                 ressize += 2+4+1;
     778         [ #  # ]:          0 :             else if (ch<100000)
     779                 :          0 :                 ressize += 2+5+1;
     780         [ #  # ]:          0 :             else if (ch<1000000)
     781                 :          0 :                 ressize += 2+6+1;
     782                 :            :             else
     783                 :          0 :                 ressize += 2+7+1;
     784                 :            :         }
     785                 :            :         /* allocate replacement */
     786                 :          0 :         res = PyUnicode_New(ressize, 127);
     787         [ #  # ]:          0 :         if (res == NULL) {
     788                 :          0 :             Py_DECREF(object);
     789                 :          0 :             return NULL;
     790                 :            :         }
     791                 :          0 :         outp = PyUnicode_1BYTE_DATA(res);
     792                 :            :         /* generate replacement */
     793         [ #  # ]:          0 :         for (i = start; i < end; ++i) {
     794                 :            :             int digits;
     795                 :            :             int base;
     796                 :          0 :             ch = PyUnicode_READ_CHAR(object, i);
     797                 :          0 :             *outp++ = '&';
     798                 :          0 :             *outp++ = '#';
     799         [ #  # ]:          0 :             if (ch<10) {
     800                 :          0 :                 digits = 1;
     801                 :          0 :                 base = 1;
     802                 :            :             }
     803         [ #  # ]:          0 :             else if (ch<100) {
     804                 :          0 :                 digits = 2;
     805                 :          0 :                 base = 10;
     806                 :            :             }
     807         [ #  # ]:          0 :             else if (ch<1000) {
     808                 :          0 :                 digits = 3;
     809                 :          0 :                 base = 100;
     810                 :            :             }
     811         [ #  # ]:          0 :             else if (ch<10000) {
     812                 :          0 :                 digits = 4;
     813                 :          0 :                 base = 1000;
     814                 :            :             }
     815         [ #  # ]:          0 :             else if (ch<100000) {
     816                 :          0 :                 digits = 5;
     817                 :          0 :                 base = 10000;
     818                 :            :             }
     819         [ #  # ]:          0 :             else if (ch<1000000) {
     820                 :          0 :                 digits = 6;
     821                 :          0 :                 base = 100000;
     822                 :            :             }
     823                 :            :             else {
     824                 :          0 :                 digits = 7;
     825                 :          0 :                 base = 1000000;
     826                 :            :             }
     827         [ #  # ]:          0 :             while (digits-->0) {
     828                 :          0 :                 *outp++ = '0' + ch/base;
     829                 :          0 :                 ch %= base;
     830                 :          0 :                 base /= 10;
     831                 :            :             }
     832                 :          0 :             *outp++ = ';';
     833                 :            :         }
     834                 :            :         assert(_PyUnicode_CheckConsistency(res, 1));
     835                 :          0 :         restuple = Py_BuildValue("(Nn)", res, end);
     836                 :          0 :         Py_DECREF(object);
     837                 :          0 :         return restuple;
     838                 :            :     }
     839                 :            :     else {
     840                 :          0 :         wrong_exception_type(exc);
     841                 :          0 :         return NULL;
     842                 :            :     }
     843                 :            : }
     844                 :            : 
     845                 :          0 : PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc)
     846                 :            : {
     847                 :            :     PyObject *object;
     848                 :            :     Py_ssize_t i;
     849                 :            :     Py_ssize_t start;
     850                 :            :     Py_ssize_t end;
     851                 :            :     PyObject *res;
     852                 :            :     Py_UCS1 *outp;
     853                 :            :     int ressize;
     854                 :            :     Py_UCS4 c;
     855                 :            : 
     856         [ #  # ]:          0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
     857                 :            :         const unsigned char *p;
     858         [ #  # ]:          0 :         if (PyUnicodeDecodeError_GetStart(exc, &start))
     859                 :          0 :             return NULL;
     860         [ #  # ]:          0 :         if (PyUnicodeDecodeError_GetEnd(exc, &end))
     861                 :          0 :             return NULL;
     862         [ #  # ]:          0 :         if (!(object = PyUnicodeDecodeError_GetObject(exc)))
     863                 :          0 :             return NULL;
     864                 :          0 :         p = (const unsigned char*)PyBytes_AS_STRING(object);
     865                 :          0 :         res = PyUnicode_New(4 * (end - start), 127);
     866         [ #  # ]:          0 :         if (res == NULL) {
     867                 :          0 :             Py_DECREF(object);
     868                 :          0 :             return NULL;
     869                 :            :         }
     870                 :          0 :         outp = PyUnicode_1BYTE_DATA(res);
     871         [ #  # ]:          0 :         for (i = start; i < end; i++, outp += 4) {
     872                 :          0 :             unsigned char c = p[i];
     873                 :          0 :             outp[0] = '\\';
     874                 :          0 :             outp[1] = 'x';
     875                 :          0 :             outp[2] = Py_hexdigits[(c>>4)&0xf];
     876                 :          0 :             outp[3] = Py_hexdigits[c&0xf];
     877                 :            :         }
     878                 :            : 
     879                 :            :         assert(_PyUnicode_CheckConsistency(res, 1));
     880                 :          0 :         Py_DECREF(object);
     881                 :          0 :         return Py_BuildValue("(Nn)", res, end);
     882                 :            :     }
     883         [ #  # ]:          0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
     884         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetStart(exc, &start))
     885                 :          0 :             return NULL;
     886         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
     887                 :          0 :             return NULL;
     888         [ #  # ]:          0 :         if (!(object = PyUnicodeEncodeError_GetObject(exc)))
     889                 :          0 :             return NULL;
     890                 :            :     }
     891         [ #  # ]:          0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {
     892         [ #  # ]:          0 :         if (PyUnicodeTranslateError_GetStart(exc, &start))
     893                 :          0 :             return NULL;
     894         [ #  # ]:          0 :         if (PyUnicodeTranslateError_GetEnd(exc, &end))
     895                 :          0 :             return NULL;
     896         [ #  # ]:          0 :         if (!(object = PyUnicodeTranslateError_GetObject(exc)))
     897                 :          0 :             return NULL;
     898                 :            :     }
     899                 :            :     else {
     900                 :          0 :         wrong_exception_type(exc);
     901                 :          0 :         return NULL;
     902                 :            :     }
     903                 :            : 
     904         [ #  # ]:          0 :     if (end - start > PY_SSIZE_T_MAX / (1+1+8))
     905                 :          0 :         end = start + PY_SSIZE_T_MAX / (1+1+8);
     906         [ #  # ]:          0 :     for (i = start, ressize = 0; i < end; ++i) {
     907                 :            :         /* object is guaranteed to be "ready" */
     908                 :          0 :         c = PyUnicode_READ_CHAR(object, i);
     909         [ #  # ]:          0 :         if (c >= 0x10000) {
     910                 :          0 :             ressize += 1+1+8;
     911                 :            :         }
     912         [ #  # ]:          0 :         else if (c >= 0x100) {
     913                 :          0 :             ressize += 1+1+4;
     914                 :            :         }
     915                 :            :         else
     916                 :          0 :             ressize += 1+1+2;
     917                 :            :     }
     918                 :          0 :     res = PyUnicode_New(ressize, 127);
     919         [ #  # ]:          0 :     if (res == NULL) {
     920                 :          0 :         Py_DECREF(object);
     921                 :          0 :         return NULL;
     922                 :            :     }
     923                 :          0 :     outp = PyUnicode_1BYTE_DATA(res);
     924         [ #  # ]:          0 :     for (i = start; i < end; ++i) {
     925                 :          0 :         c = PyUnicode_READ_CHAR(object, i);
     926                 :          0 :         *outp++ = '\\';
     927         [ #  # ]:          0 :         if (c >= 0x00010000) {
     928                 :          0 :             *outp++ = 'U';
     929                 :          0 :             *outp++ = Py_hexdigits[(c>>28)&0xf];
     930                 :          0 :             *outp++ = Py_hexdigits[(c>>24)&0xf];
     931                 :          0 :             *outp++ = Py_hexdigits[(c>>20)&0xf];
     932                 :          0 :             *outp++ = Py_hexdigits[(c>>16)&0xf];
     933                 :          0 :             *outp++ = Py_hexdigits[(c>>12)&0xf];
     934                 :          0 :             *outp++ = Py_hexdigits[(c>>8)&0xf];
     935                 :            :         }
     936         [ #  # ]:          0 :         else if (c >= 0x100) {
     937                 :          0 :             *outp++ = 'u';
     938                 :          0 :             *outp++ = Py_hexdigits[(c>>12)&0xf];
     939                 :          0 :             *outp++ = Py_hexdigits[(c>>8)&0xf];
     940                 :            :         }
     941                 :            :         else
     942                 :          0 :             *outp++ = 'x';
     943                 :          0 :         *outp++ = Py_hexdigits[(c>>4)&0xf];
     944                 :          0 :         *outp++ = Py_hexdigits[c&0xf];
     945                 :            :     }
     946                 :            : 
     947                 :            :     assert(_PyUnicode_CheckConsistency(res, 1));
     948                 :          0 :     Py_DECREF(object);
     949                 :          0 :     return Py_BuildValue("(Nn)", res, end);
     950                 :            : }
     951                 :            : 
     952                 :            : static _PyUnicode_Name_CAPI *ucnhash_capi = NULL;
     953                 :            : 
     954                 :          0 : PyObject *PyCodec_NameReplaceErrors(PyObject *exc)
     955                 :            : {
     956         [ #  # ]:          0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
     957                 :            :         PyObject *restuple;
     958                 :            :         PyObject *object;
     959                 :            :         Py_ssize_t i;
     960                 :            :         Py_ssize_t start;
     961                 :            :         Py_ssize_t end;
     962                 :            :         PyObject *res;
     963                 :            :         Py_UCS1 *outp;
     964                 :            :         Py_ssize_t ressize;
     965                 :            :         int replsize;
     966                 :            :         Py_UCS4 c;
     967                 :            :         char buffer[256]; /* NAME_MAXLEN */
     968         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetStart(exc, &start))
     969                 :          0 :             return NULL;
     970         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
     971                 :          0 :             return NULL;
     972         [ #  # ]:          0 :         if (!(object = PyUnicodeEncodeError_GetObject(exc)))
     973                 :          0 :             return NULL;
     974         [ #  # ]:          0 :         if (!ucnhash_capi) {
     975                 :            :             /* load the unicode data module */
     976                 :          0 :             ucnhash_capi = (_PyUnicode_Name_CAPI *)PyCapsule_Import(
     977                 :            :                                             PyUnicodeData_CAPSULE_NAME, 1);
     978         [ #  # ]:          0 :             if (!ucnhash_capi) {
     979                 :          0 :                 return NULL;
     980                 :            :             }
     981                 :            :         }
     982         [ #  # ]:          0 :         for (i = start, ressize = 0; i < end; ++i) {
     983                 :            :             /* object is guaranteed to be "ready" */
     984                 :          0 :             c = PyUnicode_READ_CHAR(object, i);
     985         [ #  # ]:          0 :             if (ucnhash_capi->getname(c, buffer, sizeof(buffer), 1)) {
     986                 :          0 :                 replsize = 1+1+1+(int)strlen(buffer)+1;
     987                 :            :             }
     988         [ #  # ]:          0 :             else if (c >= 0x10000) {
     989                 :          0 :                 replsize = 1+1+8;
     990                 :            :             }
     991         [ #  # ]:          0 :             else if (c >= 0x100) {
     992                 :          0 :                 replsize = 1+1+4;
     993                 :            :             }
     994                 :            :             else
     995                 :          0 :                 replsize = 1+1+2;
     996         [ #  # ]:          0 :             if (ressize > PY_SSIZE_T_MAX - replsize)
     997                 :          0 :                 break;
     998                 :          0 :             ressize += replsize;
     999                 :            :         }
    1000                 :          0 :         end = i;
    1001                 :          0 :         res = PyUnicode_New(ressize, 127);
    1002         [ #  # ]:          0 :         if (res==NULL)
    1003                 :          0 :             return NULL;
    1004                 :          0 :         for (i = start, outp = PyUnicode_1BYTE_DATA(res);
    1005         [ #  # ]:          0 :             i < end; ++i) {
    1006                 :          0 :             c = PyUnicode_READ_CHAR(object, i);
    1007                 :          0 :             *outp++ = '\\';
    1008         [ #  # ]:          0 :             if (ucnhash_capi->getname(c, buffer, sizeof(buffer), 1)) {
    1009                 :          0 :                 *outp++ = 'N';
    1010                 :          0 :                 *outp++ = '{';
    1011                 :          0 :                 strcpy((char *)outp, buffer);
    1012                 :          0 :                 outp += strlen(buffer);
    1013                 :          0 :                 *outp++ = '}';
    1014                 :          0 :                 continue;
    1015                 :            :             }
    1016         [ #  # ]:          0 :             if (c >= 0x00010000) {
    1017                 :          0 :                 *outp++ = 'U';
    1018                 :          0 :                 *outp++ = Py_hexdigits[(c>>28)&0xf];
    1019                 :          0 :                 *outp++ = Py_hexdigits[(c>>24)&0xf];
    1020                 :          0 :                 *outp++ = Py_hexdigits[(c>>20)&0xf];
    1021                 :          0 :                 *outp++ = Py_hexdigits[(c>>16)&0xf];
    1022                 :          0 :                 *outp++ = Py_hexdigits[(c>>12)&0xf];
    1023                 :          0 :                 *outp++ = Py_hexdigits[(c>>8)&0xf];
    1024                 :            :             }
    1025         [ #  # ]:          0 :             else if (c >= 0x100) {
    1026                 :          0 :                 *outp++ = 'u';
    1027                 :          0 :                 *outp++ = Py_hexdigits[(c>>12)&0xf];
    1028                 :          0 :                 *outp++ = Py_hexdigits[(c>>8)&0xf];
    1029                 :            :             }
    1030                 :            :             else
    1031                 :          0 :                 *outp++ = 'x';
    1032                 :          0 :             *outp++ = Py_hexdigits[(c>>4)&0xf];
    1033                 :          0 :             *outp++ = Py_hexdigits[c&0xf];
    1034                 :            :         }
    1035                 :            : 
    1036                 :            :         assert(outp == PyUnicode_1BYTE_DATA(res) + ressize);
    1037                 :            :         assert(_PyUnicode_CheckConsistency(res, 1));
    1038                 :          0 :         restuple = Py_BuildValue("(Nn)", res, end);
    1039                 :          0 :         Py_DECREF(object);
    1040                 :          0 :         return restuple;
    1041                 :            :     }
    1042                 :            :     else {
    1043                 :          0 :         wrong_exception_type(exc);
    1044                 :          0 :         return NULL;
    1045                 :            :     }
    1046                 :            : }
    1047                 :            : 
    1048                 :            : #define ENC_UNKNOWN     -1
    1049                 :            : #define ENC_UTF8        0
    1050                 :            : #define ENC_UTF16BE     1
    1051                 :            : #define ENC_UTF16LE     2
    1052                 :            : #define ENC_UTF32BE     3
    1053                 :            : #define ENC_UTF32LE     4
    1054                 :            : 
    1055                 :            : static int
    1056                 :          0 : get_standard_encoding(const char *encoding, int *bytelength)
    1057                 :            : {
    1058         [ #  # ]:          0 :     if (Py_TOLOWER(encoding[0]) == 'u' &&
    1059         [ #  # ]:          0 :         Py_TOLOWER(encoding[1]) == 't' &&
    1060         [ #  # ]:          0 :         Py_TOLOWER(encoding[2]) == 'f') {
    1061                 :          0 :         encoding += 3;
    1062   [ #  #  #  # ]:          0 :         if (*encoding == '-' || *encoding == '_' )
    1063                 :          0 :             encoding++;
    1064   [ #  #  #  # ]:          0 :         if (encoding[0] == '8' && encoding[1] == '\0') {
    1065                 :          0 :             *bytelength = 3;
    1066                 :          0 :             return ENC_UTF8;
    1067                 :            :         }
    1068   [ #  #  #  # ]:          0 :         else if (encoding[0] == '1' && encoding[1] == '6') {
    1069                 :          0 :             encoding += 2;
    1070                 :          0 :             *bytelength = 2;
    1071         [ #  # ]:          0 :             if (*encoding == '\0') {
    1072                 :            : #ifdef WORDS_BIGENDIAN
    1073                 :            :                 return ENC_UTF16BE;
    1074                 :            : #else
    1075                 :          0 :                 return ENC_UTF16LE;
    1076                 :            : #endif
    1077                 :            :             }
    1078   [ #  #  #  # ]:          0 :             if (*encoding == '-' || *encoding == '_' )
    1079                 :          0 :                 encoding++;
    1080   [ #  #  #  # ]:          0 :             if (Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
    1081         [ #  # ]:          0 :                 if (Py_TOLOWER(encoding[0]) == 'b')
    1082                 :          0 :                     return ENC_UTF16BE;
    1083         [ #  # ]:          0 :                 if (Py_TOLOWER(encoding[0]) == 'l')
    1084                 :          0 :                     return ENC_UTF16LE;
    1085                 :            :             }
    1086                 :            :         }
    1087   [ #  #  #  # ]:          0 :         else if (encoding[0] == '3' && encoding[1] == '2') {
    1088                 :          0 :             encoding += 2;
    1089                 :          0 :             *bytelength = 4;
    1090         [ #  # ]:          0 :             if (*encoding == '\0') {
    1091                 :            : #ifdef WORDS_BIGENDIAN
    1092                 :            :                 return ENC_UTF32BE;
    1093                 :            : #else
    1094                 :          0 :                 return ENC_UTF32LE;
    1095                 :            : #endif
    1096                 :            :             }
    1097   [ #  #  #  # ]:          0 :             if (*encoding == '-' || *encoding == '_' )
    1098                 :          0 :                 encoding++;
    1099   [ #  #  #  # ]:          0 :             if (Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\0') {
    1100         [ #  # ]:          0 :                 if (Py_TOLOWER(encoding[0]) == 'b')
    1101                 :          0 :                     return ENC_UTF32BE;
    1102         [ #  # ]:          0 :                 if (Py_TOLOWER(encoding[0]) == 'l')
    1103                 :          0 :                     return ENC_UTF32LE;
    1104                 :            :             }
    1105                 :            :         }
    1106                 :            :     }
    1107         [ #  # ]:          0 :     else if (strcmp(encoding, "CP_UTF8") == 0) {
    1108                 :          0 :         *bytelength = 3;
    1109                 :          0 :         return ENC_UTF8;
    1110                 :            :     }
    1111                 :          0 :     return ENC_UNKNOWN;
    1112                 :            : }
    1113                 :            : 
    1114                 :            : /* This handler is declared static until someone demonstrates
    1115                 :            :    a need to call it directly. */
    1116                 :            : static PyObject *
    1117                 :          0 : PyCodec_SurrogatePassErrors(PyObject *exc)
    1118                 :            : {
    1119                 :            :     PyObject *restuple;
    1120                 :            :     PyObject *object;
    1121                 :            :     PyObject *encode;
    1122                 :            :     const char *encoding;
    1123                 :            :     int code;
    1124                 :            :     int bytelength;
    1125                 :            :     Py_ssize_t i;
    1126                 :            :     Py_ssize_t start;
    1127                 :            :     Py_ssize_t end;
    1128                 :            :     PyObject *res;
    1129                 :            : 
    1130         [ #  # ]:          0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
    1131                 :            :         unsigned char *outp;
    1132         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetStart(exc, &start))
    1133                 :          0 :             return NULL;
    1134         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
    1135                 :          0 :             return NULL;
    1136         [ #  # ]:          0 :         if (!(object = PyUnicodeEncodeError_GetObject(exc)))
    1137                 :          0 :             return NULL;
    1138         [ #  # ]:          0 :         if (!(encode = PyUnicodeEncodeError_GetEncoding(exc))) {
    1139                 :          0 :             Py_DECREF(object);
    1140                 :          0 :             return NULL;
    1141                 :            :         }
    1142         [ #  # ]:          0 :         if (!(encoding = PyUnicode_AsUTF8(encode))) {
    1143                 :          0 :             Py_DECREF(object);
    1144                 :          0 :             Py_DECREF(encode);
    1145                 :          0 :             return NULL;
    1146                 :            :         }
    1147                 :          0 :         code = get_standard_encoding(encoding, &bytelength);
    1148                 :          0 :         Py_DECREF(encode);
    1149         [ #  # ]:          0 :         if (code == ENC_UNKNOWN) {
    1150                 :            :             /* Not supported, fail with original exception */
    1151                 :          0 :             PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
    1152                 :          0 :             Py_DECREF(object);
    1153                 :          0 :             return NULL;
    1154                 :            :         }
    1155                 :            : 
    1156         [ #  # ]:          0 :         if (end - start > PY_SSIZE_T_MAX / bytelength)
    1157                 :          0 :             end = start + PY_SSIZE_T_MAX / bytelength;
    1158                 :          0 :         res = PyBytes_FromStringAndSize(NULL, bytelength*(end-start));
    1159         [ #  # ]:          0 :         if (!res) {
    1160                 :          0 :             Py_DECREF(object);
    1161                 :          0 :             return NULL;
    1162                 :            :         }
    1163                 :          0 :         outp = (unsigned char*)PyBytes_AsString(res);
    1164         [ #  # ]:          0 :         for (i = start; i < end; i++) {
    1165                 :            :             /* object is guaranteed to be "ready" */
    1166                 :          0 :             Py_UCS4 ch = PyUnicode_READ_CHAR(object, i);
    1167         [ #  # ]:          0 :             if (!Py_UNICODE_IS_SURROGATE(ch)) {
    1168                 :            :                 /* Not a surrogate, fail with original exception */
    1169                 :          0 :                 PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
    1170                 :          0 :                 Py_DECREF(res);
    1171                 :          0 :                 Py_DECREF(object);
    1172                 :          0 :                 return NULL;
    1173                 :            :             }
    1174   [ #  #  #  #  :          0 :             switch (code) {
                   #  # ]
    1175                 :          0 :             case ENC_UTF8:
    1176                 :          0 :                 *outp++ = (unsigned char)(0xe0 | (ch >> 12));
    1177                 :          0 :                 *outp++ = (unsigned char)(0x80 | ((ch >> 6) & 0x3f));
    1178                 :          0 :                 *outp++ = (unsigned char)(0x80 | (ch & 0x3f));
    1179                 :          0 :                 break;
    1180                 :          0 :             case ENC_UTF16LE:
    1181                 :          0 :                 *outp++ = (unsigned char) ch;
    1182                 :          0 :                 *outp++ = (unsigned char)(ch >> 8);
    1183                 :          0 :                 break;
    1184                 :          0 :             case ENC_UTF16BE:
    1185                 :          0 :                 *outp++ = (unsigned char)(ch >> 8);
    1186                 :          0 :                 *outp++ = (unsigned char) ch;
    1187                 :          0 :                 break;
    1188                 :          0 :             case ENC_UTF32LE:
    1189                 :          0 :                 *outp++ = (unsigned char) ch;
    1190                 :          0 :                 *outp++ = (unsigned char)(ch >> 8);
    1191                 :          0 :                 *outp++ = (unsigned char)(ch >> 16);
    1192                 :          0 :                 *outp++ = (unsigned char)(ch >> 24);
    1193                 :          0 :                 break;
    1194                 :          0 :             case ENC_UTF32BE:
    1195                 :          0 :                 *outp++ = (unsigned char)(ch >> 24);
    1196                 :          0 :                 *outp++ = (unsigned char)(ch >> 16);
    1197                 :          0 :                 *outp++ = (unsigned char)(ch >> 8);
    1198                 :          0 :                 *outp++ = (unsigned char) ch;
    1199                 :          0 :                 break;
    1200                 :            :             }
    1201                 :          0 :         }
    1202                 :          0 :         restuple = Py_BuildValue("(On)", res, end);
    1203                 :          0 :         Py_DECREF(res);
    1204                 :          0 :         Py_DECREF(object);
    1205                 :          0 :         return restuple;
    1206                 :            :     }
    1207         [ #  # ]:          0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
    1208                 :            :         const unsigned char *p;
    1209                 :          0 :         Py_UCS4 ch = 0;
    1210         [ #  # ]:          0 :         if (PyUnicodeDecodeError_GetStart(exc, &start))
    1211                 :          0 :             return NULL;
    1212         [ #  # ]:          0 :         if (PyUnicodeDecodeError_GetEnd(exc, &end))
    1213                 :          0 :             return NULL;
    1214         [ #  # ]:          0 :         if (!(object = PyUnicodeDecodeError_GetObject(exc)))
    1215                 :          0 :             return NULL;
    1216                 :          0 :         p = (const unsigned char*)PyBytes_AS_STRING(object);
    1217         [ #  # ]:          0 :         if (!(encode = PyUnicodeDecodeError_GetEncoding(exc))) {
    1218                 :          0 :             Py_DECREF(object);
    1219                 :          0 :             return NULL;
    1220                 :            :         }
    1221         [ #  # ]:          0 :         if (!(encoding = PyUnicode_AsUTF8(encode))) {
    1222                 :          0 :             Py_DECREF(object);
    1223                 :          0 :             Py_DECREF(encode);
    1224                 :          0 :             return NULL;
    1225                 :            :         }
    1226                 :          0 :         code = get_standard_encoding(encoding, &bytelength);
    1227                 :          0 :         Py_DECREF(encode);
    1228         [ #  # ]:          0 :         if (code == ENC_UNKNOWN) {
    1229                 :            :             /* Not supported, fail with original exception */
    1230                 :          0 :             PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
    1231                 :          0 :             Py_DECREF(object);
    1232                 :          0 :             return NULL;
    1233                 :            :         }
    1234                 :            : 
    1235                 :            :         /* Try decoding a single surrogate character. If
    1236                 :            :            there are more, let the codec call us again. */
    1237                 :          0 :         p += start;
    1238         [ #  # ]:          0 :         if (PyBytes_GET_SIZE(object) - start >= bytelength) {
    1239   [ #  #  #  #  :          0 :             switch (code) {
                   #  # ]
    1240                 :          0 :             case ENC_UTF8:
    1241         [ #  # ]:          0 :                 if ((p[0] & 0xf0) == 0xe0 &&
    1242         [ #  # ]:          0 :                     (p[1] & 0xc0) == 0x80 &&
    1243         [ #  # ]:          0 :                     (p[2] & 0xc0) == 0x80) {
    1244                 :            :                     /* it's a three-byte code */
    1245                 :          0 :                     ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f);
    1246                 :            :                 }
    1247                 :          0 :                 break;
    1248                 :          0 :             case ENC_UTF16LE:
    1249                 :          0 :                 ch = p[1] << 8 | p[0];
    1250                 :          0 :                 break;
    1251                 :          0 :             case ENC_UTF16BE:
    1252                 :          0 :                 ch = p[0] << 8 | p[1];
    1253                 :          0 :                 break;
    1254                 :          0 :             case ENC_UTF32LE:
    1255                 :          0 :                 ch = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
    1256                 :          0 :                 break;
    1257                 :          0 :             case ENC_UTF32BE:
    1258                 :          0 :                 ch = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
    1259                 :          0 :                 break;
    1260                 :            :             }
    1261                 :          0 :         }
    1262                 :            : 
    1263                 :          0 :         Py_DECREF(object);
    1264         [ #  # ]:          0 :         if (!Py_UNICODE_IS_SURROGATE(ch)) {
    1265                 :            :             /* it's not a surrogate - fail */
    1266                 :          0 :             PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
    1267                 :          0 :             return NULL;
    1268                 :            :         }
    1269                 :          0 :         res = PyUnicode_FromOrdinal(ch);
    1270         [ #  # ]:          0 :         if (res == NULL)
    1271                 :          0 :             return NULL;
    1272                 :          0 :         return Py_BuildValue("(Nn)", res, start + bytelength);
    1273                 :            :     }
    1274                 :            :     else {
    1275                 :          0 :         wrong_exception_type(exc);
    1276                 :          0 :         return NULL;
    1277                 :            :     }
    1278                 :            : }
    1279                 :            : 
    1280                 :            : static PyObject *
    1281                 :          0 : PyCodec_SurrogateEscapeErrors(PyObject *exc)
    1282                 :            : {
    1283                 :            :     PyObject *restuple;
    1284                 :            :     PyObject *object;
    1285                 :            :     Py_ssize_t i;
    1286                 :            :     Py_ssize_t start;
    1287                 :            :     Py_ssize_t end;
    1288                 :            :     PyObject *res;
    1289                 :            : 
    1290         [ #  # ]:          0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
    1291                 :            :         char *outp;
    1292         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetStart(exc, &start))
    1293                 :          0 :             return NULL;
    1294         [ #  # ]:          0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
    1295                 :          0 :             return NULL;
    1296         [ #  # ]:          0 :         if (!(object = PyUnicodeEncodeError_GetObject(exc)))
    1297                 :          0 :             return NULL;
    1298                 :          0 :         res = PyBytes_FromStringAndSize(NULL, end-start);
    1299         [ #  # ]:          0 :         if (!res) {
    1300                 :          0 :             Py_DECREF(object);
    1301                 :          0 :             return NULL;
    1302                 :            :         }
    1303                 :          0 :         outp = PyBytes_AsString(res);
    1304         [ #  # ]:          0 :         for (i = start; i < end; i++) {
    1305                 :            :             /* object is guaranteed to be "ready" */
    1306                 :          0 :             Py_UCS4 ch = PyUnicode_READ_CHAR(object, i);
    1307   [ #  #  #  # ]:          0 :             if (ch < 0xdc80 || ch > 0xdcff) {
    1308                 :            :                 /* Not a UTF-8b surrogate, fail with original exception */
    1309                 :          0 :                 PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
    1310                 :          0 :                 Py_DECREF(res);
    1311                 :          0 :                 Py_DECREF(object);
    1312                 :          0 :                 return NULL;
    1313                 :            :             }
    1314                 :          0 :             *outp++ = ch - 0xdc00;
    1315                 :            :         }
    1316                 :          0 :         restuple = Py_BuildValue("(On)", res, end);
    1317                 :          0 :         Py_DECREF(res);
    1318                 :          0 :         Py_DECREF(object);
    1319                 :          0 :         return restuple;
    1320                 :            :     }
    1321         [ #  # ]:          0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
    1322                 :            :         PyObject *str;
    1323                 :            :         const unsigned char *p;
    1324                 :            :         Py_UCS2 ch[4]; /* decode up to 4 bad bytes. */
    1325                 :          0 :         int consumed = 0;
    1326         [ #  # ]:          0 :         if (PyUnicodeDecodeError_GetStart(exc, &start))
    1327                 :          0 :             return NULL;
    1328         [ #  # ]:          0 :         if (PyUnicodeDecodeError_GetEnd(exc, &end))
    1329                 :          0 :             return NULL;
    1330         [ #  # ]:          0 :         if (!(object = PyUnicodeDecodeError_GetObject(exc)))
    1331                 :          0 :             return NULL;
    1332                 :          0 :         p = (const unsigned char*)PyBytes_AS_STRING(object);
    1333   [ #  #  #  # ]:          0 :         while (consumed < 4 && consumed < end-start) {
    1334                 :            :             /* Refuse to escape ASCII bytes. */
    1335         [ #  # ]:          0 :             if (p[start+consumed] < 128)
    1336                 :          0 :                 break;
    1337                 :          0 :             ch[consumed] = 0xdc00 + p[start+consumed];
    1338                 :          0 :             consumed++;
    1339                 :            :         }
    1340                 :          0 :         Py_DECREF(object);
    1341         [ #  # ]:          0 :         if (!consumed) {
    1342                 :            :             /* codec complained about ASCII byte. */
    1343                 :          0 :             PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
    1344                 :          0 :             return NULL;
    1345                 :            :         }
    1346                 :          0 :         str = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, ch, consumed);
    1347         [ #  # ]:          0 :         if (str == NULL)
    1348                 :          0 :             return NULL;
    1349                 :          0 :         return Py_BuildValue("(Nn)", str, start+consumed);
    1350                 :            :     }
    1351                 :            :     else {
    1352                 :          0 :         wrong_exception_type(exc);
    1353                 :          0 :         return NULL;
    1354                 :            :     }
    1355                 :            : }
    1356                 :            : 
    1357                 :            : 
    1358                 :          2 : static PyObject *strict_errors(PyObject *self, PyObject *exc)
    1359                 :            : {
    1360                 :          2 :     return PyCodec_StrictErrors(exc);
    1361                 :            : }
    1362                 :            : 
    1363                 :            : 
    1364                 :          0 : static PyObject *ignore_errors(PyObject *self, PyObject *exc)
    1365                 :            : {
    1366                 :          0 :     return PyCodec_IgnoreErrors(exc);
    1367                 :            : }
    1368                 :            : 
    1369                 :            : 
    1370                 :          0 : static PyObject *replace_errors(PyObject *self, PyObject *exc)
    1371                 :            : {
    1372                 :          0 :     return PyCodec_ReplaceErrors(exc);
    1373                 :            : }
    1374                 :            : 
    1375                 :            : 
    1376                 :          0 : static PyObject *xmlcharrefreplace_errors(PyObject *self, PyObject *exc)
    1377                 :            : {
    1378                 :          0 :     return PyCodec_XMLCharRefReplaceErrors(exc);
    1379                 :            : }
    1380                 :            : 
    1381                 :            : 
    1382                 :          0 : static PyObject *backslashreplace_errors(PyObject *self, PyObject *exc)
    1383                 :            : {
    1384                 :          0 :     return PyCodec_BackslashReplaceErrors(exc);
    1385                 :            : }
    1386                 :            : 
    1387                 :          0 : static PyObject *namereplace_errors(PyObject *self, PyObject *exc)
    1388                 :            : {
    1389                 :          0 :     return PyCodec_NameReplaceErrors(exc);
    1390                 :            : }
    1391                 :            : 
    1392                 :          0 : static PyObject *surrogatepass_errors(PyObject *self, PyObject *exc)
    1393                 :            : {
    1394                 :          0 :     return PyCodec_SurrogatePassErrors(exc);
    1395                 :            : }
    1396                 :            : 
    1397                 :          0 : static PyObject *surrogateescape_errors(PyObject *self, PyObject *exc)
    1398                 :            : {
    1399                 :          0 :     return PyCodec_SurrogateEscapeErrors(exc);
    1400                 :            : }
    1401                 :            : 
    1402                 :         25 : static int _PyCodecRegistry_Init(void)
    1403                 :            : {
    1404                 :            :     static struct {
    1405                 :            :         const char *name;
    1406                 :            :         PyMethodDef def;
    1407                 :            :     } methods[] =
    1408                 :            :     {
    1409                 :            :         {
    1410                 :            :             "strict",
    1411                 :            :             {
    1412                 :            :                 "strict_errors",
    1413                 :            :                 strict_errors,
    1414                 :            :                 METH_O,
    1415                 :            :                 PyDoc_STR("Implements the 'strict' error handling, which "
    1416                 :            :                           "raises a UnicodeError on coding errors.")
    1417                 :            :             }
    1418                 :            :         },
    1419                 :            :         {
    1420                 :            :             "ignore",
    1421                 :            :             {
    1422                 :            :                 "ignore_errors",
    1423                 :            :                 ignore_errors,
    1424                 :            :                 METH_O,
    1425                 :            :                 PyDoc_STR("Implements the 'ignore' error handling, which "
    1426                 :            :                           "ignores malformed data and continues.")
    1427                 :            :             }
    1428                 :            :         },
    1429                 :            :         {
    1430                 :            :             "replace",
    1431                 :            :             {
    1432                 :            :                 "replace_errors",
    1433                 :            :                 replace_errors,
    1434                 :            :                 METH_O,
    1435                 :            :                 PyDoc_STR("Implements the 'replace' error handling, which "
    1436                 :            :                           "replaces malformed data with a replacement marker.")
    1437                 :            :             }
    1438                 :            :         },
    1439                 :            :         {
    1440                 :            :             "xmlcharrefreplace",
    1441                 :            :             {
    1442                 :            :                 "xmlcharrefreplace_errors",
    1443                 :            :                 xmlcharrefreplace_errors,
    1444                 :            :                 METH_O,
    1445                 :            :                 PyDoc_STR("Implements the 'xmlcharrefreplace' error handling, "
    1446                 :            :                           "which replaces an unencodable character with the "
    1447                 :            :                           "appropriate XML character reference.")
    1448                 :            :             }
    1449                 :            :         },
    1450                 :            :         {
    1451                 :            :             "backslashreplace",
    1452                 :            :             {
    1453                 :            :                 "backslashreplace_errors",
    1454                 :            :                 backslashreplace_errors,
    1455                 :            :                 METH_O,
    1456                 :            :                 PyDoc_STR("Implements the 'backslashreplace' error handling, "
    1457                 :            :                           "which replaces malformed data with a backslashed "
    1458                 :            :                           "escape sequence.")
    1459                 :            :             }
    1460                 :            :         },
    1461                 :            :         {
    1462                 :            :             "namereplace",
    1463                 :            :             {
    1464                 :            :                 "namereplace_errors",
    1465                 :            :                 namereplace_errors,
    1466                 :            :                 METH_O,
    1467                 :            :                 PyDoc_STR("Implements the 'namereplace' error handling, "
    1468                 :            :                           "which replaces an unencodable character with a "
    1469                 :            :                           "\\N{...} escape sequence.")
    1470                 :            :             }
    1471                 :            :         },
    1472                 :            :         {
    1473                 :            :             "surrogatepass",
    1474                 :            :             {
    1475                 :            :                 "surrogatepass",
    1476                 :            :                 surrogatepass_errors,
    1477                 :            :                 METH_O
    1478                 :            :             }
    1479                 :            :         },
    1480                 :            :         {
    1481                 :            :             "surrogateescape",
    1482                 :            :             {
    1483                 :            :                 "surrogateescape",
    1484                 :            :                 surrogateescape_errors,
    1485                 :            :                 METH_O
    1486                 :            :             }
    1487                 :            :         }
    1488                 :            :     };
    1489                 :            : 
    1490                 :         25 :     PyInterpreterState *interp = _PyInterpreterState_GET();
    1491                 :            :     PyObject *mod;
    1492                 :            : 
    1493         [ -  + ]:         25 :     if (interp->codec_search_path != NULL)
    1494                 :          0 :         return 0;
    1495                 :            : 
    1496                 :         25 :     interp->codec_search_path = PyList_New(0);
    1497         [ -  + ]:         25 :     if (interp->codec_search_path == NULL) {
    1498                 :          0 :         return -1;
    1499                 :            :     }
    1500                 :            : 
    1501                 :         25 :     interp->codec_search_cache = PyDict_New();
    1502         [ -  + ]:         25 :     if (interp->codec_search_cache == NULL) {
    1503                 :          0 :         return -1;
    1504                 :            :     }
    1505                 :            : 
    1506                 :         25 :     interp->codec_error_registry = PyDict_New();
    1507         [ -  + ]:         25 :     if (interp->codec_error_registry == NULL) {
    1508                 :          0 :         return -1;
    1509                 :            :     }
    1510                 :            : 
    1511         [ +  + ]:        225 :     for (size_t i = 0; i < Py_ARRAY_LENGTH(methods); ++i) {
    1512                 :        200 :         PyObject *func = PyCFunction_NewEx(&methods[i].def, NULL, NULL);
    1513         [ -  + ]:        200 :         if (!func) {
    1514                 :          0 :             return -1;
    1515                 :            :         }
    1516                 :            : 
    1517                 :        200 :         int res = PyCodec_RegisterError(methods[i].name, func);
    1518                 :        200 :         Py_DECREF(func);
    1519         [ -  + ]:        200 :         if (res) {
    1520                 :          0 :             return -1;
    1521                 :            :         }
    1522                 :            :     }
    1523                 :            : 
    1524                 :         25 :     mod = PyImport_ImportModule("encodings");
    1525         [ -  + ]:         25 :     if (mod == NULL) {
    1526                 :          0 :         return -1;
    1527                 :            :     }
    1528                 :         25 :     Py_DECREF(mod);
    1529                 :         25 :     interp->codecs_initialized = 1;
    1530                 :         25 :     return 0;
    1531                 :            : }

Generated by: LCOV version 1.14