blob: 99632306c46626584f5bd1c0c82473d933b89cde [file] [log] [blame]
Martin v. Löwis9789aef2003-01-26 11:30:36 +00001/*
2 * _iconv_codec.c
3 *
4 * libiconv adaptor for Python iconvcodec
5 *
6 * Author : Hye-Shik Chang <perky@FreeBSD.org>
7 * Created : 17 January 2003
8 */
9
10#include "Python.h"
11#include <string.h>
12#include <iconv.h>
13
14static const char *__version__ = "$Revision$";
15
16#if Py_USING_UNICODE
17# if Py_UNICODE_SIZE == 2
18# ifdef __GNU_LIBRARY__
19# define UNICODE_ENCODING "ucs-2"
20# else
21# define UNICODE_ENCODING "ucs-2-internal"
22# endif
23# define MBENCODED_LENGTH_MAX 4
24# elif Py_UNICODE_SIZE == 4
25# ifdef __GNU_LIBRARY__
26# define UNICODE_ENCODING "ucs-4"
27# else
28# define UNICODE_ENCODING "ucs-4-internal"
29# endif
30# define MBENCODED_LENGTH_MAX 6
31# endif
32#else
33# error "Unicode is not available"
34#endif
35
36typedef struct {
37 PyObject_HEAD
38 iconv_t enchdl, dechdl;
39 char *encoding;
40} iconvcodecObject;
41PyDoc_STRVAR(iconvcodec_doc, "iconvcodec object");
42
Walter Dörwaldbda1c862003-02-04 18:02:28 +000043/* does the chosen internal encoding require
Walter Dörwaldb4ff1112003-01-30 19:55:28 +000044 * byteswapping to get native endianness?
45 * 0=no, 1=yes, -1=unknown */
46static int byteswap = -1;
Martin v. Löwis9789aef2003-01-26 11:30:36 +000047
48#define ERROR_STRICT (PyObject *)(1)
49#define ERROR_IGNORE (PyObject *)(2)
50#define ERROR_REPLACE (PyObject *)(3)
51#define ERROR_MAX ERROR_REPLACE
52
53#define REPLACEMENT_CHAR_DECODE 0xFFFD
54#define REPLACEMENT_CHAR_ENCODE '?'
55
56#define DEFAULT_ENCODING "utf-8"
57
58
59static PyObject *
60get_errorcallback(const char *errors)
61{
62 if (errors == NULL || strcmp(errors, "strict") == 0)
63 return ERROR_STRICT;
64 else if (strcmp(errors, "ignore") == 0)
65 return ERROR_IGNORE;
66 else if (strcmp(errors, "replace") == 0)
67 return ERROR_REPLACE;
68 else
69 return PyCodec_LookupError(errors);
70}
71
72
73PyDoc_STRVAR(iconvcodec_encode__doc__,
74"I.encode(unicode, [,errors]) -> (string, length consumed)\n\
75\n\
76Return an encoded string version of `unicode'. errors may be given to\n\
77set a different error handling scheme. Default is 'strict' meaning that\n\
78encoding errors raise a UnicodeEncodeError. Other possible values are\n\
79'ignore', 'replace' and 'xmlcharrefreplace' as well as any other name\n\
80registered with codecs.register_error that can handle UnicodeEncodeErrors.");
81
82static PyObject *
83iconvcodec_encode(iconvcodecObject *self, PyObject *args, PyObject *kwargs)
84{
85 static char *kwlist[] = { "input", "errors", NULL };
86 Py_UNICODE *input;
87 int inputlen;
88 char *errors = NULL/*strict*/, *out, *out_top;
89 const char *inp, *inp_top;
90 size_t inplen, inplen_total, outlen, outlen_total, estep;
91 PyObject *outputobj = NULL, *errorcb = NULL,
92 *exceptionobj = NULL;
Walter Dörwald757246c2003-01-31 16:26:50 +000093 Py_UNICODE *swappedinput = NULL;
Walter Dörwaldb4ff1112003-01-30 19:55:28 +000094 int swapi;
Martin v. Löwis9789aef2003-01-26 11:30:36 +000095
96 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "u#|s:encode",
97 kwlist, &input, &inputlen, &errors))
98 return NULL; /* TypeError */
99
100 errorcb = get_errorcallback(errors);
101 if (errorcb == NULL)
102 return NULL; /* LookupError or something else from error handler */
103
104 inp = inp_top = (char *)input;
105 inplen = inplen_total = (size_t)(inputlen * Py_UNICODE_SIZE);
106
107 outlen = inputlen * MBENCODED_LENGTH_MAX;
108 if (outlen < 16)
109 outlen = 16; /* for iso-2022 codecs */
110
111 outputobj = PyString_FromStringAndSize(NULL, outlen);
112 if (outputobj == NULL)
113 return NULL;
114 out = out_top = PyString_AS_STRING(outputobj);
115 outlen_total = outlen;
116
117 estep = inputlen * Py_UNICODE_SIZE / 2;
118
119#define RESIZE_OUTBUFFER(size) { \
120 size_t toadd = (size); \
121 outlen_total += toadd; \
122 outlen += toadd; \
123 if (_PyString_Resize(&outputobj, outlen_total) == -1) \
124 goto errorexit; \
125 out = PyString_AS_STRING(outputobj) + (out - out_top); \
126 out_top = PyString_AS_STRING(outputobj); \
127}
Walter Dörwaldb4ff1112003-01-30 19:55:28 +0000128 if (byteswap) {
129 swappedinput = PyMem_Malloc(inplen);
130 if (swappedinput == NULL)
131 return NULL;
132 for (swapi = 0; swapi<inputlen; ++swapi)
133 {
134 Py_UNICODE c = input[swapi];
135#if Py_UNICODE_SIZE == 2
136 c = ((char *)&c)[0]<<8 | ((char *)&c)[1];
137#else
138 c = ((char *)&c)[0]<<24 | ((char *)&c)[1]<<16 |
139 ((char *)&c)[2]<<8 | ((char *)&c)[3];
140#endif
141 swappedinput[swapi] = c;
142 }
143 inp = inp_top = (char *)swappedinput;
144 }
145
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000146 while (inplen > 0) {
Walter Dörwaldbda1c862003-02-04 18:02:28 +0000147 if (iconv(self->enchdl, (char**)&inp, &inplen, &out, &outlen) == (size_t)-1) {
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000148 char reason[128];
149 int errpos;
150
151 if (errno == E2BIG) {
152 RESIZE_OUTBUFFER(estep);
153 continue;
154 }
155
156 if (errorcb == ERROR_IGNORE || errorcb == ERROR_REPLACE) {
157 inplen -= Py_UNICODE_SIZE;
158 inp += Py_UNICODE_SIZE;
159 if (errorcb == ERROR_REPLACE) {
160 if (outlen < 1)
161 RESIZE_OUTBUFFER(errno == EINVAL ? 1 : estep);
162 outlen--;
163 *out++ = REPLACEMENT_CHAR_ENCODE;
164 }
165 if (errno == EINVAL) break;
166 else continue;
167 }
168
169 errpos = (int)(inp - inp_top) / Py_UNICODE_SIZE;
170 sprintf(reason, "Undefined character map from "
171#if Py_UNICODE_SIZE == 2
172 "\\u%04x"
173#elif Py_UNICODE_SIZE == 4
174 "\\u%08x"
175#endif
176 , *(Py_UNICODE *)inp);
177
178 if (exceptionobj == NULL) {
179 if ((exceptionobj = PyUnicodeEncodeError_Create(
180 self->encoding, input, inputlen,
181 errpos, errpos + 1, reason)) == NULL)
182 goto errorexit;
183 } else {
184 if (PyUnicodeEncodeError_SetStart(exceptionobj, errpos) != 0)
185 goto errorexit;
186 if (PyUnicodeEncodeError_SetEnd(exceptionobj, errpos + 1) != 0)
187 goto errorexit;
188 if (PyUnicodeEncodeError_SetReason(exceptionobj, reason) != 0)
189 goto errorexit;
190 }
191
192 if (errorcb == ERROR_STRICT) {
193 PyCodec_StrictErrors(exceptionobj);
194 goto errorexit;
195 } else {
196 PyObject *argsobj, *retobj, *retuni;
197 long newpos;
198
199 argsobj = PyTuple_New(1);
200 if (argsobj == NULL)
201 goto errorexit;
202 PyTuple_SET_ITEM(argsobj, 0, exceptionobj);
203 Py_INCREF(exceptionobj);
204 retobj = PyObject_CallObject(errorcb, argsobj);
205 Py_DECREF(argsobj);
206 if (retobj == NULL)
207 goto errorexit;
208
209 if (!PyTuple_Check(retobj) || PyTuple_GET_SIZE(retobj) != 2 ||
210 !PyUnicode_Check((retuni = PyTuple_GET_ITEM(retobj, 0))) ||
211 !PyInt_Check(PyTuple_GET_ITEM(retobj, 1))) {
212 Py_DECREF(retobj);
213 PyErr_SetString(PyExc_ValueError, "encoding error handler "
214 "must return (unicode, int) tuple");
215 goto errorexit;
216 }
217 if (PyUnicode_GET_SIZE(retuni) > 0) {
218#define errorexit errorexit_cbpad
219 PyObject *retstr = NULL;
220 int retstrsize;
221
222 retstr = PyUnicode_AsEncodedString(
223 retuni, self->encoding, NULL);
224 if (retstr == NULL || !PyString_Check(retstr))
225 goto errorexit;
226
227 retstrsize = PyString_GET_SIZE(retstr);
228 if (outlen < retstrsize)
229 RESIZE_OUTBUFFER(errno == EINVAL || retstrsize > estep
230 ? retstrsize - outlen : estep);
231
232 memcpy(out, PyString_AS_STRING(retstr), retstrsize);
233 out += retstrsize;
234 outlen -= retstrsize;
235#undef errorexit
236 if (0) {
237errorexit_cbpad: Py_XDECREF(retobj);
238 Py_XDECREF(retstr);
239 goto errorexit;
240 }
241 Py_DECREF(retstr);
242 }
243
244 newpos = PyInt_AS_LONG(PyTuple_GET_ITEM(retobj, 1));
245 Py_DECREF(retobj);
246
247 if (newpos < 0)
Walter Dörwald2e0b18a2003-01-31 17:19:08 +0000248 newpos = inputlen + newpos;
249 if (newpos < 0 || newpos > inputlen) {
250 PyErr_Format(PyExc_IndexError, "position %ld from error handler"
251 " out of bounds", newpos);
252 goto errorexit;
253 }
254 if (newpos == inputlen)
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000255 break;
256 inp = inp_top + Py_UNICODE_SIZE * newpos;
257 inplen = inplen_total - Py_UNICODE_SIZE * newpos;
258 }
259 } else
260 break;
261 }
262#undef RESIZE_OUTBUFFER
263
264 {
265 PyObject *rettup;
266 int finalsize;
267
268 finalsize = (int)(out - out_top);
269
270 if (finalsize != outlen_total) {
271 if (_PyString_Resize(&outputobj, finalsize) == -1)
272 goto errorexit;
273 }
274
275 if (errorcb > ERROR_MAX) {
276 Py_DECREF(errorcb);
277 }
278 Py_XDECREF(exceptionobj);
279
280 rettup = PyTuple_New(2);
281 if (rettup == NULL) {
282 Py_DECREF(outputobj);
Walter Dörwaldb4ff1112003-01-30 19:55:28 +0000283 if (byteswap)
284 PyMem_Free(swappedinput);
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000285 return NULL;
286 }
287 PyTuple_SET_ITEM(rettup, 0, outputobj);
288 PyTuple_SET_ITEM(rettup, 1, PyInt_FromLong(inputlen));
289 return rettup;
290 }
291
292errorexit:
293 Py_XDECREF(outputobj);
294 if (errorcb > ERROR_MAX) {
295 Py_DECREF(errorcb);
296 }
297 Py_XDECREF(exceptionobj);
Walter Dörwaldb4ff1112003-01-30 19:55:28 +0000298 if (byteswap)
299 PyMem_Free(swappedinput);
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000300
301 return NULL;
302}
303
304PyDoc_STRVAR(iconvcodec_decode__doc__,
305"I.decode(string, [,errors]) -> (unicodeobject, length consumed)\n\
306\n\
307Decodes `string' using I, an iconvcodec instance. errors may be given\n\
308to set a different error handling scheme. Default is 'strict' meaning\n\
309that encoding errors raise a UnicodeDecodeError. Other possible values\n\
310are 'ignore' and 'replace' as well as any other name registerd with\n\
311codecs.register_error that is able to handle UnicodeDecodeErrors.");
312
313static PyObject *
314iconvcodec_decode(iconvcodecObject *self, PyObject *args, PyObject *kwargs)
315{
316 static char *kwlist[] = { "input", "errors", NULL };
317 char *errors = NULL/*strict*/, *out, *out_top;
318 const char *inp, *inp_top;
319 int inplen_int;
320 size_t inplen, inplen_total, outlen, outlen_total, estep;
321 PyObject *outputobj = NULL, *errorcb = NULL,
322 *exceptionobj = NULL;
323
324 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|s:decode",
325 kwlist, &inp, &inplen_int, &errors))
326 return NULL; /* TypeError */
327
328 errorcb = get_errorcallback(errors);
329 if (errorcb == NULL)
330 return NULL; /* LookupError or something else from error handler */
331
332 inp_top = inp;
333 inplen_total = inplen = (size_t)inplen_int;
334
335 outputobj = PyUnicode_FromUnicode(NULL, inplen);
336 if (outputobj == NULL)
337 return NULL;
338 outlen_total = outlen = PyUnicode_GET_DATA_SIZE(outputobj);
339 out = out_top = (char *)PyUnicode_AS_UNICODE(outputobj);
340
341 estep = outlen / 2;
342
343#define RESIZE_OUTBUFFER(size) { \
344 size_t toadd = (size); \
345 outlen_total += toadd; \
346 outlen += toadd; \
347 if (PyUnicode_Resize(&outputobj, outlen_total/Py_UNICODE_SIZE) == -1) \
348 goto errorexit; \
349 out = (char *)PyUnicode_AS_UNICODE(outputobj) + (out - out_top); \
350 out_top = (char *)PyUnicode_AS_UNICODE(outputobj); \
351}
352 while (inplen > 0) {
Walter Dörwaldb4ff1112003-01-30 19:55:28 +0000353 char *oldout = out;
Walter Dörwaldbda1c862003-02-04 18:02:28 +0000354 size_t res = iconv(self->dechdl, (char**)&inp, &inplen, &out, &outlen);
Walter Dörwaldb4ff1112003-01-30 19:55:28 +0000355
356 if (byteswap) {
357 while (oldout < out)
358 {
359 char c0 = oldout[0];
360#if Py_UNICODE_SIZE == 2
361 oldout[0] = oldout[1];
362 oldout[1] = c0;
363#else
364 char c1 = oldout[1];
365 oldout[0] = oldout[3];
366 oldout[1] = oldout[2];
367 oldout[2] = c1;
368 oldout[3] = c0;
369#endif
370 oldout += sizeof(Py_UNICODE);
371 }
372 }
Walter Dörwaldbda1c862003-02-04 18:02:28 +0000373 if (res == (size_t)-1) {
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000374 char reason[128], *reasonpos = (char *)reason;
375 int errpos;
376
377 if (errno == E2BIG) {
378 RESIZE_OUTBUFFER(estep);
379 continue;
380 }
381
382 if (errorcb == ERROR_IGNORE || errorcb == ERROR_REPLACE) {
383 inplen--; inp++;
384 if (errorcb == ERROR_REPLACE) {
385 Py_UNICODE *replp;
386
387 if (outlen < Py_UNICODE_SIZE)
388 RESIZE_OUTBUFFER(
389 errno == EINVAL || Py_UNICODE_SIZE > estep
390 ? Py_UNICODE_SIZE : estep);
391
392 /* some compilers hate casted lvalue */
393 replp = (Py_UNICODE *)out;
394 assert((long)replp % Py_UNICODE_SIZE == 0);/* aligned? */
395 *replp = REPLACEMENT_CHAR_DECODE;
396
397 out += Py_UNICODE_SIZE;
398 outlen -= Py_UNICODE_SIZE;
399 }
400 if (errno == EINVAL) break;
401 else continue;
402 }
403
404 errpos = (int)(inp - inp_top);
405 reasonpos += sprintf(reason, "Invalid multibyte sequence \\x%02x",
406 (unsigned char)*inp);
407 if (inplen > 1) {
408 reasonpos += sprintf(reasonpos,
409 "\\x%02x", (unsigned char)*(inp+1));
410 if (inplen > 2)
411 sprintf(reasonpos, "\\x%02x", (unsigned char)*(inp+2));
412 }
413
414 if (exceptionobj == NULL) {
415 exceptionobj = PyUnicodeDecodeError_Create(
416 self->encoding, inp_top, inplen_total,
417 errpos, errpos + 1, reason);
418 if (exceptionobj == NULL)
419 goto errorexit;
420 } else {
421 if (PyUnicodeDecodeError_SetStart(exceptionobj, errpos) != 0)
422 goto errorexit;
423 if (PyUnicodeDecodeError_SetEnd(exceptionobj, errpos + 1) != 0)
424 goto errorexit;
425 if (PyUnicodeDecodeError_SetReason(exceptionobj, reason) != 0)
426 goto errorexit;
427 }
428
429 if (errorcb == ERROR_STRICT) {
430 PyCodec_StrictErrors(exceptionobj);
431 goto errorexit;
432 } else {
433 PyObject *argsobj, *retobj, *retuni;
434 long newpos;
435
436 argsobj = PyTuple_New(1);
437 if (argsobj == NULL)
438 goto errorexit;
439 PyTuple_SET_ITEM(argsobj, 0, exceptionobj);
440 Py_INCREF(exceptionobj);
441 retobj = PyObject_CallObject(errorcb, argsobj);
442 Py_DECREF(argsobj);
443 if (retobj == NULL)
444 goto errorexit;
445
446 if (!PyTuple_Check(retobj) || PyTuple_GET_SIZE(retobj) != 2 ||
447 !PyUnicode_Check((retuni = PyTuple_GET_ITEM(retobj, 0))) ||
448 !PyInt_Check(PyTuple_GET_ITEM(retobj, 1))) {
449 Py_DECREF(retobj);
450 PyErr_SetString(PyExc_ValueError, "decoding error handler "
451 "must return (unicode, int) tuple");
452 goto errorexit;
453 }
454 if (PyUnicode_GET_SIZE(retuni) > 0) {
455#define errorexit errorexit_cbpad
456 size_t retunisize;
457
458 retunisize = PyUnicode_GET_DATA_SIZE(retuni);
459 if (outlen < retunisize)
460 RESIZE_OUTBUFFER(errno == EINVAL || retunisize > estep
461 ? retunisize - outlen : estep);
462
463 memcpy(out, PyUnicode_AS_DATA(retuni), retunisize);
464 out += retunisize;
465 outlen -= retunisize;
466#undef errorexit
467 if (0) {
468errorexit_cbpad: Py_DECREF(retobj);
469 goto errorexit;
470 }
471 }
472
473 newpos = PyInt_AS_LONG(PyTuple_GET_ITEM(retobj, 1));
474 Py_DECREF(retobj);
475
476 if (newpos < 0)
Walter Dörwald2e0b18a2003-01-31 17:19:08 +0000477 newpos = inplen_total + newpos;
478 if (newpos < 0 || newpos > inplen_total) {
479 PyErr_Format(PyExc_IndexError, "position %ld from error handler"
480 " out of bounds", newpos);
481 goto errorexit;
482 }
483 if (newpos == inplen_total)
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000484 break;
485 inp = inp_top + newpos;
486 inplen = inplen_total - newpos;
487 }
488 } else
489 break;
490 }
491#undef RESIZE_OUTBUFFER
492
493 {
494 PyObject *rettup;
495 int finalsize;
496
497 finalsize = (int)(out - out_top);
498 if (finalsize != outlen_total) {
499 if (PyUnicode_Resize(&outputobj, finalsize / Py_UNICODE_SIZE) == -1)
500 goto errorexit;
501 }
502
503 if (errorcb > ERROR_MAX) {
504 Py_DECREF(errorcb);
505 }
506 Py_XDECREF(exceptionobj);
507
508 rettup = PyTuple_New(2);
509 if (rettup == NULL) {
510 Py_DECREF(outputobj);
511 return NULL;
512 }
513 PyTuple_SET_ITEM(rettup, 0, outputobj);
514 PyTuple_SET_ITEM(rettup, 1, PyInt_FromLong(inplen_total));
515 return rettup;
516 }
517
518errorexit:
519 Py_XDECREF(outputobj);
520 if (errorcb > ERROR_MAX) {
521 Py_DECREF(errorcb);
522 }
523 Py_XDECREF(exceptionobj);
524
525 return NULL;
526}
527
528static struct PyMethodDef iconvcodec_methods[] = {
529 {"encode", (PyCFunction)iconvcodec_encode,
530 METH_VARARGS | METH_KEYWORDS,
531 iconvcodec_encode__doc__},
532 {"decode", (PyCFunction)iconvcodec_decode,
533 METH_VARARGS | METH_KEYWORDS,
534 iconvcodec_decode__doc__},
535 {NULL, NULL},
536};
537
538static PyObject *
539iconvcodec_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
540{
541 PyObject *encobj = NULL;
542 iconvcodecObject *new = NULL;
543
544 new = (iconvcodecObject *)type->tp_alloc(type, 0);
545 if (new == NULL)
546 return NULL;
547
548 new->encoding = NULL;
549 new->enchdl = new->dechdl = (iconv_t)(-1);
550
551 encobj = PyObject_GetAttrString((PyObject *)new, "encoding");
552 if (encobj == NULL) {
553 PyErr_Clear();
554 new->encoding = PyMem_Malloc(sizeof(DEFAULT_ENCODING));
555 strcpy(new->encoding, DEFAULT_ENCODING);
556 } else if (!PyString_Check(encobj)) {
557 Py_DECREF(encobj);
558 PyErr_SetString(PyExc_TypeError,
559 "`encoding' attribute must be a string.");
560 goto errorexit;
561 } else {
562 new->encoding = PyMem_Malloc(PyString_GET_SIZE(encobj) + 1);
563 strcpy(new->encoding, PyString_AS_STRING(encobj));
564 Py_DECREF(encobj);
565 }
566
567 new->dechdl = iconv_open(UNICODE_ENCODING, new->encoding);
568 if (new->dechdl == (iconv_t)(-1)) {
569 PyErr_SetString(PyExc_ValueError, "unsupported decoding");
570 goto errorexit;
571 }
572
573 new->enchdl = iconv_open(new->encoding, UNICODE_ENCODING);
574 if (new->enchdl == (iconv_t)(-1)) {
575 PyErr_SetString(PyExc_ValueError, "unsupported encoding");
576 iconv_close(new->dechdl);
577 new->dechdl = (iconv_t)(-1);
578 goto errorexit;
579 }
580
581 return (PyObject *)new;
582
583errorexit:
584 Py_XDECREF(new);
585
586 return NULL;
587}
588
589static void
590iconvcodec_dealloc(iconvcodecObject *self)
591{
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000592 if (self->enchdl != (iconv_t)-1)
593 iconv_close(self->enchdl);
594 if (self->dechdl != (iconv_t)-1)
595 iconv_close(self->dechdl);
596 if (self->encoding != NULL)
597 PyMem_Free(self->encoding);
598
Martin v. Löwis7a565f02003-01-27 11:39:04 +0000599 self->ob_type->tp_free((PyObject *)self);
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000600}
601
602static PyObject *
603iconvcodec_repr(PyObject *self)
604{
605 return PyString_FromFormat("<iconvcodec encoding='%s'>",
606 ((iconvcodecObject *)self)->encoding);
607}
608
Neal Norwitz7fe16e72003-02-04 20:46:50 +0000609static PyTypeObject iconvcodec_Type = {
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000610 PyObject_HEAD_INIT(&PyType_Type)
611 0, /* Number of items for varobject */
612 "iconvcodec", /* Name of this type */
613 sizeof(iconvcodecObject), /* Basic object size */
614 0, /* Item size for varobject */
615 (destructor)iconvcodec_dealloc, /* tp_dealloc */
616 0, /* tp_print */
617 0, /* tp_getattr */
618 0, /* tp_setattr */
619 0, /* tp_compare */
620 iconvcodec_repr, /* tp_repr */
621 0, /* tp_as_number */
622 0, /* tp_as_sequence */
623 0, /* tp_as_mapping */
624 0, /* tp_hash */
625 0, /* tp_call */
626 0, /* tp_str */
627 PyObject_GenericGetAttr, /* tp_getattro */
628 0, /* tp_setattro */
629 0, /* tp_as_buffer */
Martin v. Löwis7a565f02003-01-27 11:39:04 +0000630 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000631 iconvcodec_doc, /* tp_doc */
632 0, /* tp_traverse */
633 0, /* tp_clear */
634 0, /* tp_richcompare */
635 0, /* tp_weaklistoffset */
636 0, /* tp_iter */
637 0, /* tp_iterext */
638 iconvcodec_methods, /* tp_methods */
639 0, /* tp_members */
640 0, /* tp_getset */
641 0, /* tp_base */
642 0, /* tp_dict */
643 0, /* tp_descr_get */
644 0, /* tp_descr_set */
645 0, /* tp_dictoffset */
646 0, /* tp_init */
647 PyType_GenericAlloc, /* tp_alloc */
648 iconvcodec_new, /* tp_new */
Martin v. Löwis7a565f02003-01-27 11:39:04 +0000649 PyObject_Del, /* tp_free */
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000650};
651
652static struct PyMethodDef _iconv_codec_methods[] = {
653 {NULL, NULL},
654};
655
656void
657init_iconv_codec(void)
658{
Martin v. Löwis727fe662003-01-26 11:48:20 +0000659 PyObject *m;
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000660
Walter Dörwaldb4ff1112003-01-30 19:55:28 +0000661 char in = 1;
662 char *inptr = &in;
Walter Dörwaldbda1c862003-02-04 18:02:28 +0000663 size_t insize = 1;
Walter Dörwaldb4ff1112003-01-30 19:55:28 +0000664 Py_UNICODE out = 0;
665 char *outptr = (char *)&out;
Walter Dörwaldbda1c862003-02-04 18:02:28 +0000666 size_t outsize = sizeof(out);
667 size_t res;
Walter Dörwaldb4ff1112003-01-30 19:55:28 +0000668
669 iconv_t hdl = iconv_open(UNICODE_ENCODING, "ASCII");
670
671 if (hdl == (iconv_t)-1)
672 Py_FatalError("can't initialize the _iconv_codec module: iconv_open() failed");
673
674 res = iconv(hdl, &inptr, &insize, &outptr, &outsize);
Walter Dörwaldbda1c862003-02-04 18:02:28 +0000675 if (res == (size_t)-1)
Walter Dörwaldb4ff1112003-01-30 19:55:28 +0000676 Py_FatalError("can't initialize the _iconv_codec module: iconv() failed");
677
Walter Dörwaldbda1c862003-02-04 18:02:28 +0000678 /* Check whether conv() returned native endianess or not for the chosen encoding */
Walter Dörwaldb4ff1112003-01-30 19:55:28 +0000679 if (out == 0x1)
680 byteswap = 0;
681#if Py_UNICODE_SIZE == 2
682 else if (out == 0x0100)
683#else
684 else if (out == 0x01000000)
685#endif
686 byteswap = 1;
687 else
688 Py_FatalError("can't initialize the _iconv_codec module: mixed endianess");
689 iconv_close(hdl);
690
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000691 m = Py_InitModule("_iconv_codec", _iconv_codec_methods);
692
Martin v. Löwis727fe662003-01-26 11:48:20 +0000693 PyModule_AddStringConstant(m, "__version__", (char*)__version__);
Martin v. Löwis7a565f02003-01-27 11:39:04 +0000694 Py_INCREF(&iconvcodec_Type);
Martin v. Löwis727fe662003-01-26 11:48:20 +0000695 PyModule_AddObject(m, "iconvcodec", (PyObject *)(&iconvcodec_Type));
Martin v. Löwis9789aef2003-01-26 11:30:36 +0000696 PyModule_AddStringConstant(m, "internal_encoding", UNICODE_ENCODING);
697
698 if (PyErr_Occurred())
699 Py_FatalError("can't initialize the _iconv_codec module");
700}
701
702/*
703 * ex: ts=8 sts=4 et
704 * $Id$
705 */