From a0fc992c654ffc359e98f3881a65e9bab1e2558f Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 30 Dec 2011 14:44:21 +0000 Subject: [PATCH] added qse_cmgr_t. still in primitive stage. added qse_tio_getcmgr()/qse_tio_setcmgr() added qse_pio_getcmgr()/qse_pio_setcmgr() added qse_fio_getcmgr()/qse_fio_setcmgr() added qse_fio_getcmgr()/qse_fio_setcmgr() added mbs/wcs conversion functions using cmgr --- qse/cmd/awk/awk.c | 2 +- qse/cmd/sed/sed.c | 2 +- qse/include/qse/cmn/fio.h | 16 ++ qse/include/qse/cmn/pio.h | 30 ++- qse/include/qse/cmn/sio.h | 9 + qse/include/qse/cmn/tio.h | 30 ++- qse/include/qse/types.h | 24 +++ qse/lib/awk/StdAwk.cpp | 4 +- qse/lib/awk/std.c | 8 +- qse/lib/cmn/Makefile.am | 1 + qse/lib/cmn/Makefile.in | 15 +- qse/lib/cmn/fio.c | 10 + qse/lib/cmn/pio.c | 30 ++- qse/lib/cmn/sio.c | 10 + qse/lib/cmn/str-cnv.c | 2 - qse/lib/cmn/str-mbwc.c | 437 ++++++++++++++++++++++++++++++++++++++ qse/lib/cmn/tio-get.c | 4 +- qse/lib/cmn/tio-put.c | 4 +- qse/lib/cmn/tio.c | 21 ++ qse/lib/net/httpd_task.c | 15 +- qse/samples/cmn/pio.c | 6 +- 21 files changed, 626 insertions(+), 54 deletions(-) create mode 100644 qse/lib/cmn/str-mbwc.c diff --git a/qse/cmd/awk/awk.c b/qse/cmd/awk/awk.c index 3c2e07f0..1d97e490 100644 --- a/qse/cmd/awk/awk.c +++ b/qse/cmd/awk/awk.c @@ -854,7 +854,7 @@ static int awk_main (int argc, qse_char_t* argv[]) /* TODO: change it to support multiple source files */ qse_awk_parsestd_in_t psin; qse_awk_parsestd_out_t psout; - qse_mmgr_t* mmgr = QSE_NULL; + qse_mmgr_t* mmgr = QSE_MMGR_GETDFL(); memset (&arg, 0, QSE_SIZEOF(arg)); diff --git a/qse/cmd/sed/sed.c b/qse/cmd/sed/sed.c index 2e773714..82bc2344 100644 --- a/qse/cmd/sed/sed.c +++ b/qse/cmd/sed/sed.c @@ -519,7 +519,7 @@ static void trace_exec (qse_sed_t* sed, qse_sed_exec_op_t op, const qse_sed_cmd_ int sed_main (int argc, qse_char_t* argv[]) { - qse_mmgr_t* mmgr = QSE_NULL; + qse_mmgr_t* mmgr = QSE_MMGR_GETDFL(); qse_sed_t* sed = QSE_NULL; qse_fs_t* fs = QSE_NULL; qse_size_t script_count; diff --git a/qse/include/qse/cmn/fio.h b/qse/include/qse/cmn/fio.h index 6971a548..d2ca3ae8 100644 --- a/qse/include/qse/cmn/fio.h +++ b/qse/include/qse/cmn/fio.h @@ -200,6 +200,22 @@ void qse_fio_fini ( qse_fio_t* fio ); +/** + * The qse_fio_getcmgr() funcfion returns the current character manager. + * It returns #QSE_NULL is @a fio is not opened with #QSE_FIO_TEXT. + */ +qse_cmgr_t* qse_fio_getcmgr ( + qse_fio_t* fio +); + +/** + * The qse_fio_setcmgr() funcfion changes the character manager to @a cmgr. + * The character manager is used only if @a fio is opened with #QSE_FIO_TEXT. + */ +void qse_fio_setcmgr ( + qse_fio_t* fio, + qse_cmgr_t* cmgr +); /** * The qse_fio_gethandle() function returns the native file handle. diff --git a/qse/include/qse/cmn/pio.h b/qse/include/qse/cmn/pio.h index 5f959e22..5f35995d 100644 --- a/qse/include/qse/cmn/pio.h +++ b/qse/include/qse/cmn/pio.h @@ -77,7 +77,6 @@ enum qse_pio_flag_t QSE_PIO_DROPERR = (1 << 18) }; - /** * The qse_pio_hid_t type defines pipe IDs established to a child process. */ @@ -138,7 +137,7 @@ typedef enum qse_pio_errnum_t qse_pio_errnum_t; /* => typedef LHANDLE HFILE; typedef LHANDLE PID; typedef unsigned long LHANDLE; */ - typedef unsigned long qse_pio_hnd_t; /**< defines a pipe handle type */ + typedef unsigned long qse_pio_hnd_t; /**< defines a pipe handle type */ typedef unsigned long qse_pio_pid_t; /**< defined a process handle type */ # define QSE_PIO_HND_NIL ((qse_pio_hnd_t)-1) # define QSE_PIO_PID_NIL ((qse_pio_pid_t)-1) @@ -280,6 +279,25 @@ const qse_char_t* qse_pio_geterrmsg ( qse_pio_t* pio /**< pio object */ ); +/** + * The qse_pio_getcmgr() function returns the current character manager. + * It returns #QSE_NULL is @a pio is not opened with #QSE_PIO_TEXT. + */ +qse_cmgr_t* qse_pio_getcmgr ( + qse_pio_t* pio, + qse_pio_hid_t hid +); + +/** + * The qse_pio_setcmgr() function changes the character manager to @a cmgr. + * The character manager is used only if @a pio is opened with #QSE_PIO_TEXT. + */ +void qse_pio_setcmgr ( + qse_pio_t* pio, + qse_pio_hid_t hid, + qse_cmgr_t* cmgr +); + /** * The qse_pio_gethandle() function gets a pipe handle. * @return pipe handle @@ -303,9 +321,9 @@ qse_pio_pid_t qse_pio_getchild ( */ qse_ssize_t qse_pio_read ( qse_pio_t* pio, /**< pio object */ + qse_pio_hid_t hid, /**< handle ID */ void* buf, /**< buffer to fill */ - qse_size_t size, /**< buffer size */ - qse_pio_hid_t hid /**< handle ID */ + qse_size_t size /**< buffer size */ ); /** @@ -316,9 +334,9 @@ qse_ssize_t qse_pio_read ( */ qse_ssize_t qse_pio_write ( qse_pio_t* pio, /**< pio object */ + qse_pio_hid_t hid, /**< handle ID */ const void* data, /**< data to write */ - qse_size_t size, /**< data size */ - qse_pio_hid_t hid /**< handle ID */ + qse_size_t size /**< data size */ ); /** diff --git a/qse/include/qse/cmn/sio.h b/qse/include/qse/cmn/sio.h index 2fc6fd2c..5e9625d5 100644 --- a/qse/include/qse/cmn/sio.h +++ b/qse/include/qse/cmn/sio.h @@ -144,6 +144,15 @@ qse_sio_errnum_t qse_sio_geterrnum ( qse_sio_t* sio ); +qse_cmgr_t* qse_sio_getcmgr ( + qse_sio_t* sio +); + +void qse_sio_setcmgr ( + qse_sio_t* sio, + qse_cmgr_t* cmgr +); + qse_sio_hnd_t qse_sio_gethandle ( qse_sio_t* sio ); diff --git a/qse/include/qse/cmn/tio.h b/qse/include/qse/cmn/tio.h index 52fb4e3b..016611da 100644 --- a/qse/include/qse/cmn/tio.h +++ b/qse/include/qse/cmn/tio.h @@ -110,16 +110,17 @@ struct qse_tio_t { QSE_DEFINE_COMMON_FIELDS (tio) qse_tio_errnum_t errnum; - int flags; + int flags; + qse_cmgr_t* cmgr; - qse_tio_io_t in; - qse_tio_io_t out; + qse_tio_io_t in; + qse_tio_io_t out; /* for house keeping from here */ - int input_status; - qse_size_t inbuf_cur; - qse_size_t inbuf_len; - qse_size_t outbuf_len; + int input_status; + qse_size_t inbuf_cur; + qse_size_t inbuf_len; + qse_size_t outbuf_len; }; #ifdef __cplusplus @@ -176,6 +177,21 @@ const qse_char_t* qse_tio_geterrmsg ( qse_tio_t* tio ); +/** + * The qse_tio_getcmgr() function returns the character manager. + */ +qse_cmgr_t* qse_tio_getcmgr ( + qse_tio_t* tio +); + +/** + * The qse_tio_setcmgr() function changes the character manager. + */ +void qse_tio_setcmgr ( + qse_tio_t* tio, + qse_cmgr_t* cmgr +); + /** * The qse_tio_attachin() function attachs an input handler . * @return 0 on success, -1 on failure diff --git a/qse/include/qse/types.h b/qse/include/qse/types.h index 1d0247a5..a67b5291 100644 --- a/qse/include/qse/types.h +++ b/qse/include/qse/types.h @@ -716,6 +716,30 @@ struct qse_mmgr_t }; typedef struct qse_mmgr_t qse_mmgr_t; + +typedef qse_size_t (*qse_cmgr_mbtowc_t) ( + const qse_mchar_t* mb, + qse_size_t size, + qse_wchar_t* wc +); + +typedef qse_size_t (*qse_cmgr_wctomb_t) ( + qse_wchar_t wc, + qse_mchar_t* mb, + qse_size_t size +); + +/** + * The qse_cmgr_t type defines the interface to various character handling. + */ +struct qse_cmgr_t +{ + qse_cmgr_mbtowc_t mbtowc; + qse_cmgr_wctomb_t wctomb; +}; + +typedef struct qse_cmgr_t qse_cmgr_t; + /** * The #qse_foff_t type defines an integer that can represent a file offset. * Depending on your system, it's defined to one of #qse_int64_t, #qse_int32_t, diff --git a/qse/lib/awk/StdAwk.cpp b/qse/lib/awk/StdAwk.cpp index 52f6f50e..4f933d59 100644 --- a/qse/lib/awk/StdAwk.cpp +++ b/qse/lib/awk/StdAwk.cpp @@ -224,12 +224,12 @@ int StdAwk::closePipe (Pipe& io) StdAwk::ssize_t StdAwk::readPipe (Pipe& io, char_t* buf, size_t len) { - return qse_pio_read ((qse_pio_t*)io.getHandle(), buf, len, QSE_PIO_OUT); + return qse_pio_read ((qse_pio_t*)io.getHandle(), QSE_PIO_OUT, buf, len); } StdAwk::ssize_t StdAwk::writePipe (Pipe& io, const char_t* buf, size_t len) { - return qse_pio_write ((qse_pio_t*)io.getHandle(), buf, len, QSE_PIO_IN); + return qse_pio_write ((qse_pio_t*)io.getHandle(), QSE_PIO_IN, buf, len); } int StdAwk::flushPipe (Pipe& io) diff --git a/qse/lib/awk/std.c b/qse/lib/awk/std.c index 14f9689b..e369a74a 100644 --- a/qse/lib/awk/std.c +++ b/qse/lib/awk/std.c @@ -863,9 +863,7 @@ static qse_ssize_t awk_rio_pipe ( { return qse_pio_read ( (qse_pio_t*)riod->handle, - data, - size, - QSE_PIO_OUT + QSE_PIO_OUT, data, size ); } @@ -873,9 +871,7 @@ static qse_ssize_t awk_rio_pipe ( { return qse_pio_write ( (qse_pio_t*)riod->handle, - data, - size, - QSE_PIO_IN + QSE_PIO_IN, data, size ); } diff --git a/qse/lib/cmn/Makefile.am b/qse/lib/cmn/Makefile.am index a14e08a2..de8d2792 100644 --- a/qse/lib/cmn/Makefile.am +++ b/qse/lib/cmn/Makefile.am @@ -66,6 +66,7 @@ libqsecmn_la_SOURCES = \ str-fnmat.c \ str-incl.c \ str-len.c \ + str-mbwc.c \ str-pac.c \ str-pbrk.c \ str-put.c \ diff --git a/qse/lib/cmn/Makefile.in b/qse/lib/cmn/Makefile.in index b6a15875..fc7dc6d1 100644 --- a/qse/lib/cmn/Makefile.in +++ b/qse/lib/cmn/Makefile.in @@ -82,12 +82,13 @@ am_libqsecmn_la_OBJECTS = alg-rand.lo alg-search.lo alg-sort.lo \ rbt.lo rex.lo sio.lo sll.lo stdio.lo str-beg.lo str-cat.lo \ str-chr.lo str-cnv.lo str-cmp.lo str-cpy.lo str-del.lo \ str-dup.lo str-dynm.lo str-dynw.lo str-end.lo str-excl.lo \ - str-fcpy.lo str-fnmat.lo str-incl.lo str-len.lo str-pac.lo \ - str-pbrk.lo str-put.lo str-rev.lo str-rot.lo str-set.lo \ - str-spl.lo str-spn.lo str-str.lo str-subst.lo str-tok.lo \ - str-trm.lo str-word.lo time.lo tio.lo tio-get.lo tio-put.lo \ - tre.lo tre-ast.lo tre-compile.lo tre-match-backtrack.lo \ - tre-match-parallel.lo tre-parse.lo tre-stack.lo utf8.lo xma.lo + str-fcpy.lo str-fnmat.lo str-incl.lo str-len.lo str-mbwc.lo \ + str-pac.lo str-pbrk.lo str-put.lo str-rev.lo str-rot.lo \ + str-set.lo str-spl.lo str-spn.lo str-str.lo str-subst.lo \ + str-tok.lo str-trm.lo str-word.lo time.lo tio.lo tio-get.lo \ + tio-put.lo tre.lo tre-ast.lo tre-compile.lo \ + tre-match-backtrack.lo tre-match-parallel.lo tre-parse.lo \ + tre-stack.lo utf8.lo xma.lo libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS) libqsecmn_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -335,6 +336,7 @@ libqsecmn_la_SOURCES = \ str-fnmat.c \ str-incl.c \ str-len.c \ + str-mbwc.c \ str-pac.c \ str-pbrk.c \ str-put.c \ @@ -492,6 +494,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-fnmat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-incl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-len.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-mbwc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-pac.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-pbrk.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str-put.Plo@am__quote@ diff --git a/qse/lib/cmn/fio.c b/qse/lib/cmn/fio.c index ea954ff6..954b603c 100644 --- a/qse/lib/cmn/fio.c +++ b/qse/lib/cmn/fio.c @@ -551,6 +551,16 @@ void qse_fio_fini (qse_fio_t* fio) } } +qse_cmgr_t* qse_fio_getcmgr (qse_fio_t* fio) +{ + return fio->tio? qse_tio_getcmgr (fio->tio): QSE_NULL; +} + +void qse_fio_setcmgr (qse_fio_t* fio, qse_cmgr_t* cmgr) +{ + if (fio->tio) qse_tio_setcmgr (fio->tio, cmgr); +} + qse_fio_hnd_t qse_fio_gethandle (qse_fio_t* fio) { return fio->handle; diff --git a/qse/lib/cmn/pio.c b/qse/lib/cmn/pio.c index b4e2092e..516e65a0 100644 --- a/qse/lib/cmn/pio.c +++ b/qse/lib/cmn/pio.c @@ -967,6 +967,7 @@ int qse_pio_init ( if (flags & QSE_PIO_IGNOREMBWCERR) topt |= QSE_TIO_IGNOREMBWCERR; if (flags & QSE_PIO_NOAUTOFLUSH) topt |= QSE_TIO_NOAUTOFLUSH; + QSE_ASSERT (QSE_COUNTOF(tio) == QSE_COUNTOF(pio->pin)); for (i = 0; i < QSE_COUNTOF(tio); i++) { int r; @@ -979,8 +980,10 @@ int qse_pio_init ( } r = (i == QSE_PIO_IN)? - qse_tio_attachout (tio[i], pio_output, &pio->pin[i], QSE_NULL, 4096): - qse_tio_attachin (tio[i], pio_input, &pio->pin[i], QSE_NULL, 4096); + qse_tio_attachout ( + tio[i], pio_output, &pio->pin[i], QSE_NULL, 4096): + qse_tio_attachin ( + tio[i], pio_input, &pio->pin[i], QSE_NULL, 4096); if (r <= -1) goto oops; @@ -1090,6 +1093,17 @@ const qse_char_t* qse_pio_geterrmsg (qse_pio_t* pio) QSE_COUNTOF(__errstr) - 1: pio->errnum]; } +qse_cmgr_t* qse_pio_getcmgr (qse_pio_t* pio, qse_pio_hid_t hid) +{ + return pio->pin[hid].tio? + qse_tio_getcmgr(pio->pin[hid].tio): QSE_NULL; +} + +void qse_pio_setcmgr (qse_pio_t* pio, qse_pio_hid_t hid, qse_cmgr_t* cmgr) +{ + if (pio->pin[hid].tio) qse_tio_setcmgr (pio->pin[hid].tio, cmgr); +} + qse_pio_hnd_t qse_pio_gethandle (qse_pio_t* pio, qse_pio_hid_t hid) { return pio->pin[hid].handle; @@ -1190,7 +1204,7 @@ reread: } qse_ssize_t qse_pio_read ( - qse_pio_t* pio, void* buf, qse_size_t size, qse_pio_hid_t hid) + qse_pio_t* pio, qse_pio_hid_t hid, void* buf, qse_size_t size) { if (pio->pin[hid].tio == QSE_NULL) return pio_read (pio, buf, size, pio->pin[hid].handle); @@ -1285,8 +1299,8 @@ rewrite: } qse_ssize_t qse_pio_write ( - qse_pio_t* pio, const void* data, qse_size_t size, - qse_pio_hid_t hid) + qse_pio_t* pio, qse_pio_hid_t hid, + const void* data, qse_size_t size) { if (pio->pin[hid].tio == QSE_NULL) return pio_write (pio, data, size, pio->pin[hid].handle); @@ -1547,7 +1561,8 @@ int qse_pio_kill (qse_pio_t* pio) #endif } -static qse_ssize_t pio_input (qse_tio_cmd_t cmd, void* arg, void* buf, qse_size_t size) +static qse_ssize_t pio_input ( + qse_tio_cmd_t cmd, void* arg, void* buf, qse_size_t size) { qse_pio_pin_t* pin = (qse_pio_pin_t*)arg; QSE_ASSERT (pin != QSE_NULL); @@ -1562,7 +1577,8 @@ static qse_ssize_t pio_input (qse_tio_cmd_t cmd, void* arg, void* buf, qse_size_ return 0; } -static qse_ssize_t pio_output (qse_tio_cmd_t cmd, void* arg, void* buf, qse_size_t size) +static qse_ssize_t pio_output ( + qse_tio_cmd_t cmd, void* arg, void* buf, qse_size_t size) { qse_pio_pin_t* pin = (qse_pio_pin_t*)arg; QSE_ASSERT (pin != QSE_NULL); diff --git a/qse/lib/cmn/sio.c b/qse/lib/cmn/sio.c index b35841d1..e5fbf22a 100644 --- a/qse/lib/cmn/sio.c +++ b/qse/lib/cmn/sio.c @@ -140,6 +140,16 @@ void qse_sio_fini (qse_sio_t* sio) qse_fio_fini (&sio->fio); } +qse_cmgr_t* qse_sio_getcmgr (qse_sio_t* sio) +{ + return qse_tio_getcmgr (&sio->tio); +} + +void qse_sio_setcmgr (qse_sio_t* sio, qse_cmgr_t* cmgr) +{ + qse_tio_setcmgr (&sio->tio, cmgr); +} + qse_sio_errnum_t qse_sio_geterrnum (qse_sio_t* sio) { return QSE_TIO_ERRNUM(&sio->tio); diff --git a/qse/lib/cmn/str-cnv.c b/qse/lib/cmn/str-cnv.c index b8142900..d47c89ed 100644 --- a/qse/lib/cmn/str-cnv.c +++ b/qse/lib/cmn/str-cnv.c @@ -134,12 +134,10 @@ qse_ulong_t qse_strxtoulong (const qse_char_t* str, qse_size_t len) return v; } - /* * TODO: fix wrong mbstate handling */ - int qse_mbstowcs ( const qse_mchar_t* mbs, qse_size_t* mbslen, qse_wchar_t* wcs, qse_size_t* wcslen) diff --git a/qse/lib/cmn/str-mbwc.c b/qse/lib/cmn/str-mbwc.c new file mode 100644 index 00000000..a179a3cc --- /dev/null +++ b/qse/lib/cmn/str-mbwc.c @@ -0,0 +1,437 @@ +/* + * $Id: str-cnv.c 556 2011-08-31 15:43:46Z hyunghwan.chung $ + * + Copyright 2006-2011 Chung, Hyung-Hwan. + This file is part of QSE. + + QSE is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + QSE 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with QSE. If not, see . + */ + +#include +#include "mem.h" + +int qse_mbstowcswithcmgr ( + const qse_mchar_t* mbs, qse_size_t* mbslen, + qse_wchar_t* wcs, qse_size_t* wcslen, qse_cmgr_t* cmgr) +{ + const qse_mchar_t* mp; + qse_size_t mlen, wlen; + int n; + + for (mp = mbs; *mp != QSE_MT('\0'); mp++); + + mlen = mp - mbs; wlen = *wcslen; + n = qse_mbsntowcsnwithcmgr (mbs, &mlen, wcs, &wlen, cmgr); + if (wcs) + { + if (wlen < *wcslen) wcs[wlen] = QSE_WT('\0'); + else n = -2; /* buffer too small */ + } + *mbslen = mlen; *wcslen = wlen; + + return n; +} + +int qse_mbsntowcsnwithcmgr ( + const qse_mchar_t* mbs, qse_size_t* mbslen, + qse_wchar_t* wcs, qse_size_t* wcslen, qse_cmgr_t* cmgr) +{ + const qse_mchar_t* p; + int ret = 0; + qse_size_t mlen; + + if (wcs) + { + qse_wchar_t* q, * qend; + + p = mbs; + q = wcs; + qend = wcs + *wcslen; + mlen = *mbslen; + + while (mlen > 0) + { + qse_size_t n; + + if (q >= qend) + { + /* buffer too small */ + ret = -2; + break; + } + + n = cmgr->mbtowc (p, mlen, q); + if (n == 0) + { + /* invalid sequence */ + ret = -1; + break; + } + if (n > mlen) + { + /* incomplete sequence */ + ret = -3; + break; + } + + q++; + p += n; + mlen -= n; + } + + *wcslen = q - wcs; + *mbslen = p - mbs; + } + else + { + qse_wchar_t w; + qse_size_t wlen = 0; + + p = mbs; + mlen = *mbslen; + + while (mlen > 0) + { + qse_size_t n; + + n = cmgr->mbtowc (p, mlen, &w); + if (n == 0) + { + /* invalid sequence */ + ret = -1; + break; + } + if (n > mlen) + { + /* incomplete sequence */ + ret = -3; + break; + } + + p += n; + mlen -= n; + wlen += 1; + } + + *wcslen = wlen; + *mbslen = p - mbs; + } + + return ret; +} + +int qse_mbsntowcsnuptowithcmgr ( + const qse_mchar_t* mbs, qse_size_t* mbslen, + qse_wchar_t* wcs, qse_size_t* wcslen, qse_wchar_t stopper, qse_cmgr_t* cmgr) +{ + const qse_mchar_t* p; + int ret = 0; + qse_size_t mlen; + + qse_wchar_t w; + qse_size_t wlen = 0; + qse_wchar_t* wend; + + p = mbs; + mlen = *mbslen; + + if (wcs) wend = wcs + *wcslen; + + /* since it needs to break when a stopper is met, + * i can't perform bulky conversion using the buffer + * provided. so conversion is conducted character by + * character */ + while (mlen > 0) + { + qse_size_t n; + + n = cmgr->mbtowc (p, mlen, &w); + if (n == 0) + { + /* invalid sequence */ + ret = -1; + break; + } + if (n > mlen) + { + /* incomplete sequence */ + ret = -3; + break; + } + + if (wcs) + { + if (wcs >= wend) break; + *wcs++ = w; + } + + p += n; + mlen -= n; + wlen += 1; + + if (w == stopper) break; + } + + *wcslen = wlen; + *mbslen = p - mbs; + + return ret; +} + +qse_wchar_t* qse_mbstowcsdupwithcmgr ( + const qse_mchar_t* mbs, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) +{ + qse_size_t mbslen, wcslen; + qse_wchar_t* wcs; + + if (qse_mbstowcswithcmgr (mbs, &mbslen, QSE_NULL, &wcslen, cmgr) <= -1) return QSE_NULL; + + wcslen++; /* for terminating null */ + wcs = QSE_MMGR_ALLOC (mmgr, wcslen * QSE_SIZEOF(*wcs)); + if (wcs == QSE_NULL) return QSE_NULL; + + qse_mbstowcswithcmgr (mbs, &mbslen, wcs, &wcslen, cmgr); + return wcs; +} + +qse_wchar_t* qse_mbsatowcsdupwithcmgr ( + const qse_mchar_t* mbs[], qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) +{ + qse_wchar_t* buf, * ptr; + qse_size_t i; + qse_size_t capa = 0; + qse_size_t wl, ml; + + QSE_ASSERT (mmgr != QSE_NULL); + + for (i = 0; mbs[i]; i++) + { + if (qse_mbstowcswithcmgr (mbs[i], &ml, QSE_NULL, &wl, cmgr) <= -1) return QSE_NULL; + capa += wl; + } + + buf = (qse_wchar_t*) QSE_MMGR_ALLOC ( + mmgr, (capa + 1) * QSE_SIZEOF(*buf)); + if (buf == QSE_NULL) return QSE_NULL; + + ptr = buf; + for (i = 0; mbs[i]; i++) + { + wl = capa + 1; + qse_mbstowcswithcmgr (mbs[i], &ml, ptr, &wl, cmgr); + ptr += wl; + capa -= wl; + } + + return buf; +} + +int qse_wcstombswithcmgr ( + const qse_wchar_t* wcs, qse_size_t* wcslen, + qse_mchar_t* mbs, qse_size_t* mbslen, qse_cmgr_t* cmgr) +{ + const qse_wchar_t* p = wcs; + int ret = 0; + + if (mbs) + { + qse_size_t rem = *mbslen; + + while (*p != QSE_WT('\0')) + { + qse_size_t n; + + if (rem <= 0) + { + ret = -2; + break; + } + + n = cmgr->wctomb (*p, mbs, rem); + if (n == 0) + { + ret = -1; + break; /* illegal character */ + } + if (n > rem) + { + ret = -2; + break; /* buffer too small */ + } + + mbs += n; rem -= n; p++; + } + + /* update mbslen to the length of the mbs string converted excluding + * terminating null */ + *mbslen -= rem; + + /* null-terminate the multibyte sequence if it has sufficient space */ + if (rem > 0) *mbs = QSE_MT('\0'); + else + { + /* 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 */ + } + } + else + { + qse_mchar_t mbsbuf[QSE_MBLEN_MAX]; + qse_size_t mlen = 0; + + while (*p != QSE_WT('\0')) + { + qse_size_t n; + + n = cmgr->wctomb (*p, mbsbuf, QSE_COUNTOF(mbsbuf)); + if (n == 0) + { + ret = -1; + break; /* illegal character */ + } + + /* it assumes that mbs is large enough to hold a character */ + QSE_ASSERT (n <= QSE_COUNTOF(mbs)); + + p++; mlen += n; + } + + /* this length holds the number of resulting multi-byte characters + * excluding the terminating null character */ + *mbslen = mlen; + } + + *wcslen = p - wcs; /* the number of wide characters handled. */ + + return ret; +} + +int qse_wcsntombsnwithcmgr ( + const qse_wchar_t* wcs, qse_size_t* wcslen, + qse_mchar_t* mbs, qse_size_t* mbslen, qse_cmgr_t* cmgr) +{ + const qse_wchar_t* p = wcs; + const qse_wchar_t* end = wcs + *wcslen; + int ret = 0; + + if (mbs) + { + qse_size_t rem = *mbslen; + + while (p < end) + { + qse_size_t n; + + if (rem <= 0) + { + ret = -2; /* buffer too small */ + break; + } + + n = cmgr->wctomb (*p, mbs, rem); + if (n == 0) + { + ret = -1; + break; /* illegal character */ + } + if (n > rem) + { + ret = -2; /* buffer too small */ + break; + } + mbs += n; rem -= n; p++; + } + + *mbslen -= rem; + } + else + { + qse_mchar_t mbsbuf[QSE_MBLEN_MAX]; + qse_size_t mlen = 0; + + while (p < end) + { + qse_size_t n; + + n = cmgr->wctomb (*p, mbsbuf, QSE_COUNTOF(mbsbuf)); + if (n == 0) + { + ret = -1; + break; /* illegal character */ + } + + /* it assumes that mbs is large enough to hold a character */ + QSE_ASSERT (n <= QSE_COUNTOF(mbsbuf)); + + p++; mlen += n; + } + + /* this length excludes the terminating null character. + * this function doesn't event null-terminate the result. */ + *mbslen = mlen; + } + + *wcslen = p - wcs; + + return ret; +} + +qse_mchar_t* qse_wcstombsdupwithcmgr (const qse_wchar_t* wcs, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) +{ + qse_size_t wcslen, mbslen; + qse_mchar_t* mbs; + + if (qse_wcstombswithcmgr (wcs, &wcslen, QSE_NULL, &mbslen, cmgr) <= -1) return QSE_NULL; + + mbslen++; /* for the terminating null character */ + + mbs = QSE_MMGR_ALLOC (mmgr, mbslen * QSE_SIZEOF(*mbs)); + if (mbs == QSE_NULL) return QSE_NULL; + + qse_wcstombswithcmgr (wcs, &wcslen, mbs, &mbslen, cmgr); + return mbs; +} + +qse_mchar_t* qse_wcsatombsdupwithcmgr (const qse_wchar_t* wcs[], qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) +{ + qse_mchar_t* buf, * ptr; + qse_size_t i; + qse_size_t wl, ml; + qse_size_t capa = 0; + + QSE_ASSERT (mmgr != QSE_NULL); + + for (i = 0; wcs[i]; i++) + { + if (qse_wcstombswithcmgr (wcs[i], &wl, QSE_NULL, &ml, cmgr) <= -1) return QSE_NULL; + capa += ml; + } + + buf = (qse_mchar_t*) QSE_MMGR_ALLOC ( + mmgr, (capa + 1) * QSE_SIZEOF(*buf)); + if (buf == QSE_NULL) return QSE_NULL; + + ptr = buf; + for (i = 0; wcs[i]; i++) + { + ml = capa + 1; + qse_wcstombswithcmgr (wcs[i], &wl, ptr, &ml, cmgr); + ptr += ml; + capa -= ml; + } + + return buf; +} diff --git a/qse/lib/cmn/tio-get.c b/qse/lib/cmn/tio-get.c index c2f5de30..cc513969 100644 --- a/qse/lib/cmn/tio-get.c +++ b/qse/lib/cmn/tio-get.c @@ -132,9 +132,9 @@ static QSE_INLINE qse_ssize_t tio_read_widechars ( mlen = tio->inbuf_len - tio->inbuf_cur; wlen = bufsize; - x = qse_mbsntowcsnupto ( + x = qse_mbsntowcsnuptowithcmgr ( &tio->in.buf.ptr[tio->inbuf_cur], - &mlen, buf, &wlen, QSE_WT('\n')); + &mlen, buf, &wlen, QSE_WT('\n'), tio->cmgr); tio->inbuf_cur += mlen; if (x == -3) diff --git a/qse/lib/cmn/tio-put.c b/qse/lib/cmn/tio-put.c index 05af627d..533b1c61 100644 --- a/qse/lib/cmn/tio-put.c +++ b/qse/lib/cmn/tio-put.c @@ -142,8 +142,8 @@ qse_ssize_t qse_tio_writewcs ( capa = tio->out.buf.capa - tio->outbuf_len; wcnt = xwlen; mcnt = capa; - n = qse_wcsntombsn ( - wptr, &wcnt, &tio->out.buf.ptr[tio->outbuf_len], &mcnt); + n = qse_wcsntombsnwithcmgr ( + wptr, &wcnt, &tio->out.buf.ptr[tio->outbuf_len], &mcnt, tio->cmgr); tio->outbuf_len += mcnt; if (n == -2) diff --git a/qse/lib/cmn/tio.c b/qse/lib/cmn/tio.c index f15bc6c9..fca4070c 100644 --- a/qse/lib/cmn/tio.c +++ b/qse/lib/cmn/tio.c @@ -19,6 +19,7 @@ */ #include +#include #include "mem.h" QSE_IMPLEMENT_COMMON_FUNCTIONS (tio) @@ -51,9 +52,19 @@ int qse_tio_close (qse_tio_t* tio) int qse_tio_init (qse_tio_t* tio, qse_mmgr_t* mmgr, int flags) { + /* TODO: set this default_cmgr differently depending on + * build options and platforms */ + static qse_cmgr_t default_cmgr = + { + qse_utf8touc, + qse_uctoutf8 + }; + QSE_MEMSET (tio, 0, QSE_SIZEOF(*tio)); tio->mmgr = mmgr; + tio->cmgr = &default_cmgr; + /* mask off internal bits when storing the flags for safety */ tio->flags = flags & ~(QSE_TIO_DYNINBUF | QSE_TIO_DYNOUTBUF); @@ -111,6 +122,16 @@ const qse_char_t* qse_tio_geterrmsg (qse_tio_t* tio) QSE_COUNTOF(__errmsg) - 1: tio->errnum]; } +qse_cmgr_t* qse_tio_getcmgr (qse_tio_t* tio) +{ + return tio->cmgr; +} + +void qse_tio_setcmgr (qse_tio_t* tio, qse_cmgr_t* cmgr) +{ + tio->cmgr = cmgr; +} + int qse_tio_attachin ( qse_tio_t* tio, qse_tio_io_fun_t input, void* arg, qse_mchar_t* bufptr, qse_size_t bufcapa) diff --git a/qse/lib/net/httpd_task.c b/qse/lib/net/httpd_task.c index a316c3a6..de5c7e38 100644 --- a/qse/lib/net/httpd_task.c +++ b/qse/lib/net/httpd_task.c @@ -955,10 +955,9 @@ qse_printf (QSE_T("READING CHUNKED MODE...\n")); /* <- can i make it non-block?? or use select??? pio_tryread()? */ n = qse_pio_read ( - cgi->pio, + cgi->pio, QSE_PIO_OUT, &cgi->buf[cgi->buflen + QSE_SIZEOF(chunklen) - 1], - count - extra, - QSE_PIO_OUT + count - extra ); if (n <= -1) { @@ -994,10 +993,9 @@ qse_printf (QSE_T("READING CHUNKED MODE...\n")); { qse_printf (QSE_T("READING IN NON-CHUNKED MODE...\n")); n = qse_pio_read ( - cgi->pio, + cgi->pio, QSE_PIO_OUT, &cgi->buf[cgi->buflen], - QSE_SIZEOF(cgi->buf) - cgi->buflen, - QSE_PIO_OUT + QSE_SIZEOF(cgi->buf) - cgi->buflen ); if (n <= -1) { @@ -1088,10 +1086,9 @@ static int task_main_cgi_2 ( qse_printf (QSE_T("[cgi_2 ]\n")); /* <- can i make it non-block?? or use select??? pio_tryread()? */ n = qse_pio_read ( - cgi->pio, + cgi->pio, QSE_PIO_OUT, &cgi->buf[cgi->buflen], - QSE_SIZEOF(cgi->buf) - cgi->buflen, - QSE_PIO_OUT + QSE_SIZEOF(cgi->buf) - cgi->buflen ); if (n <= -1) { diff --git a/qse/samples/cmn/pio.c b/qse/samples/cmn/pio.c index f4c78a8e..b531a26f 100644 --- a/qse/samples/cmn/pio.c +++ b/qse/samples/cmn/pio.c @@ -47,7 +47,7 @@ static int pio1 (const qse_char_t* cmd, qse_env_t* env, int oflags, qse_pio_hid_ qse_ssize_t i; /*qse_pio_canread (pio, QSE_PIO_ERR, 1000)*/ - qse_ssize_t n = qse_pio_read (pio, buf, QSE_SIZEOF(buf), rhid); + qse_ssize_t n = qse_pio_read (pio, rhid, buf, QSE_SIZEOF(buf)); if (n == 0) break; if (n <= -1) { @@ -106,7 +106,7 @@ static int pio2 (const qse_char_t* cmd, qse_env_t* env, int oflags, qse_pio_hid_ qse_char_t buf[128]; qse_ssize_t i; - qse_ssize_t n = qse_pio_read (pio, buf, QSE_COUNTOF(buf), rhid); + qse_ssize_t n = qse_pio_read (pio, rhid, buf, QSE_COUNTOF(buf)); if (n == 0) break; if (n < 0) { @@ -352,7 +352,7 @@ static int test12 (void) while (1) { qse_mchar_t buf[100]; - qse_ssize_t x = qse_pio_read (pio, buf, QSE_SIZEOF(buf), QSE_PIO_OUT); + qse_ssize_t x = qse_pio_read (pio, QSE_PIO_OUT, buf, QSE_SIZEOF(buf)); if (x <= 0) break; }