--- l2_stream.c 2001/09/05 14:10:00 1.13
+++ l2_stream.c 2001/09/06 14:37:53 1.14
@@ -31,112 +31,142 @@
#include "l2.h"
#include "l2_p.h"
+/* create stream */
l2_stream_t *l2_stream_create(void)
{
l2_stream_t *st;
int i;
+ /* allocate stream structure */
if ((st = (l2_stream_t *)malloc(sizeof(l2_stream_t))) == NULL)
return NULL;
+
+ /* initialize stream structure */
st->levelmask = 0;
for (i = 0; i < L2_MAX_CHANNELS; i++)
st->channels[i].ch = NULL;
for (i = 0; i < L2_MAX_FORMATTERS; i++)
st->formatters[i].cb = NULL;
+
return st;
}
+/* attach channel to stream */
l2_result_t l2_stream_channel(l2_stream_t *st, l2_channel_t *ch, unsigned int levelmask)
{
- int i;
l2_channel_t *chC;
l2_channel_t *chN;
+ int i;
+ /* argument sanity check */
if (st == NULL || ch == NULL || levelmask == 0)
- return L2_ERROR;
+ return L2_ERR_ARG;
/* make sure the stack of channels consists of zero or more
filter channels followed by exactly one output channel */
for (chC = ch; (chN = l2_channel_downstream(chC)) != NULL; chC = chN)
if (l2_channel_type(chC) != L2_CHANNEL_FILTER)
- return L2_ERROR;
+ return L2_ERR_USE;
if (l2_channel_type(chC) != L2_CHANNEL_OUTPUT)
- return L2_ERROR;
+ return L2_ERR_USE;
/* find next free channel position in channel array */
for (i = 0; i < L2_MAX_CHANNELS && st->channels[i].ch != NULL; i++)
;
if (i == L2_MAX_CHANNELS)
- return L2_ERROR;
+ return L2_ERR_MEM;
- /* attach this channel */
+ /* attach channel to stream */
st->channels[i].ch = ch;
st->channels[i].levelmask = levelmask;
return L2_OK;
}
+/* attach formatter to stream */
l2_result_t l2_stream_formatter(l2_stream_t *st, char id, l2_formatter_t cb, l2_context_t *ctx)
{
int i;
+ /* argument sanity check */
if (st == NULL || id == '\0' || cb == NULL)
- return L2_ERROR;
+ return L2_ERR_ARG;
+
+ /* find next free formatter position in formatter array */
for (i = 0; i < L2_MAX_FORMATTERS && st->formatters[i].cb != NULL; i++)
;
if (i == L2_MAX_FORMATTERS)
- return L2_ERROR;
+ return L2_ERR_MEM;
+
+ /* attach formatter to stream */
st->formatters[i].id = id;
st->formatters[i].ctx = ctx;
st->formatters[i].cb = cb;
+
return L2_OK;
}
+/* set stream level mask */
l2_result_t l2_stream_levels(l2_stream_t *st, unsigned int levelmask)
{
+ /* argument sanity check */
if (st == NULL)
- return L2_ERROR;
+ return L2_ERR_ARG;
+
+ /* override global level mask */
st->levelmask = levelmask;
+
return L2_OK;
}
+/* log a message to stream */
l2_result_t l2_stream_log(l2_stream_t *st, unsigned int level, const char *fmt, ...)
{
va_list ap;
l2_result_t rv;
+ /* argument sanity check */
if (st == NULL || level == 0 || fmt == NULL)
- return L2_ERROR;
+ return L2_ERR_ARG;
+
+ /* pass-through to va_list-based variant */
va_start(ap, fmt);
rv = l2_stream_vlog(st, level, fmt, ap);
va_end(ap);
+
return rv;
}
+/* indirect callback function from l2_stream_vlog for flushing */
static int l2_stream_vlog_flush(l2_util_format_t *vfmt)
{
+ /* we do no format buffer flushing */
return -1;
}
+/* indirect callback function from l2_stream_vlog for formatting */
static void l2_stream_vlog_format(
l2_util_format_t *vfmt,
char *cPrefix, char *cPad, char **cppOut, size_t *npOutLen,
char *cpBuf, int nBufLenMax, char *cpParam, char cId, va_list *apArgs)
{
l2_stream_t *st = (l2_stream_t *)(vfmt->data[0].vp);
+ l2_result_t rv;
int i;
- /* init result */
+ /* init formatting result */
*cPrefix = '\0';
*cPad = ' ';
*cppOut = NULL;
*npOutLen = 0;
- /* iterate over all configured formatters */
+ /* iterate over all configured L2 formatters */
for (i = 0; i < L2_MAX_FORMATTERS && st->formatters[i].cb != NULL; i++) {
if (st->formatters[i].id == cId) {
- if (st->formatters[i].cb(st->formatters[i].ctx, cId, cpParam,
- cpBuf, nBufLenMax, npOutLen, apArgs) == L2_OK) {
+ rv = st->formatters[i].cb(st->formatters[i].ctx, cId, cpParam,
+ cpBuf, nBufLenMax, npOutLen, apArgs);
+ vfmt->data[1].i = (int)rv;
+ if (rv == L2_OK) {
*cppOut = cpBuf;
break;
}
@@ -145,6 +175,7 @@
return;
}
+/* log a message to stream (va_list-variant) */
l2_result_t l2_stream_vlog(l2_stream_t *st, unsigned int level, const char *fmt, va_list ap)
{
int i;
@@ -153,17 +184,18 @@
l2_result_t rv;
l2_util_format_t vfmt;
+ /* argument sanity check */
if (st == NULL || fmt == NULL || ap == NULL)
- return L2_ERROR;
+ return L2_ERR_ARG;
/* make sure only a single level is specified */
for (l = level, j = 0; l != 0; l = (l >> 1))
if (l & 0x1)
j++;
if (j != 1)
- return L2_ERROR;
+ return L2_ERR_ARG;
- /* check whether level is globally enabled */
+ /* check whether global level mask already stops processing */
if (!(st->levelmask & level))
return L2_OK;
@@ -171,21 +203,23 @@
vfmt.curpos = st->message;
vfmt.endpos = st->message + L2_MAX_MSGSIZE;
vfmt.data[0].vp = st;
+ vfmt.data[1].i = L2_ERR_FMT;
vfmt.flush = l2_stream_vlog_flush;
vfmt.format = l2_stream_vlog_format;
if ((len = l2_util_format(&vfmt, fmt, ap)) == -1)
- return L2_ERROR;
+ return (l2_result_t)(vfmt.data[1].i);
if (len == 0)
- return L2_ERROR;
+ return L2_ERR_FMT;
/* make sure a trailing newline exists */
if (st->message[len-1] != '\n') {
if (len == L2_MAX_MSGSIZE)
- return L2_ERROR;
+ return L2_ERR_MEM;
st->message[len++] = '\n';
st->message[len] = '\0';
}
+ /* write message to zero or more channels */
rv = L2_OK;
for (i = 0; i < L2_MAX_CHANNELS && st->channels[i].ch != NULL; i++) {
if (st->channels[i].levelmask & level) {
@@ -196,15 +230,24 @@
return rv;
}
+/* destroy stream */
l2_result_t l2_stream_destroy(l2_stream_t *st)
{
int i;
+ l2_result_t rv;
+ /* argument sanity check */
if (st == NULL)
- return L2_ERROR;
+ return L2_ERR_ARG;
+
+ /* destroy all attached channels */
for (i = 0; i < L2_MAX_CHANNELS && st->channels[i].ch != NULL; i++)
- l2_channel_destroy(st->channels[i].ch);
+ if ((rv = l2_channel_destroy(st->channels[i].ch)) != L2_OK)
+ return rv;
+
+ /* free stream structure */
free(st);
+
return L2_OK;
}
|