--- sio.c 2002/10/22 12:57:20 1.1
+++ sio.c 2002/10/23 17:05:10 1.2
@@ -57,19 +57,27 @@
struct sio_halfduplex_st {
NODE(sio_halfduplex_t) hd;
sio_stage_t *stage;
+ sio_halfduplex_t *cross;
+ al_t *al;
sio_rc_t (*func)(sio_t *, al_t *, void *);
};
struct sio_st {
struct {
- LIST(sio_halfduplex_t) hd;
+ LIST(sio_halfduplex_t) hd;
al_t *al;
} readers;
struct {
- LIST(sio_halfduplex_t) hd;
+ LIST(sio_halfduplex_t) hd;
al_t *al;
} writers;
+ sio_labelnum_t label_data;
+ sio_labelnum_t label_error;
+ sio_labelnum_t label_eof;
};
+#define SIO_LABEL_DATA(sio) ((void*)&(sio)->label_data)
+#define SIO_LABEL_ERROR(sio) ((void*)&(sio)->label_error)
+#define SIO_LABEL_EOF(sio) ((void*)&(sio)->label_eof)
struct sio_stage_st {
sio_halfduplex_t reader;
@@ -82,23 +90,38 @@
/****************************************************************************/
static
-sio_rc_t sio_strategy(sio_t *sio, sio_halfduplex_t *chain, al_t *al)
+sio_rc_t sio_strategy(sio_t *sio, sio_halfduplex_t *chain)
{
sio_rc_t rc;
sio_halfduplex_t *h;
+ /*
+ * call stage and direct data upstream/downstream
+ * according to response code
+ *
+ * if we the stage does not return a direction,
+ * simply end the code
+ *
+ * if we drop off the chain, simply result SIO_OK
+ *
+ */
h = chain;
while (h != NULL) {
- rc = h->func(sio, al, h->stage->userdata);
+ rc = h->func(sio, h->al, h->stage->userdata);
if (rc == SIO_UPSTREAM)
h = NEXT(h,hd);
else if (rc == SIO_DOWNSTREAM)
- h = NEXT(h,hd);
+ h = PREV(h,hd);
+ else if (rc == SIO_XSTREAM)
+ h = h->cross;
else
break;
}
- return SIO_OK;
+ if (h == NULL)
+ rc = SIO_OK;
+
+ return rc;
}
/**************************************************************************/
@@ -118,6 +141,10 @@
LISTINIT(&sio->readers,hd);
LISTINIT(&sio->writers,hd);
+ sio->label_data = SIO_LN_DATA;
+ sio->label_error = SIO_LN_ERROR;
+ sio->label_eof = SIO_LN_EOF;
+
*siop = sio;
return SIO_OK;
@@ -138,7 +165,6 @@
{
sio_rc_t rc;
sio_stage_t *sios;
- void *u;
/* argument sanity check(s) */
if (sio == NULL || siom == NULL || siosp == NULL)
@@ -151,19 +177,26 @@
NODEINIT(&sios->reader,hd);
NODEINIT(&sios->writer,hd);
sios->module = siom;
- sios->userdata = u;
+ sios->userdata = NULL;
sios->rw = SIO_MODE_INVALID;
sios->reader.func = siom->input;
sios->reader.stage = sios;
sios->writer.func = siom->output;
sios->writer.stage = sios;
- rc = sios->module->init(sio, sios->userdata);
+ rc = sios->module->init(sio, &sios->userdata);
+ if (rc != SIO_OK) {
+ free(sios);
+ return SIO_RC(rc);
+ }
+
+ *siosp = sios;
return SIO_RC(rc);
}
-sio_rc_t sio_cofigure_stage(sio_t *sio, sio_stage_t *sios, void *obj, void *value)
+sio_rc_t sio_configure_stage(sio_t *sio, sio_stage_t *sios,
+ void *obj, void *value)
{
sio_rc_t rc;
@@ -190,39 +223,104 @@
return SIO_OK;
}
+static
+sio_rc_t sio_create_al(sio_t *sio, sio_mode_t rw)
+{
+ al_rc_t arc;
+ int freereader = 0;
+
+ if (rw == SIO_MODE_READ || rw == SIO_MODE_READWRITE) {
+ if (ISEMPTY(&sio->readers,hd)) {
+ arc = al_create(&sio->readers.al);
+ if (arc != AL_OK)
+ return SIO_ERR_INT;
+ freereader = 1;
+ }
+ }
+ if (rw == SIO_MODE_WRITE || rw == SIO_MODE_READWRITE) {
+ if (ISEMPTY(&sio->writers,hd)) {
+ arc = al_create(&sio->writers.al);
+ if (arc != AL_OK) {
+ if (freereader)
+ al_destroy(sio->readers.al);
+ return SIO_ERR_INT;
+ }
+ }
+ }
+
+ return SIO_OK;
+}
+
+static
+sio_rc_t sio_destroy_al(sio_t *sio, sio_mode_t rw)
+{
+ if (rw == SIO_MODE_READ || rw == SIO_MODE_READWRITE) {
+ if (ISEMPTY(&sio->readers,hd)) {
+ al_destroy(sio->readers.al);
+ sio->readers.al = NULL;
+ }
+ }
+ if (rw == SIO_MODE_WRITE || rw == SIO_MODE_READWRITE) {
+ if (ISEMPTY(&sio->writers,hd)) {
+ al_destroy(sio->writers.al);
+ sio->writers.al = NULL;
+ }
+ }
+
+ return SIO_OK;
+}
+
sio_rc_t sio_attach(sio_t *sio, sio_stage_t *sios, sio_mode_t rw)
{
sio_rc_t rc;
+ int freereader = 0;
/* argument sanity check(s) */
if (sio == NULL || sios == NULL)
return SIO_RC(SIO_ERR_ARG);
-
- /* is module already attached ? */
- if (sios->rw != SIO_MODE_INVALID)
- return SIO_RC(SIO_ERR_ARG);
-
- /* prepare module for being attached */
- rc = sios->module->open(sio, sios->userdata);
- if (rc != SIO_OK) return SIO_RC(rc);
-
switch (rw) {
case SIO_MODE_READ:
- ADDTAIL(&sio->readers,hd,&sios->reader);
- break;
case SIO_MODE_WRITE:
- ADDTAIL(&sio->writers,hd,&sios->writer);
- break;
case SIO_MODE_READWRITE:
- ADDTAIL(&sio->readers,hd,&sios->reader);
- ADDTAIL(&sio->writers,hd,&sios->writer);
break;
default:
return SIO_RC(SIO_ERR_ARG);
}
- /* Remember the lists that sios has been attached to */
- sios->rw = rw;
+ /* is module already attached ? */
+ if (sios->rw != SIO_MODE_INVALID)
+ return SIO_RC(SIO_ERR_ARG);
+
+ /* create assembly lines (if aready existing) */
+ rc = sio_create_al(sio, rw);
+ if (rc != SIO_OK)
+ return SIO_RC(rc);
+
+ if (rw == SIO_MODE_READ || rw == SIO_MODE_READWRITE) {
+ rc = sios->module->openr(sio, sio->readers.al, sios->userdata);
+ if (rc != SIO_OK) {
+ sio_destroy_al(sio, rw);
+ return SIO_ERR_INT;
+ }
+ ADDTAIL(&sio->readers,hd,&sios->reader);
+ freereader = 1;
+ }
+ if (rw == SIO_MODE_WRITE || rw == SIO_MODE_READWRITE) {
+ rc = sios->module->openw(sio, sio->writers.al, sios->userdata);
+ if (rc != SIO_OK) {
+ if (freereader) {
+ REMOVE(&sio->readers,hd,&sios->reader);
+ sios->module->closer(sio, sio->readers.al, sios->userdata);
+ }
+ sio_destroy_al(sio, rw);
+ return SIO_ERR_INT;
+ }
+ ADDTAIL(&sio->writers,hd,&sios->writer);
+ }
+
+ sios->reader.al = sio->readers.al;
+ sios->writer.al = sio->writers.al;
+ sios->rw = rw;
return SIO_OK;
}
@@ -237,21 +335,33 @@
switch (sios->rw) {
case SIO_MODE_READ:
- REMOVE(&sio->readers,hd,&sios->reader);
- break;
case SIO_MODE_WRITE:
- REMOVE(&sio->writers,hd,&sios->writer);
- break;
case SIO_MODE_READWRITE:
- REMOVE(&sio->readers,hd,&sios->reader);
- REMOVE(&sio->writers,hd,&sios->writer);
break;
default:
return SIO_RC(SIO_ERR_ARG);
- break;
}
- rc = sios->module->close(sio, sios->userdata);
+ rc = SIO_OK;
+ if (sios->rw == SIO_MODE_WRITE || sios->rw == SIO_MODE_READWRITE) {
+ REMOVE(&sio->writers,hd,&sios->writer);
+ rc = sios->module->closew(sio, sio->writers.al, sios->userdata);
+ }
+ if (sios->rw == SIO_MODE_READ || sios->rw == SIO_MODE_READWRITE) {
+ REMOVE(&sio->readers,hd,&sios->reader);
+ if (rc == SIO_OK)
+ rc = sios->module->closer(sio, sio->readers.al, sios->userdata);
+ else
+ /* XXX - double error handling ? */
+ sios->module->closer(sio, sio->readers.al, sios->userdata);
+ }
+
+ sios->writer.al = NULL;
+ sios->reader.al = NULL;
+
+ sio_destroy_al(sio, sios->rw);
+
+ sios->rw = SIO_MODE_INVALID;
return SIO_RC(rc);
}
@@ -259,17 +369,23 @@
sio_rc_t sio_input(sio_t *sio, al_t *al, size_t limit)
{
sio_rc_t rc;
- al_t *src = sio->readers.al;
+ sio_halfduplex_t *h;
+ al_t *src;
size_t n;
/* argument sanity check(s) */
if (sio == NULL || al == NULL)
return SIO_RC(SIO_ERR_ARG);
+ h = HEAD(&sio->readers,hd);
+ if (h == NULL)
+ return SIO_RC(SIO_ERR_ARG);
+
+ src = h->al;
n = al_bytes(src);
if (n == 0) {
- rc = sio_strategy(sio, HEAD(&sio->readers,hd), src);
+ rc = sio_strategy(sio, h);
if (rc != SIO_OK) return SIO_RC(rc);
n = al_bytes(src);
@@ -286,61 +402,55 @@
return SIO_OK;
}
-sio_rc_t sio_discard(sio_t *sio)
-{
- sio_rc_t rc;
- al_t *src = sio->readers.al;
- size_t n;
-
- /* argument sanity check(s) */
- if (sio == NULL)
- return SIO_RC(SIO_ERR_ARG);
-
- while ((n = al_bytes(src)) > 0) {
- rc = sio_strategy(sio, HEAD(&sio->readers,hd), src);
- if (rc != SIO_OK)
- break;
- }
-
- if (rc == SIO_ERR_EOF)
- return SIO_OK;
-
- return SIO_RC(rc);
-}
-
sio_rc_t sio_output(sio_t *sio, al_t *al)
{
sio_rc_t rc;
- al_t *dst = sio->writers.al;
+ al_rc_t arc;
+ sio_halfduplex_t *h;
+ al_t *dst;
size_t n;
/* argument sanity check(s) */
if (sio == NULL || al == NULL)
return SIO_RC(SIO_ERR_ARG);
+ h = HEAD(&sio->writers,hd);
+ if (h == NULL)
+ return SIO_RC(SIO_ERR_ARG);
+ dst = h->al;
+
n = al_bytes(dst);
- al_splice(dst, n, 0, al, NULL);
+ arc = al_splice(dst, n, 0, al, NULL);
+ if (arc != AL_OK)
+ return SIO_RC(SIO_ERR_INT);
- rc = sio_strategy(sio, HEAD(&sio->writers,hd), dst);
+ rc = sio_strategy(sio, h);
return SIO_RC(rc);
}
-sio_rc_t sio_flush(sio_t *sio)
+sio_rc_t sio_push(sio_t *sio)
{
sio_rc_t rc;
- al_t *dst = sio->writers.al;
- size_t n;
+ al_rc_t arc;
+ sio_halfduplex_t *h;
+ al_t *dst;
+ char eof = '\0';
/* argument sanity check(s) */
if (sio == NULL)
return SIO_RC(SIO_ERR_ARG);
- while ((n = al_bytes(dst)) > 0) {
- rc = sio_strategy(sio, HEAD(&sio->writers,hd), sio->writers.al);
- if (rc != SIO_OK)
- break;
- }
+ h = HEAD(&sio->writers,hd);
+ if (h == NULL)
+ return SIO_RC(SIO_ERR_ARG);
+ dst = h->al;
+
+ arc = al_append_bytes(dst, &eof, 1, SIO_LABEL_EOF(sio));
+ if (arc != AL_OK)
+ return SIO_RC(SIO_ERR_INT);
+
+ rc = sio_strategy(sio, h);
return SIO_RC(rc);
}
@@ -351,12 +461,16 @@
sio_rc_t rc;
al_t *al;
+ if (n == 0)
+ return SIO_OK;
+
arc = al_create(&al);
if (arc != AL_OK) return SIO_RC(SIO_ERR_INT);
rc = sio_input(sio, al, n);
if (rc == AL_OK) {
- arc = al_flatten(al, 0, n, dst, actualp);
+ arc = al_flatten(al, 0, n, AL_FORWARD_SPAN, SIO_LABEL_DATA(sio),
+ dst, actualp);
if (arc != AL_OK)
rc = SIO_ERR_INT;
}
@@ -373,10 +487,13 @@
sio_rc_t rc;
al_t *al;
+ if (n == 0)
+ return SIO_OK;
+
arc = al_create(&al);
if (arc != AL_OK) return SIO_RC(SIO_ERR_INT);
- arc = al_append_bytes(al, src, n);
+ arc = al_append_bytes(al, src, n, SIO_LABEL_DATA(sio));
if (arc != AL_OK)
rc = SIO_ERR_INT;
else
@@ -401,9 +518,32 @@
case SIO_ERR_INT: mess = "Internal Error"; break;
case SIO_UPSTREAM: mess = "Invoke Upstream Stage"; break;
case SIO_DOWNSTREAM: mess = "Invoke Downstream Stage"; break;
+ case SIO_XSTREAM: mess = "Invoke Crossstream Stage"; break;
default: mess = "Invalid Result Code"; break;
}
return mess;
}
+sio_rc_t sio_label(sio_t *sio, sio_labelnum_t ln, void **p)
+{
+ void *label;
+
+ switch (ln) {
+ case SIO_LN_DATA:
+ label = SIO_LABEL_DATA(sio);
+ break;
+ case SIO_LN_ERROR:
+ label = SIO_LABEL_ERROR(sio);
+ break;
+ case SIO_LN_EOF:
+ label = SIO_LABEL_EOF(sio);
+ break;
+ default:
+ return SIO_ERR_ARG;
+ }
+
+ *p = label;
+ return SIO_OK;
+}
+
|