qse/qse/lib/cmn/tio_get.c

215 lines
3.9 KiB
C
Raw Normal View History

2008-10-14 05:32:58 +00:00
/*
* $Id: tio_get.c,v 1.8 2005/12/26 07:41:48 bacon Exp $
*/
2008-12-21 21:35:07 +00:00
#include <qse/cmn/tio.h>
2008-10-14 05:32:58 +00:00
#include "mem.h"
#define STATUS_GETC_EILSEQ (1 << 0)
2008-12-21 21:35:07 +00:00
qse_ssize_t qse_tio_getc (qse_tio_t* tio, qse_char_t* c)
2008-10-14 05:32:58 +00:00
{
2008-12-21 21:35:07 +00:00
qse_size_t left = 0;
qse_ssize_t n;
qse_char_t curc;
#ifndef QSE_CHAR_IS_MCHAR
qse_size_t seqlen;
2008-10-14 05:32:58 +00:00
#endif
2008-10-15 04:08:31 +00:00
/* TODO: more efficient way to check this?
2008-12-21 21:35:07 +00:00
* maybe better to use QSE_ASSERT
* QSE_ASSERT (tio->input_func != QSE_NULL);
2008-10-14 05:32:58 +00:00
*/
2008-12-21 21:35:07 +00:00
if (tio->input_func == QSE_NULL)
2008-10-14 05:32:58 +00:00
{
2008-12-21 21:35:07 +00:00
tio->errnum = QSE_TIO_ENOINF;
2008-10-14 05:32:58 +00:00
return -1;
}
if (tio->input_status & STATUS_GETC_EILSEQ)
{
tio->input_status &= ~STATUS_GETC_EILSEQ;
2008-12-21 21:35:07 +00:00
tio->errnum = QSE_TIO_EILSEQ;
2008-10-14 05:32:58 +00:00
return -1;
}
if (tio->inbuf_curp >= tio->inbuf_len)
{
2008-10-15 04:08:31 +00:00
getc_conv:
2008-10-14 05:32:58 +00:00
n = tio->input_func (
2008-12-21 21:35:07 +00:00
QSE_TIO_IO_DATA, tio->input_arg,
&tio->inbuf[left], QSE_COUNTOF(tio->inbuf) - left);
if (n == 0)
{
if (tio->inbuf_curp < tio->inbuf_len)
{
/* gargage left in the buffer */
2008-12-21 21:35:07 +00:00
tio->errnum = QSE_TIO_EICSEQ;
return -1;
}
return 0;
}
2008-10-14 05:32:58 +00:00
if (n <= -1)
{
2008-12-21 21:35:07 +00:00
tio->errnum = QSE_TIO_EINPUT;
2008-10-14 05:32:58 +00:00
return -1;
}
tio->inbuf_curp = 0;
2008-12-21 21:35:07 +00:00
tio->inbuf_len = (qse_size_t)n + left;
2008-10-14 05:32:58 +00:00
}
2008-12-21 21:35:07 +00:00
#ifdef QSE_CHAR_IS_MCHAR
2008-10-14 05:32:58 +00:00
curc = tio->inbuf[tio->inbuf_curp++];
#else
2008-10-15 04:08:31 +00:00
left = tio->inbuf_len - tio->inbuf_curp;
2008-10-16 00:14:41 +00:00
#if 0
2008-12-21 21:35:07 +00:00
seqlen = qse_mblen (tio->inbuf[tio->inbuf_curp], left);
2008-10-15 04:08:31 +00:00
if (seqlen == 0)
{
/* illegal sequence */
2008-10-14 05:32:58 +00:00
tio->inbuf_curp++; /* skip one byte */
2008-12-21 21:35:07 +00:00
tio->errnum = QSE_TIO_EILSEQ;
2008-10-14 05:32:58 +00:00
return -1;
}
2008-10-15 04:08:31 +00:00
if (seqlen > left)
{
/* incomplete sequence */
if (tio->inbuf_curp > 0)
{
2008-12-21 21:35:07 +00:00
QSE_MEMCPY (tio->inbuf, &tio->inbuf[tio->inbuf_curp], left);
2008-10-15 04:08:31 +00:00
tio->inbuf_curp = 0;
tio->inbuf_len = left;
}
2008-10-14 05:32:58 +00:00
goto getc_conv;
}
2008-12-21 21:35:07 +00:00
n = qse_mbtowc (&tio->inbuf[tio->inbuf_curp], seqlen, &curc);
2008-10-15 04:08:31 +00:00
if (n == 0)
{
/* illegal sequence */
2008-10-14 05:32:58 +00:00
tio->inbuf_curp++; /* skip one byte */
2008-12-21 21:35:07 +00:00
tio->errnum = QSE_TIO_EILSEQ;
2008-10-14 05:32:58 +00:00
return -1;
}
2008-10-15 04:08:31 +00:00
if (n > seqlen)
{
/* incomplete sequence -
2008-12-21 21:35:07 +00:00
* this check might not be needed because qse_mblen has
* checked it. would QSE_ASSERT (n <= seqlen) be enough? */
2008-10-15 04:08:31 +00:00
if (tio->inbuf_curp > 0)
{
2008-12-21 21:35:07 +00:00
QSE_MEMCPY (tio->inbuf, &tio->inbuf[tio->inbuf_curp], left);
2008-10-15 04:08:31 +00:00
tio->inbuf_curp = 0;
tio->inbuf_len = left;
}
goto getc_conv;
}
2008-10-16 00:14:41 +00:00
#endif
2008-12-21 21:35:07 +00:00
n = qse_mbtowc (&tio->inbuf[tio->inbuf_curp], left, &curc);
2008-10-16 00:14:41 +00:00
if (n == 0)
{
/* illegal sequence */
tio->inbuf_curp++; /* skip one byte */
2008-12-21 21:35:07 +00:00
tio->errnum = QSE_TIO_EILSEQ;
2008-10-16 00:14:41 +00:00
return -1;
}
if (n > left)
{
/* incomplete sequence */
if (tio->inbuf_curp > 0)
{
2008-12-21 21:35:07 +00:00
QSE_MEMCPY (tio->inbuf, &tio->inbuf[tio->inbuf_curp], left);
2008-10-16 00:14:41 +00:00
tio->inbuf_curp = 0;
tio->inbuf_len = left;
}
goto getc_conv;
}
2008-10-14 05:32:58 +00:00
tio->inbuf_curp += n;
#endif
*c = curc;
return 1;
}
2008-12-21 21:35:07 +00:00
qse_ssize_t qse_tio_gets (qse_tio_t* tio, qse_char_t* buf, qse_size_t size)
2008-10-14 05:32:58 +00:00
{
2008-12-21 21:35:07 +00:00
qse_ssize_t n;
2008-10-14 05:32:58 +00:00
if (size <= 0) return 0;
2008-12-21 21:35:07 +00:00
n = qse_tio_getsx (tio, buf, size - 1);
2008-10-14 05:32:58 +00:00
if (n == -1) return -1;
2008-12-21 21:35:07 +00:00
buf[n] = QSE_T('\0');
2008-10-14 05:32:58 +00:00
return n;
}
2008-12-21 21:35:07 +00:00
qse_ssize_t qse_tio_getsx (qse_tio_t* tio, qse_char_t* buf, qse_size_t size)
2008-10-14 05:32:58 +00:00
{
2008-12-21 21:35:07 +00:00
qse_ssize_t n;
qse_char_t* p, * end, c;
2008-10-14 05:32:58 +00:00
if (size <= 0) return 0;
p = buf; end = buf + size;
while (p < end)
{
2008-12-21 21:35:07 +00:00
n = qse_tio_getc (tio, &c);
2008-10-14 05:32:58 +00:00
if (n == -1)
{
2008-12-21 21:35:07 +00:00
if (p > buf && tio->errnum == QSE_TIO_EILSEQ)
2008-10-14 05:32:58 +00:00
{
tio->input_status |= STATUS_GETC_EILSEQ;
break;
}
return -1;
}
if (n == 0) break;
*p++ = c;
/* TODO: support a different line breaker */
2008-12-21 21:35:07 +00:00
if (c == QSE_T('\n')) break;
2008-10-14 05:32:58 +00:00
}
return p - buf;
}
2008-12-21 21:35:07 +00:00
qse_ssize_t qse_tio_getstr (qse_tio_t* tio, qse_str_t* buf)
2008-10-14 05:32:58 +00:00
{
2008-12-21 21:35:07 +00:00
qse_ssize_t n;
qse_char_t c;
2008-10-14 05:32:58 +00:00
2008-12-21 21:35:07 +00:00
qse_str_clear (buf);
2008-10-14 05:32:58 +00:00
for (;;)
{
2008-12-21 21:35:07 +00:00
n = qse_tio_getc (tio, &c);
2008-10-14 05:32:58 +00:00
if (n == -1)
{
2008-12-21 21:35:07 +00:00
if (QSE_STR_LEN(buf) > 0 && tio->errnum == QSE_TIO_EILSEQ)
2008-10-14 05:32:58 +00:00
{
tio->input_status |= STATUS_GETC_EILSEQ;
break;
}
return -1;
}
if (n == 0) break;
2008-12-21 21:35:07 +00:00
if (qse_str_ccat(buf, c) == (qse_size_t)-1)
2008-10-14 05:32:58 +00:00
{
2008-12-21 21:35:07 +00:00
tio->errnum = QSE_TIO_ENOMEM;
2008-10-14 05:32:58 +00:00
return -1;
}
/* TODO: support a different line breaker */
2008-12-21 21:35:07 +00:00
if (c == QSE_T('\n')) break;
2008-10-14 05:32:58 +00:00
}
2008-12-21 21:35:07 +00:00
return QSE_STR_LEN(buf);
2008-10-14 05:32:58 +00:00
}