diff --git a/moo/lib/fmtoutv.h b/moo/lib/fmtoutv.h index f34dfbc..cd84060 100644 --- a/moo/lib/fmtoutv.h +++ b/moo/lib/fmtoutv.h @@ -89,6 +89,9 @@ } \ } while (0) +/* TODO: redefine this */ +#define BYTE_PRINTABLE(x) ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z')) + static int fmtoutv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_data_t* data, va_list ap, moo_outbfmt_t outbfmt) { const fmtchar_t* percent; @@ -598,6 +601,87 @@ static int fmtoutv (moo_t* moo, const fmtchar_t* fmt, moo_fmtout_data_t* data, v break; } + case 'k': + case 'K': + { + const moo_uint8_t* bsp; + moo_oow_t bslen, slen, k_hex_width; + + /* zeropad must not take effect for 'k' and 'K' + * + * 'h' & 'l' is not used to differentiate qse_mchar_t and qse_wchar_t + * because 'k' means qse_byte_t. + * 'l', results in uppercase hexadecimal letters. + * 'h' drops the leading \x in the output + * -------------------------------------------------------- + * hk -> \x + non-printable in lowercase hex + * k -> all in lowercase hex + * lk -> \x + all in lowercase hex + * -------------------------------------------------------- + * hK -> \x + non-printable in uppercase hex + * K -> all in uppercase hex + * lK -> \x + all in uppercase hex + * -------------------------------------------------------- + * with 'k' or 'K', i don't substitute "(null)" for the NULL pointer + */ + if (flagc & FLAGC_ZEROPAD) padc = ' '; + + bsp = va_arg(ap, moo_uint8_t*); + k_hex_width = (lm_flag & (LF_H | LF_L))? 4: 2; + + if (lm_flag& LF_H) + { + if (flagc & FLAGC_DOT) + { + /* if precision is specifed, it doesn't stop at the value of zero unlike 's' or 'S' */ + for (n = 0; n < precision; n++) width -= BYTE_PRINTABLE(bsp[n])? 1: k_hex_width; + } + else + { + for (n = 0; bsp[n]; n++) width -= BYTE_PRINTABLE(bsp[n])? 1: k_hex_width; + } + } + else + { + if (flagc & FLAGC_DOT) + { + /* if precision is specifed, it doesn't stop at the value of zero unlike 's' or 'S' */ + for (n = 0; n < precision; n++) /* nothing */; + } + else + { + for (n = 0; bsp[n]; n++) /* nothing */; + } + width -= (n * k_hex_width); + } + + if (!(flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width); + + while (n--) + { + if ((lm_flag & LF_H) && BYTE_PRINTABLE(*bsp)) + { + PUT_OOCH(*bsp, 1); + } + else + { + moo_bch_t xbuf[3]; + moo_byte_to_bcstr (*bsp, xbuf, MOO_COUNTOF(xbuf), (16 | (ch == 'k'? MOO_BYTE_TO_BCSTR_LOWERCASE: 0)), '0'); + if (lm_flag & (LF_H | LF_L)) + { + PUT_OOCH('\\', 1); + PUT_OOCH('x', 1); + } + PUT_OOCH(xbuf[0], 1); + PUT_OOCH(xbuf[1], 1); + } + bsp++; + } + + if ((flagc & FLAGC_LEFTADJ) && width > 0) PUT_OOCH (padc, width); + break; + } + case 'O': /* object - ignore precision, width, adjustment */ if (print_object(moo, data->mask, va_arg(ap, moo_oop_t), outbfmt) <= -1) goto oops; break; diff --git a/moo/lib/moo-utl.h b/moo/lib/moo-utl.h index 05fc826..ad20243 100644 --- a/moo/lib/moo-utl.h +++ b/moo/lib/moo-utl.h @@ -428,6 +428,19 @@ MOO_EXPORT moo_oow_t moo_count_bcstr ( /* ------------------------------------------------------------------------- */ +#define MOO_BYTE_TO_BCSTR_RADIXMASK (0xFF) +#define MOO_BYTE_TO_BCSTR_LOWERCASE (1 << 8) + +moo_oow_t moo_byte_to_bcstr ( + moo_uint8_t byte, + moo_bch_t* buf, + moo_oow_t size, + int flagged_radix, + moo_bch_t fill +); + +/* ------------------------------------------------------------------------- */ + MOO_EXPORT int moo_ucwidth ( moo_uch_t uc ); diff --git a/moo/lib/utl.c b/moo/lib/utl.c index 35c07ae..20d0f49 100644 --- a/moo/lib/utl.c +++ b/moo/lib/utl.c @@ -541,6 +541,42 @@ moo_bch_t* moo_find_bchar_in_bcstr (const moo_bch_t* ptr, moo_bch_t c) /* ----------------------------------------------------------------------- */ +moo_oow_t moo_byte_to_bcstr (moo_uint8_t byte, moo_bch_t* buf, moo_oow_t size, int flagged_radix, moo_bch_t fill) +{ + moo_bch_t tmp[(MOO_SIZEOF(moo_uint8_t) * 8)]; + moo_bch_t* p = tmp, * bp = buf, * be = buf + size - 1; + int radix; + moo_bch_t radix_char; + + radix = (flagged_radix & MOO_BYTE_TO_BCSTR_RADIXMASK); + radix_char = (flagged_radix & MOO_BYTE_TO_BCSTR_LOWERCASE)? 'a': 'A'; + if (radix < 2 || radix > 36 || size <= 0) return 0; + + do + { + moo_uint8_t digit = byte % radix; + if (digit < 10) *p++ = digit + '0'; + else *p++ = digit + radix_char - 10; + byte /= radix; + } + while (byte > 0); + + if (fill != '\0') + { + while (size - 1 > p - tmp) + { + *bp++ = fill; + size--; + } + } + + while (p > tmp && bp < be) *bp++ = *--p; + *bp = '\0'; + return bp - buf; +} + +/* ----------------------------------------------------------------------- */ + MOO_INLINE int moo_conv_bchars_to_uchars_with_cmgr ( const moo_bch_t* bcs, moo_oow_t* bcslen, moo_uch_t* ucs, moo_oow_t* ucslen, moo_cmgr_t* cmgr, int all)