LCOV - code coverage report
Current view: top level - Python - codecs.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 651 780 83.5 %
Date: 2022-07-20 13:12:14 Functions: 46 50 92.0 %
Branches: 322 448 71.9 %

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

Generated by: LCOV version 1.14