/***************************************************************************
 *
 * Copyright (c) 2000, 2001 BalaBit IT Ltd, Budapest, Hungary
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: pystream.c,v 1.12.4.1 2001/09/19 19:22:17 bazsi Exp $
 *
 * Author  : Bazsi
 * Auditor : kisza
 * Last version: 1.8
 * Notes:
 *   - comments
 *
 ***************************************************************************/

#include <zorp/pystream.h>

#include <zorp/zorp.h>
#include <zorp/stream.h>


static PyObject *z_py_zorp_stream_new(PyObject *self, PyObject *args);
static void z_py_zorp_stream_destroy(PyObject *o);
static PyObject *z_py_zorp_stream_getattr(PyObject *o, char *name);
static PyObject *z_py_zorp_stream_repr(PyObject *o);
static PyObject *z_py_zorp_stream_name(PyObject *o);
static PyObject *z_py_zorp_stream_read(PyObject *o, PyObject *args);
static PyObject *z_py_zorp_stream_write(PyObject *o, PyObject *args);

PyMethodDef z_py_zorp_stream_funcs[] =
{
  { "Stream",  z_py_zorp_stream_new, METH_VARARGS },
  { NULL,          NULL }   /* sentinel*/
};

static PyMethodDef py_zorp_stream_methods[] =
{
  { "read",        z_py_zorp_stream_read, METH_VARARGS },
  { "write",       z_py_zorp_stream_write, METH_VARARGS },
  { "name",        (PyCFunction) z_py_zorp_stream_name, 0 },
  { NULL,          NULL }   /* sentinel*/
};

PyTypeObject z_py_zorp_stream_type = 
{
  PyObject_HEAD_INIT(&z_py_zorp_stream_type)
  0,
  "ZorpStream",
  sizeof(ZorpStream),
  0,
  (destructor) z_py_zorp_stream_destroy,
  0,
  (getattrfunc) z_py_zorp_stream_getattr,
  0,
  0,
  (reprfunc) z_py_zorp_stream_repr,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  "ZorpStream class for Zorp",
};

static PyObject *
z_py_zorp_stream_new(PyObject *o, PyObject *args)
{
  ZorpStream *self;
  char *name;
  int fd;

  if (!PyArg_ParseTuple(args, "is", &fd, &name))
    return NULL;
  self = PyObject_NEW(ZorpStream, &z_py_zorp_stream_type);
  if (!self)
    return NULL;

  self->stream = z_stream_new(fd, name);
  return (PyObject *) self;
}

static void
z_py_zorp_stream_destroy(PyObject *o)
{
  ZorpStream *self = (ZorpStream *) o;

  z_stream_unref(self->stream);
  PyMem_DEL(self);
}

static PyObject *
z_py_zorp_stream_getattr(PyObject *o, char *name)
{
  return Py_FindMethod(py_zorp_stream_methods, o, name);
}

static PyObject * 
z_py_zorp_stream_name(PyObject *o) 
{
  ZorpStream *self = (ZorpStream *) o;
  return PyString_FromString(self->stream->name);
}

static PyObject *
z_py_zorp_stream_repr(PyObject *o)
{
  ZorpStream *self = (ZorpStream *) o;

  return PyString_FromString(self->stream->name);
}

static PyObject *
z_py_zorp_stream_read(PyObject *o, PyObject *args)
{
  ZorpStream *self = (ZorpStream *) o;
  gchar *buf;
  guint length, bytes_read;
  gint res;
  
  if (!PyArg_ParseTuple(args, "i", &length))
    return NULL;

  buf = alloca(length);
  Py_BEGIN_ALLOW_THREADS
  res = z_stream_read(self->stream, buf, length, &bytes_read);
  Py_END_ALLOW_THREADS
  
  if (res != G_IO_ERROR_NONE)
    {
      PyErr_SetString(PyExc_IOError, "I/O error reading stream.");
      return NULL;      
    }
  return Py_BuildValue("s#", buf, bytes_read);
}

static PyObject *
z_py_zorp_stream_write(PyObject *o, PyObject *args)
{
  ZorpStream *self = (ZorpStream *) o;
  gchar *buf; 
  guint length, bytes_written;
  gint res;
  
  if (!PyArg_ParseTuple(args, "s#", &buf, &length))
    return NULL;
    
  Py_BEGIN_ALLOW_THREADS
  res = z_stream_write(self->stream, buf, length, &bytes_written);
  Py_END_ALLOW_THREADS
  
  if (res != G_IO_ERROR_NONE)
    {
      PyErr_SetString(PyExc_IOError, "I/O error writing stream.");
      return NULL;
    }
  
  Py_XINCREF(Py_None);
  return Py_None;
}

void
z_py_zorp_stream_init(void)
{
  PyImport_AddModule("Zorp.Stream");
  Py_InitModule("Zorp.Stream", z_py_zorp_stream_funcs);
}
