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 cdef extern from 'mLib/codec.h':
33 ctypedef struct codec_class:
35 codec *(*encoder)(unsigned f, char *ind, unsigned max)
36 codec *(*decoder)(unsigned f)
38 ctypedef struct codec_ops:
40 int (*code)(codec *c, void *p, size_t, dstr *d)
41 void (*destroy)(codec *c)
42 ctypedef struct codec:
63 char *_codec_strerror "codec_strerror"(int err)
67 IGNCASE = CDCF_IGNCASE
68 NOEQPAD = CDCF_NOEQPAD
69 IGNEQPAD = CDCF_IGNEQPAD
70 IGNEQMID = CDCF_IGNEQMID
71 IGNZPAD = CDCF_IGNZPAD
72 IGNNEWL = CDCF_IGNNEWL
74 IGNINVCH = CDCF_IGNINVCH
75 IGNJUNK = CDCF_IGNJUNK
80 INVEQPAD = CDCERR_INVEQPAD
81 INVZPAD = CDCERR_INVZPAD
83 class CodecError (Exception):
85 Exception from decoding operation.
87 Attributes: err = CDCERR.* code, msg = message string
89 def __init__(me, err):
91 me.msg = _codec_strerror(err)
95 def codec_strerror(err):
96 """codec_strerror(ERR) -> STR: message for CDCERR.* code"""
97 return _codec_strerror(err)
99 cdef int code(codec *c, void *p, size_t len, dstr *d) except -1:
101 err = c.ops.code(c, p, len, d)
103 raise CodecError(err)
106 cdef class _BaseCodec:
107 """Abstract superclass for codecs."""
109 def __cinit__(me, *hunoz, **hukairz):
111 def __init__(me, *hunoz, **hukairz):
112 raise TypeError, 'abstract class'
115 me.c.ops.destroy(me.c)
116 cdef code(me, text, int finishp):
122 raise ValueError, 'Encoding finished'
125 PyObject_AsReadBuffer(text, <cvp *>&p, &len)
126 code(me.c, p, len, &d)
128 code(me.c, NULL, 0, &d)
129 me.c.ops.destroy(me.c)
131 return PyString_FromStringAndSize(d.buf, d.len)
135 """C.done() -> OUT: final output"""
138 cdef class _BaseEncoder (_BaseCodec):
139 def encode(me, text, finishp = False):
140 """C.encode(IN, [finishp = False]) -> OUT: continue/finish encoding"""
141 return me.code(text, finishp)
143 cdef class _BaseDecoder (_BaseCodec):
144 def decode(me, text, finishp = False):
145 """C.decode(IN, [finishp = False]) -> OUT: continue/finish decoding"""
146 return me.code(text, finishp)
148 ###--------------------------------------------------------------------------
151 cdef extern from 'mLib/base64.h':
152 codec_class base64_class
153 codec_class file64_class
154 codec_class base64url_class
156 cdef class Base64Encoder (_BaseEncoder):
158 Base64Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
162 def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
163 me.c = base64_class.encoder(flags, indent, maxline)
165 cdef class Base64Decoder (_BaseDecoder):
167 Base64Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
171 def __init__(me, flags = CDCF_IGNJUNK):
172 me.c = base64_class.decoder(flags)
174 cdef class File64Encoder (_BaseEncoder):
176 File64Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
178 Base64 encoder, using `%' instead of `/', so encoded strings are safe as
181 def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
182 me.c = file64_class.encoder(flags, indent, maxline)
184 cdef class File64Decoder (_BaseDecoder):
186 File64Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
188 Base64 encoder, using `%' instead of `/', so encoded strings are safe as
191 def __init__(me, flags = CDCF_IGNJUNK):
192 me.c = file64_class.decoder(flags)
194 cdef class Base64URLEncoder (_BaseEncoder):
196 Base64URLEncoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
198 Base64 encoder, using `-' and `_' instead of `+' and `/', so encoded
199 strings are safe as URL components.
201 def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
202 me.c = base64url_class.encoder(flags, indent, maxline)
204 cdef class Base64URLDecoder (_BaseDecoder):
206 Base64URLDecoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
208 Base64 decoder, using `-' and `_' instead of `+' and `/', so encoded
209 strings are safe as URL components.
211 def __init__(me, flags = CDCF_IGNJUNK):
212 me.c = base64url_class.decoder(flags)
214 ###--------------------------------------------------------------------------
217 cdef extern from 'mLib/base32.h':
218 codec_class base32_class
219 codec_class base32hex_class
221 cdef class Base32Encoder (_BaseEncoder):
223 Base32Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
227 def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
228 me.c = base32_class.encoder(flags, indent, maxline)
230 cdef class Base32Decoder (_BaseDecoder):
232 Base32Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
236 def __init__(me, flags = CDCF_IGNJUNK):
237 me.c = base32_class.decoder(flags)
239 cdef class Base32HexEncoder (_BaseEncoder):
241 Base32Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
243 Base32 encoder, using digits and letters in ascending order, rather than
244 avoiding digits which visually resemble letters.
246 def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
247 me.c = base32hex_class.encoder(flags, indent, maxline)
249 cdef class Base32HexDecoder (_BaseDecoder):
251 Base32Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK])
253 Base32 decoder, using digits and letters in ascending order, rather than
254 avoiding digits which visually resemble letters.
256 def __init__(me, flags = CDCF_IGNJUNK):
257 me.c = base32hex_class.decoder(flags)
259 ###--------------------------------------------------------------------------
262 cdef extern from 'mLib/hex.h':
263 codec_class hex_class
265 cdef class HexEncoder (_BaseEncoder):
267 HexEncoder([indent = '\\n'], [maxline = 72],
268 [flags = CDCF.IGNJUNK | CDCF.LOWERC])
272 def __init__(me, indent = '\n', maxline = 72,
273 flags = CDCF_IGNJUNK | CDCF_LOWERC):
274 me.c = hex_class.encoder(flags, indent, maxline)
276 cdef class HexDecoder (_BaseDecoder):
278 HexDecoder([indent = '\\n'], [maxline = 72],
279 [flags = CDCF.IGNJUNK | CDCF.LOWERC])
283 def __init__(me, flags = CDCF_IGNJUNK | CDCF_LOWERC):
284 me.c = hex_class.decoder(flags)
286 ###----- That's all, folks --------------------------------------------------