From 55b42c189e6a40e66b7beef6056fd8a484ee85f5 Mon Sep 17 00:00:00 2001 Message-Id: <55b42c189e6a40e66b7beef6056fd8a484ee85f5.1714682873.git.mdw@distorted.org.uk> From: Mark Wooding Date: Sun, 16 Jun 2013 15:47:13 +0100 Subject: [PATCH 1/1] codec.pyx: Interface to new codec machinery. Organization: Straylight/Edgeware From: Mark Wooding The `legacy' version is still lying around for compatibility. It might not last forever. --- MANIFEST.in | 2 +- codec.pyx | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mLib.pyx | 1 + 3 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 codec.pyx diff --git a/MANIFEST.in b/MANIFEST.in index 2de4ec3..b9cc91a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -11,7 +11,7 @@ include defs.pxi grim.h utils.pyx include lbuf.pyx pkbuf.pyx ## codec -include codec.pyx.in url.pyx +include codec.pyx codec.pyx.in url.pyx ## hash include crc32.pyx unihash.pyx diff --git a/codec.pyx b/codec.pyx new file mode 100644 index 0000000..815e6b2 --- /dev/null +++ b/codec.pyx @@ -0,0 +1,206 @@ +### -*-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 -------------------------------------------------- diff --git a/mLib.pyx b/mLib.pyx index 2016173..daa6cd9 100644 --- a/mLib.pyx +++ b/mLib.pyx @@ -48,6 +48,7 @@ include 'assoc.pyx' include 'str.pyx' ## Encodings. +include 'codec.pyx' include 'base64.pyx' include 'base32.pyx' include 'hex.pyx' -- [mdw]