fixed a bug of not checking the return value of wcrtomb properly in qse_wcrtomb().
fixed a bug of passing a wrong buffer to qse_wcrtomb() in qse_wcsntombsn(). enhanced qse_tio_writembsn() and qse_tio_writewcsn()
This commit is contained in:
@ -23,7 +23,6 @@
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
#include <qse/cmn/sio.h>
|
||||
#include "mem.h"
|
||||
|
||||
@ -95,8 +94,12 @@ void qse_assert_failed (
|
||||
qse_sio_t* sio, siobuf;
|
||||
|
||||
sio = &siobuf;
|
||||
if (qse_sio_initstd (sio, QSE_MMGR_GETDFL(), QSE_SIO_STDERR, QSE_SIO_NOAUTOFLUSH) <= -1)
|
||||
if (qse_sio_initstd (
|
||||
sio, QSE_MMGR_GETDFL(), QSE_SIO_STDERR,
|
||||
QSE_SIO_WRITE | QSE_SIO_IGNOREMBWCERR | QSE_SIO_NOAUTOFLUSH) <= -1)
|
||||
{
|
||||
sio = QSE_SIO_ERR;
|
||||
}
|
||||
|
||||
qse_sio_putms (sio, QSE_MT("=[ASSERTION FAILURE]============================================================\n"));
|
||||
|
||||
|
@ -59,8 +59,8 @@ qse_size_t qse_mbrlen (
|
||||
|
||||
#if 0
|
||||
n = mblen (mb, mbl);
|
||||
if (n == 0) return 1; /* a null character */
|
||||
if (n == (size_t)-1) return 0; /* invalid or incomplete sequence */
|
||||
if (n == 0) return 1; /* a null character */
|
||||
return (qse_size_t)n;
|
||||
#endif
|
||||
#else
|
||||
@ -119,16 +119,20 @@ qse_size_t qse_wcrtomb (
|
||||
qse_mchar_t buf[QSE_MBLEN_MAX];
|
||||
|
||||
n = wcrtomb (buf, wc, (mbstate_t*)state);
|
||||
if (n > mbl) return mbl + 1; /* buffer to small */
|
||||
/* it's important that n is checked againt (size_t)-1
|
||||
* before againt mbl. n > mbl is true if n is (size_t)-1.
|
||||
* if the check comes later, i won't have a chance to
|
||||
* determine the case of an illegal character */
|
||||
if (n == (size_t)-1) return 0; /* illegal character */
|
||||
if (n > mbl) return mbl + 1; /* buffer to small */
|
||||
|
||||
QSE_MEMCPY (mb, buf, mbl);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = wcrtomb (mb, wc, (mbstate_t*)state);
|
||||
if (n > mbl) return mbl + 1; /* buffer to small */
|
||||
if (n == (size_t)-1) return 0; /* illegal character */
|
||||
if (n > mbl) return mbl + 1; /* buffer to small */
|
||||
}
|
||||
|
||||
return n; /* number of bytes written to the buffer */
|
||||
|
@ -262,7 +262,7 @@ int qse_sio_initstd (
|
||||
|
||||
void qse_sio_fini (qse_sio_t* sio)
|
||||
{
|
||||
/*if (qse_sio_flush (sio) == -1) return -1;*/
|
||||
/*if (qse_sio_flush (sio) <= -1) return -1;*/
|
||||
qse_sio_flush (sio);
|
||||
qse_tio_fini (&sio->tio);
|
||||
qse_fio_fini (&sio->fio);
|
||||
@ -325,24 +325,24 @@ qse_ssize_t qse_sio_puts (qse_sio_t* sio, const qse_char_t* str)
|
||||
|
||||
qse_ssize_t qse_sio_putms (qse_sio_t* sio, const qse_mchar_t* str)
|
||||
{
|
||||
return qse_tio_writem (&sio->tio, str, qse_mbslen(str));
|
||||
return qse_tio_writembsn (&sio->tio, str, qse_mbslen(str));
|
||||
}
|
||||
|
||||
qse_ssize_t qse_sio_putws (qse_sio_t* sio, const qse_wchar_t* str)
|
||||
{
|
||||
return qse_tio_writew (&sio->tio, str, qse_wcslen(str));
|
||||
return qse_tio_writewcsn (&sio->tio, str, qse_wcslen(str));
|
||||
}
|
||||
|
||||
qse_ssize_t qse_sio_putmsn (
|
||||
qse_sio_t* sio, const qse_mchar_t* str, qse_size_t size)
|
||||
{
|
||||
return qse_tio_writem (&sio->tio, str, size);
|
||||
return qse_tio_writembsn (&sio->tio, str, size);
|
||||
}
|
||||
|
||||
qse_ssize_t qse_sio_putwsn (
|
||||
qse_sio_t* sio, const qse_wchar_t* str, qse_size_t size)
|
||||
{
|
||||
return qse_tio_writew (&sio->tio, str, size);
|
||||
return qse_tio_writewcsn (&sio->tio, str, size);
|
||||
}
|
||||
|
||||
int qse_sio_getpos (qse_sio_t* sio, qse_sio_pos_t* pos)
|
||||
|
@ -342,7 +342,7 @@ int qse_wcstombs (
|
||||
if (rem > 0) *mbs = QSE_MT('\0');
|
||||
else
|
||||
{
|
||||
/* if ret is -2 and wcs[wcslen] == QSE_T('\0'),
|
||||
/* if ret is -2 and wcs[wcslen] == QSE_WT('\0'),
|
||||
* this means that the mbs buffer was lacking one
|
||||
* slot for the terminating null */
|
||||
ret = -2; /* buffer too small */
|
||||
@ -428,7 +428,7 @@ int qse_wcsntombsn (
|
||||
{
|
||||
qse_size_t n;
|
||||
|
||||
n = qse_wcrtomb (*p, mbs, QSE_COUNTOF(mbsbuf), &state);
|
||||
n = qse_wcrtomb (*p, mbsbuf, QSE_COUNTOF(mbsbuf), &state);
|
||||
if (n == 0)
|
||||
{
|
||||
ret = -1;
|
||||
|
@ -199,6 +199,7 @@ static int __mbsxnfnmat (
|
||||
|
||||
if (pl >= 9)
|
||||
{
|
||||
/* TODO: binary search or something more efficient ? */
|
||||
if (qse_mbszcmp(pp, QSE_MT("[:upper:]"), 9) == 0)
|
||||
{
|
||||
matched = QSE_ISMUPPER(sc);
|
||||
|
@ -129,7 +129,7 @@ qse_ssize_t qse_tio_write (qse_tio_t* tio, const qse_char_t* str, qse_size_t siz
|
||||
return p - str;
|
||||
}
|
||||
|
||||
qse_ssize_t qse_tio_writem (
|
||||
qse_ssize_t qse_tio_writembsn (
|
||||
qse_tio_t* tio, const qse_mchar_t* mptr, qse_size_t mlen)
|
||||
{
|
||||
const qse_mchar_t* xptr, * xend;
|
||||
@ -155,7 +155,7 @@ qse_ssize_t qse_tio_writem (
|
||||
{
|
||||
for (xend = xptr + capa; xptr < xend; xptr++)
|
||||
tio->outbuf[tio->outbuf_len++] = *xptr;
|
||||
if (qse_tio_flush (tio) == -1) return -1;
|
||||
if (qse_tio_flush (tio) <= -1) return -1;
|
||||
mlen -= capa;
|
||||
}
|
||||
|
||||
@ -171,20 +171,27 @@ qse_ssize_t qse_tio_writem (
|
||||
for (xend = xptr + mlen; xptr < xend; xptr++)
|
||||
{
|
||||
/* TODO: support different line terminating characeter */
|
||||
if (*xptr == QSE_MT('\n')) nl = 1;
|
||||
tio->outbuf[tio->outbuf_len++] = *xptr;
|
||||
if (*xptr == QSE_MT('\n'))
|
||||
{
|
||||
nl = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (; xptr < xend; xptr++)
|
||||
tio->outbuf[tio->outbuf_len++] = *xptr;
|
||||
}
|
||||
|
||||
/* if the last part contains a new line, flush the internal
|
||||
* buffer. note that this flushes characters after nl also.*/
|
||||
if (nl && qse_tio_flush (tio) == -1) return -1;
|
||||
if (nl && qse_tio_flush (tio) <= -1) return -1;
|
||||
|
||||
/* returns the number multi-bytes characters handled */
|
||||
return xptr - mptr;
|
||||
}
|
||||
|
||||
qse_ssize_t qse_tio_writew (
|
||||
qse_ssize_t qse_tio_writewcsn (
|
||||
qse_tio_t* tio, const qse_wchar_t* wptr, qse_size_t wlen)
|
||||
{
|
||||
qse_size_t capa, wcnt, mcnt, xwlen;
|
||||
@ -198,49 +205,69 @@ qse_ssize_t qse_tio_writew (
|
||||
capa = QSE_COUNTOF(tio->outbuf) - tio->outbuf_len;
|
||||
wcnt = xwlen; mcnt = capa;
|
||||
|
||||
n = qse_wcsntombsn (wptr, &wcnt, &tio->outbuf[tio->outbuf_len], &mcnt);
|
||||
n = qse_wcsntombsn (
|
||||
wptr, &wcnt, &tio->outbuf[tio->outbuf_len], &mcnt);
|
||||
tio->outbuf_len += mcnt;
|
||||
|
||||
if (n == -2)
|
||||
{
|
||||
/* the buffer is not large enough to
|
||||
* convert more. so flush now and continue */
|
||||
if (qse_tio_flush (tio) == -1) return -1;
|
||||
* convert more. so flush now and continue.
|
||||
* note that the buffer may not be full though
|
||||
* it not large enough in this case */
|
||||
if (qse_tio_flush (tio) <= -1) return -1;
|
||||
nl = 0;
|
||||
}
|
||||
else if (n <= -1)
|
||||
else
|
||||
{
|
||||
/* invalid wide-character is encountered. */
|
||||
if (tio->flags & QSE_TIO_IGNOREMBWCERR)
|
||||
if (tio->outbuf_len >= QSE_COUNTOF(tio->outbuf))
|
||||
{
|
||||
/* though an error occurred, wcnt and mcnt
|
||||
* are valid for the bytes and characters
|
||||
* processed so far. so i can insert a question
|
||||
* mark using mcnt as an index */
|
||||
tio->outbuf[tio->outbuf_len + mcnt] = QSE_MT('?');
|
||||
mcnt++; wcnt++;
|
||||
/* flush the full buffer regardless of conversion
|
||||
* result. */
|
||||
if (qse_tio_flush (tio) <= -1) return -1;
|
||||
nl = 0;
|
||||
}
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
/* an invalid wide-character is encountered. */
|
||||
if (tio->flags & QSE_TIO_IGNOREMBWCERR)
|
||||
{
|
||||
/* insert a question mark for an illegal
|
||||
* character. */
|
||||
QSE_ASSERT (tio->outbuf_len < QSE_COUNTOF(tio->outbuf));
|
||||
tio->outbuf[tio->outbuf_len++] = QSE_MT('?');
|
||||
wcnt++; /* skip this illegal character */
|
||||
/* don't need to increment mcnt since
|
||||
* it's not used below */
|
||||
}
|
||||
else
|
||||
{
|
||||
tio->errnum = QSE_TIO_EILCHR;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tio->errnum = QSE_TIO_EILCHR;
|
||||
return -1;
|
||||
if (!(tio->flags & QSE_TIO_NOAUTOFLUSH) && !nl)
|
||||
{
|
||||
qse_size_t i;
|
||||
/* checking for a newline this way looks damn ugly.
|
||||
* TODO: how can i do this more elegantly? */
|
||||
for (i = 0; i < wcnt; i++)
|
||||
{
|
||||
if (wptr[i] == QSE_WT('\n'))
|
||||
{
|
||||
nl = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(tio->flags & QSE_TIO_NOAUTOFLUSH))
|
||||
{
|
||||
qse_size_t i;
|
||||
/* checking for a newline this way looks damn ugly.
|
||||
* TODO: how can i do this more elegantly? */
|
||||
for (i = 0; i < wcnt; i++)
|
||||
if (wptr[i] == QSE_WT('\n')) nl = 1;
|
||||
}
|
||||
|
||||
}
|
||||
wptr += wcnt; xwlen -= wcnt;
|
||||
}
|
||||
|
||||
if (nl && qse_tio_flush (tio) == -1) return -1;
|
||||
if (nl && qse_tio_flush (tio) <= -1) return -1;
|
||||
return wlen;
|
||||
}
|
||||
|
Reference in New Issue
Block a user