LCOV - code coverage report
Current view: top level - Python - codecs.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 89 481 18.5 %
Date: 2017-04-19 Functions: 8 40 20.0 %

          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 <ctype.h>
      13             : 
      14             : /* --- Codec Registry ----------------------------------------------------- */
      15             : 
      16             : /* Import the standard encodings package which will register the first
      17             :    codec search function.
      18             : 
      19             :    This is done in a lazy way so that the Unicode implementation does
      20             :    not downgrade startup time of scripts not needing it.
      21             : 
      22             :    ImportErrors are silently ignored by this function. Only one try is
      23             :    made.
      24             : 
      25             : */
      26             : 
      27             : static int _PyCodecRegistry_Init(void); /* Forward */
      28             : 
      29           3 : int PyCodec_Register(PyObject *search_function)
      30             : {
      31           3 :     PyInterpreterState *interp = PyThreadState_GET()->interp;
      32           3 :     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
      33           0 :         goto onError;
      34           3 :     if (search_function == NULL) {
      35           0 :         PyErr_BadArgument();
      36           0 :         goto onError;
      37             :     }
      38           3 :     if (!PyCallable_Check(search_function)) {
      39           0 :         PyErr_SetString(PyExc_TypeError, "argument must be callable");
      40           0 :         goto onError;
      41             :     }
      42           3 :     return PyList_Append(interp->codec_search_path, search_function);
      43             : 
      44             :  onError:
      45           0 :     return -1;
      46             : }
      47             : 
      48             : /* Convert a string to a normalized Python string: all characters are
      49             :    converted to lower case, spaces are replaced with underscores. */
      50             : 
      51             : static
      52           3 : PyObject *normalizestring(const char *string)
      53             : {
      54             :     register size_t i;
      55           3 :     size_t len = strlen(string);
      56             :     char *p;
      57             :     PyObject *v;
      58             : 
      59           3 :     if (len > PY_SSIZE_T_MAX) {
      60           0 :         PyErr_SetString(PyExc_OverflowError, "string is too large");
      61           0 :         return NULL;
      62             :     }
      63             : 
      64           3 :     v = PyString_FromStringAndSize(NULL, len);
      65           3 :     if (v == NULL)
      66           0 :         return NULL;
      67           3 :     p = PyString_AS_STRING(v);
      68          18 :     for (i = 0; i < len; i++) {
      69          15 :         register char ch = string[i];
      70          15 :         if (ch == ' ')
      71           0 :             ch = '-';
      72             :         else
      73          15 :             ch = Py_TOLOWER(Py_CHARMASK(ch));
      74          15 :         p[i] = ch;
      75             :     }
      76           3 :     return v;
      77             : }
      78             : 
      79             : /* Lookup the given encoding and return a tuple providing the codec
      80             :    facilities.
      81             : 
      82             :    The encoding string is looked up converted to all lower-case
      83             :    characters. This makes encodings looked up through this mechanism
      84             :    effectively case-insensitive.
      85             : 
      86             :    If no codec is found, a LookupError is set and NULL returned.
      87             : 
      88             :    As side effect, this tries to load the encodings package, if not
      89             :    yet done. This is part of the lazy load strategy for the encodings
      90             :    package.
      91             : 
      92             : */
      93             : 
      94           3 : PyObject *_PyCodec_Lookup(const char *encoding)
      95             : {
      96             :     PyInterpreterState *interp;
      97           3 :     PyObject *result, *args = NULL, *v;
      98             :     Py_ssize_t i, len;
      99             : 
     100           3 :     if (encoding == NULL) {
     101           0 :         PyErr_BadArgument();
     102           0 :         goto onError;
     103             :     }
     104             : 
     105           3 :     interp = PyThreadState_GET()->interp;
     106           3 :     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
     107           0 :         goto onError;
     108             : 
     109             :     /* Convert the encoding to a normalized Python string: all
     110             :        characters are converted to lower case, spaces and hyphens are
     111             :        replaced with underscores. */
     112           3 :     v = normalizestring(encoding);
     113           3 :     if (v == NULL)
     114           0 :         goto onError;
     115           3 :     PyString_InternInPlace(&v);
     116             : 
     117             :     /* First, try to lookup the name in the registry dictionary */
     118           3 :     result = PyDict_GetItem(interp->codec_search_cache, v);
     119           3 :     if (result != NULL) {
     120           0 :         Py_INCREF(result);
     121           0 :         Py_DECREF(v);
     122           0 :         return result;
     123             :     }
     124             : 
     125             :     /* Next, scan the search functions in order of registration */
     126           3 :     args = PyTuple_New(1);
     127           3 :     if (args == NULL)
     128           0 :         goto onError;
     129           3 :     PyTuple_SET_ITEM(args,0,v);
     130             : 
     131           3 :     len = PyList_Size(interp->codec_search_path);
     132           3 :     if (len < 0)
     133           0 :         goto onError;
     134           3 :     if (len == 0) {
     135           0 :         PyErr_SetString(PyExc_LookupError,
     136             :                         "no codec search functions registered: "
     137             :                         "can't find encoding");
     138           0 :         goto onError;
     139             :     }
     140             : 
     141           6 :     for (i = 0; i < len; i++) {
     142             :         PyObject *func;
     143             : 
     144           3 :         func = PyList_GetItem(interp->codec_search_path, i);
     145           3 :         if (func == NULL)
     146           0 :             goto onError;
     147           3 :         result = PyEval_CallObject(func, args);
     148           3 :         if (result == NULL)
     149           0 :             goto onError;
     150           3 :         if (result == Py_None) {
     151           0 :             Py_DECREF(result);
     152           0 :             continue;
     153             :         }
     154           3 :         if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 4) {
     155           0 :             PyErr_SetString(PyExc_TypeError,
     156             :                             "codec search functions must return 4-tuples");
     157           0 :             Py_DECREF(result);
     158           0 :             goto onError;
     159             :         }
     160           3 :         break;
     161             :     }
     162           3 :     if (i == len) {
     163             :         /* XXX Perhaps we should cache misses too ? */
     164           0 :         PyErr_Format(PyExc_LookupError,
     165             :                      "unknown encoding: %s", encoding);
     166           0 :         goto onError;
     167             :     }
     168             : 
     169             :     /* Cache and return the result */
     170           3 :     PyDict_SetItem(interp->codec_search_cache, v, result);
     171           3 :     Py_DECREF(args);
     172           3 :     return result;
     173             : 
     174             :  onError:
     175           0 :     Py_XDECREF(args);
     176           0 :     return NULL;
     177             : }
     178             : 
     179             : static
     180           0 : PyObject *args_tuple(PyObject *object,
     181             :                      const char *errors)
     182             : {
     183             :     PyObject *args;
     184             : 
     185           0 :     args = PyTuple_New(1 + (errors != NULL));
     186           0 :     if (args == NULL)
     187           0 :         return NULL;
     188           0 :     Py_INCREF(object);
     189           0 :     PyTuple_SET_ITEM(args,0,object);
     190           0 :     if (errors) {
     191             :         PyObject *v;
     192             : 
     193           0 :         v = PyString_FromString(errors);
     194           0 :         if (v == NULL) {
     195           0 :             Py_DECREF(args);
     196           0 :             return NULL;
     197             :         }
     198           0 :         PyTuple_SET_ITEM(args, 1, v);
     199             :     }
     200           0 :     return args;
     201             : }
     202             : 
     203             : /* Helper function to get a codec item */
     204             : 
     205             : static
     206           3 : PyObject *codec_getitem(const char *encoding, int index)
     207             : {
     208             :     PyObject *codecs;
     209             :     PyObject *v;
     210             : 
     211           3 :     codecs = _PyCodec_Lookup(encoding);
     212           3 :     if (codecs == NULL)
     213           0 :         return NULL;
     214           3 :     v = PyTuple_GET_ITEM(codecs, index);
     215           3 :     Py_DECREF(codecs);
     216           3 :     Py_INCREF(v);
     217           3 :     return v;
     218             : }
     219             : 
     220             : /* Helper functions to create an incremental codec. */
     221             : static
     222           0 : PyObject *codec_makeincrementalcodec(PyObject *codec_info,
     223             :                                      const char *errors,
     224             :                                      const char *attrname)
     225             : {
     226             :     PyObject *ret, *inccodec;
     227             : 
     228           0 :     inccodec = PyObject_GetAttrString(codec_info, attrname);
     229           0 :     if (inccodec == NULL)
     230           0 :         return NULL;
     231           0 :     if (errors)
     232           0 :         ret = PyObject_CallFunction(inccodec, "s", errors);
     233             :     else
     234           0 :         ret = PyObject_CallFunction(inccodec, NULL);
     235           0 :     Py_DECREF(inccodec);
     236           0 :     return ret;
     237             : }
     238             : 
     239             : static
     240           0 : PyObject *codec_getincrementalcodec(const char *encoding,
     241             :                                     const char *errors,
     242             :                                     const char *attrname)
     243             : {
     244             :     PyObject *codec_info, *ret;
     245             : 
     246           0 :     codec_info = _PyCodec_Lookup(encoding);
     247           0 :     if (codec_info == NULL)
     248           0 :         return NULL;
     249           0 :     ret = codec_makeincrementalcodec(codec_info, errors, attrname);
     250           0 :     Py_DECREF(codec_info);
     251           0 :     return ret;
     252             : }
     253             : 
     254             : /* Helper function to create a stream codec. */
     255             : 
     256             : static
     257           0 : PyObject *codec_getstreamcodec(const char *encoding,
     258             :                                PyObject *stream,
     259             :                                const char *errors,
     260             :                                const int index)
     261             : {
     262             :     PyObject *codecs, *streamcodec, *codeccls;
     263             : 
     264           0 :     codecs = _PyCodec_Lookup(encoding);
     265           0 :     if (codecs == NULL)
     266           0 :         return NULL;
     267             : 
     268           0 :     codeccls = PyTuple_GET_ITEM(codecs, index);
     269           0 :     if (errors != NULL)
     270           0 :         streamcodec = PyObject_CallFunction(codeccls, "Os", stream, errors);
     271             :     else
     272           0 :         streamcodec = PyObject_CallFunction(codeccls, "O", stream);
     273           0 :     Py_DECREF(codecs);
     274           0 :     return streamcodec;
     275             : }
     276             : 
     277             : /* Helpers to work with the result of _PyCodec_Lookup
     278             : 
     279             :  */
     280           0 : PyObject *_PyCodecInfo_GetIncrementalDecoder(PyObject *codec_info,
     281             :                                              const char *errors)
     282             : {
     283           0 :     return codec_makeincrementalcodec(codec_info, errors,
     284             :                                       "incrementaldecoder");
     285             : }
     286             : 
     287           0 : PyObject *_PyCodecInfo_GetIncrementalEncoder(PyObject *codec_info,
     288             :                                              const char *errors)
     289             : {
     290           0 :     return codec_makeincrementalcodec(codec_info, errors,
     291             :                                       "incrementalencoder");
     292             : }
     293             : 
     294             : 
     295             : /* Convenience APIs to query the Codec registry.
     296             : 
     297             :    All APIs return a codec object with incremented refcount.
     298             : 
     299             :  */
     300             : 
     301           3 : PyObject *PyCodec_Encoder(const char *encoding)
     302             : {
     303           3 :     return codec_getitem(encoding, 0);
     304             : }
     305             : 
     306           0 : PyObject *PyCodec_Decoder(const char *encoding)
     307             : {
     308           0 :     return codec_getitem(encoding, 1);
     309             : }
     310             : 
     311           0 : PyObject *PyCodec_IncrementalEncoder(const char *encoding,
     312             :                                      const char *errors)
     313             : {
     314           0 :     return codec_getincrementalcodec(encoding, errors, "incrementalencoder");
     315             : }
     316             : 
     317           0 : PyObject *PyCodec_IncrementalDecoder(const char *encoding,
     318             :                                      const char *errors)
     319             : {
     320           0 :     return codec_getincrementalcodec(encoding, errors, "incrementaldecoder");
     321             : }
     322             : 
     323           0 : PyObject *PyCodec_StreamReader(const char *encoding,
     324             :                                PyObject *stream,
     325             :                                const char *errors)
     326             : {
     327           0 :     return codec_getstreamcodec(encoding, stream, errors, 2);
     328             : }
     329             : 
     330           0 : PyObject *PyCodec_StreamWriter(const char *encoding,
     331             :                                PyObject *stream,
     332             :                                const char *errors)
     333             : {
     334           0 :     return codec_getstreamcodec(encoding, stream, errors, 3);
     335             : }
     336             : 
     337             : /* Encode an object (e.g. a Unicode object) using the given encoding
     338             :    and return the resulting encoded object (usually a Python string).
     339             : 
     340             :    errors is passed to the encoder factory as argument if non-NULL. */
     341             : 
     342             : static PyObject *
     343           0 : _PyCodec_EncodeInternal(PyObject *object,
     344             :                         PyObject *encoder,
     345             :                         const char *encoding,
     346             :                         const char *errors)
     347             : {
     348           0 :     PyObject *args = NULL, *result = NULL;
     349             :     PyObject *v;
     350             : 
     351           0 :     args = args_tuple(object, errors);
     352           0 :     if (args == NULL)
     353           0 :         goto onError;
     354             : 
     355           0 :     result = PyEval_CallObject(encoder,args);
     356           0 :     if (result == NULL)
     357           0 :         goto onError;
     358             : 
     359           0 :     if (!PyTuple_Check(result) ||
     360           0 :         PyTuple_GET_SIZE(result) != 2) {
     361           0 :         PyErr_SetString(PyExc_TypeError,
     362             :                         "encoder must return a tuple (object,integer)");
     363           0 :         goto onError;
     364             :     }
     365           0 :     v = PyTuple_GET_ITEM(result,0);
     366           0 :     Py_INCREF(v);
     367             :     /* We don't check or use the second (integer) entry. */
     368             : 
     369           0 :     Py_DECREF(args);
     370           0 :     Py_DECREF(encoder);
     371           0 :     Py_DECREF(result);
     372           0 :     return v;
     373             : 
     374             :  onError:
     375           0 :     Py_XDECREF(result);
     376           0 :     Py_XDECREF(args);
     377           0 :     Py_XDECREF(encoder);
     378           0 :     return NULL;
     379             : }
     380             : 
     381             : /* Decode an object (usually a Python string) using the given encoding
     382             :    and return an equivalent object (e.g. a Unicode object).
     383             : 
     384             :    errors is passed to the decoder factory as argument if non-NULL. */
     385             : 
     386             : static PyObject *
     387           0 : _PyCodec_DecodeInternal(PyObject *object,
     388             :                         PyObject *decoder,
     389             :                         const char *encoding,
     390             :                         const char *errors)
     391             : {
     392           0 :     PyObject *args = NULL, *result = NULL;
     393             :     PyObject *v;
     394             : 
     395           0 :     args = args_tuple(object, errors);
     396           0 :     if (args == NULL)
     397           0 :         goto onError;
     398             : 
     399           0 :     result = PyEval_CallObject(decoder,args);
     400           0 :     if (result == NULL)
     401           0 :         goto onError;
     402           0 :     if (!PyTuple_Check(result) ||
     403           0 :         PyTuple_GET_SIZE(result) != 2) {
     404           0 :         PyErr_SetString(PyExc_TypeError,
     405             :                         "decoder must return a tuple (object,integer)");
     406           0 :         goto onError;
     407             :     }
     408           0 :     v = PyTuple_GET_ITEM(result,0);
     409           0 :     Py_INCREF(v);
     410             :     /* We don't check or use the second (integer) entry. */
     411             : 
     412           0 :     Py_DECREF(args);
     413           0 :     Py_DECREF(decoder);
     414           0 :     Py_DECREF(result);
     415           0 :     return v;
     416             : 
     417             :  onError:
     418           0 :     Py_XDECREF(args);
     419           0 :     Py_XDECREF(decoder);
     420           0 :     Py_XDECREF(result);
     421           0 :     return NULL;
     422             : }
     423             : 
     424             : /* Generic encoding/decoding API */
     425           0 : PyObject *PyCodec_Encode(PyObject *object,
     426             :                          const char *encoding,
     427             :                          const char *errors)
     428             : {
     429             :     PyObject *encoder;
     430             : 
     431           0 :     encoder = PyCodec_Encoder(encoding);
     432           0 :     if (encoder == NULL)
     433           0 :         return NULL;
     434             : 
     435           0 :     return _PyCodec_EncodeInternal(object, encoder, encoding, errors);
     436             : }
     437             : 
     438           0 : PyObject *PyCodec_Decode(PyObject *object,
     439             :                          const char *encoding,
     440             :                          const char *errors)
     441             : {
     442             :     PyObject *decoder;
     443             : 
     444           0 :     decoder = PyCodec_Decoder(encoding);
     445           0 :     if (decoder == NULL)
     446           0 :         return NULL;
     447             : 
     448           0 :     return _PyCodec_DecodeInternal(object, decoder, encoding, errors);
     449             : }
     450             : 
     451             : /* Text encoding/decoding API */
     452           0 : PyObject * _PyCodec_LookupTextEncoding(const char *encoding,
     453             :                                        const char *alternate_command)
     454             : {
     455             :     PyObject *codec;
     456             :     PyObject *attr;
     457             :     int is_text_codec;
     458             : 
     459           0 :     codec = _PyCodec_Lookup(encoding);
     460           0 :     if (codec == NULL)
     461           0 :         return NULL;
     462             : 
     463             :     /* Backwards compatibility: assume any raw tuple describes a text
     464             :      * encoding, and the same for anything lacking the private
     465             :      * attribute.
     466             :      */
     467           0 :     if (Py_Py3kWarningFlag && !PyTuple_CheckExact(codec)) {
     468           0 :         attr = PyObject_GetAttrString(codec, "_is_text_encoding");
     469           0 :         if (attr == NULL) {
     470           0 :             if (!PyErr_ExceptionMatches(PyExc_AttributeError))
     471           0 :                 goto onError;
     472           0 :             PyErr_Clear();
     473             :         } else {
     474           0 :             is_text_codec = PyObject_IsTrue(attr);
     475           0 :             Py_DECREF(attr);
     476           0 :             if (is_text_codec < 0)
     477           0 :                 goto onError;
     478           0 :             if (!is_text_codec) {
     479           0 :                 PyObject *msg = PyString_FromFormat(
     480             :                             "'%.400s' is not a text encoding; "
     481             :                             "use %s to handle arbitrary codecs",
     482             :                             encoding, alternate_command);
     483           0 :                 if (msg == NULL)
     484           0 :                     goto onError;
     485           0 :                 if (PyErr_WarnPy3k(PyString_AS_STRING(msg), 1) < 0) {
     486           0 :                     Py_DECREF(msg);
     487           0 :                     goto onError;
     488             :                 }
     489           0 :                 Py_DECREF(msg);
     490             :             }
     491             :         }
     492             :     }
     493             : 
     494             :     /* This appears to be a valid text encoding */
     495           0 :     return codec;
     496             : 
     497             :  onError:
     498           0 :     Py_DECREF(codec);
     499           0 :     return NULL;
     500             : }
     501             : 
     502             : 
     503             : static
     504           0 : PyObject *codec_getitem_checked(const char *encoding,
     505             :                                 const char *alternate_command,
     506             :                                 int index)
     507             : {
     508             :     PyObject *codec;
     509             :     PyObject *v;
     510             : 
     511           0 :     codec = _PyCodec_LookupTextEncoding(encoding, alternate_command);
     512           0 :     if (codec == NULL)
     513           0 :         return NULL;
     514             : 
     515           0 :     v = PyTuple_GET_ITEM(codec, index);
     516           0 :     Py_INCREF(v);
     517           0 :     Py_DECREF(codec);
     518           0 :     return v;
     519             : }
     520             : 
     521           0 : static PyObject * _PyCodec_TextEncoder(const char *encoding)
     522             : {
     523           0 :     return codec_getitem_checked(encoding, "codecs.encode()", 0);
     524             : }
     525             : 
     526           0 : static PyObject * _PyCodec_TextDecoder(const char *encoding)
     527             : {
     528           0 :     return codec_getitem_checked(encoding, "codecs.decode()", 1);
     529             : }
     530             : 
     531           0 : PyObject *_PyCodec_EncodeText(PyObject *object,
     532             :                               const char *encoding,
     533             :                               const char *errors)
     534             : {
     535             :     PyObject *encoder;
     536             : 
     537           0 :     encoder = _PyCodec_TextEncoder(encoding);
     538           0 :     if (encoder == NULL)
     539           0 :         return NULL;
     540             : 
     541           0 :     return _PyCodec_EncodeInternal(object, encoder, encoding, errors);
     542             : }
     543             : 
     544           0 : PyObject *_PyCodec_DecodeText(PyObject *object,
     545             :                               const char *encoding,
     546             :                               const char *errors)
     547             : {
     548             :     PyObject *decoder;
     549             : 
     550           0 :     decoder = _PyCodec_TextDecoder(encoding);
     551           0 :     if (decoder == NULL)
     552           0 :         return NULL;
     553             : 
     554           0 :     return _PyCodec_DecodeInternal(object, decoder, encoding, errors);
     555             : }
     556             : 
     557             : /* Register the error handling callback function error under the name
     558             :    name. This function will be called by the codec when it encounters
     559             :    an unencodable characters/undecodable bytes and doesn't know the
     560             :    callback name, when name is specified as the error parameter
     561             :    in the call to the encode/decode function.
     562             :    Return 0 on success, -1 on error */
     563          15 : int PyCodec_RegisterError(const char *name, PyObject *error)
     564             : {
     565          15 :     PyInterpreterState *interp = PyThreadState_GET()->interp;
     566          15 :     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
     567           0 :         return -1;
     568          15 :     if (!PyCallable_Check(error)) {
     569           0 :         PyErr_SetString(PyExc_TypeError, "handler must be callable");
     570           0 :         return -1;
     571             :     }
     572          15 :     return PyDict_SetItemString(interp->codec_error_registry,
     573             :                                 (char *)name, error);
     574             : }
     575             : 
     576             : /* Lookup the error handling callback function registered under the
     577             :    name error. As a special case NULL can be passed, in which case
     578             :    the error handling callback for strict encoding will be returned. */
     579          15 : PyObject *PyCodec_LookupError(const char *name)
     580             : {
     581          15 :     PyObject *handler = NULL;
     582             : 
     583          15 :     PyInterpreterState *interp = PyThreadState_GET()->interp;
     584          15 :     if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
     585           0 :         return NULL;
     586             : 
     587          15 :     if (name==NULL)
     588           0 :         name = "strict";
     589          15 :     handler = PyDict_GetItemString(interp->codec_error_registry, (char *)name);
     590          15 :     if (!handler)
     591           0 :         PyErr_Format(PyExc_LookupError, "unknown error handler name '%.400s'", name);
     592             :     else
     593          15 :         Py_INCREF(handler);
     594          15 :     return handler;
     595             : }
     596             : 
     597           0 : static void wrong_exception_type(PyObject *exc)
     598             : {
     599           0 :     PyObject *type = PyObject_GetAttrString(exc, "__class__");
     600           0 :     if (type != NULL) {
     601           0 :         PyObject *name = PyObject_GetAttrString(type, "__name__");
     602           0 :         Py_DECREF(type);
     603           0 :         if (name != NULL) {
     604           0 :             PyObject *string = PyObject_Str(name);
     605           0 :             Py_DECREF(name);
     606           0 :             if (string != NULL) {
     607           0 :                 PyErr_Format(PyExc_TypeError,
     608             :                     "don't know how to handle %.400s in error callback",
     609           0 :                     PyString_AS_STRING(string));
     610           0 :                 Py_DECREF(string);
     611             :             }
     612             :         }
     613             :     }
     614           0 : }
     615             : 
     616           0 : PyObject *PyCodec_StrictErrors(PyObject *exc)
     617             : {
     618           0 :     if (PyExceptionInstance_Check(exc))
     619           0 :         PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
     620             :     else
     621           0 :         PyErr_SetString(PyExc_TypeError, "codec must pass exception instance");
     622           0 :     return NULL;
     623             : }
     624             : 
     625             : 
     626             : #ifdef Py_USING_UNICODE
     627           0 : PyObject *PyCodec_IgnoreErrors(PyObject *exc)
     628             : {
     629             :     Py_ssize_t end;
     630             : 
     631           0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
     632           0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
     633           0 :             return NULL;
     634             :     }
     635           0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
     636           0 :         if (PyUnicodeDecodeError_GetEnd(exc, &end))
     637           0 :             return NULL;
     638             :     }
     639           0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {
     640           0 :         if (PyUnicodeTranslateError_GetEnd(exc, &end))
     641           0 :             return NULL;
     642             :     }
     643             :     else {
     644           0 :         wrong_exception_type(exc);
     645           0 :         return NULL;
     646             :     }
     647             :     /* ouch: passing NULL, 0, pos gives None instead of u'' */
     648           0 :     return Py_BuildValue("(u#n)", &end, 0, end);
     649             : }
     650             : 
     651             : 
     652           0 : PyObject *PyCodec_ReplaceErrors(PyObject *exc)
     653             : {
     654             :     PyObject *restuple;
     655             :     Py_ssize_t start;
     656             :     Py_ssize_t end;
     657             :     Py_ssize_t i;
     658             : 
     659           0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
     660             :         PyObject *res;
     661             :         Py_UNICODE *p;
     662           0 :         if (PyUnicodeEncodeError_GetStart(exc, &start))
     663           0 :             return NULL;
     664           0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
     665           0 :             return NULL;
     666           0 :         res = PyUnicode_FromUnicode(NULL, end-start);
     667           0 :         if (res == NULL)
     668           0 :             return NULL;
     669           0 :         for (p = PyUnicode_AS_UNICODE(res), i = start;
     670           0 :             i<end; ++p, ++i)
     671           0 :             *p = '?';
     672           0 :         restuple = Py_BuildValue("(On)", res, end);
     673           0 :         Py_DECREF(res);
     674           0 :         return restuple;
     675             :     }
     676           0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {
     677           0 :         Py_UNICODE res = Py_UNICODE_REPLACEMENT_CHARACTER;
     678           0 :         if (PyUnicodeDecodeError_GetEnd(exc, &end))
     679           0 :             return NULL;
     680           0 :         return Py_BuildValue("(u#n)", &res, (Py_ssize_t)1, end);
     681             :     }
     682           0 :     else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {
     683             :         PyObject *res;
     684             :         Py_UNICODE *p;
     685           0 :         if (PyUnicodeTranslateError_GetStart(exc, &start))
     686           0 :             return NULL;
     687           0 :         if (PyUnicodeTranslateError_GetEnd(exc, &end))
     688           0 :             return NULL;
     689           0 :         res = PyUnicode_FromUnicode(NULL, end-start);
     690           0 :         if (res == NULL)
     691           0 :             return NULL;
     692           0 :         for (p = PyUnicode_AS_UNICODE(res), i = start;
     693           0 :             i<end; ++p, ++i)
     694           0 :             *p = Py_UNICODE_REPLACEMENT_CHARACTER;
     695           0 :         restuple = Py_BuildValue("(On)", res, end);
     696           0 :         Py_DECREF(res);
     697           0 :         return restuple;
     698             :     }
     699             :     else {
     700           0 :         wrong_exception_type(exc);
     701           0 :         return NULL;
     702             :     }
     703             : }
     704             : 
     705           0 : PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc)
     706             : {
     707           0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
     708             :         PyObject *restuple;
     709             :         PyObject *object;
     710             :         Py_ssize_t start;
     711             :         Py_ssize_t end;
     712             :         PyObject *res;
     713             :         Py_UNICODE *p;
     714             :         Py_UNICODE *startp;
     715             :         Py_UNICODE *e;
     716             :         Py_UNICODE *outp;
     717             :         Py_ssize_t ressize;
     718           0 :         if (PyUnicodeEncodeError_GetStart(exc, &start))
     719           0 :             return NULL;
     720           0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
     721           0 :             return NULL;
     722           0 :         if (!(object = PyUnicodeEncodeError_GetObject(exc)))
     723           0 :             return NULL;
     724           0 :         startp = PyUnicode_AS_UNICODE(object);
     725           0 :         if (end - start > PY_SSIZE_T_MAX / (2+7+1)) {
     726           0 :             end = start + PY_SSIZE_T_MAX / (2+7+1);
     727             : #ifndef Py_UNICODE_WIDE
     728           0 :             if (0xD800 <= startp[end - 1] && startp[end - 1] <= 0xDBFF)
     729           0 :                 end--;
     730             : #endif
     731             :         }
     732           0 :         e = startp + end;
     733           0 :         for (p = startp+start, ressize = 0; p < e;) {
     734           0 :             Py_UCS4 ch = *p++;
     735             : #ifndef Py_UNICODE_WIDE
     736           0 :             if ((0xD800 <= ch && ch <= 0xDBFF) &&
     737           0 :                 (p < e) &&
     738           0 :                 (0xDC00 <= *p && *p <= 0xDFFF)) {
     739           0 :                 ch = ((((ch & 0x03FF) << 10) |
     740           0 :                        ((Py_UCS4)*p++ & 0x03FF)) + 0x10000);
     741             :             }
     742             : #endif
     743           0 :             if (ch < 10)
     744           0 :                 ressize += 2+1+1;
     745           0 :             else if (ch < 100)
     746           0 :                 ressize += 2+2+1;
     747           0 :             else if (ch < 1000)
     748           0 :                 ressize += 2+3+1;
     749           0 :             else if (ch < 10000)
     750           0 :                 ressize += 2+4+1;
     751           0 :             else if (ch < 100000)
     752           0 :                 ressize += 2+5+1;
     753           0 :             else if (ch < 1000000)
     754           0 :                 ressize += 2+6+1;
     755             :             else
     756           0 :                 ressize += 2+7+1;
     757             :         }
     758             :         /* allocate replacement */
     759           0 :         res = PyUnicode_FromUnicode(NULL, ressize);
     760           0 :         if (res == NULL) {
     761           0 :             Py_DECREF(object);
     762           0 :             return NULL;
     763             :         }
     764             :         /* generate replacement */
     765           0 :         for (p = startp+start, outp = PyUnicode_AS_UNICODE(res); p < e;) {
     766             :             int digits;
     767             :             int base;
     768           0 :             Py_UCS4 ch = *p++;
     769             : #ifndef Py_UNICODE_WIDE
     770           0 :             if ((0xD800 <= ch && ch <= 0xDBFF) &&
     771           0 :                 (p < startp+end) &&
     772           0 :                 (0xDC00 <= *p && *p <= 0xDFFF)) {
     773           0 :                 ch = ((((ch & 0x03FF) << 10) |
     774           0 :                        ((Py_UCS4)*p++ & 0x03FF)) + 0x10000);
     775             :             }
     776             : #endif
     777           0 :             *outp++ = '&';
     778           0 :             *outp++ = '#';
     779           0 :             if (ch < 10) {
     780           0 :                 digits = 1;
     781           0 :                 base = 1;
     782             :             }
     783           0 :             else if (ch < 100) {
     784           0 :                 digits = 2;
     785           0 :                 base = 10;
     786             :             }
     787           0 :             else if (ch < 1000) {
     788           0 :                 digits = 3;
     789           0 :                 base = 100;
     790             :             }
     791           0 :             else if (ch < 10000) {
     792           0 :                 digits = 4;
     793           0 :                 base = 1000;
     794             :             }
     795           0 :             else if (ch < 100000) {
     796           0 :                 digits = 5;
     797           0 :                 base = 10000;
     798             :             }
     799           0 :             else if (ch < 1000000) {
     800           0 :                 digits = 6;
     801           0 :                 base = 100000;
     802             :             }
     803             :             else {
     804           0 :                 digits = 7;
     805           0 :                 base = 1000000;
     806             :             }
     807           0 :             while (digits-->0) {
     808           0 :                 *outp++ = '0' + ch/base;
     809           0 :                 ch %= base;
     810           0 :                 base /= 10;
     811             :             }
     812           0 :             *outp++ = ';';
     813             :         }
     814           0 :         restuple = Py_BuildValue("(On)", res, end);
     815           0 :         Py_DECREF(res);
     816           0 :         Py_DECREF(object);
     817           0 :         return restuple;
     818             :     }
     819             :     else {
     820           0 :         wrong_exception_type(exc);
     821           0 :         return NULL;
     822             :     }
     823             : }
     824             : 
     825             : static Py_UNICODE hexdigits[] = {
     826             :     '0', '1', '2', '3', '4', '5', '6', '7',
     827             :     '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
     828             : };
     829             : 
     830           0 : PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc)
     831             : {
     832           0 :     if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {
     833             :         PyObject *restuple;
     834             :         PyObject *object;
     835             :         Py_ssize_t start;
     836             :         Py_ssize_t end;
     837             :         PyObject *res;
     838             :         Py_UNICODE *p;
     839             :         Py_UNICODE *startp;
     840             :         Py_UNICODE *outp;
     841             :         Py_ssize_t ressize;
     842           0 :         if (PyUnicodeEncodeError_GetStart(exc, &start))
     843           0 :             return NULL;
     844           0 :         if (PyUnicodeEncodeError_GetEnd(exc, &end))
     845           0 :             return NULL;
     846           0 :         if (!(object = PyUnicodeEncodeError_GetObject(exc)))
     847           0 :             return NULL;
     848           0 :         if (end - start > PY_SSIZE_T_MAX / (1+1+8))
     849           0 :             end = start + PY_SSIZE_T_MAX / (1+1+8);
     850           0 :         startp = PyUnicode_AS_UNICODE(object);
     851           0 :         for (p = startp+start, ressize = 0; p < startp+end; ++p) {
     852             : #ifdef Py_UNICODE_WIDE
     853             :             if (*p >= 0x00010000)
     854             :                 ressize += 1+1+8;
     855             :             else
     856             : #endif
     857           0 :             if (*p >= 0x100) {
     858           0 :                 ressize += 1+1+4;
     859             :             }
     860             :             else
     861           0 :                 ressize += 1+1+2;
     862             :         }
     863           0 :         res = PyUnicode_FromUnicode(NULL, ressize);
     864           0 :         if (res == NULL) {
     865           0 :             Py_DECREF(object);
     866           0 :             return NULL;
     867             :         }
     868           0 :         for (p = startp+start, outp = PyUnicode_AS_UNICODE(res);
     869           0 :             p < startp+end; ++p) {
     870           0 :             Py_UNICODE c = *p;
     871           0 :             *outp++ = '\\';
     872             : #ifdef Py_UNICODE_WIDE
     873             :             if (c >= 0x00010000) {
     874             :                 *outp++ = 'U';
     875             :                 *outp++ = hexdigits[(c>>28)&0xf];
     876             :                 *outp++ = hexdigits[(c>>24)&0xf];
     877             :                 *outp++ = hexdigits[(c>>20)&0xf];
     878             :                 *outp++ = hexdigits[(c>>16)&0xf];
     879             :                 *outp++ = hexdigits[(c>>12)&0xf];
     880             :                 *outp++ = hexdigits[(c>>8)&0xf];
     881             :             }
     882             :             else
     883             : #endif
     884           0 :             if (c >= 0x100) {
     885           0 :                 *outp++ = 'u';
     886           0 :                 *outp++ = hexdigits[(c>>12)&0xf];
     887           0 :                 *outp++ = hexdigits[(c>>8)&0xf];
     888             :             }
     889             :             else
     890           0 :                 *outp++ = 'x';
     891           0 :             *outp++ = hexdigits[(c>>4)&0xf];
     892           0 :             *outp++ = hexdigits[c&0xf];
     893             :         }
     894             : 
     895           0 :         restuple = Py_BuildValue("(On)", res, end);
     896           0 :         Py_DECREF(res);
     897           0 :         Py_DECREF(object);
     898           0 :         return restuple;
     899             :     }
     900             :     else {
     901           0 :         wrong_exception_type(exc);
     902           0 :         return NULL;
     903             :     }
     904             : }
     905             : #endif
     906             : 
     907           0 : static PyObject *strict_errors(PyObject *self, PyObject *exc)
     908             : {
     909           0 :     return PyCodec_StrictErrors(exc);
     910             : }
     911             : 
     912             : 
     913             : #ifdef Py_USING_UNICODE
     914           0 : static PyObject *ignore_errors(PyObject *self, PyObject *exc)
     915             : {
     916           0 :     return PyCodec_IgnoreErrors(exc);
     917             : }
     918             : 
     919             : 
     920           0 : static PyObject *replace_errors(PyObject *self, PyObject *exc)
     921             : {
     922           0 :     return PyCodec_ReplaceErrors(exc);
     923             : }
     924             : 
     925             : 
     926           0 : static PyObject *xmlcharrefreplace_errors(PyObject *self, PyObject *exc)
     927             : {
     928           0 :     return PyCodec_XMLCharRefReplaceErrors(exc);
     929             : }
     930             : 
     931             : 
     932           0 : static PyObject *backslashreplace_errors(PyObject *self, PyObject *exc)
     933             : {
     934           0 :     return PyCodec_BackslashReplaceErrors(exc);
     935             : }
     936             : #endif
     937             : 
     938           3 : static int _PyCodecRegistry_Init(void)
     939             : {
     940             :     static struct {
     941             :         char *name;
     942             :         PyMethodDef def;
     943             :     } methods[] =
     944             :     {
     945             :         {
     946             :             "strict",
     947             :             {
     948             :                 "strict_errors",
     949             :                 strict_errors,
     950             :                 METH_O,
     951             :                 PyDoc_STR("Implements the 'strict' error handling, which "
     952             :                           "raises a UnicodeError on coding errors.")
     953             :             }
     954             :         },
     955             : #ifdef Py_USING_UNICODE
     956             :         {
     957             :             "ignore",
     958             :             {
     959             :                 "ignore_errors",
     960             :                 ignore_errors,
     961             :                 METH_O,
     962             :                 PyDoc_STR("Implements the 'ignore' error handling, which "
     963             :                           "ignores malformed data and continues.")
     964             :             }
     965             :         },
     966             :         {
     967             :             "replace",
     968             :             {
     969             :                 "replace_errors",
     970             :                 replace_errors,
     971             :                 METH_O,
     972             :                 PyDoc_STR("Implements the 'replace' error handling, which "
     973             :                           "replaces malformed data with a replacement marker.")
     974             :             }
     975             :         },
     976             :         {
     977             :             "xmlcharrefreplace",
     978             :             {
     979             :                 "xmlcharrefreplace_errors",
     980             :                 xmlcharrefreplace_errors,
     981             :                 METH_O,
     982             :                 PyDoc_STR("Implements the 'xmlcharrefreplace' error handling, "
     983             :                           "which replaces an unencodable character with the "
     984             :                           "appropriate XML character reference.")
     985             :             }
     986             :         },
     987             :         {
     988             :             "backslashreplace",
     989             :             {
     990             :                 "backslashreplace_errors",
     991             :                 backslashreplace_errors,
     992             :                 METH_O,
     993             :                 PyDoc_STR("Implements the 'backslashreplace' error handling, "
     994             :                           "which replaces an unencodable character with a "
     995             :                           "backslashed escape sequence.")
     996             :             }
     997             :         }
     998             : #endif
     999             :     };
    1000             : 
    1001           3 :     PyInterpreterState *interp = PyThreadState_GET()->interp;
    1002             :     PyObject *mod;
    1003             :     unsigned i;
    1004             : 
    1005           3 :     if (interp->codec_search_path != NULL)
    1006           0 :         return 0;
    1007             : 
    1008           3 :     interp->codec_search_path = PyList_New(0);
    1009           3 :     interp->codec_search_cache = PyDict_New();
    1010           3 :     interp->codec_error_registry = PyDict_New();
    1011             : 
    1012           3 :     if (interp->codec_error_registry) {
    1013          18 :         for (i = 0; i < sizeof(methods)/sizeof(methods[0]); ++i) {
    1014          15 :             PyObject *func = PyCFunction_New(&methods[i].def, NULL);
    1015             :             int res;
    1016          15 :             if (!func)
    1017           0 :                 Py_FatalError("can't initialize codec error registry");
    1018          15 :             res = PyCodec_RegisterError(methods[i].name, func);
    1019          15 :             Py_DECREF(func);
    1020          15 :             if (res)
    1021           0 :                 Py_FatalError("can't initialize codec error registry");
    1022             :         }
    1023             :     }
    1024             : 
    1025           6 :     if (interp->codec_search_path == NULL ||
    1026           6 :         interp->codec_search_cache == NULL ||
    1027           3 :         interp->codec_error_registry == NULL)
    1028           0 :         Py_FatalError("can't initialize codec registry");
    1029             : 
    1030           3 :     mod = PyImport_ImportModuleLevel("encodings", NULL, NULL, NULL, 0);
    1031           3 :     if (mod == NULL) {
    1032           0 :         if (PyErr_ExceptionMatches(PyExc_ImportError)) {
    1033             :             /* Ignore ImportErrors... this is done so that
    1034             :                distributions can disable the encodings package. Note
    1035             :                that other errors are not masked, e.g. SystemErrors
    1036             :                raised to inform the user of an error in the Python
    1037             :                configuration are still reported back to the user. */
    1038           0 :             PyErr_Clear();
    1039           0 :             return 0;
    1040             :         }
    1041           0 :         return -1;
    1042             :     }
    1043           3 :     Py_DECREF(mod);
    1044           3 :     return 0;
    1045             : }

Generated by: LCOV version 1.10