/* ALF objects */
#include <stdio.h>
#ifndef NULL
# define NULL ((void*)0)
#endif
#include <errno.h>
#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: ***
*/
syntax highlighted by Code2HTML, v. 0.9.1