chiark / gitweb /
Release 1.0.4.
[mLib-python] / codec.pyx
1 ### -*-pyrex-*-
2 ###
3 ### Generic encoder/decoder
4 ###
5 ### (c) 2005 Straylight/Edgeware
6 ###
7
8 ###----- Licensing notice ---------------------------------------------------
9 ###
10 ### This file is part of the Python interface to mLib.
11 ###
12 ### mLib/Python is free software; you can redistribute it and/or modify
13 ### it under the terms of the GNU General Public License as published by
14 ### the Free Software Foundation; either version 2 of the License, or
15 ### (at your option) any later version.
16 ###
17 ### mLib/Python is distributed in the hope that it will be useful,
18 ### but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ### GNU General Public License for more details.
21 ###
22 ### You should have received a copy of the GNU General Public License
23 ### along with mLib/Python; if not, write to the Free Software Foundation,
24 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26 ###--------------------------------------------------------------------------
27 ### Base classes.
28
29 cdef extern from 'mLib/codec.h':
30
31   ctypedef struct codec
32
33   ctypedef struct codec_class:
34     char *name
35     codec *(*encoder)(unsigned f, char *ind, unsigned max)
36     codec *(*decoder)(unsigned f)
37
38   ctypedef struct codec_ops:
39     codec_class *c
40     int (*code)(codec *c, void *p, size_t, dstr *d)
41     void (*destroy)(codec *c)
42   ctypedef struct codec:
43     codec_ops *ops
44
45   enum:
46     CDCF_LOWERC
47     CDCF_IGNCASE
48     CDCF_NOEQPAD
49     CDCF_IGNEQPAD
50     CDCF_IGNEQMID
51     CDCF_IGNZPAD
52     CDCF_IGNNEWL
53     CDCF_IGNINVCH
54     CDCF_IGNJUNK
55
56   enum:
57     CDCERR_OK
58     CDCERR_INVCH
59     CDCERR_INVEQPAD
60     CDCERR_INVZPAD
61
62   char *_codec_strerror "codec_strerror"(int err)
63
64 class CDCF:
65   LOWERC = CDCF_LOWERC
66   IGNCASE = CDCF_IGNCASE
67   NOEQPAD = CDCF_NOEQPAD
68   IGNEQPAD = CDCF_IGNEQPAD
69   IGNEQMID = CDCF_IGNEQMID
70   IGNZPAD = CDCF_IGNZPAD
71   IGNNEWL = CDCF_IGNNEWL
72   IGNINVCH = CDCF_IGNINVCH
73   IGNJUNK = CDCF_IGNJUNK
74
75 class CDCERR:
76   OK = CDCERR_OK
77   INVCH = CDCERR_INVCH
78   INVEQPAD = CDCERR_INVEQPAD
79   INVZPAD = CDCERR_INVZPAD
80
81 class CodecError (Exception):
82   def __init__(me, err):
83     me.err = err
84     me.msg = _codec_strerror(err)
85   def __str__(me):
86     return me.msg
87
88 def codec_strerror(err):
89   return _codec_strerror(err)
90
91 cdef int code(codec *c, void *p, size_t len, dstr *d) except -1:
92   cdef int err
93   err = c.ops.code(c, p, len, d)
94   if err:
95     raise CodecError(err)
96   return 0
97
98 cdef class _BaseCodec:
99   cdef codec *c
100   def __cinit__(me, *hunoz, **hukairz):
101     me.c = NULL
102   def __init__(me, *hunoz, **hukairz):
103     raise TypeError, 'abstract class'
104   def __dealloc__(me):
105     if me.c is not NULL:
106       me.c.ops.destroy(me.c)
107   cdef code(me, text, int finishp):
108     cdef void *p
109     cdef int len
110     cdef dstr d
111     cdef int err
112     if me.c is NULL:
113       raise ValueError, 'Encoding finished'
114     DCREATE(&d)
115     try:
116       PyObject_AsReadBuffer(text, &p, &len)
117       code(me.c, p, len, &d)
118       if finishp:
119         code(me.c, NULL, 0, &d)
120         me.c.ops.destroy(me.c)
121         me.c = NULL
122       return PyString_FromStringAndSize(d.buf, d.len)
123     finally:
124       dstr_destroy(&d)
125   def done(me):
126     me.code('', True)
127
128 cdef class _BaseEncoder (_BaseCodec):
129   def encode(me, text, finishp = False):
130     return me.code(text, finishp)
131
132 cdef class _BaseDecoder (_BaseCodec):
133   def decode(me, text, finishp = False):
134     return me.code(text, finishp)
135
136 ###--------------------------------------------------------------------------
137 ### Base64.
138
139 cdef extern from 'mLib/base64.h':
140   codec_class base64_class
141   codec_class file64_class
142   codec_class base64url_class
143
144 cdef class Base64Encoder (_BaseEncoder):
145   def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
146     me.c = base64_class.encoder(flags, indent, maxline)
147
148 cdef class Base64Decoder (_BaseDecoder):
149   def __init__(me, flags = CDCF_IGNJUNK):
150     me.c = base64_class.decoder(flags)
151
152 cdef class File64Encoder (_BaseEncoder):
153   def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
154     me.c = file64_class.encoder(flags, indent, maxline)
155
156 cdef class File64Decoder (_BaseDecoder):
157   def __init__(me, flags = CDCF_IGNJUNK):
158     me.c = file64_class.decoder(flags)
159
160 cdef class Base64URLEncoder (_BaseEncoder):
161   def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
162     me.c = base64url_class.encoder(flags, indent, maxline)
163
164 cdef class Base64URLDecoder (_BaseDecoder):
165   def __init__(me, flags = CDCF_IGNJUNK):
166     me.c = base64url_class.decoder(flags)
167
168 ###--------------------------------------------------------------------------
169 ### Base32.
170
171 cdef extern from 'mLib/base32.h':
172   codec_class base32_class
173   codec_class base32hex_class
174
175 cdef class Base32Encoder (_BaseEncoder):
176   def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
177     me.c = base32_class.encoder(flags, indent, maxline)
178
179 cdef class Base32Decoder (_BaseDecoder):
180   def __init__(me, flags = CDCF_IGNJUNK):
181     me.c = base32_class.decoder(flags)
182
183 cdef class Base32HexEncoder (_BaseEncoder):
184   def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
185     me.c = base32hex_class.encoder(flags, indent, maxline)
186
187 cdef class Base32HexDecoder (_BaseDecoder):
188   def __init__(me, flags = CDCF_IGNJUNK):
189     me.c = base32hex_class.decoder(flags)
190
191 ###--------------------------------------------------------------------------
192 ### Hex.
193
194 cdef extern from 'mLib/hex.h':
195   codec_class hex_class
196
197 cdef class HexEncoder (_BaseEncoder):
198   def __init__(me, indent = '\n', maxline = 72,
199                flags = CDCF_IGNJUNK | CDCF_LOWERC):
200     me.c = hex_class.encoder(flags, indent, maxline)
201
202 cdef class HexDecoder (_BaseDecoder):
203   def __init__(me, flags = CDCF_IGNJUNK | CDCF_LOWERC):
204     me.c = hex_class.decoder(flags)
205
206 ###----- That's all, folks --------------------------------------------------