From c9caef5ae8a2c781fe7bf949b6d5cdee06ccb82a Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 28 Mar 2011 08:32:37 +0000 Subject: [PATCH] added qse_mbsxsubst()/qse_wcsxsubst() --- qse/include/qse/cmn/str.h | 134 ++++++++++++++++++++++++----------- qse/lib/cmn/Makefile.am | 2 +- qse/lib/cmn/Makefile.in | 11 +-- qse/lib/cmn/str_bas.c | 64 +---------------- qse/lib/cmn/str_subst.c | 145 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+), 109 deletions(-) create mode 100644 qse/lib/cmn/str_subst.c diff --git a/qse/include/qse/cmn/str.h b/qse/include/qse/cmn/str.h index 594f20dc..5e0f77ca 100644 --- a/qse/include/qse/cmn/str.h +++ b/qse/include/qse/cmn/str.h @@ -1,5 +1,5 @@ /* - * $Id: str.h 416 2011-03-27 05:04:24Z hyunghwan.chung $ + * $Id: str.h 417 2011-03-27 14:32:37Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -57,16 +57,32 @@ struct qse_str_t }; /** - * The qse_strxsubst_subst_t type defines a callback function - * for qse_strxsubst() to substitue a new value for an identifier @a ident. + * The qse_mbsxsubst_subst_t type defines a callback function + * for qse_mbsxsubst() to substitue a new value for an identifier @a ident. */ -typedef qse_char_t* (*qse_strxsubst_subst_t) ( - qse_char_t* buf, - qse_size_t bsz, - const qse_cstr_t* ident, - void* ctx +typedef qse_mchar_t* (*qse_mbsxsubst_subst_t) ( + qse_mchar_t* buf, + qse_size_t bsz, + const qse_mcstr_t* ident, + void* ctx ); +/** + * The qse_wcsxsubst_subst_t type defines a callback function + * for qse_wcsxsubst() to substitue a new value for an identifier @a ident. + */ +typedef qse_wchar_t* (*qse_wcsxsubst_subst_t) ( + qse_wchar_t* buf, + qse_size_t bsz, + const qse_wcstr_t* ident, + void* ctx +); + +#ifdef QSE_CHAR_IS_MCHAR +# define qse_strxsubst_subst_t qse_mbsxsubst_subst_t +#else +# define qse_strxsubst_subst_t qse_wcsxsubst_subst_t +#endif /* int qse_chartonum (qse_char_t c, int base) */ #define QSE_CHARTONUM(c,base) \ @@ -435,31 +451,63 @@ qse_size_t qse_wcsxfncpy ( #endif /** - * The qse_strxsubst() function expands @a fmt into a buffer @a buf of the size + * The qse_mbsxsubst() function expands @a fmt into a buffer @a buf of the size * @a bsz by substituting new values for ${} segments within it. The actual * substitution is made by invoking the callback function @a subst. * @code - * qse_char_t* subst (qse_char_t* buf, qse_size_t bsz, const qse_cstr_t* ident, void* ctx) + * qse_mchar_t* subst (qse_mchar_t* buf, qse_size_t bsz, const qse_mcstr_t* ident, void* ctx) * { - * if (qse_strxcmp (ident->ptr, ident->len, QSE_T("USER")) == 0) - * return buf + qse_strxput (buf, bsz, QSE_T("sam")); - * else if (qse_strxcmp (ident->ptr, ident->len, QSE_T("GROUP")) == 0) - * return buf + qse_strxput (buf, bsz, QSE_T("coders")); + * if (qse_mbsxcmp (ident->ptr, ident->len, QSE_MT("USER")) == 0) + * return buf + qse_mbsxput (buf, bsz, QSE_MT("sam")); + * else if (qse_mbsxcmp (ident->ptr, ident->len, QSE_MT("GROUP")) == 0) + * return buf + qse_mbsxput (buf, bsz, QSE_MT("coders")); * return buf; * } * - * qse_char_t buf[25]; - * qse_strxsubst (buf, i, QSE_T("user=${USER},group=${GROUP}"), subst, QSE_NULL); + * qse_mchar_t buf[25]; + * qse_mbsxsubst (buf, i, QSE_MT("user=${USER},group=${GROUP}"), subst, QSE_NULL); * @endcode */ -qse_size_t qse_strxsubst ( - qse_char_t* buf, +qse_size_t qse_mbsxsubst ( + qse_mchar_t* buf, qse_size_t bsz, - const qse_char_t* fmt, - qse_strxsubst_subst_t subst, + const qse_mchar_t* fmt, + qse_mbsxsubst_subst_t subst, void* ctx ); +/** + * The qse_wcsxsubst() function expands @a fmt into a buffer @a buf of the size + * @a bsz by substituting new values for ${} segments within it. The actual + * substitution is made by invoking the callback function @a subst. + * @code + * qse_wchar_t* subst (qse_wchar_t* buf, qse_size_t bsz, const qse_wcstr_t* ident, void* ctx) + * { + * if (qse_wcsxcmp (ident->ptr, ident->len, QSE_WT("USER")) == 0) + * return buf + qse_wcsxput (buf, bsz, QSE_WT("sam")); + * else if (qse_wcsxcmp (ident->ptr, ident->len, QSE_WT("GROUP")) == 0) + * return buf + qse_wcsxput (buf, bsz, QSE_WT("coders")); + * return buf; + * } + * + * qse_wchar_t buf[25]; + * qse_wcsxsubst (buf, i, QSE_WT("user=${USER},group=${GROUP}"), subst, QSE_NULL); + * @endcode + */ +qse_size_t qse_wcsxsubst ( + qse_wchar_t* buf, + qse_size_t bsz, + const qse_wchar_t* fmt, + qse_wcsxsubst_subst_t subst, + void* ctx +); + +#ifdef QSE_CHAR_IS_MCHAR +# define qse_strxsubst(buf,bsz,fmt,subst,ctx) qse_mbsxsubst(buf,bsz,fmt,subst,ctx) +#else +# define qse_strxsubst(buf,bsz,fmt,subst,ctx) qse_wcsxsubst(buf,bsz,fmt,subst,ctx) +#endif + qse_size_t qse_strxcat ( qse_char_t* buf, qse_size_t bsz, @@ -713,11 +761,37 @@ qse_char_t* qse_strxnrstr ( qse_size_t subsz ); +/** + * The qse_strxword() function finds a whole word in a string. + */ +const qse_char_t* qse_strxword ( + const qse_char_t* str, + qse_size_t len, + const qse_char_t* word +); + +/** + * The qse_strxcaseword() function finds a whole word in a string + * case-insensitively. + */ +const qse_char_t* qse_strxcaseword ( + const qse_char_t* str, + qse_size_t len, + const qse_char_t* word +); + + +/** + * The qse_mbschr() function finds a chracter in a string. + */ qse_mchar_t* qse_mbschr ( const qse_mchar_t* str, qse_mcint_t c ); +/** + * The qse_wcschr() function finds a chracter in a string. + */ qse_wchar_t* qse_wcschr ( const qse_wchar_t* str, qse_wcint_t c @@ -769,26 +843,6 @@ qse_wchar_t* qse_wcsxrchr ( # define qse_strxrrchr(str,len,c) qse_wcsxrchr(str,len,c) #endif - -/** - * The qse_strxword() function finds a whole word in a string. - */ -const qse_char_t* qse_strxword ( - const qse_char_t* str, - qse_size_t len, - const qse_char_t* word -); - -/** - * The qse_strxcaseword() function finds a whole word in a string - * case-insensitively. - */ -const qse_char_t* qse_strxcaseword ( - const qse_char_t* str, - qse_size_t len, - const qse_char_t* word -); - /** * The qse_strbeg() function checks if the a string begins with a substring. * @return the pointer to a beginning of a matching beginning, diff --git a/qse/lib/cmn/Makefile.am b/qse/lib/cmn/Makefile.am index 68778d4f..92c95baa 100644 --- a/qse/lib/cmn/Makefile.am +++ b/qse/lib/cmn/Makefile.am @@ -10,7 +10,7 @@ libqsecmn_la_SOURCES = \ syscall.h mem.h \ mem.c xma.c fma.c chr.c chr_cnv.c rex.c \ str_bas.c str_chr.c str_cnv.c str_cmp.c str_cpy.c str_dyn.c str_fcpy.c \ - str_pbrk.c str_put.c str_spn.c str_utl.c \ + str_pbrk.c str_put.c str_spn.c str_subst.c str_utl.c \ lda.c oht.c htb.c rbt.c sll.c gdl.c dll.c opt.c \ tio.c tio_get.c tio_put.c \ fio.c pio.c sio.c \ diff --git a/qse/lib/cmn/Makefile.in b/qse/lib/cmn/Makefile.in index 9a1f1db0..3324000d 100644 --- a/qse/lib/cmn/Makefile.in +++ b/qse/lib/cmn/Makefile.in @@ -75,10 +75,10 @@ libqsecmn_la_DEPENDENCIES = am_libqsecmn_la_OBJECTS = mem.lo xma.lo fma.lo chr.lo chr_cnv.lo \ rex.lo str_bas.lo str_chr.lo str_cnv.lo str_cmp.lo str_cpy.lo \ str_dyn.lo str_fcpy.lo str_pbrk.lo str_put.lo str_spn.lo \ - str_utl.lo lda.lo oht.lo htb.lo rbt.lo sll.lo gdl.lo dll.lo \ - opt.lo tio.lo tio_get.lo tio_put.lo fio.lo pio.lo sio.lo \ - alg_search.lo alg_sort.lo time.lo misc.lo assert.lo main.lo \ - stdio.lo + str_subst.lo str_utl.lo lda.lo oht.lo htb.lo rbt.lo sll.lo \ + gdl.lo dll.lo opt.lo tio.lo tio_get.lo tio_put.lo fio.lo \ + pio.lo sio.lo alg_search.lo alg_sort.lo time.lo misc.lo \ + assert.lo main.lo stdio.lo libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS) libqsecmn_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -267,7 +267,7 @@ libqsecmn_la_SOURCES = \ syscall.h mem.h \ mem.c xma.c fma.c chr.c chr_cnv.c rex.c \ str_bas.c str_chr.c str_cnv.c str_cmp.c str_cpy.c str_dyn.c str_fcpy.c \ - str_pbrk.c str_put.c str_spn.c str_utl.c \ + str_pbrk.c str_put.c str_spn.c str_subst.c str_utl.c \ lda.c oht.c htb.c rbt.c sll.c gdl.c dll.c opt.c \ tio.c tio_get.c tio_put.c \ fio.c pio.c sio.c \ @@ -395,6 +395,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str_pbrk.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str_put.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str_spn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str_subst.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str_utl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tio.Plo@am__quote@ diff --git a/qse/lib/cmn/str_bas.c b/qse/lib/cmn/str_bas.c index ad2a5c2c..741cff4d 100644 --- a/qse/lib/cmn/str_bas.c +++ b/qse/lib/cmn/str_bas.c @@ -1,5 +1,5 @@ /* - * $Id: str_bas.c 416 2011-03-27 05:04:24Z hyunghwan.chung $ + * $Id: str_bas.c 417 2011-03-27 14:32:37Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -43,68 +43,6 @@ qse_size_t qse_strbytes (const qse_char_t* str) return (p - str) * QSE_SIZEOF(qse_char_t); } -qse_size_t qse_strxsubst ( - qse_char_t* buf, qse_size_t bsz, const qse_char_t* fmt, - qse_strxsubst_subst_t subst, void* ctx) -{ - qse_char_t* b = buf; - qse_char_t* end = buf + bsz - 1; - const qse_char_t* f = fmt; - - if (bsz <= 0) return 0; - - while (*f != QSE_T('\0')) - { - if (*f == QSE_T('\\')) - { - // get the escaped character and treat it normally. - // if the escaper is the last character, treat it - // normally also. - if (f[1] != QSE_T('\0')) f++; - } - else if (*f == QSE_T('$')) - { - if (f[1] == QSE_T('{')) - { - const qse_char_t* tmp; - qse_cstr_t ident; - - f += 2; /* skip ${ */ - tmp = f; /* mark the beginning */ - - /* scan an enclosed segment */ - while (*f != QSE_T('\0') && *f != QSE_T('}')) f++; - - if (*f != QSE_T('}')) - { - /* restore to the position of $ */ - f = tmp - 2; - goto normal; - } - - f++; /* skip } */ - - ident.ptr = tmp; - ident.len = f - tmp - 1; - - b = subst (b, end - b, &ident, ctx); - if (b >= end) goto fini; - - continue; - } - else if (f[1] == QSE_T('$')) f++; - } - - normal: - if (b >= end) break; - *b++ = *f++; - } - -fini: - *b = QSE_T('\0'); - return b - buf; -} - qse_size_t qse_strxcat (qse_char_t* buf, qse_size_t bsz, const qse_char_t* str) { qse_char_t* p, * p2; diff --git a/qse/lib/cmn/str_subst.c b/qse/lib/cmn/str_subst.c new file mode 100644 index 00000000..36d5f643 --- /dev/null +++ b/qse/lib/cmn/str_subst.c @@ -0,0 +1,145 @@ +/* + * $Id$ + * + Copyright 2006-2009 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 + +qse_size_t qse_mbsxsubst ( + qse_mchar_t* buf, qse_size_t bsz, const qse_mchar_t* fmt, + qse_mbsxsubst_subst_t subst, void* ctx) +{ + qse_mchar_t* b = buf; + qse_mchar_t* end = buf + bsz - 1; + const qse_mchar_t* f = fmt; + + if (bsz <= 0) return 0; + + while (*f != QSE_MT('\0')) + { + if (*f == QSE_MT('\\')) + { + // get the escaped character and treat it normally. + // if the escaper is the last character, treat it + // normally also. + if (f[1] != QSE_MT('\0')) f++; + } + else if (*f == QSE_MT('$')) + { + if (f[1] == QSE_MT('{')) + { + const qse_mchar_t* tmp; + qse_mcstr_t ident; + + f += 2; /* skip ${ */ + tmp = f; /* mark the beginning */ + + /* scan an enclosed segment */ + while (*f != QSE_MT('\0') && *f != QSE_MT('}')) f++; + + if (*f != QSE_MT('}')) + { + /* restore to the position of $ */ + f = tmp - 2; + goto normal; + } + + f++; /* skip } */ + + ident.ptr = tmp; + ident.len = f - tmp - 1; + + b = subst (b, end - b, &ident, ctx); + if (b >= end) goto fini; + + continue; + } + else if (f[1] == QSE_MT('$')) f++; + } + + normal: + if (b >= end) break; + *b++ = *f++; + } + +fini: + *b = QSE_MT('\0'); + return b - buf; +} + +qse_size_t qse_wcsxsubst ( + qse_wchar_t* buf, qse_size_t bsz, const qse_wchar_t* fmt, + qse_wcsxsubst_subst_t subst, void* ctx) +{ + qse_wchar_t* b = buf; + qse_wchar_t* end = buf + bsz - 1; + const qse_wchar_t* f = fmt; + + if (bsz <= 0) return 0; + + while (*f != QSE_WT('\0')) + { + if (*f == QSE_WT('\\')) + { + // get the escaped character and treat it normally. + // if the escaper is the last character, treat it + // normally also. + if (f[1] != QSE_WT('\0')) f++; + } + else if (*f == QSE_WT('$')) + { + if (f[1] == QSE_WT('{')) + { + const qse_wchar_t* tmp; + qse_wcstr_t ident; + + f += 2; /* skip ${ */ + tmp = f; /* mark the beginning */ + + /* scan an enclosed segment */ + while (*f != QSE_WT('\0') && *f != QSE_WT('}')) f++; + + if (*f != QSE_WT('}')) + { + /* restore to the position of $ */ + f = tmp - 2; + goto normal; + } + + f++; /* skip } */ + + ident.ptr = tmp; + ident.len = f - tmp - 1; + + b = subst (b, end - b, &ident, ctx); + if (b >= end) goto fini; + + continue; + } + else if (f[1] == QSE_WT('$')) f++; + } + + normal: + if (b >= end) break; + *b++ = *f++; + } + +fini: + *b = QSE_WT('\0'); + return b - buf; +}