LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Python - codecs.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 101 530 19.1 %
Date: 2012-12-17 Functions: 9 34 26.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10