chiark / gitweb /
codec.pyx: Interface to new codec machinery.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 16 Jun 2013 14:47:13 +0000 (15:47 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 16 Jun 2013 19:42:35 +0000 (20:42 +0100)
The `legacy' version is still lying around for compatibility.  It might
not last forever.

MANIFEST.in
codec.pyx [new file with mode: 0644]
mLib.pyx

index 2de4ec3cad0cdf64c67866724951b774ee6416bc..b9cc91a0d629090e0433ec08fcb029caa10c833f 100644 (file)
@@ -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 (file)
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 --------------------------------------------------
index 201617368073b4a661b0d327bcee142dd7d57a68..daa6cd971043b4bd304d814312a884fc5d999f70 100644 (file)
--- 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'