enhanced qse_strxsubst().

added qse_strxnsubst()
This commit is contained in:
hyung-hwan 2013-09-08 17:26:43 +00:00
parent f1485520ea
commit 5734b05114
3 changed files with 351 additions and 234 deletions

View File

@ -24,7 +24,7 @@
#include <qse/types.h> #include <qse/types.h>
#include <qse/macros.h> #include <qse/macros.h>
/** @file /** \file
* This file provides various functions, types, macros for string manipulation. * This file provides various functions, types, macros for string manipulation.
* *
* The #qse_cstr_t type and the #qse_xstr_t defined in <qse/types.h> help you * The #qse_cstr_t type and the #qse_xstr_t defined in <qse/types.h> help you
@ -126,10 +126,10 @@ struct qse_wcs_t
}; };
/** /**
* The qse_mbsxsubst_subst_t type defines a callback function * The qse_mbssubst_t type defines a callback function for qse_mbsxsubst()
* for qse_mbsxsubst() to substitue a new value for an identifier @a ident. * and qse_mbsxnsubst() to substitue a new value for an identifier \a ident.
*/ */
typedef qse_mchar_t* (*qse_mbsxsubst_subst_t) ( typedef qse_mchar_t* (*qse_mbssubst_t) (
qse_mchar_t* buf, qse_mchar_t* buf,
qse_size_t bsz, qse_size_t bsz,
const qse_mcstr_t* ident, const qse_mcstr_t* ident,
@ -137,10 +137,10 @@ typedef qse_mchar_t* (*qse_mbsxsubst_subst_t) (
); );
/** /**
* The qse_wcsxsubst_subst_t type defines a callback function * The qse_wcssubst_t type defines a callback function for qse_wcsxsubst()
* for qse_wcsxsubst() to substitue a new value for an identifier @a ident. * and qse_wcsxnsubst() to substitue a new value for an identifier \a ident.
*/ */
typedef qse_wchar_t* (*qse_wcsxsubst_subst_t) ( typedef qse_wchar_t* (*qse_wcssubst_t) (
qse_wchar_t* buf, qse_wchar_t* buf,
qse_size_t bsz, qse_size_t bsz,
const qse_wcstr_t* ident, const qse_wcstr_t* ident,
@ -148,9 +148,9 @@ typedef qse_wchar_t* (*qse_wcsxsubst_subst_t) (
); );
#if defined(QSE_CHAR_IS_MCHAR) #if defined(QSE_CHAR_IS_MCHAR)
# define qse_strxsubst_subst_t qse_mbsxsubst_subst_t # define qse_strsubst_t qse_mbssubst_t
#else #else
# define qse_strxsubst_subst_t qse_wcsxsubst_subst_t # define qse_strsubst_t qse_wcssubst_t
#endif #endif
/* int qse_chartonum (qse_char_t c, int base) */ /* int qse_chartonum (qse_char_t c, int base) */
@ -500,8 +500,8 @@ QSE_EXPORT qse_size_t qse_wcsput (
); );
/** /**
* The qse_mbsxput() function copies the string @a str into the buffer @a buf * The qse_mbsxput() function copies the string \a str into the buffer \a buf
* of the size @a bsz. Unlike qse_strxcpy(), it does not null-terminate the * of the size \a bsz. Unlike qse_strxcpy(), it does not null-terminate the
* buffer. * buffer.
*/ */
QSE_EXPORT qse_size_t qse_mbsxput ( QSE_EXPORT qse_size_t qse_mbsxput (
@ -511,8 +511,8 @@ QSE_EXPORT qse_size_t qse_mbsxput (
); );
/** /**
* The qse_wcsxput() function copies the string @a str into the buffer @a buf * The qse_wcsxput() function copies the string \a str into the buffer \a buf
* of the size @a bsz. Unlike qse_strxcpy(), it does not null-terminate the * of the size \a bsz. Unlike qse_strxcpy(), it does not null-terminate the
* buffer. * buffer.
*/ */
QSE_EXPORT qse_size_t qse_wcsxput ( QSE_EXPORT qse_size_t qse_wcsxput (
@ -550,12 +550,12 @@ QSE_EXPORT qse_size_t qse_wcsxnput (
* The position specifier is a number enclosed in ${ and }. * The position specifier is a number enclosed in ${ and }.
* When ${ is preceeded by a backslash, it is treated literally. * When ${ is preceeded by a backslash, it is treated literally.
* See the example below: * See the example below:
* @code * \code
* qse_char_t buf[256] * qse_char_t buf[256]
* qse_char_t* colors[] = { QSE_MT("blue"), QSE_MT("green"), QSE_MT("red") }; * qse_char_t* colors[] = { QSE_MT("blue"), QSE_MT("green"), QSE_MT("red") };
* qse_mbsfcpy(buf, QSE_MT("RGB: ${2}, ${1}, ${0}"), colors); * qse_mbsfcpy(buf, QSE_MT("RGB: ${2}, ${1}, ${0}"), colors);
* @endcode * \endcode
* @sa qse_mbsfncpy, qse_mbsxfcpy, qse_mbsxfncpy * \sa qse_mbsfncpy, qse_mbsxfcpy, qse_mbsxfncpy
*/ */
QSE_EXPORT qse_size_t qse_mbsfcpy ( QSE_EXPORT qse_size_t qse_mbsfcpy (
qse_mchar_t* buf, qse_mchar_t* buf,
@ -568,12 +568,12 @@ QSE_EXPORT qse_size_t qse_mbsfcpy (
* The position specifier is a number enclosed in ${ and }. * The position specifier is a number enclosed in ${ and }.
* When ${ is preceeded by a backslash, it is treated literally. * When ${ is preceeded by a backslash, it is treated literally.
* See the example below: * See the example below:
* @code * \code
* qse_char_t buf[256] * qse_char_t buf[256]
* qse_char_t* colors[] = { QSE_WT("blue"), QSE_WT("green"), QSE_WT("red") }; * qse_char_t* colors[] = { QSE_WT("blue"), QSE_WT("green"), QSE_WT("red") };
* qse_wcsfcpy(buf, QSE_WT("RGB: ${2}, ${1}, ${0}"), colors); * qse_wcsfcpy(buf, QSE_WT("RGB: ${2}, ${1}, ${0}"), colors);
* @endcode * \endcode
* @sa qse_wcsfncpy, qse_wcsxfcpy, qse_wcsxfncpy * \sa qse_wcsfncpy, qse_wcsxfcpy, qse_wcsxfncpy
*/ */
QSE_EXPORT qse_size_t qse_wcsfcpy ( QSE_EXPORT qse_size_t qse_wcsfcpy (
qse_wchar_t* buf, qse_wchar_t* buf,
@ -583,9 +583,9 @@ QSE_EXPORT qse_size_t qse_wcsfcpy (
/** /**
* The qse_mbsfncpy() function formats a string by position. * The qse_mbsfncpy() function formats a string by position.
* It differs from qse_mbsfcpy() in that @a str is an array of the * It differs from qse_mbsfcpy() in that \a str is an array of the
* #qse_mcstr_t type. * #qse_mcstr_t type.
* @sa qse_mbsfcpy, qse_mbsxfcpy, qse_mbsxfncpy * \sa qse_mbsfcpy, qse_mbsxfcpy, qse_mbsxfncpy
*/ */
QSE_EXPORT qse_size_t qse_mbsfncpy ( QSE_EXPORT qse_size_t qse_mbsfncpy (
qse_mchar_t* buf, qse_mchar_t* buf,
@ -595,9 +595,9 @@ QSE_EXPORT qse_size_t qse_mbsfncpy (
/** /**
* The qse_wcsfncpy() function formats a string by position. * The qse_wcsfncpy() function formats a string by position.
* It differs from qse_wcsfcpy() in that @a str is an array of the * It differs from qse_wcsfcpy() in that \a str is an array of the
* #qse_wcstr_t type. * #qse_wcstr_t type.
* @sa qse_wcsfcpy, qse_wcsxfcpy, qse_wcsxfncpy * \sa qse_wcsfcpy, qse_wcsxfcpy, qse_wcsxfncpy
*/ */
QSE_EXPORT qse_size_t qse_wcsfncpy ( QSE_EXPORT qse_size_t qse_wcsfncpy (
qse_wchar_t* buf, qse_wchar_t* buf,
@ -607,14 +607,14 @@ QSE_EXPORT qse_size_t qse_wcsfncpy (
/** /**
* The qse_mbsxfcpy() function formats a string by position. * The qse_mbsxfcpy() function formats a string by position.
* It differs from qse_strfcpy() in that @a buf is length-bounded of @a bsz * It differs from qse_strfcpy() in that \a buf is length-bounded of \a bsz
* characters. * characters.
* @code * \code
* qse_mchar_t buf[256] * qse_mchar_t buf[256]
* qse_mchar_t* colors[] = { QSE_MT("blue"), QSE_MT("green"), QSE_MT("red") }; * qse_mchar_t* colors[] = { QSE_MT("blue"), QSE_MT("green"), QSE_MT("red") };
* qse_mbsxfcpy(buf, QSE_COUNTOF(buf), QSE_MT("RGB: ${2}, ${1}, ${0}"), colors); * qse_mbsxfcpy(buf, QSE_COUNTOF(buf), QSE_MT("RGB: ${2}, ${1}, ${0}"), colors);
* @endcode * \endcode
* @sa qse_mbsfcpy, qse_mbsfncpy, qse_mbsxfncpy * \sa qse_mbsfcpy, qse_mbsfncpy, qse_mbsxfncpy
*/ */
QSE_EXPORT qse_size_t qse_mbsxfcpy ( QSE_EXPORT qse_size_t qse_mbsxfcpy (
qse_mchar_t* buf, qse_mchar_t* buf,
@ -625,14 +625,14 @@ QSE_EXPORT qse_size_t qse_mbsxfcpy (
/** /**
* The qse_wcsxfcpy() function formats a string by position. * The qse_wcsxfcpy() function formats a string by position.
* It differs from qse_wcsfcpy() in that @a buf is length-bounded of @a bsz * It differs from qse_wcsfcpy() in that \a buf is length-bounded of \a bsz
* characters. * characters.
* @code * \code
* qse_char_t buf[256] * qse_char_t buf[256]
* qse_char_t* colors[] = { QSE_WT("blue"), QSE_WT("green"), QSE_WT("red") }; * qse_char_t* colors[] = { QSE_WT("blue"), QSE_WT("green"), QSE_WT("red") };
* qse_wcsxfcpy(buf, QSE_COUNTOF(buf), QSE_WT("RGB: ${2}, ${1}, ${0}"), colors); * qse_wcsxfcpy(buf, QSE_COUNTOF(buf), QSE_WT("RGB: ${2}, ${1}, ${0}"), colors);
* @endcode * \endcode
* @sa qse_wcsfcpy, qse_wcsfncpy, qse_wcsxfncpy * \sa qse_wcsfcpy, qse_wcsfncpy, qse_wcsxfncpy
*/ */
QSE_EXPORT qse_size_t qse_wcsxfcpy ( QSE_EXPORT qse_size_t qse_wcsxfcpy (
qse_wchar_t* buf, qse_wchar_t* buf,
@ -643,9 +643,9 @@ QSE_EXPORT qse_size_t qse_wcsxfcpy (
/** /**
* The qse_mbsxfncpy() function formats a string by position. * The qse_mbsxfncpy() function formats a string by position.
* It differs from qse_strfcpy() in that @a buf is length-bounded of @a bsz * It differs from qse_strfcpy() in that \a buf is length-bounded of \a bsz
* characters and @a str is an array of the #qse_mcstr_t type. * characters and \a str is an array of the #qse_mcstr_t type.
* @sa qse_mbsfcpy, qse_mbsfncpy, qse_mbsxfcpy * \sa qse_mbsfcpy, qse_mbsfncpy, qse_mbsxfcpy
*/ */
QSE_EXPORT qse_size_t qse_mbsxfncpy ( QSE_EXPORT qse_size_t qse_mbsxfncpy (
qse_mchar_t* buf, qse_mchar_t* buf,
@ -656,9 +656,9 @@ QSE_EXPORT qse_size_t qse_mbsxfncpy (
/** /**
* The qse_wcsxfncpy() function formats a string by position. * The qse_wcsxfncpy() function formats a string by position.
* It differs from qse_strfcpy() in that @a buf is length-bounded of @a bsz * It differs from qse_strfcpy() in that \a buf is length-bounded of \a bsz
* characters and @a str is an array of the #qse_wcstr_t type. * characters and \a str is an array of the #qse_wcstr_t type.
* @sa qse_wcsfcpy, qse_wcsfncpy, qse_wcsxfcpy * \sa qse_wcsfcpy, qse_wcsfncpy, qse_wcsxfcpy
*/ */
QSE_EXPORT qse_size_t qse_wcsxfncpy ( QSE_EXPORT qse_size_t qse_wcsxfncpy (
qse_wchar_t* buf, qse_wchar_t* buf,
@ -680,10 +680,10 @@ QSE_EXPORT qse_size_t qse_wcsxfncpy (
#endif #endif
/** /**
* The qse_mbsxsubst() 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 * \a bsz by substituting new values for ${} segments within it. The actual
* substitution is made by invoking the callback function @a subst. * substitution is made by invoking the callback function \a subst.
* @code * \code
* qse_mchar_t* subst (qse_mchar_t* buf, qse_size_t bsz, const qse_mcstr_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_mbsxcmp (ident->ptr, ident->len, QSE_MT("USER")) == 0) * if (qse_mbsxcmp (ident->ptr, ident->len, QSE_MT("USER")) == 0)
@ -695,21 +695,30 @@ QSE_EXPORT qse_size_t qse_wcsxfncpy (
* *
* qse_mchar_t buf[25]; * qse_mchar_t buf[25];
* qse_mbsxsubst (buf, i, QSE_MT("user=${USER},group=${GROUP}"), subst, QSE_NULL); * qse_mbsxsubst (buf, i, QSE_MT("user=${USER},group=${GROUP}"), subst, QSE_NULL);
* @endcode * \endcode
*/ */
QSE_EXPORT qse_size_t qse_mbsxsubst ( QSE_EXPORT qse_size_t qse_mbsxsubst (
qse_mchar_t* buf, qse_mchar_t* buf,
qse_size_t bsz, qse_size_t bsz,
const qse_mchar_t* fmt, const qse_mchar_t* fmt,
qse_mbsxsubst_subst_t subst, qse_mbssubst_t subst,
void* ctx
);
QSE_EXPORT qse_size_t qse_mbsxnsubst (
qse_mchar_t* buf,
qse_size_t bsz,
const qse_mchar_t* fmt,
qse_size_t fsz,
qse_mbssubst_t subst,
void* ctx void* ctx
); );
/** /**
* The qse_wcsxsubst() function expands @a fmt into a buffer @a buf of the size * 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 * \a bsz by substituting new values for ${} segments within it. The actual
* substitution is made by invoking the callback function @a subst. * substitution is made by invoking the callback function \a subst.
* @code * \code
* qse_wchar_t* subst (qse_wchar_t* buf, qse_size_t bsz, const qse_wcstr_t* ident, void* ctx) * 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) * if (qse_wcsxcmp (ident->ptr, ident->len, QSE_WT("USER")) == 0)
@ -721,20 +730,31 @@ QSE_EXPORT qse_size_t qse_mbsxsubst (
* *
* qse_wchar_t buf[25]; * qse_wchar_t buf[25];
* qse_wcsxsubst (buf, i, QSE_WT("user=${USER},group=${GROUP}"), subst, QSE_NULL); * qse_wcsxsubst (buf, i, QSE_WT("user=${USER},group=${GROUP}"), subst, QSE_NULL);
* @endcode * \endcode
*/ */
QSE_EXPORT qse_size_t qse_wcsxsubst ( QSE_EXPORT qse_size_t qse_wcsxsubst (
qse_wchar_t* buf, qse_wchar_t* buf,
qse_size_t bsz, qse_size_t bsz,
const qse_wchar_t* fmt, const qse_wchar_t* fmt,
qse_wcsxsubst_subst_t subst, qse_wcssubst_t subst,
void* ctx
);
QSE_EXPORT qse_size_t qse_wcsxnsubst (
qse_wchar_t* buf,
qse_size_t bsz,
const qse_wchar_t* fmt,
qse_size_t fsz,
qse_wcssubst_t subst,
void* ctx void* ctx
); );
#if defined(QSE_CHAR_IS_MCHAR) #if defined(QSE_CHAR_IS_MCHAR)
# define qse_strxsubst(buf,bsz,fmt,subst,ctx) qse_mbsxsubst(buf,bsz,fmt,subst,ctx) # define qse_strxsubst(buf,bsz,fmt,subst,ctx) qse_mbsxsubst(buf,bsz,fmt,subst,ctx)
# define qse_strxnsubst(buf,bsz,fmt,fsz,subst,ctx) qse_mbsxnsubst(buf,bsz,fmt,fsz,subst,ctx)
#else #else
# define qse_strxsubst(buf,bsz,fmt,subst,ctx) qse_wcsxsubst(buf,bsz,fmt,subst,ctx) # define qse_strxsubst(buf,bsz,fmt,subst,ctx) qse_wcsxsubst(buf,bsz,fmt,subst,ctx)
# define qse_strxnsubst(buf,bsz,fmt,fsz,subst,ctx) qse_wcsxnsubst(buf,bsz,fmt,fsz,subst,ctx)
#endif #endif
QSE_EXPORT qse_size_t qse_mbscat ( QSE_EXPORT qse_size_t qse_mbscat (
@ -880,11 +900,11 @@ QSE_EXPORT int qse_wcsxcasecmp (
* second string. * second string.
* *
* The following code snippet compares "foo" and "FoO" case-insenstively. * The following code snippet compares "foo" and "FoO" case-insenstively.
* @code * \code
* qse_mbsxncasecmp (QSE_MT("foo"), 3, QSE_MT("FoO"), 3); * qse_mbsxncasecmp (QSE_MT("foo"), 3, QSE_MT("FoO"), 3);
* @endcode * \endcode
* *
* @return 0 if two strings are equal, * \return 0 if two strings are equal,
* a positive number if the first string is larger, * a positive number if the first string is larger,
* -1 if the second string is larger. * -1 if the second string is larger.
* *
@ -907,11 +927,11 @@ QSE_EXPORT int qse_mbsxncasecmp (
* second string. * second string.
* *
* The following code snippet compares "foo" and "FoO" case-insenstively. * The following code snippet compares "foo" and "FoO" case-insenstively.
* @code * \code
* qse_wcsxncasecmp (QSE_WT("foo"), 3, QSE_WT("FoO"), 3); * qse_wcsxncasecmp (QSE_WT("foo"), 3, QSE_WT("FoO"), 3);
* @endcode * \endcode
* *
* @return 0 if two strings are equal, * \return 0 if two strings are equal,
* a positive number if the first string is larger, * a positive number if the first string is larger,
* -1 if the second string is larger. * -1 if the second string is larger.
* *
@ -1074,9 +1094,9 @@ QSE_EXPORT qse_wchar_t* qse_wcstradup (
#endif #endif
/** /**
* The qse_mbsstr() function searchs a string @a str for the first occurrence * The qse_mbsstr() function searchs a string \a str for the first occurrence
* of a substring @a sub. * of a substring \a sub.
* @return pointer to the first occurrence in @a str if @a sub is found, * \return pointer to the first occurrence in \a str if \a sub is found,
* #QSE_NULL if not. * #QSE_NULL if not.
*/ */
QSE_EXPORT qse_mchar_t* qse_mbsstr ( QSE_EXPORT qse_mchar_t* qse_mbsstr (
@ -1085,9 +1105,9 @@ QSE_EXPORT qse_mchar_t* qse_mbsstr (
); );
/** /**
* The qse_wcsstr() function searchs a string @a str for the first occurrence * The qse_wcsstr() function searchs a string \a str for the first occurrence
* of a substring @a sub. * of a substring \a sub.
* @return pointer to the first occurrence in @a str if @a sub is found, * \return pointer to the first occurrence in \a str if \a sub is found,
* #QSE_NULL if not. * #QSE_NULL if not.
*/ */
QSE_EXPORT qse_wchar_t* qse_wcsstr ( QSE_EXPORT qse_wchar_t* qse_wcsstr (
@ -1158,9 +1178,9 @@ QSE_EXPORT qse_wchar_t* qse_wcsxncasestr (
); );
/** /**
* The qse_mbsrstr() function searchs a string @a str for the last occurrence * The qse_mbsrstr() function searchs a string \a str for the last occurrence
* of a substring @a sub. * of a substring \a sub.
* @return pointer to the last occurrence in @a str if @a sub is found, * \return pointer to the last occurrence in \a str if \a sub is found,
* #QSE_NULL if not. * #QSE_NULL if not.
*/ */
QSE_EXPORT qse_mchar_t* qse_mbsrstr ( QSE_EXPORT qse_mchar_t* qse_mbsrstr (
@ -1169,9 +1189,9 @@ QSE_EXPORT qse_mchar_t* qse_mbsrstr (
); );
/** /**
* The qse_wcsrstr() function searchs a string @a str for the last occurrence * The qse_wcsrstr() function searchs a string \a str for the last occurrence
* of a substring @a sub. * of a substring \a sub.
* @return pointer to the last occurrence in @a str if @a sub is found, * \return pointer to the last occurrence in \a str if \a sub is found,
* #QSE_NULL if not. * #QSE_NULL if not.
*/ */
QSE_EXPORT qse_wchar_t* qse_wcsrstr ( QSE_EXPORT qse_wchar_t* qse_wcsrstr (
@ -1403,7 +1423,7 @@ QSE_EXPORT qse_wchar_t* qse_wcsxrchr (
/** /**
* The qse_mbsbeg() function checks if a string begins with a substring. * The qse_mbsbeg() function checks if a string begins with a substring.
* @return pointer to the beginning of a matching beginning, * \return pointer to the beginning of a matching beginning,
* #SE_NULL if no match is found. * #SE_NULL if no match is found.
*/ */
QSE_EXPORT qse_mchar_t* qse_mbsbeg ( QSE_EXPORT qse_mchar_t* qse_mbsbeg (
@ -1413,7 +1433,7 @@ QSE_EXPORT qse_mchar_t* qse_mbsbeg (
/** /**
* The qse_wcsbeg() function checks if a string begins with a substring. * The qse_wcsbeg() function checks if a string begins with a substring.
* @return pointer to the beginning of a matching beginning, * \return pointer to the beginning of a matching beginning,
* #QSE_NULL if no match is found. * #QSE_NULL if no match is found.
*/ */
QSE_EXPORT qse_wchar_t* qse_wcsbeg ( QSE_EXPORT qse_wchar_t* qse_wcsbeg (
@ -1485,7 +1505,7 @@ QSE_EXPORT qse_wchar_t* qse_wcscasebeg (
/** /**
* The qse_mbsend() function checks if a string ends with a substring. * The qse_mbsend() function checks if a string ends with a substring.
* @return pointer to the beginning of a matching ending, * \return pointer to the beginning of a matching ending,
* #SE_NULL if no match is found. * #SE_NULL if no match is found.
*/ */
QSE_EXPORT qse_mchar_t* qse_mbsend ( QSE_EXPORT qse_mchar_t* qse_mbsend (
@ -1495,7 +1515,7 @@ QSE_EXPORT qse_mchar_t* qse_mbsend (
/** /**
* The qse_wcsend() function checks if a string ends with a substring. * The qse_wcsend() function checks if a string ends with a substring.
* @return pointer to the beginning of a matching ending, * \return pointer to the beginning of a matching ending,
* #QSE_NULL if no match is found. * #QSE_NULL if no match is found.
*/ */
QSE_EXPORT qse_wchar_t* qse_wcsend ( QSE_EXPORT qse_wchar_t* qse_wcsend (
@ -1582,9 +1602,9 @@ QSE_EXPORT qse_size_t qse_wcscspn (
#endif #endif
/* /*
* The qse_mbspbrk() function searches @a str1 for the first occurrence of * The qse_mbspbrk() function searches \a str1 for the first occurrence of
* a character in @a str2. * a character in \a str2.
* @return pointer to the first occurrence in @a str1 if one is found. * \return pointer to the first occurrence in \a str1 if one is found.
* QSE_NULL if none is found. * QSE_NULL if none is found.
*/ */
QSE_EXPORT qse_mchar_t* qse_mbspbrk ( QSE_EXPORT qse_mchar_t* qse_mbspbrk (
@ -1610,9 +1630,9 @@ QSE_EXPORT qse_mchar_t* qse_mbsxrpbrk (
); );
/* /*
* The qse_wcspbrk() function searches @a str1 for the first occurrence of * The qse_wcspbrk() function searches \a str1 for the first occurrence of
* a character in @a str2. * a character in \a str2.
* @return pointer to the first occurrence in @a str1 if one is found. * \return pointer to the first occurrence in \a str1 if one is found.
* QSE_NULL if none is found. * QSE_NULL if none is found.
*/ */
QSE_EXPORT qse_wchar_t* qse_wcspbrk ( QSE_EXPORT qse_wchar_t* qse_wcspbrk (
@ -1967,25 +1987,25 @@ QSE_EXPORT int qse_wcsspl (
/** /**
* The qse_mbsspltrn() function splits a string translating special * The qse_mbsspltrn() function splits a string translating special
* escape sequences. * escape sequences.
* The argument @a trset is a translation character set which is composed * The argument \a trset is a translation character set which is composed
* of multiple character pairs. An escape character followed by the * of multiple character pairs. An escape character followed by the
* first character in a pair is translated into the second character * first character in a pair is translated into the second character
* in the pair. If trset is #QSE_NULL, no translation is performed. * in the pair. If trset is #QSE_NULL, no translation is performed.
* *
* Let's translate a sequence of '\n' and '\r' to a new line and a carriage * Let's translate a sequence of '\n' and '\r' to a new line and a carriage
* return respectively. * return respectively.
* @code * \code
* nfields = qse_mbsspltrn ( * nfields = qse_mbsspltrn (
* str, QSE_MT(':'), QSE_MT('['), QSE_MT(']'), * str, QSE_MT(':'), QSE_MT('['), QSE_MT(']'),
* QSE_MT('\\'), QSE_MT("n\nr\r") * QSE_MT('\\'), QSE_MT("n\nr\r")
* ); * );
* @endcode * \endcode
* Given [xxx]:[\rabc\ndef]:[] as an input, the example breaks the second * Given [xxx]:[\rabc\ndef]:[] as an input, the example breaks the second
* fields to <CR>abc<NL>def where <CR> is a carriage return and <NL> is a * fields to <CR>abc<NL>def where <CR> is a carriage return and <NL> is a
* new line. * new line.
* *
* If you don't need translation, you may call qse_mbsspl() instead. * If you don't need translation, you may call qse_mbsspl() instead.
* @return number of resulting fields on success, -1 on failure * \return number of resulting fields on success, -1 on failure
*/ */
QSE_EXPORT int qse_mbsspltrn ( QSE_EXPORT int qse_mbsspltrn (
qse_mchar_t* str, qse_mchar_t* str,
@ -1999,25 +2019,25 @@ QSE_EXPORT int qse_mbsspltrn (
/** /**
* The qse_wcsspltrn() function splits a string translating special * The qse_wcsspltrn() function splits a string translating special
* escape sequences. * escape sequences.
* The argument @a trset is a translation character set which is composed * The argument \a trset is a translation character set which is composed
* of multiple character pairs. An escape character followed by the * of multiple character pairs. An escape character followed by the
* first character in a pair is translated into the second character * first character in a pair is translated into the second character
* in the pair. If trset is #QSE_NULL, no translation is performed. * in the pair. If trset is #QSE_NULL, no translation is performed.
* *
* Let's translate a sequence of '\n' and '\r' to a new line and a carriage * Let's translate a sequence of '\n' and '\r' to a new line and a carriage
* return respectively. * return respectively.
* @code * \code
* nfields = qse_wcsspltrn ( * nfields = qse_wcsspltrn (
* str, QSE_WT(':'), QSE_WT('['), QSE_WT(']'), * str, QSE_WT(':'), QSE_WT('['), QSE_WT(']'),
* QSE_WT('\\'), QSE_WT("n\nr\r") * QSE_WT('\\'), QSE_WT("n\nr\r")
* ); * );
* @endcode * \endcode
* Given [xxx]:[\rabc\ndef]:[] as an input, the example breaks the second * Given [xxx]:[\rabc\ndef]:[] as an input, the example breaks the second
* fields to <CR>abc<NL>def where <CR> is a carriage return and <NL> is a * fields to <CR>abc<NL>def where <CR> is a carriage return and <NL> is a
* new line. * new line.
* *
* If you don't need translation, you may call qse_wcsspl() instead. * If you don't need translation, you may call qse_wcsspl() instead.
* @return number of resulting fields on success, -1 on failure * \return number of resulting fields on success, -1 on failure
*/ */
QSE_EXPORT int qse_wcsspltrn ( QSE_EXPORT int qse_wcsspltrn (
qse_wchar_t* str, qse_wchar_t* str,
@ -2103,12 +2123,12 @@ QSE_EXPORT qse_wchar_t* qse_wcsxntok (
* spaces, it inserts a QSE_MT('\0') character after the last non-space * spaces, it inserts a QSE_MT('\0') character after the last non-space
* characters. Take note of this behavior. * characters. Take note of this behavior.
* *
* @code * \code
* qse_mchar_t a[] = QSE_MT(" this is a test string "); * qse_mchar_t a[] = QSE_MT(" this is a test string ");
* qse_mbstrmx (a, QSE_MBSTRMX_LEFT|QSE_MBSTRMX_RIGHT); * qse_mbstrmx (a, QSE_MBSTRMX_LEFT|QSE_MBSTRMX_RIGHT);
* @endcode * \endcode
* *
* @return pointer to a trimmed string. * \return pointer to a trimmed string.
*/ */
QSE_EXPORT qse_mchar_t* qse_mbstrmx ( QSE_EXPORT qse_mchar_t* qse_mbstrmx (
qse_mchar_t* str, /**< string */ qse_mchar_t* str, /**< string */
@ -2135,12 +2155,12 @@ QSE_EXPORT qse_mchar_t* qse_mbsxtrmx (
* spaces, it inserts a QSE_WT('\0') character after the last non-space * spaces, it inserts a QSE_WT('\0') character after the last non-space
* characters. Take note of this behavior. * characters. Take note of this behavior.
* *
* @code * \code
* qse_wchar_t a[] = QSE_WT(" this is a test string "); * qse_wchar_t a[] = QSE_WT(" this is a test string ");
* qse_wcstrmx (a, QSE_STRTRMX_LEFT|QSE_STRTRMX_RIGHT); * qse_wcstrmx (a, QSE_STRTRMX_LEFT|QSE_STRTRMX_RIGHT);
* @endcode * \endcode
* *
* @return pointer to a trimmed string. * \return pointer to a trimmed string.
*/ */
QSE_EXPORT qse_wchar_t* qse_wcstrmx ( QSE_EXPORT qse_wchar_t* qse_wcstrmx (
qse_wchar_t* str, /**< string */ qse_wchar_t* str, /**< string */
@ -2157,8 +2177,8 @@ QSE_EXPORT qse_wchar_t* qse_wcsxtrmx (
* The qse_mbstrm() function strips leading spaces and/or trailing * The qse_mbstrm() function strips leading spaces and/or trailing
* spaces off a string. All characters between the first and the last non-space * spaces off a string. All characters between the first and the last non-space
* character inclusive are relocated to the beginning of memory pointed to * character inclusive are relocated to the beginning of memory pointed to
* by @a str; QSE_MT('\0') is inserted after the last non-space character. * by \a str; QSE_MT('\0') is inserted after the last non-space character.
* @return length of the string without leading and trailing spaces. * \return length of the string without leading and trailing spaces.
*/ */
QSE_EXPORT qse_size_t qse_mbstrm ( QSE_EXPORT qse_size_t qse_mbstrm (
qse_mchar_t* str /**< string */ qse_mchar_t* str /**< string */
@ -2168,8 +2188,8 @@ QSE_EXPORT qse_size_t qse_mbstrm (
* The qse_wcstrm() function strips leading spaces and/or trailing * The qse_wcstrm() function strips leading spaces and/or trailing
* spaces off a string. All characters between the first and the last non-space * spaces off a string. All characters between the first and the last non-space
* character inclusive are relocated to the beginning of memory pointed to * character inclusive are relocated to the beginning of memory pointed to
* by @a str; QSE_WT('\0') is inserted after the last non-space character. * by \a str; QSE_WT('\0') is inserted after the last non-space character.
* @return length of the string without leading and trailing spaces. * \return length of the string without leading and trailing spaces.
*/ */
QSE_EXPORT qse_size_t qse_wcstrm ( QSE_EXPORT qse_size_t qse_wcstrm (
qse_wchar_t* str /**< string */ qse_wchar_t* str /**< string */
@ -2179,8 +2199,8 @@ QSE_EXPORT qse_size_t qse_wcstrm (
* The qse_mbsxtrm() function strips leading spaces and/or trailing * The qse_mbsxtrm() function strips leading spaces and/or trailing
* spaces off a string. All characters between the first and the last non-space * spaces off a string. All characters between the first and the last non-space
* character inclusive are relocated to the beginning of memory pointed to * character inclusive are relocated to the beginning of memory pointed to
* by @a str; QSE_MT('\0') is inserted after the last non-space character. * by \a str; QSE_MT('\0') is inserted after the last non-space character.
* @return length of the string without leading and trailing spaces. * \return length of the string without leading and trailing spaces.
*/ */
QSE_EXPORT qse_size_t qse_mbsxtrm ( QSE_EXPORT qse_size_t qse_mbsxtrm (
qse_mchar_t* str, /**< string */ qse_mchar_t* str, /**< string */
@ -2191,8 +2211,8 @@ QSE_EXPORT qse_size_t qse_mbsxtrm (
* The qse_wcsxtrm() function strips leading spaces and/or trailing * The qse_wcsxtrm() function strips leading spaces and/or trailing
* spaces off a string. All characters between the first and the last non-space * spaces off a string. All characters between the first and the last non-space
* character inclusive are relocated to the beginning of memory pointed to * character inclusive are relocated to the beginning of memory pointed to
* by @a str; QSE_WT('\0') is inserted after the last non-space character. * by \a str; QSE_WT('\0') is inserted after the last non-space character.
* @return length of the string without leading and trailing spaces. * \return length of the string without leading and trailing spaces.
*/ */
QSE_EXPORT qse_size_t qse_wcsxtrm ( QSE_EXPORT qse_size_t qse_wcsxtrm (
qse_wchar_t* str, /**< string */ qse_wchar_t* str, /**< string */
@ -2214,7 +2234,7 @@ QSE_EXPORT qse_size_t qse_wcsxtrm (
/** /**
* The qse_mbspac() function folds repeated whitespaces into one as well * The qse_mbspac() function folds repeated whitespaces into one as well
* as stripping leading whitespaces and trailing whitespaces. * as stripping leading whitespaces and trailing whitespaces.
* @return length of the string without leading and trailing spaces. * \return length of the string without leading and trailing spaces.
*/ */
QSE_EXPORT qse_size_t qse_mbspac ( QSE_EXPORT qse_size_t qse_mbspac (
qse_mchar_t* str /**< string */ qse_mchar_t* str /**< string */
@ -2223,7 +2243,7 @@ QSE_EXPORT qse_size_t qse_mbspac (
/** /**
* The qse_wcspac() function folds repeated whitespaces into one as well * The qse_wcspac() function folds repeated whitespaces into one as well
* as stripping leading whitespaces and trailing whitespaces. * as stripping leading whitespaces and trailing whitespaces.
* @return length of the string without leading and trailing spaces. * \return length of the string without leading and trailing spaces.
*/ */
QSE_EXPORT qse_size_t qse_wcspac ( QSE_EXPORT qse_size_t qse_wcspac (
qse_wchar_t* str /**< string */ qse_wchar_t* str /**< string */
@ -2233,7 +2253,7 @@ QSE_EXPORT qse_size_t qse_wcspac (
/** /**
* The qse_mbsxpac() function folds repeated whitespaces into one as well * The qse_mbsxpac() function folds repeated whitespaces into one as well
* as stripping leading whitespaces and trailing whitespaces. * as stripping leading whitespaces and trailing whitespaces.
* @return length of the string without leading and trailing spaces. * \return length of the string without leading and trailing spaces.
*/ */
QSE_EXPORT qse_size_t qse_mbsxpac ( QSE_EXPORT qse_size_t qse_mbsxpac (
qse_mchar_t* str, /**< string */ qse_mchar_t* str, /**< string */
@ -2243,7 +2263,7 @@ QSE_EXPORT qse_size_t qse_mbsxpac (
/** /**
* The qse_wcsxpac() function folds repeated whitespaces into one as well * The qse_wcsxpac() function folds repeated whitespaces into one as well
* as stripping leading whitespaces and trailing whitespaces. * as stripping leading whitespaces and trailing whitespaces.
* @return length of the string without leading and trailing spaces. * \return length of the string without leading and trailing spaces.
*/ */
QSE_EXPORT qse_size_t qse_wcsxpac ( QSE_EXPORT qse_size_t qse_wcsxpac (
qse_wchar_t* str, /**< string */ qse_wchar_t* str, /**< string */
@ -2344,7 +2364,7 @@ QSE_EXPORT void qse_mbs_close (
* The qse_mbs_init() function initializes a dynamically resizable string * The qse_mbs_init() function initializes a dynamically resizable string
* If the parameter capa is 0, it doesn't allocate the internal buffer * If the parameter capa is 0, it doesn't allocate the internal buffer
* in advance and always succeeds. * in advance and always succeeds.
* @return 0 on success, -1 on failure. * \return 0 on success, -1 on failure.
*/ */
QSE_EXPORT int qse_mbs_init ( QSE_EXPORT int qse_mbs_init (
qse_mbs_t* mbs, qse_mbs_t* mbs,
@ -2369,9 +2389,9 @@ QSE_EXPORT void* qse_mbs_getxtn (
/** /**
* The qse_mbs_yield() function assigns the buffer to an variable of the * The qse_mbs_yield() function assigns the buffer to an variable of the
* #qse_mxstr_t type and recreate a new buffer of the @a new_capa capacity. * #qse_mxstr_t type and recreate a new buffer of the \a new_capa capacity.
* The function fails if it fails to allocate a new buffer. * The function fails if it fails to allocate a new buffer.
* @return 0 on success, and -1 on failure. * \return 0 on success, and -1 on failure.
*/ */
QSE_EXPORT int qse_mbs_yield ( QSE_EXPORT int qse_mbs_yield (
qse_mbs_t* str, /**< string */ qse_mbs_t* str, /**< string */
@ -2386,7 +2406,7 @@ QSE_EXPORT qse_mchar_t* qse_mbs_yieldptr (
/** /**
* The qse_mbs_getsizer() function gets the sizer. * The qse_mbs_getsizer() function gets the sizer.
* @return sizer function set or QSE_NULL if no sizer is set. * \return sizer function set or QSE_NULL if no sizer is set.
*/ */
QSE_EXPORT qse_mbs_sizer_t qse_mbs_getsizer ( QSE_EXPORT qse_mbs_sizer_t qse_mbs_getsizer (
qse_mbs_t* str qse_mbs_t* str
@ -2408,7 +2428,7 @@ QSE_EXPORT void qse_mbs_setsizer (
/** /**
* The qse_mbs_getcapa() function returns the current capacity. * The qse_mbs_getcapa() function returns the current capacity.
* You may use QSE_STR_CAPA(str) macro for performance sake. * You may use QSE_STR_CAPA(str) macro for performance sake.
* @return current capacity in number of characters. * \return current capacity in number of characters.
*/ */
QSE_EXPORT qse_size_t qse_mbs_getcapa ( QSE_EXPORT qse_size_t qse_mbs_getcapa (
qse_mbs_t* str qse_mbs_t* str
@ -2418,7 +2438,7 @@ QSE_EXPORT qse_size_t qse_mbs_getcapa (
* The qse_mbs_setcapa() function sets the new capacity. If the new capacity * The qse_mbs_setcapa() function sets the new capacity. If the new capacity
* is smaller than the old, the overflowing characters are removed from * is smaller than the old, the overflowing characters are removed from
* from the buffer. * from the buffer.
* @return (qse_size_t)-1 on failure, new capacity on success * \return (qse_size_t)-1 on failure, new capacity on success
*/ */
QSE_EXPORT qse_size_t qse_mbs_setcapa ( QSE_EXPORT qse_size_t qse_mbs_setcapa (
qse_mbs_t* str, qse_mbs_t* str,
@ -2434,7 +2454,7 @@ QSE_EXPORT qse_size_t qse_mbs_getlen (
/** /**
* The qse_mbs_setlen() function changes the string length. * The qse_mbs_setlen() function changes the string length.
* @return (qse_size_t)-1 on failure, new length on success * \return (qse_size_t)-1 on failure, new length on success
*/ */
QSE_EXPORT qse_size_t qse_mbs_setlen ( QSE_EXPORT qse_size_t qse_mbs_setlen (
qse_mbs_t* str, qse_mbs_t* str,
@ -2529,7 +2549,7 @@ QSE_EXPORT void qse_wcs_close (
* The qse_wcs_init() function initializes a dynamically resizable string * The qse_wcs_init() function initializes a dynamically resizable string
* If the parameter capa is 0, it doesn't allocate the internal buffer * If the parameter capa is 0, it doesn't allocate the internal buffer
* in advance and always succeeds. * in advance and always succeeds.
* @return 0 on success, -1 on failure. * \return 0 on success, -1 on failure.
*/ */
QSE_EXPORT int qse_wcs_init ( QSE_EXPORT int qse_wcs_init (
qse_wcs_t* wcs, qse_wcs_t* wcs,
@ -2554,9 +2574,9 @@ QSE_EXPORT void* qse_wcs_getxtn (
/** /**
* The qse_wcs_yield() function assigns the buffer to an variable of the * The qse_wcs_yield() function assigns the buffer to an variable of the
* #qse_wxstr_t type and recreate a new buffer of the @a new_capa capacity. * #qse_wxstr_t type and recreate a new buffer of the \a new_capa capacity.
* The function fails if it fails to allocate a new buffer. * The function fails if it fails to allocate a new buffer.
* @return 0 on success, and -1 on failure. * \return 0 on success, and -1 on failure.
*/ */
QSE_EXPORT int qse_wcs_yield ( QSE_EXPORT int qse_wcs_yield (
qse_wcs_t* str, /**< string */ qse_wcs_t* str, /**< string */
@ -2571,7 +2591,7 @@ QSE_EXPORT qse_wchar_t* qse_wcs_yieldptr (
/** /**
* The qse_wcs_getsizer() function gets the sizer. * The qse_wcs_getsizer() function gets the sizer.
* @return sizer function set or QSE_NULL if no sizer is set. * \return sizer function set or QSE_NULL if no sizer is set.
*/ */
QSE_EXPORT qse_wcs_sizer_t qse_wcs_getsizer ( QSE_EXPORT qse_wcs_sizer_t qse_wcs_getsizer (
qse_wcs_t* str qse_wcs_t* str
@ -2593,7 +2613,7 @@ QSE_EXPORT void qse_wcs_setsizer (
/** /**
* The qse_wcs_getcapa() function returns the current capacity. * The qse_wcs_getcapa() function returns the current capacity.
* You may use QSE_STR_CAPA(str) macro for performance sake. * You may use QSE_STR_CAPA(str) macro for performance sake.
* @return current capacity in number of characters. * \return current capacity in number of characters.
*/ */
QSE_EXPORT qse_size_t qse_wcs_getcapa ( QSE_EXPORT qse_size_t qse_wcs_getcapa (
qse_wcs_t* str qse_wcs_t* str
@ -2603,7 +2623,7 @@ QSE_EXPORT qse_size_t qse_wcs_getcapa (
* The qse_wcs_setcapa() function sets the new capacity. If the new capacity * The qse_wcs_setcapa() function sets the new capacity. If the new capacity
* is smaller than the old, the overflowing characters are removed from * is smaller than the old, the overflowing characters are removed from
* from the buffer. * from the buffer.
* @return (qse_size_t)-1 on failure, new capacity on success * \return (qse_size_t)-1 on failure, new capacity on success
*/ */
QSE_EXPORT qse_size_t qse_wcs_setcapa ( QSE_EXPORT qse_size_t qse_wcs_setcapa (
qse_wcs_t* str, qse_wcs_t* str,
@ -2619,7 +2639,7 @@ QSE_EXPORT qse_size_t qse_wcs_getlen (
/** /**
* The qse_wcs_setlen() function changes the string length. * The qse_wcs_setlen() function changes the string length.
* @return (qse_size_t)-1 on failure, new length on success * \return (qse_size_t)-1 on failure, new length on success
*/ */
QSE_EXPORT qse_size_t qse_wcs_setlen ( QSE_EXPORT qse_size_t qse_wcs_setlen (
qse_wcs_t* str, qse_wcs_t* str,

View File

@ -20,126 +20,49 @@
#include <qse/cmn/str.h> #include <qse/cmn/str.h>
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; #undef char_t
#undef cstr_t
#undef T
#undef strlen
#undef scan_dollar
#undef expand_dollar
#undef subst_t
#undef strxsubst
#undef strxnsubst
while (*f != QSE_MT('\0')) #define char_t qse_mchar_t
{ #define cstr_t qse_mcstr_t
if (*f == QSE_MT('\\')) #define T(x) QSE_MT(x)
{ #define strlen qse_mbslen
/* get the escaped character and treat it normally. #define scan_dollar mbs_scan_dollar
* if the escaper is the last character, treat it #define expand_dollar mbs_expand_dollar
* normally also. */ #define subst_t qse_mbssubst_t
if (f[1] != QSE_MT('\0')) f++; #define strxsubst qse_mbsxsubst
} #define strxnsubst qse_mbsxnsubst
else if (*f == QSE_MT('$')) #include "str-subst.h"
{
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 */ #undef char_t
while (*f != QSE_MT('\0') && *f != QSE_MT('}')) f++; #undef cstr_t
#undef T
if (*f != QSE_MT('}')) #undef strlen
{ #undef scan_dollar
/* restore to the position of $ */ #undef expand_dollar
f = tmp - 2; #undef subst_t
goto normal; #undef strxsubst
} #undef strxnsubst
f++; /* skip } */ #define char_t qse_wchar_t
#define cstr_t qse_wcstr_t
ident.ptr = tmp; #define T(x) QSE_WT(x)
ident.len = f - tmp - 1; #define strlen qse_wcslen
#define scan_dollar wcs_scan_dollar
#define expand_dollar wcs_expand_dollar
#define subst_t qse_wcssubst_t
#define strxsubst qse_wcsxsubst
#define strxnsubst qse_wcsxnsubst
#include "str-subst.h"
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;
}

174
qse/lib/cmn/str-subst.h Normal file
View File

@ -0,0 +1,174 @@
/*
* $Id$
*
Copyright 2006-2012 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 <http://www.gnu.org/licenses/>.
*/
#if !defined(char_t) && !defined(cstr_t) && !defined(strxsubst)
# error Never include this file
#endif
static const char_t* scan_dollar (
const char_t* f, qse_size_t l, cstr_t* ident, cstr_t* dfl, int depth)
{
const char_t* end = f + l;
QSE_ASSERT (l >= 2);
f += 2; /* skip ${ */
if (ident) ident->ptr = f;
while (1)
{
if (f >= end) return QSE_NULL;
if (*f == T('}') || *f == T(':')) break;
f++;
}
if (*f == T(':'))
{
if (f >= end || *(f + 1) != T('='))
{
/* not := */
return QSE_NULL;
}
if (ident) ident->len = f - ident->ptr;
f += 2; /* skip := */
if (dfl) dfl->ptr = f;
while (1)
{
if (f >= end) return QSE_NULL;
else if (*f == T('$') && *(f + 1) == T('{'))
{
if (depth >= 64) return QSE_NULL; /* depth too deep */
/* TODO: remove recursion */
f = scan_dollar (f, end - f, QSE_NULL, QSE_NULL, depth + 1);
if (f == QSE_NULL) return QSE_NULL;
}
else if (*f == T('}'))
{
/* ending bracket */
if (dfl) dfl->len = f - dfl->ptr;
return f + 1;
}
else f++;
}
}
else if (*f == T('}'))
{
if (ident) ident->len = f - ident->ptr;
if (dfl)
{
dfl->ptr = QSE_NULL;
dfl->len = 0;
}
return f + 1;
}
/* this part must not be reached */
return QSE_NULL;
}
static char_t* expand_dollar (
char_t* buf, qse_size_t bsz, const cstr_t* ident, const cstr_t* dfl,
subst_t subst, void* ctx)
{
char_t* tmp;
tmp = subst (buf, bsz, ident, ctx);
if (tmp == QSE_NULL)
{
/* substitution failed */
if (dfl->len > 0)
{
/* take the default value */
qse_size_t len;
/* TODO: remove recursion */
len = strxnsubst (buf, bsz, dfl->ptr, dfl->len, subst, ctx);
tmp = buf + len;
}
else tmp = buf;
}
return tmp;
}
qse_size_t strxnsubst (
char_t* buf, qse_size_t bsz, const char_t* fmt, qse_size_t fsz,
subst_t subst, void* ctx)
{
char_t* b = buf;
char_t* end = buf + bsz - 1;
const char_t* f = fmt;
const char_t* fend = fmt + fsz;
if (bsz <= 0) return 0;
while (f < fend)
{
if (*f == T('\\'))
{
/* get the escaped character and treat it normally.
* if the escaper is the last character, treat it
* normally also. */
if (f < fend - 1) f++;
}
else if (*f == T('$') && f < fend - 1)
{
if (*(f + 1) == T('{'))
{
const char_t* tmp;
cstr_t ident, dfl;
tmp = scan_dollar (f, fend - f, &ident, &dfl, 0);
if (tmp == QSE_NULL || ident.len <= 0) goto normal;
f = tmp;
b = expand_dollar (b, end - b + 1, &ident, &dfl, subst, ctx);
if (b >= end) goto fini;
continue;
}
else if (*(f + 1) == T('$'))
{
/* $$ -> $. \$ is also $. */
f++;
}
}
normal:
if (b >= end) break;
*b++ = *f++;
}
fini:
*b = T('\0');
return b - buf;
}
qse_size_t strxsubst (
char_t* buf, qse_size_t bsz, const char_t* fmt,
subst_t subst, void* ctx)
{
return strxnsubst (buf, bsz, fmt, strlen(fmt), subst, ctx);
}