Commit | Line | Data |
---|---|---|
55b42c18 MW |
1 | ### -*-pyrex-*- |
2 | ### | |
3 | ### Generic encoder/decoder | |
4 | ### | |
5 | ### (c) 2005 Straylight/Edgeware | |
6 | ### | |
7 | ||
8 | ###----- Licensing notice --------------------------------------------------- | |
9 | ### | |
10 | ### This file is part of the Python interface to mLib. | |
11 | ### | |
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. | |
16 | ### | |
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. | |
21 | ### | |
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. | |
25 | ||
26 | ###-------------------------------------------------------------------------- | |
27 | ### Base classes. | |
28 | ||
29 | cdef extern from 'mLib/codec.h': | |
30 | ||
31 | ctypedef struct codec | |
32 | ||
33 | ctypedef struct codec_class: | |
34 | char *name | |
35 | codec *(*encoder)(unsigned f, char *ind, unsigned max) | |
36 | codec *(*decoder)(unsigned f) | |
37 | ||
38 | ctypedef struct codec_ops: | |
39 | codec_class *c | |
40 | int (*code)(codec *c, void *p, size_t, dstr *d) | |
41 | void (*destroy)(codec *c) | |
42 | ctypedef struct codec: | |
43 | codec_ops *ops | |
44 | ||
45 | enum: | |
46 | CDCF_LOWERC | |
47 | CDCF_IGNCASE | |
48 | CDCF_NOEQPAD | |
49 | CDCF_IGNEQPAD | |
50 | CDCF_IGNEQMID | |
51 | CDCF_IGNZPAD | |
52 | CDCF_IGNNEWL | |
53 | CDCF_IGNINVCH | |
54 | CDCF_IGNJUNK | |
55 | ||
56 | enum: | |
57 | CDCERR_OK | |
58 | CDCERR_INVCH | |
59 | CDCERR_INVEQPAD | |
60 | CDCERR_INVZPAD | |
61 | ||
62 | char *_codec_strerror "codec_strerror"(int err) | |
63 | ||
64 | class CDCF: | |
65 | LOWERC = CDCF_LOWERC | |
66 | IGNCASE = CDCF_IGNCASE | |
67 | NOEQPAD = CDCF_NOEQPAD | |
68 | IGNEQPAD = CDCF_IGNEQPAD | |
69 | IGNEQMID = CDCF_IGNEQMID | |
70 | IGNZPAD = CDCF_IGNZPAD | |
71 | IGNNEWL = CDCF_IGNNEWL | |
72 | IGNINVCH = CDCF_IGNINVCH | |
73 | IGNJUNK = CDCF_IGNJUNK | |
74 | ||
75 | class CDCERR: | |
76 | OK = CDCERR_OK | |
77 | INVCH = CDCERR_INVCH | |
78 | INVEQPAD = CDCERR_INVEQPAD | |
79 | INVZPAD = CDCERR_INVZPAD | |
80 | ||
81 | class CodecError (Exception): | |
82 | def __init__(me, err): | |
83 | me.err = err | |
84 | me.msg = _codec_strerror(err) | |
85 | def __str__(me): | |
86 | return me.msg | |
87 | ||
88 | def codec_strerror(err): | |
89 | return _codec_strerror(err) | |
90 | ||
91 | cdef int code(codec *c, void *p, size_t len, dstr *d) except -1: | |
92 | cdef int err | |
93 | err = c.ops.code(c, p, len, d) | |
94 | if err: | |
95 | raise CodecError(err) | |
96 | return 0 | |
97 | ||
98 | cdef class _BaseCodec: | |
99 | cdef codec *c | |
100 | def __cinit__(me, *hunoz, **hukairz): | |
101 | me.c = NULL | |
102 | def __init__(me, *hunoz, **hukairz): | |
103 | raise TypeError, 'abstract class' | |
104 | def __dealloc__(me): | |
105 | if me.c is not NULL: | |
106 | me.c.ops.destroy(me.c) | |
107 | cdef code(me, text, int finishp): | |
108 | cdef void *p | |
109 | cdef int len | |
110 | cdef dstr d | |
111 | cdef int err | |
112 | if me.c is NULL: | |
113 | raise ValueError, 'Encoding finished' | |
114 | DCREATE(&d) | |
115 | try: | |
116 | PyObject_AsReadBuffer(text, &p, &len) | |
117 | code(me.c, p, len, &d) | |
118 | if finishp: | |
119 | code(me.c, NULL, 0, &d) | |
120 | me.c.ops.destroy(me.c) | |
121 | me.c = NULL | |
122 | return PyString_FromStringAndSize(d.buf, d.len) | |
123 | finally: | |
124 | dstr_destroy(&d) | |
125 | def done(me): | |
126 | me.code('', True) | |
127 | ||
128 | cdef class _BaseEncoder (_BaseCodec): | |
129 | def encode(me, text, finishp = False): | |
130 | return me.code(text, finishp) | |
131 | ||
132 | cdef class _BaseDecoder (_BaseCodec): | |
133 | def decode(me, text, finishp = False): | |
134 | return me.code(text, finishp) | |
135 | ||
136 | ###-------------------------------------------------------------------------- | |
137 | ### Base64. | |
138 | ||
139 | cdef extern from 'mLib/base64.h': | |
140 | codec_class base64_class | |
141 | codec_class file64_class | |
142 | codec_class base64url_class | |
143 | ||
144 | cdef class Base64Encoder (_BaseEncoder): | |
145 | def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK): | |
146 | me.c = base64_class.encoder(flags, indent, maxline) | |
147 | ||
148 | cdef class Base64Decoder (_BaseDecoder): | |
149 | def __init__(me, flags = CDCF_IGNJUNK): | |
150 | me.c = base64_class.decoder(flags) | |
151 | ||
152 | cdef class File64Encoder (_BaseEncoder): | |
153 | def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK): | |
154 | me.c = file64_class.encoder(flags, indent, maxline) | |
155 | ||
156 | cdef class File64Decoder (_BaseDecoder): | |
157 | def __init__(me, flags = CDCF_IGNJUNK): | |
158 | me.c = file64_class.decoder(flags) | |
159 | ||
160 | cdef class Base64URLEncoder (_BaseEncoder): | |
161 | def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK): | |
162 | me.c = base64url_class.encoder(flags, indent, maxline) | |
163 | ||
164 | cdef class Base64URLDecoder (_BaseDecoder): | |
165 | def __init__(me, flags = CDCF_IGNJUNK): | |
166 | me.c = base64url_class.decoder(flags) | |
167 | ||
168 | ###-------------------------------------------------------------------------- | |
169 | ### Base32. | |
170 | ||
171 | cdef extern from 'mLib/base32.h': | |
172 | codec_class base32_class | |
173 | codec_class base32hex_class | |
174 | ||
175 | cdef class Base32Encoder (_BaseEncoder): | |
176 | def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK): | |
177 | me.c = base32_class.encoder(flags, indent, maxline) | |
178 | ||
179 | cdef class Base32Decoder (_BaseDecoder): | |
180 | def __init__(me, flags = CDCF_IGNJUNK): | |
181 | me.c = base32_class.decoder(flags) | |
182 | ||
183 | cdef class Base32HexEncoder (_BaseEncoder): | |
184 | def __init__(me, indent = '\n', maxline = 72, flags = CDCF_IGNJUNK): | |
185 | me.c = base32hex_class.encoder(flags, indent, maxline) | |
186 | ||
187 | cdef class Base32HexDecoder (_BaseDecoder): | |
188 | def __init__(me, flags = CDCF_IGNJUNK): | |
189 | me.c = base32hex_class.decoder(flags) | |
190 | ||
191 | ###-------------------------------------------------------------------------- | |
192 | ### Hex. | |
193 | ||
194 | cdef extern from 'mLib/hex.h': | |
195 | codec_class hex_class | |
196 | ||
197 | cdef class HexEncoder (_BaseEncoder): | |
198 | def __init__(me, indent = '\n', maxline = 72, | |
199 | flags = CDCF_IGNJUNK | CDCF_LOWERC): | |
200 | me.c = hex_class.encoder(flags, indent, maxline) | |
201 | ||
202 | cdef class HexDecoder (_BaseDecoder): | |
203 | def __init__(me, flags = CDCF_IGNJUNK | CDCF_LOWERC): | |
204 | me.c = hex_class.decoder(flags) | |
205 | ||
206 | ###----- That's all, folks -------------------------------------------------- |