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

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

Generated by: LCOV version 1.14