From 656e0150a9028dfb39b8c60489ace104aa104ffb Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sun, 15 Nov 2020 10:26:14 +0000 Subject: [PATCH] cleaned up code and build files --- lib/Makefile.am | 2 + lib/Makefile.in | 10 +- lib/err.c | 16 +- lib/exec.c | 8 +- lib/fmt-imp.h | 228 ++++++++++++++++++++++++++++ lib/fmt.c | 364 ++++++++++++++++++++++++++++++-------------- lib/hcl-cmn.h | 44 ++++++ lib/hcl-fmt.h | 389 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/hcl-prv.h | 4 + lib/hcl-rbt.h | 8 +- lib/hcl-utl.h | 74 --------- 11 files changed, 944 insertions(+), 203 deletions(-) create mode 100644 lib/fmt-imp.h create mode 100644 lib/hcl-fmt.h diff --git a/lib/Makefile.am b/lib/Makefile.am index ffb5097..cce002a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -49,6 +49,7 @@ pkglibdir = $(libdir) pkginclude_HEADERS = \ hcl.h \ hcl-cmn.h \ + hcl-fmt.h \ hcl-opt.h \ hcl-rbt.h \ hcl-utl.h @@ -68,6 +69,7 @@ libhcl_la_SOURCES = \ dic.c \ err.c \ exec.c \ + fmt-imp.h \ fmt.c \ gc.c \ hcl.c \ diff --git a/lib/Makefile.in b/lib/Makefile.in index 6f2e2f2..badb447 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -236,8 +236,9 @@ am__can_run_installinfo = \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac -am__pkginclude_HEADERS_DIST = hcl.h hcl-cmn.h hcl-opt.h hcl-rbt.h \ - hcl-utl.h hcl-c.h hcl-s.h hcl-tmr.h hcl-xutl.h hcl-json.h +am__pkginclude_HEADERS_DIST = hcl.h hcl-cmn.h hcl-fmt.h hcl-opt.h \ + hcl-rbt.h hcl-utl.h hcl-c.h hcl-s.h hcl-tmr.h hcl-xutl.h \ + hcl-json.h HEADERS = $(pkginclude_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)hcl-cfg.h.in @@ -422,8 +423,8 @@ LIBADD_LIB_COMMON = $(LIBM) $(am__append_1) $(am__append_2) \ @WIN32_TRUE@CPPFLAGS_PFMOD = -DHCL_DEFAULT_PFMODPREFIX=\"libhcl-\" \ @WIN32_TRUE@ -DHCL_DEFAULT_PFMODPOSTFIX=\"-1.dll\" \ @WIN32_TRUE@ $(am__append_4) $(am__append_5) -pkginclude_HEADERS = hcl.h hcl-cmn.h hcl-opt.h hcl-rbt.h hcl-utl.h \ - $(am__append_9) +pkginclude_HEADERS = hcl.h hcl-cmn.h hcl-fmt.h hcl-opt.h hcl-rbt.h \ + hcl-utl.h $(am__append_9) pkglib_LTLIBRARIES = libhcl.la $(am__append_8) libhcl_la_SOURCES = \ hcl.h \ @@ -439,6 +440,7 @@ libhcl_la_SOURCES = \ dic.c \ err.c \ exec.c \ + fmt-imp.h \ fmt.c \ gc.c \ hcl.c \ diff --git a/lib/err.c b/lib/err.c index 89837ca..837345a 100644 --- a/lib/err.c +++ b/lib/err.c @@ -245,8 +245,8 @@ void hcl_seterrbfmt (hcl_t* hcl, hcl_errnum_t errnum, const hcl_bch_t* fmt, ...) hcl->errmsg.len = 0; HCL_MEMSET (&fo, 0, HCL_SIZEOF(fo)); - fo.putbcs = err_bcs; - fo.putucs = err_ucs; + fo.putbchars = err_bcs; + fo.putuchars = err_ucs; fo.putobj = hcl_fmt_object_; fo.ctx = hcl; @@ -266,8 +266,8 @@ void hcl_seterrufmt (hcl_t* hcl, hcl_errnum_t errnum, const hcl_uch_t* fmt, ...) hcl->errmsg.len = 0; HCL_MEMSET (&fo, 0, HCL_SIZEOF(fo)); - fo.putbcs = err_bcs; - fo.putucs = err_ucs; + fo.putbchars = err_bcs; + fo.putuchars = err_ucs; fo.putobj = hcl_fmt_object_; fo.ctx = hcl; @@ -288,8 +288,8 @@ void hcl_seterrbfmtv (hcl_t* hcl, hcl_errnum_t errnum, const hcl_bch_t* fmt, va_ hcl->errmsg.len = 0; HCL_MEMSET (&fo, 0, HCL_SIZEOF(fo)); - fo.putbcs = err_bcs; - fo.putucs = err_ucs; + fo.putbchars = err_bcs; + fo.putuchars = err_ucs; fo.putobj = hcl_fmt_object_; fo.ctx = hcl; @@ -306,8 +306,8 @@ void hcl_seterrufmtv (hcl_t* hcl, hcl_errnum_t errnum, const hcl_uch_t* fmt, va_ hcl->errmsg.len = 0; HCL_MEMSET (&fo, 0, HCL_SIZEOF(fo)); - fo.putbcs = err_bcs; - fo.putucs = err_ucs; + fo.putbchars = err_bcs; + fo.putuchars = err_ucs; fo.putobj = hcl_fmt_object_; fo.ctx = hcl; diff --git a/lib/exec.c b/lib/exec.c index 66aa166..a0c2288 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -158,8 +158,8 @@ static HCL_INLINE int vm_startup (hcl_t* hcl) } #if defined(ENABLE_GCFIN) - moo->sem_gcfin = (moo_oop_semaphore_t)moo->_nil; - moo->sem_gcfin_sigreq = 0; + hcl->sem_gcfin = (moo_oop_semaphore_t)hcl->_nil; + hcl->sem_gcfin_sigreq = 0; #endif hcl->vmprim.vm_gettime (hcl, &hcl->exec_start_time); /* raw time. no adjustment */ @@ -208,8 +208,8 @@ static void vm_cleanup (hcl_t* hcl) } #if defined(ENABLE_GCFIN) - moo->sem_gcfin = (moo_oop_semaphore_t)moo->_nil; - moo->sem_gcfin_sigreq = 0; + hcl->sem_gcfin = (moo_oop_semaphore_t)hcl->_nil; + hcl->sem_gcfin_sigreq = 0; /* deregister all pending finalizable objects pending just in case these * have not been removed for various reasons. (e.g. sudden VM abortion) diff --git a/lib/fmt-imp.h b/lib/fmt-imp.h new file mode 100644 index 0000000..d7f23b5 --- /dev/null +++ b/lib/fmt-imp.h @@ -0,0 +1,228 @@ +/* + * $Id$ + * + Copyright (c) 2016-2018 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +static int fmt_uintmax ( + char_t* buf, int size, + hcl_uintmax_t value, int base_and_flags, int prec, + char_t fillchar, char_t signchar, const char_t* prefix) +{ + char_t tmp[(HCL_SIZEOF(hcl_uintmax_t) * 8)]; + int reslen, base, fillsize, reqlen, pflen, preczero; + char_t* p, * bp, * be; + const hcl_bch_t* xbasestr; + + base = base_and_flags & 0x3F; + if (base < 2 || base > 36) return -1; + + xbasestr = (base_and_flags & HCL_FMT_INTMAX_UPPERCASE)? + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ": + "0123456789abcdefghijklmnopqrstuvwxyz"; + + if ((base_and_flags & HCL_FMT_INTMAX_NOZERO) && value == 0) + { + p = tmp; + if (base_and_flags & HCL_FMT_INTMAX_ZEROLEAD) + { + /* NOZERO emits no digit, ZEROLEAD emits 1 digit. + * so it emits '0' */ + reslen = 1; + preczero = 1; + } + else + { + /* since the value is zero, emit no digits */ + reslen = 0; + preczero = 0; + } + } + else + { + hcl_uintmax_t v = value; + + /* store the resulting numeric string into 'tmp' first */ + p = tmp; + do + { + *p++ = xbasestr[v % base]; + v /= base; + } + while (v > 0); + + /* reslen is the length of the resulting string without padding. */ + reslen = (int)(p - tmp); + + /* precision specified the minum number of digits to produce. + * so if the precision is larger that the digits produced, + * reslen should be adjusted to precision */ + if (prec > reslen) + { + /* if the precision is greater than the actual digits + * made from the value, 0 is inserted in front. + * ZEROLEAD doesn't have to be handled explicitly + * since it's achieved effortlessly */ + preczero = prec - reslen; + reslen = prec; + } + else + { + preczero = 0; + if ((base_and_flags & HCL_FMT_INTMAX_ZEROLEAD) && value != 0) + { + /* if value is zero, 0 is emitted from it. + * so ZEROLEAD don't need to add another 0. */ + preczero++; + reslen++; + } + } + } + + if (signchar) reslen++; /* increment reslen for the sign character */ + if (prefix) + { + /* since the length can be truncated for different type sizes, + * don't pass in a very long prefix. */ + const char_t* pp; + for (pp = prefix; *pp != '\0'; pp++) ; + pflen = pp - prefix; + reslen += pflen; + } + else pflen = 0; + + /* get the required buffer size for lossless formatting */ + reqlen = (base_and_flags & HCL_FMT_INTMAX_NONULL)? reslen: (reslen + 1); + + if (size <= 0 || + ((base_and_flags & HCL_FMT_INTMAX_NOTRUNC) && size < reqlen)) + { + return -reqlen; + } + + /* get the size to fill with fill characters */ + fillsize = (base_and_flags & HCL_FMT_INTMAX_NONULL)? size: (size - 1); + bp = buf; + be = buf + fillsize; + + /* fill space */ + if (fillchar != '\0') + { + if (base_and_flags & HCL_FMT_INTMAX_FILLRIGHT) + { + /* emit sign */ + if (signchar && bp < be) *bp++ = signchar; + + /* copy prefix if necessary */ + if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; + + /* add 0s for precision */ + while (preczero > 0 && bp < be) + { + *bp++ = '0'; + preczero--; + } + + /* copy the numeric string to the destination buffer */ + while (p > tmp && bp < be) *bp++ = *--p; + + /* fill the right side */ + while (fillsize > reslen) + { + *bp++ = fillchar; + fillsize--; + } + } + else if (base_and_flags & HCL_FMT_INTMAX_FILLCENTER) + { + /* emit sign */ + if (signchar && bp < be) *bp++ = signchar; + + /* fill the left side */ + while (fillsize > reslen) + { + *bp++ = fillchar; + fillsize--; + } + + /* copy prefix if necessary */ + if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; + + /* add 0s for precision */ + while (preczero > 0 && bp < be) + { + *bp++ = '0'; + preczero--; + } + + /* copy the numeric string to the destination buffer */ + while (p > tmp && bp < be) *bp++ = *--p; + } + else + { + /* fill the left side */ + while (fillsize > reslen) + { + *bp++ = fillchar; + fillsize--; + } + + /* emit sign */ + if (signchar && bp < be) *bp++ = signchar; + + /* copy prefix if necessary */ + if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; + + /* add 0s for precision */ + while (preczero > 0 && bp < be) + { + *bp++ = '0'; + preczero--; + } + + /* copy the numeric string to the destination buffer */ + while (p > tmp && bp < be) *bp++ = *--p; + } + } + else + { + /* emit sign */ + if (signchar && bp < be) *bp++ = signchar; + + /* copy prefix if necessary */ + if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; + + /* add 0s for precision */ + while (preczero > 0 && bp < be) + { + *bp++ = '0'; + preczero--; + } + + /* copy the numeric string to the destination buffer */ + while (p > tmp && bp < be) *bp++ = *--p; + } + + if (!(base_and_flags & HCL_FMT_INTMAX_NONULL)) *bp = '\0'; + return bp - buf; +} diff --git a/lib/fmt.c b/lib/fmt.c index a83cf34..56422ab 100644 --- a/lib/fmt.c +++ b/lib/fmt.c @@ -1,7 +1,7 @@ /* * $Id$ * - Copyright (c) 2014-2018 Chung, Hyung-Hwan. All rights reserved. + Copyright (c) 2016-2018 Chung, Hyung-Hwan. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -68,7 +68,8 @@ #include "hcl-prv.h" -#if 0 +#if defined(HCL_ENABLE_FLTFMT) + #include /* for snrintf(). used for floating-point number formatting */ #if defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1200)) # define snprintf _snprintf @@ -79,6 +80,7 @@ #if defined(HAVE_QUADMATH_H) # include /* for quadmath_snprintf() */ #endif + #endif /* Max number conversion buffer length: @@ -169,6 +171,135 @@ static const hcl_bch_t hex2ascii_upper[] = static hcl_uch_t uch_nullstr[] = { '(','n','u','l','l', ')','\0' }; static hcl_bch_t bch_nullstr[] = { '(','n','u','l','l', ')','\0' }; +/* ------------------------------------------------------------------------- */ + +/*define static int fmt_uintmax_to_bcstr(...)*/ +#undef char_t +#undef fmt_uintmax +#define char_t hcl_bch_t +#define fmt_uintmax fmt_uintmax_to_bcstr +#include "fmt-imp.h" + +/*define static int fmt_uintmax_to_ucstr(...)*/ +#undef char_t +#undef fmt_uintmax +#define char_t hcl_uch_t +#define fmt_uintmax fmt_uintmax_to_ucstr +#include "fmt-imp.h" + +int hcl_fmt_intmax_to_bcstr ( + hcl_bch_t* buf, int size, + hcl_intmax_t value, int base_and_flags, int prec, + hcl_bch_t fillchar, const hcl_bch_t* prefix) +{ + hcl_bch_t signchar; + hcl_uintmax_t absvalue; + + if (value < 0) + { + signchar = '-'; + absvalue = -value; + } + else if (base_and_flags & HCL_FMT_INTMAX_TO_BCSTR_PLUSSIGN) + { + signchar = '+'; + absvalue = value; + } + else if (base_and_flags & HCL_FMT_INTMAX_TO_BCSTR_EMPTYSIGN) + { + signchar = ' '; + absvalue = value; + } + else + { + signchar = '\0'; + absvalue = value; + } + + return fmt_uintmax_to_bcstr(buf, size, absvalue, base_and_flags, prec, fillchar, signchar, prefix); +} + +int hcl_fmt_uintmax_to_bcstr ( + hcl_bch_t* buf, int size, + hcl_uintmax_t value, int base_and_flags, int prec, + hcl_bch_t fillchar, const hcl_bch_t* prefix) +{ + hcl_bch_t signchar; + + /* determine if a sign character is needed */ + if (base_and_flags & HCL_FMT_INTMAX_TO_BCSTR_PLUSSIGN) + { + signchar = '+'; + } + else if (base_and_flags & HCL_FMT_INTMAX_TO_BCSTR_EMPTYSIGN) + { + signchar = ' '; + } + else + { + signchar = '\0'; + } + + return fmt_uintmax_to_bcstr(buf, size, value, base_and_flags, prec, fillchar, signchar, prefix); +} + +/* ==================== wide-char ===================================== */ + +int hcl_fmt_intmax_to_ucstr ( + hcl_uch_t* buf, int size, + hcl_intmax_t value, int base_and_flags, int prec, + hcl_uch_t fillchar, const hcl_uch_t* prefix) +{ + hcl_uch_t signchar; + hcl_uintmax_t absvalue; + + if (value < 0) + { + signchar = '-'; + absvalue = -value; + } + else if (base_and_flags & HCL_FMT_INTMAX_TO_UCSTR_PLUSSIGN) + { + signchar = '+'; + absvalue = value; + } + else if (base_and_flags & HCL_FMT_INTMAX_TO_UCSTR_EMPTYSIGN) + { + signchar = ' '; + absvalue = value; + } + else + { + signchar = '\0'; + absvalue = value; + } + + return fmt_uintmax_to_ucstr(buf, size, absvalue, base_and_flags, prec, fillchar, signchar, prefix); +} + +int hcl_fmt_uintmax_to_ucstr ( + hcl_uch_t* buf, int size, + hcl_uintmax_t value, int base_and_flags, int prec, + hcl_uch_t fillchar, const hcl_uch_t* prefix) +{ + hcl_uch_t signchar; + + /* determine if a sign character is needed */ + if (base_and_flags & HCL_FMT_INTMAX_TO_UCSTR_PLUSSIGN) + { + signchar = '+'; + } + else if (base_and_flags & HCL_FMT_INTMAX_TO_UCSTR_EMPTYSIGN) + { + signchar = ' '; + } + else + { + signchar = '\0'; + } + + return fmt_uintmax_to_ucstr(buf, size, value, base_and_flags, prec, fillchar, signchar, prefix); +} /* ------------------------------------------------------------------------- */ /* @@ -211,7 +342,7 @@ static hcl_bch_t* sprintn_upper (hcl_bch_t* nbuf, hcl_uintmax_t num, int base, h for (_yy = 0; _yy < n; _yy++) \ { \ int _xx; \ - if ((_xx = fmtout->putbcs(fmtout, &_cc, 1)) <= -1) goto oops; \ + if ((_xx = fmtout->putbchars(fmtout, &_cc, 1)) <= -1) goto oops; \ if (_xx == 0) goto done; \ fmtout->count++; \ } \ @@ -221,7 +352,7 @@ static hcl_bch_t* sprintn_upper (hcl_bch_t* nbuf, hcl_uintmax_t num, int base, h #define PUT_BCS(fmtout,ptr,len) do { \ if (len > 0) { \ int _xx; \ - if ((_xx = fmtout->putbcs(fmtout, ptr, len)) <= -1) goto oops; \ + if ((_xx = fmtout->putbchars(fmtout, ptr, len)) <= -1) goto oops; \ if (_xx == 0) goto done; \ fmtout->count += len; \ } \ @@ -234,7 +365,7 @@ static hcl_bch_t* sprintn_upper (hcl_bch_t* nbuf, hcl_uintmax_t num, int base, h for (_yy = 0; _yy < n; _yy++) \ { \ int _xx; \ - if ((_xx = fmtout->putucs(fmtout, &_cc, 1)) <= -1) goto oops; \ + if ((_xx = fmtout->putuchars(fmtout, &_cc, 1)) <= -1) goto oops; \ if (_xx == 0) goto done; \ fmtout->count++; \ } \ @@ -244,7 +375,7 @@ static hcl_bch_t* sprintn_upper (hcl_bch_t* nbuf, hcl_uintmax_t num, int base, h #define PUT_UCS(fmtout,ptr,len) do { \ if (len > 0) { \ int _xx; \ - if ((_xx = fmtout->putucs(fmtout, ptr, len)) <= -1) goto oops; \ + if ((_xx = fmtout->putuchars(fmtout, ptr, len)) <= -1) goto oops; \ if (_xx == 0) goto done; \ fmtout->count += len; \ } \ @@ -287,10 +418,25 @@ static int fmt_outv (hcl_fmtout_t* fmtout, va_list ap) hcl_bch_t nbuf[MAXNBUF]; const hcl_bch_t* nbufp; int stop = 0; -#if 0 - hcl_bchbuf_t* fltfmt; - hcl_oochbuf_t* fltout; + +#if defined(HCL_ENABLE_FLTFMT) + struct + { + struct + { + hcl_bch_t sbuf[32]; + hcl_bch_t* ptr; + hcl_oow_t capa; + } fmt; + struct + { + hcl_bch_t sbuf[64]; + hcl_bch_t* ptr; + hcl_oow_t capa; + } out; + } fb; /* some buffers for handling float-point number formatting */ #endif + hcl_bch_t* (*sprintn) (hcl_bch_t* nbuf, hcl_uintmax_t num, int base, hcl_ooi_t* lenp); fmtptr = (const hcl_uint8_t*)fmtout->fmt_str; @@ -306,16 +452,11 @@ static int fmt_outv (hcl_fmtout_t* fmtout, va_list ap) /* this is an internal function. it doesn't reset count to 0 */ /* fmtout->count = 0; */ - -#if 0 - fltfmt = &hcl->d->fltfmt; - fltout = &hcl->d->fltout; - - fltfmt->ptr = fltfmt->buf; - fltfmt->capa = HCL_COUNTOF(fltfmt->buf) - 1; - - fltout->ptr = fltout->buf; - fltout->capa = HCL_COUNTOF(fltout->buf) - 1; +#if defined(HCL_ENABLE_FLTFMT) + fb.fmt.ptr = fb.fmt.sbuf; + fb.fmt.capa = HCL_COUNTOF(fb.fmt.sbuf) - 1; + fb.out.ptr = fb.out.sbuf; + fb.out.capa = HCL_COUNTOF(fb.out.sbuf) - 1; #endif while (1) @@ -891,7 +1032,7 @@ static int fmt_outv (hcl_fmtout_t* fmtout, va_list ap) break; } -#if 0 +#if defined(HCL_ENABLE_FLTFMT) case 'e': case 'E': case 'f': @@ -906,23 +1047,27 @@ static int fmt_outv (hcl_fmtout_t* fmtout, va_list ap) /* let me rely on snprintf until i implement float-point to string conversion */ int q; hcl_oow_t fmtlen; - #if (HCL_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF) - __float128 v_qd; - #endif - long double v_ld; - double v_d; + union + { + #if (HCL_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF) + __float128 qd; + #endif + long double ld; + double d; + } v; int dtype = 0; hcl_oow_t newcapa; + hcl_bch_t* bsp; if (lm_flag & LF_J) { #if (HCL_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF) && (HCL_SIZEOF_FLTMAX_T == HCL_SIZEOF___FLOAT128) - v_qd = va_arg (ap, hcl_fltmax_t); + v.qd = va_arg(ap, hcl_fltmax_t); dtype = LF_QD; #elif HCL_SIZEOF_FLTMAX_T == HCL_SIZEOF_DOUBLE - v_d = va_arg(ap, hcl_fltmax_t); + v.d = va_arg(ap, hcl_fltmax_t); #elif HCL_SIZEOF_FLTMAX_T == HCL_SIZEOF_LONG_DOUBLE - v_ld = va_arg(ap, hcl_fltmax_t); + v.ld = va_arg(ap, hcl_fltmax_t); dtype = LF_LD; #else #error Unsupported hcl_flt_t @@ -937,9 +1082,9 @@ static int fmt_outv (hcl_fmtout_t* fmtout, va_list ap) * so i prefer the format specifier with no modifier. */ #if HCL_SIZEOF_FLT_T == HCL_SIZEOF_DOUBLE - v_d = va_arg(ap, hcl_flt_t); + v.d = va_arg(ap, hcl_flt_t); #elif HCL_SIZEOF_FLT_T == HCL_SIZEOF_LONG_DOUBLE - v_ld = va_arg(ap, hcl_flt_t); + v.ld = va_arg(ap, hcl_flt_t); dtype = LF_LD; #else #error Unsupported hcl_flt_t @@ -947,13 +1092,13 @@ static int fmt_outv (hcl_fmtout_t* fmtout, va_list ap) } else if (lm_flag & (LF_LD | LF_L)) { - v_ld = va_arg (ap, long double); + v.ld = va_arg(ap, long double); dtype = LF_LD; } #if (HCL_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 @@ -963,63 +1108,63 @@ static int fmt_outv (hcl_fmtout_t* fmtout, va_list ap) } else { - v_d = va_arg (ap, double); + v.d = va_arg(ap, double); } - fmtlen = fmt - percent; - if (fmtlen > fltfmt->capa) + fmtlen = fmtptr - percent; + if (fmtlen > fb.fmt.capa) { - if (fltfmt->ptr == fltfmt->buf) + if (fb.fmt.ptr == fb.fmt.sbuf) { - fltfmt->ptr = HCL_MMGR_ALLOC(HCL_MMGR_GETDFL(), HCL_SIZEOF(*fltfmt->ptr) * (fmtlen + 1)); - if (!fltfmt->ptr) goto oops; + fb.fmt.ptr = (hcl_bch_t*)HCL_MMGR_ALLOC(fmtout->mmgr, HCL_SIZEOF(*fb.fmt.ptr) * (fmtlen + 1)); + if (!fb.fmt.ptr) goto oops; } else { hcl_bch_t* tmpptr; - tmpptr = HCL_MMGR_REALLOC(HCL_MMGR_GETDFL(), fltfmt->ptr, HCL_SIZEOF(*fltfmt->ptr) * (fmtlen + 1)); + tmpptr = (hcl_bch_t*)HCL_MMGR_REALLOC(fmtout->mmgr, fb.fmt.ptr, HCL_SIZEOF(*fb.fmt.ptr) * (fmtlen + 1)); if (!tmpptr) goto oops; - fltfmt->ptr = tmpptr; + fb.fmt.ptr = tmpptr; } - fltfmt->capa = fmtlen; + fb.fmt.capa = fmtlen; } /* compose back the format specifier */ fmtlen = 0; - fltfmt->ptr[fmtlen++] = '%'; - if (flagc & FLAGC_SPACE) fltfmt->ptr[fmtlen++] = ' '; - if (flagc & FLAGC_SHARP) fltfmt->ptr[fmtlen++] = '#'; - if (flagc & FLAGC_SIGN) fltfmt->ptr[fmtlen++] = '+'; - if (flagc & FLAGC_LEFTADJ) fltfmt->ptr[fmtlen++] = '-'; - if (flagc & FLAGC_ZEROPAD) fltfmt->ptr[fmtlen++] = '0'; + fb.fmt.ptr[fmtlen++] = '%'; + if (flagc & FLAGC_SPACE) fb.fmt.ptr[fmtlen++] = ' '; + if (flagc & FLAGC_SHARP) fb.fmt.ptr[fmtlen++] = '#'; + if (flagc & FLAGC_SIGN) fb.fmt.ptr[fmtlen++] = '+'; + if (flagc & FLAGC_LEFTADJ) fb.fmt.ptr[fmtlen++] = '-'; + if (flagc & FLAGC_ZEROPAD) fb.fmt.ptr[fmtlen++] = '0'; - if (flagc & FLAGC_STAR1) fltfmt->ptr[fmtlen++] = '*'; + if (flagc & FLAGC_STAR1) fb.fmt.ptr[fmtlen++] = '*'; else if (flagc & FLAGC_WIDTH) { - fmtlen += hcl_fmtuintmaxtombs ( - &fltfmt->ptr[fmtlen], fltfmt->capa - fmtlen, + fmtlen += hcl_fmt_uintmax_to_bcstr( + &fb.fmt.ptr[fmtlen], fb.fmt.capa - fmtlen, width, 10, -1, '\0', HCL_NULL); } - if (flagc & FLAGC_DOT) fltfmt->ptr[fmtlen++] = '.'; - if (flagc & FLAGC_STAR2) fltfmt->ptr[fmtlen++] = '*'; + if (flagc & FLAGC_DOT) fb.fmt.ptr[fmtlen++] = '.'; + if (flagc & FLAGC_STAR2) fb.fmt.ptr[fmtlen++] = '*'; else if (flagc & FLAGC_PRECISION) { - fmtlen += hcl_fmtuintmaxtombs ( - &fltfmt->ptr[fmtlen], fltfmt->capa - fmtlen, + fmtlen += hcl_fmt_uintmax_to_bcstr( + &fb.fmt.ptr[fmtlen], fb.fmt.capa - fmtlen, precision, 10, -1, '\0', HCL_NULL); } if (dtype == LF_LD) - fltfmt->ptr[fmtlen++] = 'L'; + fb.fmt.ptr[fmtlen++] = 'L'; #if (HCL_SIZEOF___FLOAT128 > 0) else if (dtype == LF_QD) - fltfmt->ptr[fmtlen++] = 'Q'; + fb.fmt.ptr[fmtlen++] = 'Q'; #endif - fltfmt->ptr[fmtlen++] = ch; - fltfmt->ptr[fmtlen] = '\0'; + fb.fmt.ptr[fmtlen++] = uch; + fb.fmt.ptr[fmtlen] = '\0'; #if defined(HAVE_SNPRINTF) /* nothing special here */ @@ -1027,78 +1172,65 @@ static int fmt_outv (hcl_fmtout_t* fmtout, va_list ap) /* best effort to avoid buffer overflow when no snprintf is available. * i really can't do much if it happens. */ newcapa = precision + width + 32; - if (fltout->capa < newcapa) + if (fb.out.capa < newcapa) { - HCL_ASSERT (hcl, fltout->ptr == fltout->buf); + HCL_ASSERT (moo, fb.out.ptr == fb.out.sbuf); - fltout->ptr = HCL_MMGR_ALLOC(HCL_MMGR_GETDFL(), HCL_SIZEOF(char_t) * (newcapa + 1)); - if (!fltout->ptr) goto oops; - fltout->capa = newcapa; + fb.out.ptr = HCL_MMGR_ALLOC(fmtout->mmgr, HCL_SIZEOF(hcl_bch_t) * (newcapa + 1)); + if (!fb.out.ptr) goto oops; + fb.out.capa = newcapa; } #endif while (1) { - if (dtype == LF_LD) { #if defined(HAVE_SNPRINTF) - q = snprintf ((hcl_bch_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_ld); + q = snprintf((hcl_bch_t*)fb.out.ptr, fb.out.capa + 1, fb.fmt.ptr, v.ld); #else - q = sprintf ((hcl_bch_t*)fltout->ptr, fltfmt->ptr, v_ld); + q = sprintf((hcl_bch_t*)fb.out.ptr, fb.fmt.ptr, v.ld); #endif } #if (HCL_SIZEOF___FLOAT128 > 0) && defined(HAVE_QUADMATH_SNPRINTF) else if (dtype == LF_QD) { - q = quadmath_snprintf((hcl_bch_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_qd); + q = quadmath_snprintf((hcl_bch_t*)fb.out.ptr, fb.out.capa + 1, fb.fmt.ptr, v.qd); } #endif else { #if defined(HAVE_SNPRINTF) - q = snprintf ((hcl_bch_t*)fltout->ptr, fltout->capa + 1, fltfmt->ptr, v_d); + q = snprintf((hcl_bch_t*)fb.out.ptr, fb.out.capa + 1, fb.fmt.ptr, v.d); #else - q = sprintf ((hcl_bch_t*)fltout->ptr, fltfmt->ptr, v_d); + q = sprintf((hcl_bch_t*)fb.out.ptr, fb.fmt.ptr, v.d); #endif } if (q <= -1) goto oops; - if (q <= fltout->capa) break; + if (q <= fb.out.capa) break; - newcapa = fltout->capa * 2; + newcapa = fb.out.capa * 2; if (newcapa < q) newcapa = q; - if (fltout->ptr == fltout->sbuf) + if (fb.out.ptr == fb.out.sbuf) { - fltout->ptr = HCL_MMGR_ALLOC(HCL_MMGR_GETDFL(), HCL_SIZEOF(char_t) * (newcapa + 1)); - if (!fltout->ptr) goto oops; + fb.out.ptr = (hcl_bch_t*)HCL_MMGR_ALLOC(fmtout->mmgr, HCL_SIZEOF(hcl_bch_t) * (newcapa + 1)); + if (!fb.out.ptr) goto oops; } else { - char_t* tmpptr; - - tmpptr = HCL_MMGR_REALLOC(HCL_MMGR_GETDFL(), fltout->ptr, HCL_SIZEOF(char_t) * (newcapa + 1)); + hcl_bch_t* tmpptr; + tmpptr = (hcl_bch_t*)HCL_MMGR_REALLOC(fmtout->mmgr, fb.out.ptr, HCL_SIZEOF(hcl_bch_t) * (newcapa + 1)); if (!tmpptr) goto oops; - fltout->ptr = tmpptr; + fb.out.ptr = tmpptr; } - fltout->capa = newcapa; + fb.out.capa = newcapa; } - if (HCL_SIZEOF(char_t) != HCL_SIZEOF(hcl_bch_t)) - { - fltout->ptr[q] = '\0'; - while (q > 0) - { - q--; - fltout->ptr[q] = ((hcl_bch_t*)fltout->ptr)[q]; - } - } - - sp = fltout->ptr; - flagc &= ~FLAGC_DOT; - width = 0; - precision = 0; - goto print_lowercase_s; + bsp = fb.out.ptr; + n = 0; while (bsp[n] != '\0') n++; + PUT_BCS (fmtout, bsp, n); + break; } #endif @@ -1297,9 +1429,17 @@ static int fmt_outv (hcl_fmtout_t* fmtout, va_list ap) } done: +#if defined(HCL_ENABLE_FLTFMT) + if (fb.fmt.ptr != fb.fmt.sbuf) HCL_MMGR_FREE (fmtout->mmgr, fb.fmt.ptr); + if (fb.out.ptr != fb.out.sbuf) HCL_MMGR_FREE (fmtout->mmgr, fb.out.ptr); +#endif return 0; oops: +#if defined(HCL_ENABLE_FLTFMT) + if (fb.fmt.ptr != fb.fmt.sbuf) HCL_MMGR_FREE (fmtout->mmgr, fb.fmt.ptr); + if (fb.out.ptr != fb.out.sbuf) HCL_MMGR_FREE (fmtout->mmgr, fb.out.ptr); +#endif return -1; } @@ -1557,8 +1697,9 @@ hcl_ooi_t hcl_logbfmtv (hcl_t* hcl, hcl_bitmask_t mask, const hcl_bch_t* fmt, va fo.fmt_str = fmt; fo.ctx = hcl; fo.mask = mask; - fo.putbcs = log_bcs; - fo.putucs = log_ucs; + fo.mmgr = hcl_getmmgr(hcl); + fo.putbchars = log_bcs; + fo.putuchars = log_ucs; fo.putobj = hcl_fmt_object_; x = fmt_outv(&fo, ap); @@ -1611,8 +1752,9 @@ hcl_ooi_t hcl_logufmtv (hcl_t* hcl, hcl_bitmask_t mask, const hcl_uch_t* fmt, va fo.fmt_str = fmt; fo.ctx = hcl; fo.mask = mask; - fo.putbcs = log_bcs; - fo.putucs = log_ucs; + fo.mmgr = hcl_getmmgr(hcl); + fo.putbchars = log_bcs; + fo.putuchars = log_ucs; fo.putobj = hcl_fmt_object_; x = fmt_outv(&fo, ap); @@ -1756,8 +1898,9 @@ hcl_ooi_t hcl_prbfmtv (hcl_t* hcl, const hcl_bch_t* fmt, va_list ap) fo.fmt_str = fmt; fo.ctx = hcl; fo.mask = 0; - fo.putbcs = print_bcs; - fo.putucs = print_ucs; + fo.mmgr = hcl_getmmgr(hcl); + fo.putbchars = print_bcs; + fo.putuchars = print_ucs; fo.putobj = hcl_fmt_object_; x = fmt_outv(&fo, ap); @@ -1788,8 +1931,9 @@ hcl_ooi_t hcl_prufmtv (hcl_t* hcl, const hcl_uch_t* fmt, va_list ap) fo.fmt_str = fmt; fo.ctx = hcl; fo.mask = 0; - fo.putbcs = print_bcs; - fo.putucs = print_ucs; + fo.mmgr = hcl_getmmgr(hcl); + fo.putbchars = print_bcs; + fo.putuchars = print_ucs; fo.putobj = hcl_fmt_object_; x = fmt_outv(&fo, ap); @@ -2637,8 +2781,8 @@ int hcl_strfmtcallstack (hcl_t* hcl, hcl_ooi_t nargs) HCL_MEMSET (&fo, 0, HCL_SIZEOF(fo)); fo.ctx = hcl; - fo.putbcs = sprint_bcs; - fo.putucs = sprint_ucs; + fo.putbchars = sprint_bcs; + fo.putuchars = sprint_ucs; fo.putobj = hcl_fmt_object_; /* format_stack_args doesn't use fmt_str and fmt_type. * it takes the format string from the stack. */ @@ -2653,9 +2797,12 @@ int hcl_prfmtcallstack (hcl_t* hcl, hcl_ooi_t nargs) hcl_fmtout_t fo; HCL_MEMSET (&fo, 0, HCL_SIZEOF(fo)); + + fo.mask = 0; + fo.mmgr = hcl_getmmgr(hcl); fo.ctx = hcl; - fo.putbcs = print_bcs; - fo.putucs = print_ucs; + fo.putbchars = print_bcs; + fo.putuchars = print_ucs; fo.putobj = hcl_fmt_object_; /* format_stack_args doesn't use fmt_str and fmt_type. * it takes the format string from the stack. */ @@ -2681,9 +2828,10 @@ int hcl_logfmtcallstack (hcl_t* hcl, hcl_ooi_t nargs) fo.mask |= (hcl->log.default_type_mask & HCL_LOG_ALL_TYPES); } + fo.mmgr = hcl_getmmgr(hcl); fo.ctx = hcl; - fo.putbcs = log_bcs; - fo.putucs = log_ucs; + fo.putbchars = log_bcs; + fo.putuchars = log_ucs; fo.putobj = hcl_fmt_object_; /* format_stack_args doesn't use fmt_str and fmt_type. * it takes the format string from the stack. */ diff --git a/lib/hcl-cmn.h b/lib/hcl-cmn.h index caf127b..5564c09 100644 --- a/lib/hcl-cmn.h +++ b/lib/hcl-cmn.h @@ -335,6 +335,50 @@ # error UNKNOWN INTMAX SIZE #endif +/* ========================================================================= + * FLOATING-POINT TYPE + * ========================================================================= */ +/** \typedef hcl_fltbas_t + * The hcl_fltbas_t type defines the largest floating-pointer number type + * naturally supported. + */ +#if defined(__FreeBSD__) || defined(__MINGW32__) + /* TODO: check if the support for long double is complete. + * if so, use long double for hcl_flt_t */ + typedef double hcl_fltbas_t; +# define HCL_SIZEOF_FLTBAS_T HCL_SIZEOF_DOUBLE +#elif HCL_SIZEOF_LONG_DOUBLE > HCL_SIZEOF_DOUBLE + typedef long double hcl_fltbas_t; +# define HCL_SIZEOF_FLTBAS_T HCL_SIZEOF_LONG_DOUBLE +#else + typedef double hcl_fltbas_t; +# define HCL_SIZEOF_FLTBAS_T HCL_SIZEOF_DOUBLE +#endif + +/** \typedef hcl_fltmax_t + * The hcl_fltmax_t type defines the largest floating-pointer number type + * ever supported. + */ +#if HCL_SIZEOF___FLOAT128 >= HCL_SIZEOF_FLTBAS_T + /* the size of long double may be equal to the size of __float128 + * for alignment on some platforms */ + typedef __float128 hcl_fltmax_t; +# define HCL_SIZEOF_FLTMAX_T HCL_SIZEOF___FLOAT128 +# define HCL_FLTMAX_REQUIRE_QUADMATH 1 +#else + typedef hcl_fltbas_t hcl_fltmax_t; +# define HCL_SIZEOF_FLTMAX_T HCL_SIZEOF_FLTBAS_T +# undef HCL_FLTMAX_REQUIRE_QUADMATH +#endif + +#if defined(HCL_USE_FLTMAX) +typedef hcl_fltmax_t hcl_flt_t; +#define HCL_SIZEOF_FLT_T HCL_SIZEOF_FLTMAX_T +#else +typedef hcl_fltbas_t hcl_flt_t; +#define HCL_SIZEOF_FLT_T HCL_SIZEOF_FLTBAS_T +#endif + /* ========================================================================= * BASIC HARD-CODED DEFINES * ========================================================================= */ diff --git a/lib/hcl-fmt.h b/lib/hcl-fmt.h new file mode 100644 index 0000000..8520d53 --- /dev/null +++ b/lib/hcl-fmt.h @@ -0,0 +1,389 @@ +/* + * $Id$ + * + Copyright (c) 2016-2018 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _HCL_FMT_H_ +#define _HCL_FMT_H_ + +#include "hcl-cmn.h" +#include + +/** \file + * This file defines various formatting functions. + */ + +/** + * The hcl_fmt_intmax_flag_t type defines enumerators to change the + * behavior of hcl_fmt_intmax() and hcl_fmt_uintmax(). + */ +enum hcl_fmt_intmax_flag_t +{ + /* Use lower 6 bits to represent base between 2 and 36 inclusive. + * Upper bits are used for these flag options */ + + /** Don't truncate if the buffer is not large enough */ + HCL_FMT_INTMAX_NOTRUNC = (0x40 << 0), +#define HCL_FMT_INTMAX_NOTRUNC HCL_FMT_INTMAX_NOTRUNC +#define HCL_FMT_UINTMAX_NOTRUNC HCL_FMT_INTMAX_NOTRUNC +#define HCL_FMT_INTMAX_TO_BCSTR_NOTRUNC HCL_FMT_INTMAX_NOTRUNC +#define HCL_FMT_UINTMAX_TO_BCSTR_NOTRUNC HCL_FMT_INTMAX_NOTRUNC +#define HCL_FMT_INTMAX_TO_UCSTR_NOTRUNC HCL_FMT_INTMAX_NOTRUNC +#define HCL_FMT_UINTMAX_TO_UCSTR_NOTRUNC HCL_FMT_INTMAX_NOTRUNC +#define HCL_FMT_INTMAX_TO_OOCSTR_NOTRUNC HCL_FMT_INTMAX_NOTRUNC +#define HCL_FMT_UINTMAX_TO_OOCSTR_NOTRUNC HCL_FMT_INTMAX_NOTRUNC + + /** Don't append a terminating null */ + HCL_FMT_INTMAX_NONULL = (0x40 << 1), +#define HCL_FMT_INTMAX_NONULL HCL_FMT_INTMAX_NONULL +#define HCL_FMT_UINTMAX_NONULL HCL_FMT_INTMAX_NONULL +#define HCL_FMT_INTMAX_TO_BCSTR_NONULL HCL_FMT_INTMAX_NONULL +#define HCL_FMT_UINTMAX_TO_BCSTR_NONULL HCL_FMT_INTMAX_NONULL +#define HCL_FMT_INTMAX_TO_UCSTR_NONULL HCL_FMT_INTMAX_NONULL +#define HCL_FMT_UINTMAX_TO_UCSTR_NONULL HCL_FMT_INTMAX_NONULL +#define HCL_FMT_INTMAX_TO_OOCSTR_NONULL HCL_FMT_INTMAX_NONULL +#define HCL_FMT_UINTMAX_TO_OOCSTR_NONULL HCL_FMT_INTMAX_NONULL + + /** Produce no digit for a value of zero */ + HCL_FMT_INTMAX_NOZERO = (0x40 << 2), +#define HCL_FMT_INTMAX_NOZERO HCL_FMT_INTMAX_NOZERO +#define HCL_FMT_UINTMAX_NOZERO HCL_FMT_INTMAX_NOZERO +#define HCL_FMT_INTMAX_TO_BCSTR_NOZERO HCL_FMT_INTMAX_NOZERO +#define HCL_FMT_UINTMAX_TO_BCSTR_NOZERO HCL_FMT_INTMAX_NOZERO +#define HCL_FMT_INTMAX_TO_UCSTR_NOZERO HCL_FMT_INTMAX_NOZERO +#define HCL_FMT_UINTMAX_TO_UCSTR_NOZERO HCL_FMT_INTMAX_NOZERO +#define HCL_FMT_INTMAX_TO_OOCSTR_NOZERO HCL_FMT_INTMAX_NOZERO +#define HCL_FMT_UINTMAX_TO_OOCSTR_NOZERO HCL_FMT_INTMAX_NOZERO + + /** Produce a leading zero for a non-zero value */ + HCL_FMT_INTMAX_ZEROLEAD = (0x40 << 3), +#define HCL_FMT_INTMAX_ZEROLEAD HCL_FMT_INTMAX_ZEROLEAD +#define HCL_FMT_UINTMAX_ZEROLEAD HCL_FMT_INTMAX_ZEROLEAD +#define HCL_FMT_INTMAX_TO_BCSTR_ZEROLEAD HCL_FMT_INTMAX_ZEROLEAD +#define HCL_FMT_UINTMAX_TO_BCSTR_ZEROLEAD HCL_FMT_INTMAX_ZEROLEAD +#define HCL_FMT_INTMAX_TO_UCSTR_ZEROLEAD HCL_FMT_INTMAX_ZEROLEAD +#define HCL_FMT_UINTMAX_TO_UCSTR_ZEROLEAD HCL_FMT_INTMAX_ZEROLEAD +#define HCL_FMT_INTMAX_TO_OOCSTR_ZEROLEAD HCL_FMT_INTMAX_ZEROLEAD +#define HCL_FMT_UINTMAX_TO_OOCSTR_ZEROLEAD HCL_FMT_INTMAX_ZEROLEAD + + /** Use uppercase letters for alphabetic digits */ + HCL_FMT_INTMAX_UPPERCASE = (0x40 << 4), +#define HCL_FMT_INTMAX_UPPERCASE HCL_FMT_INTMAX_UPPERCASE +#define HCL_FMT_UINTMAX_UPPERCASE HCL_FMT_INTMAX_UPPERCASE +#define HCL_FMT_INTMAX_TO_BCSTR_UPPERCASE HCL_FMT_INTMAX_UPPERCASE +#define HCL_FMT_UINTMAX_TO_BCSTR_UPPERCASE HCL_FMT_INTMAX_UPPERCASE +#define HCL_FMT_INTMAX_TO_UCSTR_UPPERCASE HCL_FMT_INTMAX_UPPERCASE +#define HCL_FMT_UINTMAX_TO_UCSTR_UPPERCASE HCL_FMT_INTMAX_UPPERCASE +#define HCL_FMT_INTMAX_TO_OOCSTR_UPPERCASE HCL_FMT_INTMAX_UPPERCASE +#define HCL_FMT_UINTMAX_TO_OOCSTR_UPPERCASE HCL_FMT_INTMAX_UPPERCASE + + /** Insert a plus sign for a positive integer including 0 */ + HCL_FMT_INTMAX_PLUSSIGN = (0x40 << 5), +#define HCL_FMT_INTMAX_PLUSSIGN HCL_FMT_INTMAX_PLUSSIGN +#define HCL_FMT_UINTMAX_PLUSSIGN HCL_FMT_INTMAX_PLUSSIGN +#define HCL_FMT_INTMAX_TO_BCSTR_PLUSSIGN HCL_FMT_INTMAX_PLUSSIGN +#define HCL_FMT_UINTMAX_TO_BCSTR_PLUSSIGN HCL_FMT_INTMAX_PLUSSIGN +#define HCL_FMT_INTMAX_TO_UCSTR_PLUSSIGN HCL_FMT_INTMAX_PLUSSIGN +#define HCL_FMT_UINTMAX_TO_UCSTR_PLUSSIGN HCL_FMT_INTMAX_PLUSSIGN +#define HCL_FMT_INTMAX_TO_OOCSTR_PLUSSIGN HCL_FMT_INTMAX_PLUSSIGN +#define HCL_FMT_UINTMAX_TO_OOCSTR_PLUSSIGN HCL_FMT_INTMAX_PLUSSIGN + + /** Insert a space for a positive integer including 0 */ + HCL_FMT_INTMAX_EMPTYSIGN = (0x40 << 6), +#define HCL_FMT_INTMAX_EMPTYSIGN HCL_FMT_INTMAX_EMPTYSIGN +#define HCL_FMT_UINTMAX_EMPTYSIGN HCL_FMT_INTMAX_EMPTYSIGN +#define HCL_FMT_INTMAX_TO_BCSTR_EMPTYSIGN HCL_FMT_INTMAX_EMPTYSIGN +#define HCL_FMT_UINTMAX_TO_BCSTR_EMPTYSIGN HCL_FMT_INTMAX_EMPTYSIGN +#define HCL_FMT_INTMAX_TO_UCSTR_EMPTYSIGN HCL_FMT_INTMAX_EMPTYSIGN +#define HCL_FMT_UINTMAX_TO_UCSTR_EMPTYSIGN HCL_FMT_INTMAX_EMPTYSIGN + + /** Fill the right part of the string */ + HCL_FMT_INTMAX_FILLRIGHT = (0x40 << 7), +#define HCL_FMT_INTMAX_FILLRIGHT HCL_FMT_INTMAX_FILLRIGHT +#define HCL_FMT_UINTMAX_FILLRIGHT HCL_FMT_INTMAX_FILLRIGHT +#define HCL_FMT_INTMAX_TO_BCSTR_FILLRIGHT HCL_FMT_INTMAX_FILLRIGHT +#define HCL_FMT_UINTMAX_TO_BCSTR_FILLRIGHT HCL_FMT_INTMAX_FILLRIGHT +#define HCL_FMT_INTMAX_TO_UCSTR_FILLRIGHT HCL_FMT_INTMAX_FILLRIGHT +#define HCL_FMT_UINTMAX_TO_UCSTR_FILLRIGHT HCL_FMT_INTMAX_FILLRIGHT +#define HCL_FMT_INTMAX_TO_OOCSTR_FILLRIGHT HCL_FMT_INTMAX_FILLRIGHT +#define HCL_FMT_UINTMAX_TO_OOCSTR_FILLRIGHT HCL_FMT_INTMAX_FILLRIGHT + + /** Fill between the sign chacter and the digit part */ + HCL_FMT_INTMAX_FILLCENTER = (0x40 << 8) +#define HCL_FMT_INTMAX_FILLCENTER HCL_FMT_INTMAX_FILLCENTER +#define HCL_FMT_UINTMAX_FILLCENTER HCL_FMT_INTMAX_FILLCENTER +#define HCL_FMT_INTMAX_TO_BCSTR_FILLCENTER HCL_FMT_INTMAX_FILLCENTER +#define HCL_FMT_UINTMAX_TO_BCSTR_FILLCENTER HCL_FMT_INTMAX_FILLCENTER +#define HCL_FMT_INTMAX_TO_UCSTR_FILLCENTER HCL_FMT_INTMAX_FILLCENTER +#define HCL_FMT_UINTMAX_TO_UCSTR_FILLCENTER HCL_FMT_INTMAX_FILLCENTER +#define HCL_FMT_INTMAX_TO_OOCSTR_FILLCENTER HCL_FMT_INTMAX_FILLCENTER +#define HCL_FMT_UINTMAX_TO_OOCSTR_FILLCENTER HCL_FMT_INTMAX_FILLCENTER +}; + +/* ========================================================================= + * FORMATTED OUTPUT + * ========================================================================= */ +typedef struct hcl_fmtout_t hcl_fmtout_t; + +typedef int (*hcl_fmtout_putbchars_t) ( + hcl_fmtout_t* fmtout, + const hcl_bch_t* ptr, + hcl_oow_t len +); + +typedef int (*hcl_fmtout_putuchars_t) ( + hcl_fmtout_t* fmtout, + const hcl_uch_t* ptr, + hcl_oow_t len +); + +typedef int (*hcl_fmtout_putobj_t) ( + hcl_fmtout_t* fmtout, + hcl_oop_t obj +); + +enum hcl_fmtout_fmt_type_t +{ + HCL_FMTOUT_FMT_TYPE_BCH = 0, + HCL_FMTOUT_FMT_TYPE_UCH +}; +typedef enum hcl_fmtout_fmt_type_t hcl_fmtout_fmt_type_t; + + +struct hcl_fmtout_t +{ + hcl_oow_t count; /* out */ + + hcl_mmgr_t* mmgr; /* in */ + hcl_fmtout_putbchars_t putbchars; /* in */ + hcl_fmtout_putuchars_t putuchars; /* in */ + hcl_fmtout_putobj_t putobj; /* in - %O is not handled if it's not set. */ + hcl_bitmask_t mask; /* in */ + void* ctx; /* in */ + + + /* internally set as input */ + hcl_fmtout_fmt_type_t fmt_type; + const void* fmt_str; +}; + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * The hcl_fmt_intmax_to_bcstr() function formats an integer \a value to a + * multibyte string according to the given base and writes it to a buffer + * pointed to by \a buf. It writes to the buffer at most \a size characters + * including the terminating null. The base must be between 2 and 36 inclusive + * and can be ORed with zero or more #hcl_fmt_intmax_to_bcstr_flag_t enumerators. + * This ORed value is passed to the function via the \a base_and_flags + * parameter. If the formatted string is shorter than \a bufsize, the redundant + * slots are filled with the fill character \a fillchar if it is not a null + * character. The filling behavior is determined by the flags shown below: + * + * - If #HCL_FMT_INTMAX_TO_BCSTR_FILLRIGHT is set in \a base_and_flags, slots + * after the formatting string are filled. + * - If #HCL_FMT_INTMAX_TO_BCSTR_FILLCENTER is set in \a base_and_flags, slots + * before the formatting string are filled. However, if it contains the + * sign character, the slots between the sign character and the digit part + * are filled. + * - If neither #HCL_FMT_INTMAX_TO_BCSTR_FILLRIGHT nor #HCL_FMT_INTMAX_TO_BCSTR_FILLCENTER + * , slots before the formatting string are filled. + * + * The \a precision parameter specified the minimum number of digits to + * produce from the \a value. If \a value produces fewer digits than + * \a precision, the actual digits are padded with '0' to meet the precision + * requirement. You can pass a negative number if you don't wish to specify + * precision. + * + * The terminating null is not added if #HCL_FMT_INTMAX_TO_BCSTR_NONULL is set; + * The #HCL_FMT_INTMAX_TO_BCSTR_UPPERCASE flag indicates that the function should + * use the uppercase letter for a alphabetic digit; + * You can set #HCL_FMT_INTMAX_TO_BCSTR_NOTRUNC if you require lossless formatting. + * The #HCL_FMT_INTMAX_TO_BCSTR_PLUSSIGN flag and #HCL_FMT_INTMAX_TO_BCSTR_EMPTYSIGN + * ensures that the plus sign and a space is added for a positive integer + * including 0 respectively. + * The #HCL_FMT_INTMAX_TO_BCSTR_ZEROLEAD flag ensures that the numeric string + * begins with '0' before applying the prefix. + * You can set the #HCL_FMT_INTMAX_TO_BCSTR_NOZERO flag if you want the value of + * 0 to produce nothing. If both #HCL_FMT_INTMAX_TO_BCSTR_NOZERO and + * #HCL_FMT_INTMAX_TO_BCSTR_ZEROLEAD are specified, '0' is still produced. + * + * If \a prefix is not #HCL_NULL, it is inserted before the digits. + * + * \return + * - -1 if the base is not between 2 and 36 inclusive. + * - negated number of characters required for lossless formatting + * - if \a bufsize is 0. + * - if #HCL_FMT_INTMAX_TO_BCSTR_NOTRUNC is set and \a bufsize is less than + * the minimum required for lossless formatting. + * - number of characters written to the buffer excluding a terminating + * null in all other cases. + */ +HCL_EXPORT int hcl_fmt_intmax_to_bcstr ( + hcl_bch_t* buf, /**< buffer pointer */ + int bufsize, /**< buffer size */ + hcl_intmax_t value, /**< integer to format */ + int base_and_flags, /**< base ORed with flags */ + int precision, /**< precision */ + hcl_bch_t fillchar, /**< fill character */ + const hcl_bch_t* prefix /**< prefix */ +); + +/** + * The hcl_fmt_intmax_to_ucstr() function formats an integer \a value to a + * wide-character string according to the given base and writes it to a buffer + * pointed to by \a buf. It writes to the buffer at most \a size characters + * including the terminating null. The base must be between 2 and 36 inclusive + * and can be ORed with zero or more #hcl_fmt_intmax_to_ucstr_flag_t enumerators. + * This ORed value is passed to the function via the \a base_and_flags + * parameter. If the formatted string is shorter than \a bufsize, the redundant + * slots are filled with the fill character \a fillchar if it is not a null + * character. The filling behavior is determined by the flags shown below: + * + * - If #HCL_FMT_INTMAX_TO_UCSTR_FILLRIGHT is set in \a base_and_flags, slots + * after the formatting string are filled. + * - If #HCL_FMT_INTMAX_TO_UCSTR_FILLCENTER is set in \a base_and_flags, slots + * before the formatting string are filled. However, if it contains the + * sign character, the slots between the sign character and the digit part + * are filled. + * - If neither #HCL_FMT_INTMAX_TO_UCSTR_FILLRIGHT nor #HCL_FMT_INTMAX_TO_UCSTR_FILLCENTER + * , slots before the formatting string are filled. + * + * The \a precision parameter specified the minimum number of digits to + * produce from the \ value. If \a value produces fewer digits than + * \a precision, the actual digits are padded with '0' to meet the precision + * requirement. You can pass a negative number if don't wish to specify + * precision. + * + * The terminating null is not added if #HCL_FMT_INTMAX_TO_UCSTR_NONULL is set; + * The #HCL_FMT_INTMAX_TO_UCSTR_UPPERCASE flag indicates that the function should + * use the uppercase letter for a alphabetic digit; + * You can set #HCL_FMT_INTMAX_TO_UCSTR_NOTRUNC if you require lossless formatting. + * The #HCL_FMT_INTMAX_TO_UCSTR_PLUSSIGN flag and #HCL_FMT_INTMAX_TO_UCSTR_EMPTYSIGN + * ensures that the plus sign and a space is added for a positive integer + * including 0 respectively. + * The #HCL_FMT_INTMAX_TO_UCSTR_ZEROLEAD flag ensures that the numeric string + * begins with 0 before applying the prefix. + * You can set the #HCL_FMT_INTMAX_TO_UCSTR_NOZERO flag if you want the value of + * 0 to produce nothing. If both #HCL_FMT_INTMAX_TO_UCSTR_NOZERO and + * #HCL_FMT_INTMAX_TO_UCSTR_ZEROLEAD are specified, '0' is still produced. + * + * If \a prefix is not #HCL_NULL, it is inserted before the digits. + * + * \return + * - -1 if the base is not between 2 and 36 inclusive. + * - negated number of characters required for lossless formatting + * - if \a bufsize is 0. + * - if #HCL_FMT_INTMAX_TO_UCSTR_NOTRUNC is set and \a bufsize is less than + * the minimum required for lossless formatting. + * - number of characters written to the buffer excluding a terminating + * null in all other cases. + */ +HCL_EXPORT int hcl_fmt_intmax_to_ucstr ( + hcl_uch_t* buf, /**< buffer pointer */ + int bufsize, /**< buffer size */ + hcl_intmax_t value, /**< integer to format */ + int base_and_flags, /**< base ORed with flags */ + int precision, /**< precision */ + hcl_uch_t fillchar, /**< fill character */ + const hcl_uch_t* prefix /**< prefix */ +); + +/** + * The hcl_fmt_uintmax_to_bcstr() function formats an unsigned integer \a value + * to a multibyte string buffer. It behaves the same as hcl_fmt_intmax_to_bcstr() + * except that it handles an unsigned integer. + */ +HCL_EXPORT int hcl_fmt_uintmax_to_bcstr ( + hcl_bch_t* buf, /**< buffer pointer */ + int bufsize, /**< buffer size */ + hcl_uintmax_t value, /**< integer to format */ + int base_and_flags, /**< base ORed with flags */ + int precision, /**< precision */ + hcl_bch_t fillchar, /**< fill character */ + const hcl_bch_t* prefix /**< prefix */ +); + +/** + * The hcl_fmt_uintmax_to_ucstr() function formats an unsigned integer \a value + * to a multibyte string buffer. It behaves the same as hcl_fmt_intmax_to_ucstr() + * except that it handles an unsigned integer. + */ +HCL_EXPORT int hcl_fmt_uintmax_to_ucstr ( + hcl_uch_t* buf, /**< buffer pointer */ + int bufsize, /**< buffer size */ + hcl_uintmax_t value, /**< integer to format */ + int base_and_flags, /**< base ORed with flags */ + int precision, /**< precision */ + hcl_uch_t fillchar, /**< fill character */ + const hcl_uch_t* prefix /**< prefix */ +); + +#if defined(HCL_OOCH_IS_BCH) +# define hcl_fmt_intmax_to_oocstr hcl_fmt_intmax_to_bcstr +# define hcl_fmt_uintmax_to_oocstr hcl_fmt_uintmax_to_bcstr +#else +# define hcl_fmt_intmax_to_oocstr hcl_fmt_intmax_to_ucstr +# define hcl_fmt_uintmax_to_oocstr hcl_fmt_uintmax_to_ucstr +#endif + + +/* TODO: hcl_fmt_fltmax_to_bcstr()... hcl_fmt_fltmax_to_ucstr() */ + + +/* ========================================================================= + * FORMATTED OUTPUT + * ========================================================================= */ +HCL_EXPORT int hcl_bfmt_outv ( + hcl_fmtout_t* fmtout, + const hcl_bch_t* fmt, + va_list ap +); + +HCL_EXPORT int hcl_ufmt_outv ( + hcl_fmtout_t* fmtout, + const hcl_uch_t* fmt, + va_list ap +); + + +HCL_EXPORT int hcl_bfmt_out ( + hcl_fmtout_t* fmtout, + const hcl_bch_t* fmt, + ... +); + +HCL_EXPORT int hcl_ufmt_out ( + hcl_fmtout_t* fmtout, + const hcl_uch_t* fmt, + ... +); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index 6ec7a42..d7dc10b 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -28,6 +28,7 @@ #define _HCL_PRV_H_ #include "hcl.h" +#include "hcl-fmt.h" #include "hcl-utl.h" /* you can define this to either 1 or 2 */ @@ -42,6 +43,9 @@ #define HCL_KARATSUBA_CUTOFF 32 #define HCL_KARATSUBA_CUTOFF_DEBUG 3 +/* enable floating-pointer number support in the basic formatting functions */ +#define HCL_ENABLE_FLTFMT + #if defined(HCL_BUILD_DEBUG) #define HCL_DEBUG_LEXER 1 #define HCL_DEBUG_VM_PROCESSOR 1 diff --git a/lib/hcl-rbt.h b/lib/hcl-rbt.h index 6246c04..51f32a5 100644 --- a/lib/hcl-rbt.h +++ b/lib/hcl-rbt.h @@ -37,9 +37,7 @@ * This sample code adds a series of keys and values and print them * in descending key order. * \code - * #include - * #include - * #include + * #include * * static hcl_rbt_walk_t walk (hcl_rbt_t* rbt, hcl_rbt_pair_t* pair, void* ctx) * { @@ -53,8 +51,8 @@ * hcl_rbt_t* s1; * int i; * - * s1 = hcl_rbt_open (HCL_MMGR_GETDFL(), 0, 1, 1); // error handling skipped - * hcl_rbt_setstyle (s1, hcl_get_rbt_style(HCL_RBT_STYLE_INLINE_COPIERS)); + * s1 = hcl_rbt_open(HCL_MMGR_GETDFL(), 0, 1, 1); // error handling skipped + * hcl_rbt_setstyle(s1, hcl_get_rbt_style(HCL_RBT_STYLE_INLINE_COPIERS)); * * for (i = 0; i < 20; i++) * { diff --git a/lib/hcl-utl.h b/lib/hcl-utl.h index f2d7d43..fee469f 100644 --- a/lib/hcl-utl.h +++ b/lib/hcl-utl.h @@ -288,52 +288,6 @@ #define HCL_HASH_MORE_UCSTR(hv, ptr) HCL_HASH_MORE_VPTR(hv, ptr, const hcl_uch_t) - -/* ========================================================================= - * FORMATTED OUTPUT - * ========================================================================= */ -typedef struct hcl_fmtout_t hcl_fmtout_t; - -typedef int (*hcl_fmtout_putbcs_t) ( - hcl_fmtout_t* fmtout, - const hcl_bch_t* ptr, - hcl_oow_t len -); - -typedef int (*hcl_fmtout_putucs_t) ( - hcl_fmtout_t* fmtout, - const hcl_uch_t* ptr, - hcl_oow_t len -); - -typedef int (*hcl_fmtout_putobj_t) ( - hcl_fmtout_t* fmtout, - hcl_oop_t obj -); - -enum hcl_fmtout_fmt_type_t -{ - HCL_FMTOUT_FMT_TYPE_BCH = 0, - HCL_FMTOUT_FMT_TYPE_UCH -}; -typedef enum hcl_fmtout_fmt_type_t hcl_fmtout_fmt_type_t; - - -struct hcl_fmtout_t -{ - hcl_oow_t count; /* out */ - - hcl_fmtout_putbcs_t putbcs; /* in */ - hcl_fmtout_putucs_t putucs; /* in */ - hcl_fmtout_putobj_t putobj; /* in - %O is not handled if it's not set. */ - hcl_bitmask_t mask; /* in */ - void* ctx; /* in */ - - hcl_fmtout_fmt_type_t fmt_type; - const void* fmt_str; -}; - - #if defined(__cplusplus) extern "C" { #endif @@ -730,34 +684,6 @@ HCL_EXPORT int hcl_ucwidth ( hcl_uch_t uc ); -/* ========================================================================= - * FORMATTED OUTPUT - * ========================================================================= */ -HCL_EXPORT int hcl_bfmt_outv ( - hcl_fmtout_t* fmtout, - const hcl_bch_t* fmt, - va_list ap -); - -HCL_EXPORT int hcl_ufmt_outv ( - hcl_fmtout_t* fmtout, - const hcl_uch_t* fmt, - va_list ap -); - - -HCL_EXPORT int hcl_bfmt_out ( - hcl_fmtout_t* fmtout, - const hcl_bch_t* fmt, - ... -); - -HCL_EXPORT int hcl_ufmt_out ( - hcl_fmtout_t* fmtout, - const hcl_uch_t* fmt, - ... -); - /* ========================================================================= * TIME CALCULATION WITH OVERFLOW/UNDERFLOW DETECTION * ========================================================================= */