diff --git a/qse/include/qse/cmn/str.h b/qse/include/qse/cmn/str.h index 436c4125..e81b6520 100644 --- a/qse/include/qse/cmn/str.h +++ b/qse/include/qse/cmn/str.h @@ -2736,6 +2736,12 @@ QSE_EXPORT qse_size_t qse_mbs_fcat ( ... ); +QSE_EXPORT qse_size_t qse_mbs_fmt ( + qse_mbs_t* str, + const qse_mchar_t* fmt, + ... +); + /** * The qse_wcs_open() function creates a dynamically resizable wide-character * string. @@ -2927,6 +2933,12 @@ QSE_EXPORT qse_size_t qse_wcs_fcat ( ... ); +QSE_EXPORT qse_size_t qse_wcs_fmt ( + qse_wcs_t* str, + const qse_wchar_t* fmt, + ... +); + #if defined(QSE_CHAR_IS_MCHAR) # define qse_str_setmmgr(str,mmgr) qse_mbs_wetmmgr(str,mmgr) # define qse_str_getmmgr(str) qse_mbs_getmmgr(str) @@ -2955,6 +2967,7 @@ QSE_EXPORT qse_size_t qse_wcs_fcat ( # define qse_str_trm(str) qse_mbs_trm(str) # define qse_str_pac(str) qse_mbs_pac(str) # define qse_str_fcat qse_mbs_fcat +# define qse_str_fmt qse_mbs_fmt #else # define qse_str_setmmgr(str,mmgr) qse_wcs_wetmmgr(str,mmgr) # define qse_str_getmmgr(str) qse_wcs_getmmgr(str) @@ -2983,6 +2996,7 @@ QSE_EXPORT qse_size_t qse_wcs_fcat ( # define qse_str_trm(str) qse_wcs_trm(str) # define qse_str_pac(str) qse_wcs_pac(str) # define qse_str_fcat qse_wcs_fcat +# define qse_str_fmt qse_wcs_fmt #endif diff --git a/qse/lib/cmn/str-dyn.c b/qse/lib/cmn/str-dyn.c index 13c4b304..09ffe6e7 100644 --- a/qse/lib/cmn/str-dyn.c +++ b/qse/lib/cmn/str-dyn.c @@ -32,20 +32,34 @@ static int put_wchar_null (qse_wchar_t c, void* ctx) return 1; } -static int put_mchar (qse_mchar_t c, void* ctx) +static int put_mchar_check (qse_mchar_t c, void* ctx) { qse_mbs_t* str = (qse_mbs_t*)ctx; if (str->val.len < str->capa) str->val.ptr[str->val.len++] = c; return 1; } -static int put_wchar (qse_wchar_t c, void* ctx) +static int put_wchar_check (qse_wchar_t c, void* ctx) { qse_wcs_t* str = (qse_wcs_t*)ctx; if (str->val.len < str->capa) str->val.ptr[str->val.len++] = c; return 1; } +static int put_mchar_nocheck (qse_mchar_t c, void* ctx) +{ + qse_mbs_t* str = (qse_mbs_t*)ctx; + str->val.ptr[str->val.len++] = c; + return 1; +} + +static int put_wchar_nocheck (qse_wchar_t* c, void* ctx) +{ + qse_wcs_t* str = (qse_wcs_t*)ctx; + str->val.ptr[str->val.len++] = c; + return 1; +} + static int wcs_to_mbs ( const qse_wchar_t* wcs, qse_size_t* wcslen, qse_mchar_t* mbs, qse_size_t* mbslen, void* ctx) @@ -73,7 +87,8 @@ static int mbs_to_wcs ( #undef fmtout_t #undef fmtout #undef put_char_null -#undef put_char +#undef put_char_check +#undef put_char_nocheck #undef conv_char #undef str_t #undef str_open @@ -104,7 +119,9 @@ static int mbs_to_wcs ( #undef str_trm #undef str_pac #undef str_fmt +#undef str_vfmt #undef str_fcat +#undef str_vfcat #define char_t qse_mchar_t #define xstr_t qse_mxstr_t @@ -117,7 +134,8 @@ static int mbs_to_wcs ( #define fmtout_t qse_mfmtout_t #define fmtout qse_mfmtout #define put_char_null put_mchar_null -#define put_char put_mchar +#define put_char_check put_mchar_check +#define put_char_nocheck put_mchar_nocheck #define conv_char wcs_to_mbs #define str_t qse_mbs_t #define str_open qse_mbs_open @@ -148,7 +166,9 @@ static int mbs_to_wcs ( #define str_trm qse_mbs_trm #define str_pac qse_mbs_pac #define str_fmt qse_mbs_fmt +#define str_vfmt qse_mbs_vfmt #define str_fcat qse_mbs_fcat +#define str_vfcat qse_mbs_vfcat #include "str-dyn.h" /* -------------------------------------------------------- */ @@ -164,7 +184,8 @@ static int mbs_to_wcs ( #undef fmtout_t #undef fmtout #undef put_char_null -#undef put_char +#undef put_char_check +#undef put_char_nocheck #undef conv_char #undef str_t #undef str_open @@ -195,7 +216,9 @@ static int mbs_to_wcs ( #undef str_trm #undef str_pac #undef str_fmt +#undef str_vfmt #undef str_fcat +#undef str_vfcat #define char_t qse_wchar_t #define xstr_t qse_wxstr_t @@ -208,7 +231,8 @@ static int mbs_to_wcs ( #define fmtout_t qse_wfmtout_t #define fmtout qse_wfmtout #define put_char_null put_wchar_null -#define put_char put_wchar +#define put_char_check put_wchar_check +#define put_char_nocheck put_wchar_nocheck #define conv_char mbs_to_wcs #define str_t qse_wcs_t #define str_open qse_wcs_open @@ -239,5 +263,7 @@ static int mbs_to_wcs ( #define str_trm qse_wcs_trm #define str_pac qse_wcs_pac #define str_fmt qse_wcs_fmt +#define str_vfmt qse_wcs_vfmt #define str_fcat qse_wcs_fcat +#define str_vfcat qse_wcs_vfcat #include "str-dyn.h" diff --git a/qse/lib/cmn/str-dyn.h b/qse/lib/cmn/str-dyn.h index 9320c6d8..ec0f5249 100644 --- a/qse/lib/cmn/str-dyn.h +++ b/qse/lib/cmn/str-dyn.h @@ -426,13 +426,52 @@ qse_size_t str_pac (str_t* str) } -qse_size_t str_fmt (str_t* str, const char_t* fmt, ...) + +qse_size_t str_vfcat (str_t* str, const char_t* fmt, va_list ap) { - return (qse_size_t)-1; + va_list orgap; + fmtout_t fo; + int x; + qse_size_t old_len; + + old_len = str->val.len; + + fo.limit = QSE_TYPE_MAX(qse_size_t) - 1; + fo.ctx = str; + fo.put = str->val.ptr? put_char_check: put_char_null; + fo.conv = conv_char; + + va_copy (orgap, ap); + x = fmtout (fmt, &fo, ap); + + if (x <= -1) + { + str->val.len = old_len; + return (qse_size_t)-1; + } + + if (str->val.ptr == QSE_NULL || str->val.len - old_len < fo.count) + { + str->val.len = old_len; + + /* resizing is required */ + x = resize_for_ncat (str, fo.count); + + if (x <= -1) return (qse_size_t)-1; + if (x >= 1) + { + fo.put = put_char_nocheck; + x = fmtout (fmt, &fo, orgap); + } + } + + str->val.ptr[str->val.len] = T('\0'); + return str->val.len; } qse_size_t str_fcat (str_t* str, const char_t* fmt, ...) { +#if 0 va_list ap; fmtout_t fo; int x; @@ -475,4 +514,53 @@ qse_size_t str_fcat (str_t* str, const char_t* fmt, ...) str->val.ptr[str->val.len] = T('\0'); return str->val.len; +#endif + qse_size_t x; + va_list ap; + + va_start (ap, fmt); + x = str_vfcat (str, fmt, ap); + va_end (ap); + + return x; +} + +qse_size_t str_vfmt (str_t* str, const char_t* fmt, va_list ap) +{ + int x; + fmtout_t fo; + va_list orgap; + + fo.limit = QSE_TYPE_MAX(qse_size_t) - 1; + fo.ctx = str; + fo.put = put_char_null; + fo.conv = conv_char; + + va_copy (orgap, ap); + if (fmtout (fmt, &fo, ap) <= -1) return (qse_size_t)-1; + + str_clear (str); + x = resize_for_ncat (str, fo.count); + + if (x <= -1) return (qse_size_t)-1; + if (x >= 1) + { + fo.put = put_char_nocheck; + x = fmtout (fmt, &fo, orgap); + } + + str->val.ptr[str->val.len] = T('\0'); + return str->val.len; +} + +qse_size_t str_fmt (str_t* str, const char_t* fmt, ...) +{ + qse_size_t x; + va_list ap; + + va_start (ap, fmt); + x = str_vfmt (str, fmt, ap); + va_end (ap); + + return x; }