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
This commit is contained in:
hyung-hwan 2018-02-15 08:05:48 +00:00
parent 46a4bd1561
commit 2a0551df2d
6 changed files with 93 additions and 55 deletions

View File

@ -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);

View File

@ -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 */
/* ========================================================================= */

View File

@ -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)

View File

@ -1017,6 +1017,7 @@ struct hcl_t
{
hcl_uch_t* ptr;
hcl_oow_t capa;
hcl_oow_t len;
} xbuf;
struct
{

View File

@ -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;
}

View File

@ -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 */