3 ### Generic encoder/decoder
5 ### (c) 2005 Straylight/Edgeware
8 ###----- Licensing notice ---------------------------------------------------
10 ### This file is part of the Python interface to mLib.
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.
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.
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.
26 ###--------------------------------------------------------------------------
29 CDCF_LOWERC = _CDCF_LOWERC
30 CDCF_IGNCASE = _CDCF_IGNCASE
31 CDCF_NOEQPAD = _CDCF_NOEQPAD
32 CDCF_IGNEQPAD = _CDCF_IGNEQPAD
33 CDCF_IGNEQMID = _CDCF_IGNEQMID
34 CDCF_IGNZPAD = _CDCF_IGNZPAD
35 CDCF_IGNNEWL = _CDCF_IGNNEWL
36 CDCF_IGNSPC = _CDCF_IGNSPC
37 CDCF_IGNINVCH = _CDCF_IGNINVCH
38 CDCF_IGNJUNK = _CDCF_IGNJUNK
41 ## DEPRECATED. Use the original names at module level.
43 IGNCASE = _CDCF_IGNCASE
44 NOEQPAD = _CDCF_NOEQPAD
45 IGNEQPAD = _CDCF_IGNEQPAD
46 IGNEQMID = _CDCF_IGNEQMID
47 IGNZPAD = _CDCF_IGNZPAD
48 IGNNEWL = _CDCF_IGNNEWL
50 IGNINVCH = _CDCF_IGNINVCH
51 IGNJUNK = _CDCF_IGNJUNK
53 CDCERR_OK = _CDCERR_OK
54 CDCERR_INVCH = _CDCERR_INVCH
55 CDCERR_INVEQPAD = _CDCERR_INVEQPAD
56 CDCERR_INVZPAD = _CDCERR_INVZPAD
59 ## DEPRECATED. Use the original names at module level.
62 INVEQPAD = _CDCERR_INVEQPAD
63 INVZPAD = _CDCERR_INVZPAD
65 ###--------------------------------------------------------------------------
68 class CodecError (Exception):
70 Exception from decoding operation.
72 Attributes: `err' = `CDCERR_*' code, `msg' = message string
74 def __init__(me, err):
76 me.msg = <str>_codec_strerror(err)
80 def codec_strerror(err):
81 """codec_strerror(ERR) -> STR: message for `CDCERR_*' code"""
82 return <str>_codec_strerror(err)
84 cdef class _BaseCodec:
85 """Abstract superclass for codecs."""
87 def __cinit__(me, *hunoz, **hukairz):
91 me.c.ops.destroy(me.c)
92 def __init__(me, *hunoz, **hukairz):
93 raise TypeError('abstract class')
94 cdef int _code(me, const void *p, Py_ssize_t sz,
95 dstr *d, bint finishp) except -1:
98 raise ValueError('Encoding finished')
99 err = me.c.ops.code(me.c, p, sz, d)
101 raise CodecError(err)
103 err = me.c.ops.code(me.c, p, sz, d)
104 me.c.ops.destroy(me.c)
107 raise CodecError(err)
111 """C.done() -> OUT: final output"""
114 cdef class _BaseEncoder (_BaseCodec):
115 def encode(me, input, finishp = False):
116 """C.encode(IN, [finishp = False]) -> OUT: continue/finish encoding"""
122 PyObject_AsReadBuffer(input, &p, &sz)
123 me._code(p, sz, &d, finishp)
124 return TEXT_FROMSTRLEN(d.buf, d.len)
128 """C.done() -> OUT: final output"""
132 me._code(NULL, 0, &d, True)
133 return TEXT_FROMSTRLEN(d.buf, d.len)
137 cdef class _BaseDecoder (_BaseCodec):
138 def decode(me, input, finishp = False):
139 """C.decode(IN, [finishp = False]) -> OUT: continue/finish decoding"""
145 TEXT_PTRLEN(input, &p, &sz)
146 me._code(p, sz, &d, finishp)
147 return BIN_FROMSTRLEN(d.buf, d.len)
151 """C.done() -> OUT: final output"""
155 me._code(NULL, 0, &d, True)
156 return BIN_FROMSTRLEN(d.buf, d.len)
160 ###--------------------------------------------------------------------------
163 cdef extern from 'mLib/base64.h':
164 codec_class base64_class
165 codec_class file64_class
166 codec_class base64url_class
168 cdef class Base64Encoder (_BaseEncoder):
170 Base64Encoder([indent = '\\n'], [maxline = 72], [flags = 0])
174 def __init__(me, indent = '\n', maxline = 72, flags = 0):
175 me.c = base64_class.encoder(flags, TEXT_PTR(indent), maxline)
177 cdef class Base64Decoder (_BaseDecoder):
179 Base64Decoder([flags = CDCF_IGNSPC | CDCF_IGNNEWL])
183 def __init__(me, flags = _CDCF_IGNSPC | _CDCF_IGNNEWL):
184 me.c = base64_class.decoder(flags)
186 cdef class File64Encoder (_BaseEncoder):
188 File64Encoder([indent = '\\n'], [maxline = 72], [flags = 0])
190 Base64 encoder, using `%' instead of `/', so encoded strings are safe as
193 def __init__(me, indent = '\n', maxline = 72, flags = 0):
194 me.c = file64_class.encoder(flags, TEXT_PTR(indent), maxline)
196 cdef class File64Decoder (_BaseDecoder):
198 File64Decoder([flags = CDCF_IGNSPC | CDCF_IGNNEWL])
200 Base64 encoder, using `%' instead of `/', so encoded strings are safe as
203 def __init__(me, flags = _CDCF_IGNSPC | _CDCF_IGNNEWL):
204 me.c = file64_class.decoder(flags)
206 cdef class Base64URLEncoder (_BaseEncoder):
208 Base64URLEncoder([indent = '\\n'], [maxline = 72], [flags = 0])
210 Base64 encoder, using `-' and `_' instead of `+' and `/', so encoded
211 strings are safe as URL components.
213 def __init__(me, indent = '\n', maxline = 72, flags = 0):
214 me.c = base64url_class.encoder(flags, TEXT_PTR(indent), maxline)
216 cdef class Base64URLDecoder (_BaseDecoder):
218 Base64URLDecoder([flags = CDCF_IGNSPC | CDCF_IGNNEWL])
220 Base64 decoder, using `-' and `_' instead of `+' and `/', so encoded
221 strings are safe as URL components.
223 def __init__(me, flags = _CDCF_IGNSPC | _CDCF_IGNNEWL):
224 me.c = base64url_class.decoder(flags)
226 ###--------------------------------------------------------------------------
229 cdef extern from 'mLib/base32.h':
230 codec_class base32_class
231 codec_class base32hex_class
233 cdef class Base32Encoder (_BaseEncoder):
235 Base32Encoder([indent = '\\n'], [maxline = 72], [flags = 0])
239 def __init__(me, indent = '\n', maxline = 72, flags = 0):
240 me.c = base32_class.encoder(flags, TEXT_PTR(indent), maxline)
242 cdef class Base32Decoder (_BaseDecoder):
244 Base32Decoder([flags = CDCF_IGNSPC | CDCF_IGNNEWL | CDCF_IGNCASE])
248 def __init__(me, flags = _CDCF_IGNSPC | _CDCF_IGNNEWL | _CDCF_IGNCASE):
249 me.c = base32_class.decoder(flags)
251 cdef class Base32HexEncoder (_BaseEncoder):
253 Base32Encoder([indent = '\\n'], [maxline = 72], [flags = 0])
255 Base32 encoder, using digits and letters in ascending order, rather than
256 avoiding digits which visually resemble letters.
258 def __init__(me, indent = '\n', maxline = 72, flags = 0):
259 me.c = base32hex_class.encoder(flags, TEXT_PTR(indent), maxline)
261 cdef class Base32HexDecoder (_BaseDecoder):
263 Base32Decoder([flags = CDCF_IGNSPC | CDCF_IGNNEWL | CDCF_IGNCASE])
265 Base32 decoder, using digits and letters in ascending order, rather than
266 avoiding digits which visually resemble letters.
268 def __init__(me, flags = _CDCF_IGNSPC | _CDCF_IGNNEWL | _CDCF_IGNCASE):
269 me.c = base32hex_class.decoder(flags)
271 ###--------------------------------------------------------------------------
274 cdef extern from 'mLib/hex.h':
275 codec_class hex_class
277 cdef class HexEncoder (_BaseEncoder):
279 HexEncoder([indent = '\\n'], [maxline = 72], [flags = CDCF_LOWERC])
283 def __init__(me, indent = '\n', maxline = 72, flags = _CDCF_LOWERC):
284 me.c = hex_class.encoder(flags, TEXT_PTR(indent), maxline)
286 cdef class HexDecoder (_BaseDecoder):
288 HexDecoder([flags = CDCF_IGNSPC | CDCF_IGNNEWL | CDCF_IGNCASE])
292 def __init__(me, flags = _CDCF_IGNSPC | _CDCF_IGNNEWL | _CDCF_IGNCASE):
293 me.c = hex_class.decoder(flags)
295 ###----- That's all, folks --------------------------------------------------