+### -*-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_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
+ IGNINVCH = CDCF_IGNINVCH
+ IGNJUNK = CDCF_IGNJUNK
+
+class CDCERR:
+ OK = CDCERR_OK
+ INVCH = CDCERR_INVCH
+ INVEQPAD = CDCERR_INVEQPAD
+ INVZPAD = CDCERR_INVZPAD
+
+class CodecError (Exception):
+ def __init__(me, err):
+ me.err = err
+ me.msg = _codec_strerror(err)
+ def __str__(me):
+ return me.msg
+
+def codec_strerror(err):
+ 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:
+ 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 int 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):
+ me.code('', True)
+
+cdef class _BaseEncoder (_BaseCodec):
+ def encode(me, text, finishp = False):
+ return me.code(text, finishp)
+
+cdef class _BaseDecoder (_BaseCodec):
+ def decode(me, text, finishp = False):
+ 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):
+ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
+ me.c = base64_class.encoder(flags, indent, maxline)
+
+cdef class Base64Decoder (_BaseDecoder):
+ def __init__(me, flags = CDCF_IGNJUNK):
+ me.c = base64_class.decoder(flags)
+
+cdef class File64Encoder (_BaseEncoder):
+ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
+ me.c = file64_class.encoder(flags, indent, maxline)
+
+cdef class File64Decoder (_BaseDecoder):
+ def __init__(me, flags = CDCF_IGNJUNK):
+ me.c = file64_class.decoder(flags)
+
+cdef class Base64URLEncoder (_BaseEncoder):
+ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
+ me.c = base64url_class.encoder(flags, indent, maxline)
+
+cdef class Base64URLDecoder (_BaseDecoder):
+ 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):
+ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
+ me.c = base32_class.encoder(flags, indent, maxline)
+
+cdef class Base32Decoder (_BaseDecoder):
+ def __init__(me, flags = CDCF_IGNJUNK):
+ me.c = base32_class.decoder(flags)
+
+cdef class Base32HexEncoder (_BaseEncoder):
+ def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK):
+ me.c = base32hex_class.encoder(flags, indent, maxline)
+
+cdef class Base32HexDecoder (_BaseDecoder):
+ 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):
+ def __init__(me, indent = '\n', maxline = 72,
+ flags = CDCF_IGNJUNK | CDCF_LOWERC):
+ me.c = hex_class.encoder(flags, indent, maxline)
+
+cdef class HexDecoder (_BaseDecoder):
+ def __init__(me, flags = CDCF_IGNJUNK | CDCF_LOWERC):
+ me.c = hex_class.decoder(flags)
+
+###----- That's all, folks --------------------------------------------------