|
|
@@ -244,106 +244,6 @@ static PyObject *Rocket_get_file_size(Rocket *self) |
|
|
|
return PyInt_FromLong(self->file_size); |
|
|
|
} |
|
|
|
|
|
|
|
/**** |
|
|
|
* Append from iterator |
|
|
|
*/ |
|
|
|
|
|
|
|
/* Helper for writing Python objects to the file */ |
|
|
|
static inline void append_pyobject(FILE *out, PyObject *val, layout_type_t type) |
|
|
|
{ |
|
|
|
union8_t t8; |
|
|
|
union16_t t16; |
|
|
|
union32_t t32; |
|
|
|
union64_t t64; |
|
|
|
int ret = 0; |
|
|
|
|
|
|
|
switch (type) { |
|
|
|
#define CASE(type, pyconvert, pytype, disktype, htole, bytes) \ |
|
|
|
case LAYOUT_TYPE_##type: \ |
|
|
|
pytype = pyconvert(val); \ |
|
|
|
if (PyErr_Occurred()) \ |
|
|
|
return; \ |
|
|
|
disktype = htole(disktype); \ |
|
|
|
ret = fwrite(&disktype, bytes, 1, out); \ |
|
|
|
break |
|
|
|
CASE(INT8, PyInt_AsLong, t8.i, t8.u, , 1); |
|
|
|
CASE(UINT8, PyInt_AsLong, t8.u, t8.u, , 1); |
|
|
|
CASE(INT16, PyInt_AsLong, t16.i, t16.u, htole16, 2); |
|
|
|
CASE(UINT16, PyInt_AsLong, t16.u, t16.u, htole16, 2); |
|
|
|
CASE(INT32, PyInt_AsLong, t32.i, t32.u, htole32, 4); |
|
|
|
CASE(UINT32, PyInt_AsLong, t32.u, t32.u, htole32, 4); |
|
|
|
CASE(INT64, PyInt_AsLong, t64.i, t64.u, htole64, 8); |
|
|
|
CASE(UINT64, PyInt_AsLong, t64.u, t64.u, htole64, 8); |
|
|
|
CASE(FLOAT32, PyFloat_AsDouble, t32.f, t32.u, htole32, 4); |
|
|
|
CASE(FLOAT64, PyFloat_AsDouble, t64.d, t64.u, htole64, 8); |
|
|
|
#undef CASE |
|
|
|
default: |
|
|
|
PyErr_SetString(PyExc_TypeError, "unknown type"); |
|
|
|
return; |
|
|
|
} |
|
|
|
if (ret <= 0) { |
|
|
|
PyErr_SetFromErrno(PyExc_OSError); |
|
|
|
} |
|
|
|
} |
|
|
|
/* .append_iter(maxrows, dataiter) */ |
|
|
|
static PyObject *Rocket_append_iter(Rocket *self, PyObject *args) |
|
|
|
{ |
|
|
|
int maxrows; |
|
|
|
PyObject *iter; |
|
|
|
PyObject *rowlist; |
|
|
|
if (!PyArg_ParseTuple(args, "iO:append_iter", &maxrows, &iter)) |
|
|
|
return NULL; |
|
|
|
if (!PyIter_Check(iter)) { |
|
|
|
PyErr_SetString(PyExc_TypeError, "need an iterable"); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
if (!self->file) { |
|
|
|
PyErr_SetString(PyExc_Exception, "no file"); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
/* Mark file size so that it will get updated next time it's read */ |
|
|
|
self->file_size = -1; |
|
|
|
|
|
|
|
int row; |
|
|
|
for (row = 0; row < maxrows; row++) { |
|
|
|
rowlist = PyIter_Next(iter); |
|
|
|
if (!rowlist) |
|
|
|
break; |
|
|
|
if (!PyList_Check(rowlist)) { |
|
|
|
PyErr_SetString(PyExc_TypeError, "rows must be lists"); |
|
|
|
goto row_err; |
|
|
|
} |
|
|
|
if (PyList_Size(rowlist) != self->layout_count + 1) { |
|
|
|
PyErr_SetString(PyExc_TypeError, "short row"); |
|
|
|
goto row_err; |
|
|
|
} |
|
|
|
|
|
|
|
/* Extract and write timestamp */ |
|
|
|
append_pyobject(self->file, PyList_GetItem(rowlist, 0), |
|
|
|
LAYOUT_TYPE_INT64); |
|
|
|
if (PyErr_Occurred()) |
|
|
|
goto row_err; |
|
|
|
|
|
|
|
/* Extract and write values */ |
|
|
|
int i; |
|
|
|
for (i = 0; i < self->layout_count; i++) { |
|
|
|
append_pyobject(self->file, |
|
|
|
PyList_GetItem(rowlist, i+1), |
|
|
|
self->layout_type); |
|
|
|
if (PyErr_Occurred()) |
|
|
|
goto row_err; |
|
|
|
} |
|
|
|
} |
|
|
|
fflush(self->file); |
|
|
|
/* All done */ |
|
|
|
return PyLong_FromLong(row); |
|
|
|
row_err: |
|
|
|
fflush(self->file); |
|
|
|
Py_DECREF(rowlist); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
/**** |
|
|
|
* Append from string |
|
|
|
*/ |
|
|
@@ -745,10 +645,6 @@ static PyMethodDef Rocket_methods[] = { |
|
|
|
"close(self)\n\n" |
|
|
|
"Close file handle" }, |
|
|
|
|
|
|
|
{ "append_iter", (PyCFunction)Rocket_append_iter, METH_VARARGS, |
|
|
|
"append_iter(self, maxrows, iterable)\n\n" |
|
|
|
"Append up to maxrows of data from iter to the file" }, |
|
|
|
|
|
|
|
{ "append_string", (PyCFunction)Rocket_append_string, METH_VARARGS, |
|
|
|
"append_string(self, count, data, offset, line, start, end, ts)\n\n" |
|
|
|
"Parse string and append data.\n" |
|
|
|