From 88b39ee0afabc0cd5f7e47d3a120d9e50b7d126e Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 15 Mar 2019 08:10:13 +0000 Subject: [PATCH] added qse_bytetombs()/qse_bytetowcs() implemeting %k for formatted output to hex-dump a given string --- qse/include/qse/cmn/str.h | 23 +++++++++++++ qse/lib/cmn/fmt-out.h | 69 ++++++++++++++++++++++++++++++++----- qse/lib/cmn/str-cnv.c | 72 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 8 deletions(-) diff --git a/qse/include/qse/cmn/str.h b/qse/include/qse/cmn/str.h index 7135d6d5..919b526d 100644 --- a/qse/include/qse/cmn/str.h +++ b/qse/include/qse/cmn/str.h @@ -2463,10 +2463,33 @@ QSE_EXPORT int qse_wcshextobin ( qse_size_t buflen ); + +#define QSE_BYTETOSTR_RADIXMASK (0xFF) +#define QSE_BYTETOSTR_LOWERCASE (1 << 8) + +qse_size_t qse_bytetombs ( + qse_byte_t byte, + qse_mchar_t* buf, + qse_size_t size, + int flagged_radix, + qse_mchar_t fill +); + +qse_size_t qse_bytetowcs ( + qse_byte_t byte, + qse_wchar_t* buf, + qse_size_t size, + int flagged_radix, + qse_wchar_t fill +); + + #if defined(QSE_CHAR_IS_MCHAR) # define qse_strhextobin qse_mbshextobin +# define qse_bytetostr qse_bytetombs #else # define qse_strhextobin qse_wcshextobin +# define qse_bytetostr qse_bytetowcs #endif QSE_EXPORT qse_size_t qse_mbsdel ( diff --git a/qse/lib/cmn/fmt-out.h b/qse/lib/cmn/fmt-out.h index 7e5b0036..ded633e3 100644 --- a/qse/lib/cmn/fmt-out.h +++ b/qse/lib/cmn/fmt-out.h @@ -109,6 +109,7 @@ int fmtout (const char_t* fmt, fmtout_t* data, va_list ap) char_t ach, padc, * sp; ochar_t oach, * osp; qse_size_t oslen, slen; + qse_byte_t* bytep; int lm_flag, lm_dflag, flagc, numlen; qse_uintmax_t num = 0; int stop = 0; @@ -367,8 +368,7 @@ reswitch: flagc |= FLAGC_LENMOD; goto reswitch; } - - + /* end of length modifiers */ case T('n'): @@ -538,10 +538,18 @@ reswitch: /* get the length */ for (oslen = 0; osp[oslen]; oslen++); - if (data->conv (osp, &oslen, QSE_NULL, &slen, data->ctx) <= -1) + if (ch == T('K')) { - /* conversion error */ - goto oops; + oslen = 1; + slen = 2; + } + else + { + if (data->conv (osp, &oslen, QSE_NULL, &slen, data->ctx) <= -1) + { + /* conversion error */ + goto oops; + } } /* slen hold the length after conversion */ @@ -568,8 +576,17 @@ reswitch: #endif conv_len = QSE_COUNTOF(conv_buf); - /* this must not fail since the dry-run above was successful */ - data->conv (&osp[tot_len], &src_len, conv_buf, &conv_len, data->ctx); + if (ch == T('K')) + { + src_len = 1; + conv_len = 2; + qse_bytetombs(osp[tot_len], conv_buf, 2, 16, '0'); + } + else + { + /* this must not fail since the dry-run above was successful */ + data->conv (&osp[tot_len], &src_len, conv_buf, &conv_len, data->ctx); + } tot_len += src_len; /* stop outputting if a converted character can't be printed @@ -591,6 +608,42 @@ reswitch: } break; + case T('k'): + /* zerpad must not take effect for 's'. H & L doesn't take effect on 'k' */ + if (flagc & FLAGC_ZEROPAD) padc = T(' '); + + bytep = va_arg (ap, qse_byte_t*); + if (bytep == QSE_NULL) p = T("(null)"); + + if (flagc & FLAGC_DOT) + { + for (n = 0; n < precision && bytep[n]; n++); + } + else + { + for (n = 0; bytep[n]; n++); + } + + width -= (n * 2); + + if (!(flagc & FLAGC_LEFTADJ) && width > 0) + { + while (width--) PUT_CHAR(padc); + } + while (n--) + { + qse_mchar_t xbuf[3]; + qse_bytetombs (*bytep, xbuf, QSE_COUNTOF(xbuf), 16, QSE_MT('0')); + PUT_CHAR(xbuf[0]); + PUT_CHAR(xbuf[1]); + bytep++; + } + if ((flagc & FLAGC_LEFTADJ) && width > 0) + { + while (width--) PUT_CHAR(padc); + } + break; + case T('e'): case T('E'): case T('f'): @@ -652,7 +705,7 @@ reswitch: #if (QSE_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF) else if (lm_flag & (LF_QD | LF_Q)) { - v_qd = va_arg (ap, __float128); + v_qd = va_arg(ap, __float128); dtype = LF_QD; } #endif diff --git a/qse/lib/cmn/str-cnv.c b/qse/lib/cmn/str-cnv.c index 9e33d7d8..d0f3f42d 100644 --- a/qse/lib/cmn/str-cnv.c +++ b/qse/lib/cmn/str-cnv.c @@ -420,3 +420,75 @@ int qse_wcshextobin (const qse_wchar_t* hex, qse_size_t hexlen, qse_uint8_t* buf return 0; } + + +/*--------------------------------------------------------------- + * Byte to string conversion + *---------------------------------------------------------------*/ +qse_size_t qse_bytetombs (qse_byte_t byte, qse_mchar_t* buf, qse_size_t size, int flagged_radix, qse_mchar_t fill) +{ + qse_mchar_t tmp[(QSE_SIZEOF(qse_byte_t) * 8)]; + qse_mchar_t* p = tmp, * bp = buf, * be = buf + size - 1; + int radix; + qse_mchar_t radix_char; + + radix = (flagged_radix & QSE_BYTETOSTR_RADIXMASK); + radix_char = (flagged_radix & QSE_BYTETOSTR_LOWERCASE)? QSE_MT('a'): QSE_MT('A'); + if (radix < 2 || radix > 36 || size <= 0) return 0; + + do + { + qse_byte_t digit = byte % radix; + if (digit < 10) *p++ = digit + QSE_MT('0'); + else *p++ = digit + radix_char - 10; + byte /= radix; + } + while (byte > 0); + + if (fill != QSE_MT('\0')) + { + while (size - 1 > p - tmp) + { + *bp++ = fill; + size--; + } + } + + while (p > tmp && bp < be) *bp++ = *--p; + *bp = QSE_MT('\0'); + return bp - buf; +} + +qse_size_t qse_bytetowcs (qse_byte_t byte, qse_wchar_t* buf, qse_size_t size, int flagged_radix, qse_wchar_t fill) +{ + qse_wchar_t tmp[(QSE_SIZEOF(qse_byte_t) * 8)]; + qse_wchar_t* p = tmp, * bp = buf, * be = buf + size - 1; + int radix; + qse_wchar_t radix_char; + + radix = (flagged_radix & QSE_BYTETOSTR_RADIXMASK); + radix_char = (flagged_radix & QSE_BYTETOSTR_LOWERCASE)? QSE_WT('a'): QSE_WT('A'); + if (radix < 2 || radix > 36 || size <= 0) return 0; + + do + { + qse_byte_t digit = byte % radix; + if (digit < 10) *p++ = digit + QSE_WT('0'); + else *p++ = digit + radix_char - 10; + byte /= radix; + } + while (byte > 0); + + if (fill != QSE_WT('\0')) + { + while (size - 1 > p - tmp) + { + *bp++ = fill; + size--; + } + } + + while (p > tmp && bp < be) *bp++ = *--p; + *bp = QSE_WT('\0'); + return bp - buf; +}