mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-12 19:49:32 +02:00
Add a streaming base64 encoder
This commit is contained in:
@@ -108,6 +108,7 @@ pybase64_decode(PyObject UNUSED *self, PyObject *args) {
|
||||
typedef struct StreamingBase64Decoder {
|
||||
PyObject_HEAD
|
||||
struct base64_state state;
|
||||
bool add_trailing_bytes;
|
||||
} StreamingBase64Decoder;
|
||||
|
||||
static int
|
||||
@@ -154,6 +155,58 @@ static PyTypeObject StreamingBase64Decoder_Type = {
|
||||
.tp_init = StreamingBase64Decoder_init,
|
||||
};
|
||||
|
||||
static int
|
||||
StreamingBase64Encoder_init(PyObject *s, PyObject *args, PyObject *kwds UNUSED) {
|
||||
StreamingBase64Decoder *self = (StreamingBase64Decoder*)s;
|
||||
self->add_trailing_bytes = true;
|
||||
switch (PyTuple_GET_SIZE(args)) {
|
||||
case 0: break;
|
||||
case 1: self->add_trailing_bytes = PyObject_IsTrue(PyTuple_GET_ITEM(args, 0)); break;
|
||||
default: PyErr_SetString(PyExc_TypeError, "constructor takes no more than one argument"); return -1;
|
||||
}
|
||||
base64_stream_encode_init(&self->state, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
StreamingBase64Encoder_encode(StreamingBase64Decoder *self, PyObject *a) {
|
||||
RAII_PY_BUFFER(data);
|
||||
if (PyObject_GetBuffer(a, &data, PyBUF_SIMPLE) != 0) return NULL;
|
||||
if (!data.buf || !data.len) return PyBytes_FromStringAndSize(NULL, 0);
|
||||
size_t sz = required_buffer_size_for_base64_encode(data.len);
|
||||
RAII_PyObject(ans, PyBytes_FromStringAndSize(NULL, sz));
|
||||
if (!ans) return NULL;
|
||||
base64_stream_encode(&self->state, data.buf, data.len, PyBytes_AS_STRING(ans), &sz);
|
||||
if (_PyBytes_Resize(&ans, sz) != 0) return NULL;
|
||||
return Py_NewRef(ans);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
StreamingBase64Encoder_reset(StreamingBase64Decoder *self, PyObject *args UNUSED) {
|
||||
char trailer[4];
|
||||
size_t sz;
|
||||
base64_stream_encode_final(&self->state, trailer, &sz);
|
||||
base64_stream_encode_init(&self->state, 0);
|
||||
if (!self->add_trailing_bytes) { while(sz && trailer[sz-1] == '=') sz--; }
|
||||
return PyBytes_FromStringAndSize(trailer, sz);
|
||||
}
|
||||
|
||||
static PyTypeObject StreamingBase64Encoder_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
.tp_name = "kitty.fast_data_types.StreamingBase64Encoder",
|
||||
.tp_basicsize = sizeof(StreamingBase64Decoder),
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||
.tp_doc = "StreamingBase64Encoder",
|
||||
.tp_methods = (PyMethodDef[]){
|
||||
{"encode", (PyCFunction)StreamingBase64Encoder_encode, METH_O, ""},
|
||||
{"reset", (PyCFunction)StreamingBase64Encoder_reset, METH_NOARGS, ""},
|
||||
{NULL, NULL, 0, NULL},
|
||||
},
|
||||
.tp_new = PyType_GenericNew,
|
||||
.tp_init = StreamingBase64Encoder_init,
|
||||
};
|
||||
|
||||
|
||||
static PyObject*
|
||||
pyset_iutf8(PyObject UNUSED *self, PyObject *args) {
|
||||
int fd, on;
|
||||
@@ -661,6 +714,8 @@ PyInit_fast_data_types(void) {
|
||||
|
||||
if (PyType_Ready(&StreamingBase64Decoder_Type) < 0) return NULL;
|
||||
if (PyModule_AddObject(m, "StreamingBase64Decoder", (PyObject *) &StreamingBase64Decoder_Type) < 0) return NULL;
|
||||
if (PyType_Ready(&StreamingBase64Encoder_Type) < 0) return NULL;
|
||||
if (PyModule_AddObject(m, "StreamingBase64Encoder", (PyObject *) &StreamingBase64Encoder_Type) < 0) return NULL;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -1709,6 +1709,13 @@ class StreamingBase64Decoder:
|
||||
def reset(self) -> None: ... # reset the state to empty to start decoding a new stream
|
||||
|
||||
|
||||
class StreamingBase64Encodeer:
|
||||
def __init__(self, add_trailing_bytes: bool = True) -> None: ...
|
||||
def encode(self, data: ReadOnlyBuffer) -> bytes: ... # decode the specified data
|
||||
def reset(self) -> bytes: ... # reset the state to empty to start decoding a new stream, return any trailing bytes
|
||||
|
||||
|
||||
|
||||
class DiskCache:
|
||||
small_hole_threshold: int
|
||||
defrag_factor: int
|
||||
|
||||
Reference in New Issue
Block a user