/* ALF objects */ #include #ifndef NULL # define NULL ((void*)0) #endif #include #include "Python.h" #include "../src/alf.h" #ifdef DMALLOC #include "dmalloc.h" #endif static char alf_doc[] = "The alf module provides the appearance of large files on systems that don't\n" "support them. Large files are simulated using a directory containing\n" "individual files that represent the chunks of data in the file. Holes are\n" "represented implicitly. The interface is as close to that of a regular\n" "file as practical."; static PyObject *ErrorObject; typedef struct { PyObject_HEAD ALF *obj; /* real ALF object */ } ALFObject; staticforward PyTypeObject ALF_Type; #define ALFObject_Check(v) ((v)->ob_type == &ALF_Type) /* ALF methods */ static PyObject * ALF_read(ALFObject *self, PyObject *args) { size_t nbytes = 8192; void *buf; PyObject *rv; /* this needs to adapt to allow nbytes to be optional */ if (!PyArg_ParseTuple(args, "|i:read", &nbytes)) return NULL; if ((buf = malloc(nbytes)) == NULL) return PyErr_NoMemory(); if (PySequence_Length(args) != 0) { /* user provided an arg - read only that many bytes */ nbytes = alf_read(buf, 1, nbytes, self->obj); if (nbytes == 0 && alf_error(self->obj)) { free(buf); return PyErr_SetFromErrno(ErrorObject); } else { rv = Py_BuildValue("s#", buf, nbytes); free(buf); return rv; } } else { /* read was called without an arg - read the remainder of the file */ size_t ind = 0; size_t n = 0; while (1) { n = alf_read(buf+ind, 1, nbytes, self->obj); if (n == 0) { if (alf_error(self->obj)) { free(buf); return PyErr_SetFromErrno(ErrorObject); } rv = Py_BuildValue("s#", buf, ind); free(buf); return rv; } else { ind += n; nbytes *= 2; if ((buf = realloc(buf, nbytes)) == NULL) return PyErr_NoMemory(); } } } } static PyObject * ALF_readline(ALFObject *self, PyObject *args) { char *buf; int bufsize; int index; PyObject *result = NULL; if (!PyArg_ParseTuple(args, ":readline")) return NULL; bufsize = 160; index = 0; buf = malloc(bufsize); while (alf_gets(&buf[index], bufsize-index-1, self->obj) != NULL) { index += strlen(&buf[index]); if (buf[index-1] == '\n') { break; } /* must have filled up the buffer */ bufsize *= 2; buf = realloc(buf, bufsize); } result = PyString_FromStringAndSize(buf, index); free(buf); return result; } static PyObject * ALF_write(ALFObject *self, PyObject *args) { size_t nbytes; char *buf; if (!PyArg_ParseTuple(args, "s#:write", &buf, &nbytes)) return NULL; nbytes = alf_write(buf, 1, nbytes, self->obj); if (nbytes == -1) return PyErr_SetFromErrno(ErrorObject); return Py_BuildValue("i", nbytes); } static PyObject * ALF_flush(ALFObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":flush")) return NULL; if (alf_flush(self->obj) == -1) return PyErr_SetFromErrno(ErrorObject); Py_INCREF(Py_None); return Py_None; } static PyObject * ALF_close(ALFObject *self, PyObject *args) { int rv; if (!PyArg_ParseTuple(args, ":close")) return NULL; rv = alf_close(self->obj); self->obj = NULL; if (rv == -1) return PyErr_SetFromErrno(ErrorObject); Py_INCREF(Py_None); return Py_None; } static PyObject * ALF_seek(ALFObject *self, PyObject *args) { long long offset; int whence; if (!PyArg_ParseTuple(args, "Li:seek", &offset, &whence)) return NULL; if (alf_seek(self->obj, offset, whence) == -1) return PyErr_SetFromErrno(ErrorObject); Py_INCREF(Py_None); return Py_None; } static PyObject * ALF_rewind(ALFObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":rewind")) return NULL; alf_rewind(self->obj); Py_INCREF(Py_None); return Py_None; } static PyObject * ALF_tell(ALFObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":tell")) return NULL; return Py_BuildValue("L", alf_tell(self->obj)); } static PyObject * ALF_truncate(ALFObject *self, PyObject *args) { long long nbytes; if (!PyArg_ParseTuple(args, "L:truncate", &nbytes)) return NULL; if (alf_truncate(self->obj, nbytes) == -1) return PyErr_SetFromErrno(ErrorObject); Py_INCREF(Py_None); return Py_None; } static PyObject * ALF_getalf(ALFObject *self, PyObject *args) { return PyCObject_FromVoidPtr(self->obj, NULL); } static PyMethodDef ALF_methods[] = { {"read", (PyCFunction)ALF_read, METH_VARARGS, "read([nbytes]) -> string"}, {"readline", (PyCFunction)ALF_readline, METH_VARARGS, "readline() -> string"}, {"write", (PyCFunction)ALF_write, METH_VARARGS, "write(nbytes) -> int"}, {"flush", (PyCFunction)ALF_flush, METH_VARARGS, "flush() -> None"}, {"close", (PyCFunction)ALF_close, METH_VARARGS, "close() -> None"}, {"seek", (PyCFunction)ALF_seek, METH_VARARGS, "seek(offset, whence) -> None"}, {"rewind", (PyCFunction)ALF_rewind, METH_VARARGS, "rewind() -> None"}, {"tell", (PyCFunction)ALF_tell, METH_VARARGS, "tell() -> int"}, {"truncate", (PyCFunction)ALF_truncate, METH_VARARGS, "truncate(n) -> None"}, {"getalf", (PyCFunction)ALF_getalf, METH_NOARGS, "getalf() -> Cpointer"}, {NULL, NULL, 0, NULL} /* sentinel */ }; static PyObject * ALF_getattr(ALFObject *self, char *name) { return Py_FindMethod(ALF_methods, (PyObject *)self, name); } static void ALF_dealloc(ALFObject *self) { if (self->obj != NULL) (void)alf_close(self->obj); PyObject_Del(self); } statichere PyTypeObject ALF_Type = { /* The ob_type field must be initialized in the module init function * to be portable to Windows without using C++. */ PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "alf", /*tp_name*/ sizeof(ALFObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ (destructor)ALF_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ (getattrfunc)ALF_getattr, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ 0, /*tp_call*/ 0, /*tp_str*/ 0, /*tp_getattro*/ 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ 0, /*tp_doc*/ 0, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ 0, /*tp_weaklistoffset*/ 0, /*tp_iter*/ 0, /*tp_iternext*/ 0, /*tp_methods*/ 0, /*tp_members*/ 0, /*tp_getset*/ 0, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, /*tp_new*/ 0, /*tp_free*/ 0, /*tp_is_gc*/ }; /* --------------------------------------------------------------------- */ static PyObject * alf_new(/*@unused@*/ PyObject *self, PyObject *args) { ALFObject *rv; char *path; char *mode = "r"; unsigned int use_large = 0; if (!PyArg_ParseTuple(args, "s|si:new", &path, &mode, &use_large)) return NULL; rv = PyObject_New(ALFObject, &ALF_Type); if (rv == NULL) return NULL; errno = 0; rv->obj = alf_open(path, mode, use_large); if (rv->obj == NULL){ PyObject_Del(rv); return PyErr_SetFromErrno(ErrorObject); } #if 0 fprintf(stderr, "self: %p\n", rv); fprintf(stderr, "self->obj: %p\n", rv->obj); fprintf(stderr, "rv->ob_type: %p\n", rv->ob_type); #endif return (PyObject *)rv; } /* List of functions defined in the module */ static PyMethodDef alf_methods[] = { {"new", alf_new, METH_VARARGS, "new(path[, mode]) -> ALF object"}, {"open", alf_new, METH_VARARGS, "open(path[, mode]) -> ALF object"}, {NULL, NULL, 0, NULL} /* sentinel */ }; /* Initialization function for the module (*must* be called initalf) */ DL_EXPORT(void) initalf(void) { PyObject *m, *d; /* Initialize the type of the new type object here; doing it here * is required for portability to Windows without requiring C++. */ ALF_Type.ob_type = &PyType_Type; /* Create the module and add the functions */ m = Py_InitModule3("alf", alf_methods, alf_doc); /* Add some symbolic constants to the module */ d = PyModule_GetDict(m); ErrorObject = PyErr_NewException("alf.error", NULL, NULL); PyDict_SetItemString(d, "error", ErrorObject); } /* * Local Variables: *** * c-basic-offset: 4 *** * End: *** */