From 2a0551df2dd99701828365bca877da73a3631d89 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 15 Feb 2018 08:05:48 +0000 Subject: [PATCH] enhanced hcl_inttostr() to keep results in the temporary buffer when ngc is negative. changed the integer printing function to utilize this change in print.c --- lib/bigint.c | 81 +++++++++++++++++++++++++++------------------------ lib/hcl-prv.h | 10 ++++++- lib/hcl.c | 1 + lib/hcl.h | 1 + lib/print.c | 18 +++++------- lib/read.c | 37 +++++++++++++++++++---- 6 files changed, 93 insertions(+), 55 deletions(-) diff --git a/lib/bigint.c b/lib/bigint.c index d25cd50..afd6dec 100644 --- a/lib/bigint.c +++ b/lib/bigint.c @@ -3954,7 +3954,6 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int radix, int ngc) hcl_liw_t* t = HCL_NULL; hcl_ooch_t* xbuf = HCL_NULL; hcl_oow_t xlen = 0, seglen, reqcapa; - hcl_oop_t s; HCL_ASSERT (hcl, radix >= 2 && radix <= 36); @@ -3963,19 +3962,36 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int radix, int ngc) if (v) { - /* Use a static buffer for simple conversion as the largest - * size is known. The largest buffer is required for radix 2. + /* The largest buffer is required for radix 2. * For a binary conversion(radix 2), the number of bits is * the maximum number of digits that can be produced. +1 is * needed for the sign. */ - hcl_ooch_t buf[HCL_OOW_BITS + 1]; - hcl_oow_t len; - len = oow_to_text(hcl, w, radix, buf); - if (v < 0) buf[len++] = '-'; + reqcapa = HCL_OOW_BITS + 1; + if (hcl->inttostr.xbuf.capa < reqcapa) + { + xbuf = (hcl_ooch_t*)hcl_reallocmem(hcl, hcl->inttostr.xbuf.ptr, reqcapa); + if (!xbuf) return HCL_NULL; + hcl->inttostr.xbuf.capa = reqcapa; + hcl->inttostr.xbuf.ptr = xbuf; + } + else + { + xbuf = hcl->inttostr.xbuf.ptr; + } - reverse_string (buf, len); - return hcl_makestring(hcl, buf, len, ngc); + xlen = oow_to_text(hcl, w, radix, xbuf); + if (v < 0) xbuf[xlen++] = '-'; + + reverse_string (xbuf, xlen); + if (ngc < 0) + { + /* special case. don't create a new object. + * the caller can use the data left in hcl->inttostr.xbuf */ + hcl->inttostr.xbuf.len = xlen; + return hcl->_nil; + } + return hcl_makestring(hcl, xbuf, xlen, ngc); } as = HCL_OBJ_GET_SIZE(num); @@ -3990,10 +4006,6 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int radix, int ngc) xlen = as * ((HCL_LIW_BITS + exp) / exp) + 1; xpos = xlen; -#if 0 - xbuf = (hcl_ooch_t*)hcl_allocmem(hcl, HCL_SIZEOF(*xbuf) * xlen); - if (!xbuf) return HCL_NULL; -#else reqcapa = HCL_SIZEOF(*xbuf) * xlen; if (hcl->inttostr.xbuf.capa < reqcapa) { @@ -4006,7 +4018,6 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int radix, int ngc) { xbuf = hcl->inttostr.xbuf.ptr; } -#endif acc = 0; accbits = 0; @@ -4038,27 +4049,20 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int radix, int ngc) HCL_ASSERT (hcl, xpos >= 1); if (HCL_IS_NBIGINT(hcl, num)) xbuf[--xpos] = '-'; - s = hcl_makestring(hcl, &xbuf[xpos], xlen - xpos, ngc); -#if 0 - hcl_freemem (hcl, xbuf); -#endif - return s; + if (ngc < 0) + { + /* special case. don't create a new object. + * the caller can use the data left in hcl->inttostr.xbuf */ + HCL_MEMMOVE (&xbuf[0], &xbuf[xpos], HCL_SIZEOF(*xbuf) * (xlen - xpos)); + hcl->inttostr.xbuf.len = xlen - xpos; + return hcl->_nil; + } + + return hcl_makestring(hcl, &xbuf[xpos], xlen - xpos, ngc); } /* Do it in a hard way for other cases */ -/* TODO: migrate these buffers into hcl_t? */ /* TODO: find an optimial buffer size */ -#if 0 - xbuf = (hcl_ooch_t*)hcl_allocmem (hcl, HCL_SIZEOF(*xbuf) * (as * HCL_LIW_BITS + 1)); - if (!xbuf) return HCL_NULL; - - t = (hcl_liw_t*)hcl_callocmem(hcl, HCL_SIZEOF(*t) * as * 3); - if (!t) - { - hcl_freemem (hcl, xbuf); - return HCL_NULL; - } -#else reqcapa = HCL_SIZEOF(*xbuf) * (as * HCL_LIW_BITS + 1); if (hcl->inttostr.xbuf.capa < reqcapa) { @@ -4084,7 +4088,6 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int radix, int ngc) { t = hcl->inttostr.t.ptr; } -#endif #if (HCL_LIW_BITS == HCL_OOW_BITS) b[0] = hcl->bigint[radix].multiplier; /* block divisor */ @@ -4157,13 +4160,15 @@ hcl_oop_t hcl_inttostr (hcl_t* hcl, hcl_oop_t num, int radix, int ngc) if (HCL_IS_NBIGINT(hcl, num)) xbuf[xlen++] = '-'; reverse_string (xbuf, xlen); - s = hcl_makestring(hcl, xbuf, xlen, ngc); + if (ngc < 0) + { + /* special case. don't create a new object. + * the caller can use the data left in hcl->inttostr.xbuf */ + hcl->inttostr.xbuf.len = xlen; + return hcl->_nil; + } -#if 0 - hcl_freemem (hcl, t); - hcl_freemem (hcl, xbuf); -#endif - return s; + return hcl_makestring(hcl, xbuf, xlen, ngc); oops_einval: hcl_seterrnum (hcl, HCL_EINVAL); diff --git a/lib/hcl-prv.h b/lib/hcl-prv.h index 77a254c..d200b4e 100644 --- a/lib/hcl-prv.h +++ b/lib/hcl-prv.h @@ -970,6 +970,15 @@ hcl_oop_t hcl_strtoint ( int radix ); +/** + * The hcl_inttostr() function converts an integer object to a string object + * printed in the given radix. If ngc is 0, it creates a normal string object + * managed by object memory manager. If ngc greater than 0, it creates a non-GC + * string object that should be destroyed with hcl_freengcobj() later. If ngc + * is less than 0, it returns hcl->_nil but keeps the result in the buffer + * pointed to by hcl->inttostr.xbuf.ptr with the length stored in + * hcl->inttostr.xbuf.len. If the function fails, it returns #HCL_NULL. + */ hcl_oop_t hcl_inttostr ( hcl_t* hcl, hcl_oop_t num, @@ -977,7 +986,6 @@ hcl_oop_t hcl_inttostr ( int ngc ); - /* ========================================================================= */ /* print.c */ /* ========================================================================= */ diff --git a/lib/hcl.c b/lib/hcl.c index 7fbf508..c9e5c4f 100644 --- a/lib/hcl.c +++ b/lib/hcl.c @@ -236,6 +236,7 @@ void hcl_fini (hcl_t* hcl) hcl_freemem (hcl, hcl->inttostr.xbuf.ptr); hcl->inttostr.xbuf.ptr = HCL_NULL; hcl->inttostr.xbuf.capa = 0; + hcl->inttostr.xbuf.len = 0; } if (hcl->inttostr.t.ptr) diff --git a/lib/hcl.h b/lib/hcl.h index 0a6ad01..2da638c 100644 --- a/lib/hcl.h +++ b/lib/hcl.h @@ -1017,6 +1017,7 @@ struct hcl_t { hcl_uch_t* ptr; hcl_oow_t capa; + hcl_oow_t len; } xbuf; struct { diff --git a/lib/print.c b/lib/print.c index f9bac36..7f35056 100644 --- a/lib/print.c +++ b/lib/print.c @@ -156,18 +156,16 @@ next: case HCL_BRAND_PBIGINT: case HCL_BRAND_NBIGINT: { - hcl_oop_t str; + hcl_oop_t tmp; - /* TODO: can i do this without memory allocation? */ - str = hcl_inttostr(hcl, obj, 10, 1); /* inttostr with ngc on. not using object memory */ - if (!str) return -1; + /* -1 to drive hcl_inttostr() to not create a new string object. + * not using the object memory. the result stays in the temporary + * buffer */ + tmp = hcl_inttostr(hcl, obj, 10, -1); + if (!tmp) return -1; - if (outbfmt(hcl, mask, "%.*js", HCL_OBJ_GET_SIZE(str), HCL_OBJ_GET_CHAR_SLOT(str)) <= -1) - { - hcl_freengcobj (hcl, str); - return -1; - } - hcl_freengcobj (hcl, str); + HCL_ASSERT (hcl, (hcl_oop_t)tmp == hcl->_nil); + if (outbfmt(hcl, mask, "%.*js", hcl->inttostr.xbuf.len, hcl->inttostr.xbuf.ptr) <= -1) return -1; break; } diff --git a/lib/read.c b/lib/read.c index 7d23517..ed71855 100644 --- a/lib/read.c +++ b/lib/read.c @@ -195,6 +195,7 @@ static hcl_oop_t string_to_num (hcl_t* hcl, hcl_oocs_t* str, int radixed) ptr++; } +#if 0 if (radixed) { HCL_ASSERT (hcl, ptr < end); @@ -210,10 +211,34 @@ static hcl_oop_t string_to_num (hcl_t* hcl, hcl_oocs_t* str, int radixed) ptr++; } else base = 10; +#else + if (radixed) + { + HCL_ASSERT (hcl, ptr < end); + + if (*ptr != '#') + { + hcl_seterrnum (hcl, HCL_EINVAL); + return -1; + } + ptr++; /* skip '#' */ + + if (*ptr == 'x') base = 16; + else if (*ptr == 'o') base = 8; + else if (*ptr == 'b') base = 2; + else + { + hcl_seterrnum (hcl, HCL_EINVAL); + return -1; + } + ptr++; + } + else base = 10; +#endif /* TODO: handle floating point numbers ... etc */ if (negsign) base = -base; - return hcl_strtoint (hcl, ptr, end - ptr, base); + return hcl_strtoint(hcl, ptr, end - ptr, base); } static HCL_INLINE int is_spacechar (hcl_ooci_t c) { @@ -1878,7 +1903,7 @@ static int read_object (hcl_t* hcl) hcl_setsynerr (hcl, HCL_SYNERR_VBARBANNED, TOKEN_LOC(hcl), TOKEN_NAME(hcl)); return -1; } - if (get_symbol_array_literal (hcl, &obj) <= -1) return -1; + if (get_symbol_array_literal(hcl, &obj) <= -1) return -1; break; case HCL_IOTOK_NIL: @@ -1899,12 +1924,12 @@ static int read_object (hcl_t* hcl) case HCL_IOTOK_NUMLIT: case HCL_IOTOK_RADNUMLIT: - obj = string_to_num(hcl, TOKEN_NAME(hcl), TOKEN_TYPE(hcl) == HCL_IOTOK_RADNUMLIT); - break; + obj = string_to_num(hcl, TOKEN_NAME(hcl), TOKEN_TYPE(hcl) == HCL_IOTOK_RADNUMLIT); + break; /* case HCL_IOTOK_REAL: - obj = hcl_makerealnum (hcl, HCL_IOTOK_RVAL(hcl)); + obj = hcl_makerealnum(hcl, HCL_IOTOK_RVAL(hcl)); break; */ @@ -1923,7 +1948,7 @@ static int read_object (hcl_t* hcl) hcl_pfbase_t* pfbase; hcl_oop_t prim; - pfbase = hcl_querymod (hcl, TOKEN_NAME_PTR(hcl), TOKEN_NAME_LEN(hcl)); + pfbase = hcl_querymod(hcl, TOKEN_NAME_PTR(hcl), TOKEN_NAME_LEN(hcl)); if (!pfbase) { /* TODO switch to syntax error */