enhanced qse_mbsxsubst() and qse_wcsxsubst() for buffer size prediction
This commit is contained in:
parent
88266f1b2e
commit
04e6df3dd8
@ -125,6 +125,10 @@ struct qse_wcs_t
|
|||||||
qse_size_t capa; /**< buffer capacity */
|
qse_size_t capa; /**< buffer capacity */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define QSE_MBSSUBST_NOBUF ((qse_mchar_t*)1)
|
||||||
|
#define QSE_WCSSUBST_NOBUF ((qse_wchar_t*)1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_mbssubst_t type defines a callback function for qse_mbsxsubst()
|
* The qse_mbssubst_t type defines a callback function for qse_mbsxsubst()
|
||||||
* and qse_mbsxnsubst() to substitue a new value for an identifier \a ident.
|
* and qse_mbsxnsubst() to substitue a new value for an identifier \a ident.
|
||||||
@ -148,8 +152,10 @@ typedef qse_wchar_t* (*qse_wcssubst_t) (
|
|||||||
);
|
);
|
||||||
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
#if defined(QSE_CHAR_IS_MCHAR)
|
||||||
|
# define QSE_STRSUBST_NOBUF QSE_MBSSUBST_NOBUF
|
||||||
# define qse_strsubst_t qse_mbssubst_t
|
# define qse_strsubst_t qse_mbssubst_t
|
||||||
#else
|
#else
|
||||||
|
# define QSE_STRSUBST_NOBUF QSE_WCSSUBST_NOBUF
|
||||||
# define qse_strsubst_t qse_wcssubst_t
|
# define qse_strsubst_t qse_wcssubst_t
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -696,6 +702,45 @@ 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
|
||||||
|
*
|
||||||
|
* If \a buf is #QSE_MBSSUBST_NOBUF, the function returns the length of the
|
||||||
|
* resulting string that a buffer large enough would be able to hold. You can
|
||||||
|
* pass #QSE_MBSSUBST_NOBUF to find out how large a buffer you need to perform
|
||||||
|
* substitution without truncation. The substitution callback function should
|
||||||
|
* handle this special case for buffer size prediction. The sample callback shown
|
||||||
|
* above can be extended to return the buffer pointer without actual copying
|
||||||
|
* if the buffer points to #QSE_MBSSUBST_NOBUF as shown belown.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* qse_mchar_t* subst (qse_mchar_t* buf, qse_size_t bsz, const qse_mcstr_t* ident, void* ctx)
|
||||||
|
* {
|
||||||
|
* if (qse_mcsxcmp (ident->ptr, ident->len, QSE_MT("USER")) == 0)
|
||||||
|
* return buf + (buf == QSE_MBSSUBST_NOBUF? 3: qse_mcsxput (buf, bsz, QSE_MT("sam")));
|
||||||
|
* else if (qse_mcsxcmp (ident->ptr, ident->len, QSE_MT("GROUP")) == 0)
|
||||||
|
* return buf + (buf == QSE_MBSSUBST_NOBUF? 6: qse_mcsxput (buf, bsz, QSE_MT("coders")));
|
||||||
|
* return buf;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* len = qse_mbsxsubst (QSE_MBSSUBST_NOBUF, 0, QSE_MT("user=${USER},group=${GROUP}"), subst, QSE_NULL);
|
||||||
|
* buf = malloc (QSE_SIZEOF(qse_mbs_t) * (len + 1));
|
||||||
|
* qse_mbsxsubst (buf, len + 1, QSE_MT("user=${USER},group=${GROUP}"), subst, QSE_NULL);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* A ${} segment may contain a default value. For example, the segment
|
||||||
|
* ${USER:=Unknown} translates to Unknown if the callback function returns
|
||||||
|
* #QSE_NULL for USER. The default value part may contain ${} segments
|
||||||
|
* recursively.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* 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)
|
||||||
|
* return QSE_NULL;
|
||||||
|
* else if (qse_mbsxcmp (ident->ptr, ident->len, QSE_MT("GROUP")) == 0)
|
||||||
|
* return buf + (buf == QSE_MBSSUBST_NOBUF? 6: qse_wcsxput (buf, bsz, QSE_MT("coders")));
|
||||||
|
* return buf;
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
*/
|
*/
|
||||||
QSE_EXPORT qse_size_t qse_mbsxsubst (
|
QSE_EXPORT qse_size_t qse_mbsxsubst (
|
||||||
qse_mchar_t* buf,
|
qse_mchar_t* buf,
|
||||||
@ -731,6 +776,44 @@ QSE_EXPORT qse_size_t qse_mbsxnsubst (
|
|||||||
* 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
|
||||||
|
*
|
||||||
|
* If \a buf is #QSE_WCSSUBST_NOBUF, the function returns the length of the
|
||||||
|
* resulting string that a buffer large enough would be able to hold. You can
|
||||||
|
* pass #QSE_WCSSUBST_NOBUF to find out how large a buffer you need to perform
|
||||||
|
* substitution without truncation. The substitution callback function should
|
||||||
|
* handle this special case for buffer size prediction. The sample callback shown
|
||||||
|
* above can be extended to return the buffer pointer without actual copying
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* qse_mchar_t* subst (qse_mchar_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 + (buf == QSE_WCSSUBST_NOBUF? 3: qse_wcsxput (buf, bsz, QSE_WT("sam")));
|
||||||
|
* else if (qse_wcsxcmp (ident->ptr, ident->len, QSE_WT("GROUP")) == 0)
|
||||||
|
* return buf + (buf == QSE_WCSSUBST_NOBUF? 6: qse_wcsxput (buf, bsz, QSE_WT("coders")));
|
||||||
|
* return buf;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* len = qse_wcsxsubst (QSE_WCSSUBST_NOBUF, 0, QSE_WT("user=${USER},group=${GROUP}"), subst, QSE_NULL);
|
||||||
|
* buf = malloc (QSE_SIZEOF(qse_wcs_t) * (len + 1));
|
||||||
|
* qse_wcsxsubst (buf, len + 1, QSE_WT("user=${USER},group=${GROUP}"), subst, QSE_NULL);
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* A ${} segment may contain a default value. For example, the segment
|
||||||
|
* ${USER:=Unknown} translates to Unknown if the callback function returns
|
||||||
|
* #QSE_NULL for USER. The default value part may contain ${} segments
|
||||||
|
* recursively.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* qse_mchar_t* subst (qse_mchar_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 QSE_NULL;
|
||||||
|
* else if (qse_wcsxcmp (ident->ptr, ident->len, QSE_WT("GROUP")) == 0)
|
||||||
|
* return buf + (buf == QSE_WCSSUBST_NOBUF? 6: qse_wcsxput (buf, bsz, QSE_WT("coders")));
|
||||||
|
* return buf;
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
*/
|
*/
|
||||||
QSE_EXPORT qse_size_t qse_wcsxsubst (
|
QSE_EXPORT qse_size_t qse_wcsxsubst (
|
||||||
qse_wchar_t* buf,
|
qse_wchar_t* buf,
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#undef char_t
|
#undef char_t
|
||||||
#undef cstr_t
|
#undef cstr_t
|
||||||
#undef T
|
#undef T
|
||||||
|
#undef NOBUF
|
||||||
#undef strlen
|
#undef strlen
|
||||||
#undef scan_dollar
|
#undef scan_dollar
|
||||||
#undef expand_dollar
|
#undef expand_dollar
|
||||||
@ -35,6 +36,7 @@
|
|||||||
#define char_t qse_mchar_t
|
#define char_t qse_mchar_t
|
||||||
#define cstr_t qse_mcstr_t
|
#define cstr_t qse_mcstr_t
|
||||||
#define T(x) QSE_MT(x)
|
#define T(x) QSE_MT(x)
|
||||||
|
#define NOBUF QSE_MBSSUBST_NOBUF
|
||||||
#define strlen qse_mbslen
|
#define strlen qse_mbslen
|
||||||
#define scan_dollar mbs_scan_dollar
|
#define scan_dollar mbs_scan_dollar
|
||||||
#define expand_dollar mbs_expand_dollar
|
#define expand_dollar mbs_expand_dollar
|
||||||
@ -48,6 +50,7 @@
|
|||||||
#undef char_t
|
#undef char_t
|
||||||
#undef cstr_t
|
#undef cstr_t
|
||||||
#undef T
|
#undef T
|
||||||
|
#undef NOBUF
|
||||||
#undef strlen
|
#undef strlen
|
||||||
#undef scan_dollar
|
#undef scan_dollar
|
||||||
#undef expand_dollar
|
#undef expand_dollar
|
||||||
@ -58,6 +61,7 @@
|
|||||||
#define char_t qse_wchar_t
|
#define char_t qse_wchar_t
|
||||||
#define cstr_t qse_wcstr_t
|
#define cstr_t qse_wcstr_t
|
||||||
#define T(x) QSE_WT(x)
|
#define T(x) QSE_WT(x)
|
||||||
|
#define NOBUF QSE_WCSSUBST_NOBUF
|
||||||
#define strlen qse_wcslen
|
#define strlen qse_wcslen
|
||||||
#define scan_dollar wcs_scan_dollar
|
#define scan_dollar wcs_scan_dollar
|
||||||
#define expand_dollar wcs_expand_dollar
|
#define expand_dollar wcs_expand_dollar
|
||||||
|
@ -122,7 +122,7 @@ qse_size_t strxnsubst (
|
|||||||
const char_t* f = fmt;
|
const char_t* f = fmt;
|
||||||
const char_t* fend = fmt + fsz;
|
const char_t* fend = fmt + fsz;
|
||||||
|
|
||||||
if (bsz <= 0) return 0;
|
if (buf != NOBUF && bsz <= 0) return 0;
|
||||||
|
|
||||||
while (f < fend)
|
while (f < fend)
|
||||||
{
|
{
|
||||||
@ -144,8 +144,18 @@ qse_size_t strxnsubst (
|
|||||||
if (tmp == QSE_NULL || ident.len <= 0) goto normal;
|
if (tmp == QSE_NULL || ident.len <= 0) goto normal;
|
||||||
f = tmp;
|
f = tmp;
|
||||||
|
|
||||||
|
if (buf != NOBUF)
|
||||||
|
{
|
||||||
b = expand_dollar (b, end - b + 1, &ident, &dfl, subst, ctx);
|
b = expand_dollar (b, end - b + 1, &ident, &dfl, subst, ctx);
|
||||||
if (b >= end) goto fini;
|
if (b >= end) goto fini;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* the buffer points to NOBUF. */
|
||||||
|
tmp = expand_dollar (buf, bsz, &ident, &dfl, subst, ctx);
|
||||||
|
/* increment b by the length of the expanded string */
|
||||||
|
b += (tmp - buf);
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -157,12 +167,16 @@ qse_size_t strxnsubst (
|
|||||||
}
|
}
|
||||||
|
|
||||||
normal:
|
normal:
|
||||||
|
if (buf != NOBUF)
|
||||||
|
{
|
||||||
if (b >= end) break;
|
if (b >= end) break;
|
||||||
*b++ = *f++;
|
*b = *f;
|
||||||
|
}
|
||||||
|
b++; f++;
|
||||||
}
|
}
|
||||||
|
|
||||||
fini:
|
fini:
|
||||||
*b = T('\0');
|
if (buf != NOBUF) *b = T('\0');
|
||||||
return b - buf;
|
return b - buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,3 +186,4 @@ qse_size_t strxsubst (
|
|||||||
{
|
{
|
||||||
return strxnsubst (buf, bsz, fmt, strlen(fmt), subst, ctx);
|
return strxnsubst (buf, bsz, fmt, strlen(fmt), subst, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user