### -*-pyrex-*- ### ### Generic encoder/decoder ### ### (c) 2005 Straylight/Edgeware ### ###----- Licensing notice --------------------------------------------------- ### ### This file is part of the Python interface to mLib. ### ### mLib/Python is free software; you can redistribute it and/or modify ### it under the terms of the GNU General Public License as published by ### the Free Software Foundation; either version 2 of the License, or ### (at your option) any later version. ### ### mLib/Python is distributed in the hope that it will be useful, ### but WITHOUT ANY WARRANTY; without even the implied warranty of ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ### GNU General Public License for more details. ### ### You should have received a copy of the GNU General Public License ### along with mLib/Python; if not, write to the Free Software Foundation, ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ###-------------------------------------------------------------------------- ### Base classes. cdef extern from 'mLib/codec.h': ctypedef struct codec ctypedef struct codec_class: char *name codec *(*encoder)(unsigned f, char *ind, unsigned max) codec *(*decoder)(unsigned f) ctypedef struct codec_ops: codec_class *c int (*code)(codec *c, void *p, size_t, dstr *d) void (*destroy)(codec *c) ctypedef struct codec: codec_ops *ops enum: CDCF_LOWERC CDCF_IGNCASE CDCF_NOEQPAD CDCF_IGNEQPAD CDCF_IGNEQMID CDCF_IGNZPAD CDCF_IGNNEWL CDCF_IGNSPC CDCF_IGNINVCH CDCF_IGNJUNK enum: CDCERR_OK CDCERR_INVCH CDCERR_INVEQPAD CDCERR_INVZPAD char *_codec_strerror "codec_strerror"(int err) class CDCF: LOWERC = CDCF_LOWERC IGNCASE = CDCF_IGNCASE NOEQPAD = CDCF_NOEQPAD IGNEQPAD = CDCF_IGNEQPAD IGNEQMID = CDCF_IGNEQMID IGNZPAD = CDCF_IGNZPAD IGNNEWL = CDCF_IGNNEWL IGNSPC = CDCF_IGNSPC IGNINVCH = CDCF_IGNINVCH IGNJUNK = CDCF_IGNJUNK class CDCERR: OK = CDCERR_OK INVCH = CDCERR_INVCH INVEQPAD = CDCERR_INVEQPAD INVZPAD = CDCERR_INVZPAD class CodecError (Exception): """ Exception from decoding operation. Attributes: err = CDCERR.* code, msg = message string """ def __init__(me, err): me.err = err me.msg = _codec_strerror(err) def __str__(me): return me.msg def codec_strerror(err): """codec_strerror(ERR) -> STR: message for CDCERR.* code""" return _codec_strerror(err) cdef int code(codec *c, void *p, size_t len, dstr *d) except -1: cdef int err err = c.ops.code(c, p, len, d) if err: raise CodecError(err) return 0 cdef class _BaseCodec: """Abstract superclass for codecs.""" cdef codec *c def __cinit__(me, *hunoz, **hukairz): me.c = NULL def __init__(me, *hunoz, **hukairz): raise TypeError, 'abstract class' def __dealloc__(me): if me.c is not NULL: me.c.ops.destroy(me.c) cdef code(me, text, int finishp): cdef void *p cdef Py_ssize_t len cdef dstr d cdef int err if me.c is NULL: raise ValueError, 'Encoding finished' DCREATE(&d) try: PyObject_AsReadBuffer(text, &p, &len) code(me.c, p, len, &d) if finishp: code(me.c, NULL, 0, &d) me.c.ops.destroy(me.c) me.c = NULL return PyString_FromStringAndSize(d.buf, d.len) finally: dstr_destroy(&d) def done(me): """C.done() -> OUT: final output""" me.code('', True) cdef class _BaseEncoder (_BaseCodec): def encode(me, text, finishp = False): """C.encode(IN, [finishp = False]) -> OUT: continue/finish encoding""" return me.code(text, finishp) cdef class _BaseDecoder (_BaseCodec): def decode(me, text, finishp = False): """C.decode(IN, [finishp = False]) -> OUT: continue/finish decoding""" return me.code(text, finishp) ###-------------------------------------------------------------------------- ### Base64. cdef extern from 'mLib/base64.h': codec_class base64_class codec_class file64_class codec_class base64url_class cdef class Base64Encoder (_BaseEncoder): """ Base64Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK]) Base64 encoder. """ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK): me.c = base64_class.encoder(flags, indent, maxline) cdef class Base64Decoder (_BaseDecoder): """ Base64Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK]) Base64 decoder. """ def __init__(me, flags = CDCF_IGNJUNK): me.c = base64_class.decoder(flags) cdef class File64Encoder (_BaseEncoder): """ File64Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK]) Base64 encoder, using `%' instead of `/', so encoded strings are safe as filenames. """ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK): me.c = file64_class.encoder(flags, indent, maxline) cdef class File64Decoder (_BaseDecoder): """ File64Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK]) Base64 encoder, using `%' instead of `/', so encoded strings are safe as filenames. """ def __init__(me, flags = CDCF_IGNJUNK): me.c = file64_class.decoder(flags) cdef class Base64URLEncoder (_BaseEncoder): """ Base64URLEncoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK]) Base64 encoder, using `-' and `_' instead of `+' and `/', so encoded strings are safe as URL components. """ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK): me.c = base64url_class.encoder(flags, indent, maxline) cdef class Base64URLDecoder (_BaseDecoder): """ Base64URLDecoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK]) Base64 decoder, using `-' and `_' instead of `+' and `/', so encoded strings are safe as URL components. """ def __init__(me, flags = CDCF_IGNJUNK): me.c = base64url_class.decoder(flags) ###-------------------------------------------------------------------------- ### Base32. cdef extern from 'mLib/base32.h': codec_class base32_class codec_class base32hex_class cdef class Base32Encoder (_BaseEncoder): """ Base32Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK]) Base32 encoder. """ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK): me.c = base32_class.encoder(flags, indent, maxline) cdef class Base32Decoder (_BaseDecoder): """ Base32Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK]) Base32 decoder. """ def __init__(me, flags = CDCF_IGNJUNK): me.c = base32_class.decoder(flags) cdef class Base32HexEncoder (_BaseEncoder): """ Base32Encoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK]) Base32 encoder, using digits and letters in ascending order, rather than avoiding digits which visually resemble letters. """ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK): me.c = base32hex_class.encoder(flags, indent, maxline) cdef class Base32HexDecoder (_BaseDecoder): """ Base32Decoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK]) Base32 decoder, using digits and letters in ascending order, rather than avoiding digits which visually resemble letters. """ def __init__(me, flags = CDCF_IGNJUNK): me.c = base32hex_class.decoder(flags) ###-------------------------------------------------------------------------- ### Hex. cdef extern from 'mLib/hex.h': codec_class hex_class cdef class HexEncoder (_BaseEncoder): """ HexEncoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK | CDCF.LOWERC]) Hexadecimal encoder. """ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK | CDCF_LOWERC): me.c = hex_class.encoder(flags, indent, maxline) cdef class HexDecoder (_BaseDecoder): """ HexDecoder([indent = '\\n'], [maxline = 72], [flags = CDCF.IGNJUNK | CDCF.LOWERC]) Hexadecimal decoder. """ def __init__(me, flags = CDCF_IGNJUNK | CDCF_LOWERC): me.c = hex_class.decoder(flags) ###----- That's all, folks --------------------------------------------------