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 : }
|