mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-13 04:03:16 +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 {
|
typedef struct StreamingBase64Decoder {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
struct base64_state state;
|
struct base64_state state;
|
||||||
|
bool add_trailing_bytes;
|
||||||
} StreamingBase64Decoder;
|
} StreamingBase64Decoder;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -154,6 +155,58 @@ static PyTypeObject StreamingBase64Decoder_Type = {
|
|||||||
.tp_init = StreamingBase64Decoder_init,
|
.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*
|
static PyObject*
|
||||||
pyset_iutf8(PyObject UNUSED *self, PyObject *args) {
|
pyset_iutf8(PyObject UNUSED *self, PyObject *args) {
|
||||||
int fd, on;
|
int fd, on;
|
||||||
@@ -661,6 +714,8 @@ PyInit_fast_data_types(void) {
|
|||||||
|
|
||||||
if (PyType_Ready(&StreamingBase64Decoder_Type) < 0) return NULL;
|
if (PyType_Ready(&StreamingBase64Decoder_Type) < 0) return NULL;
|
||||||
if (PyModule_AddObject(m, "StreamingBase64Decoder", (PyObject *) &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;
|
return m;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1709,6 +1709,13 @@ class StreamingBase64Decoder:
|
|||||||
def reset(self) -> None: ... # reset the state to empty to start decoding a new stream
|
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:
|
class DiskCache:
|
||||||
small_hole_threshold: int
|
small_hole_threshold: int
|
||||||
defrag_factor: int
|
defrag_factor: int
|
||||||
|
|||||||
Reference in New Issue
Block a user