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_liw_t* t = HCL_NULL;
hcl_ooch_t* xbuf = HCL_NULL; hcl_ooch_t* xbuf = HCL_NULL;
hcl_oow_t xlen = 0, seglen, reqcapa; hcl_oow_t xlen = 0, seglen, reqcapa;
hcl_oop_t s;
HCL_ASSERT (hcl, radix >= 2 && radix <= 36); 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) if (v)
{ {
/* Use a static buffer for simple conversion as the largest /* The largest buffer is required for radix 2.
* size is known. The largest buffer is required for radix 2.
* For a binary conversion(radix 2), the number of bits is * For a binary conversion(radix 2), the number of bits is
* the maximum number of digits that can be produced. +1 is * the maximum number of digits that can be produced. +1 is
* needed for the sign. */ * needed for the sign. */
hcl_ooch_t buf[HCL_OOW_BITS + 1];
hcl_oow_t len;
len = oow_to_text(hcl, w, radix, buf); reqcapa = HCL_OOW_BITS + 1;
if (v < 0) buf[len++] = '-'; 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); xlen = oow_to_text(hcl, w, radix, xbuf);
return hcl_makestring(hcl, buf, len, ngc); 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); 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; xlen = as * ((HCL_LIW_BITS + exp) / exp) + 1;
xpos = xlen; 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; reqcapa = HCL_SIZEOF(*xbuf) * xlen;
if (hcl->inttostr.xbuf.capa < reqcapa) 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; xbuf = hcl->inttostr.xbuf.ptr;
} }
#endif
acc = 0; acc = 0;
accbits = 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); HCL_ASSERT (hcl, xpos >= 1);
if (HCL_IS_NBIGINT(hcl, num)) xbuf[--xpos] = '-'; if (HCL_IS_NBIGINT(hcl, num)) xbuf[--xpos] = '-';
s = hcl_makestring(hcl, &xbuf[xpos], xlen - xpos, ngc); if (ngc < 0)
#if 0 {
hcl_freemem (hcl, xbuf); /* special case. don't create a new object.
#endif * the caller can use the data left in hcl->inttostr.xbuf */
return s; 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 */ /* Do it in a hard way for other cases */
/* TODO: migrate these buffers into hcl_t? */
/* TODO: find an optimial buffer size */ /* 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); reqcapa = HCL_SIZEOF(*xbuf) * (as * HCL_LIW_BITS + 1);
if (hcl->inttostr.xbuf.capa < reqcapa) 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; t = hcl->inttostr.t.ptr;
} }
#endif
#if (HCL_LIW_BITS == HCL_OOW_BITS) #if (HCL_LIW_BITS == HCL_OOW_BITS)
b[0] = hcl->bigint[radix].multiplier; /* block divisor */ 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++] = '-'; if (HCL_IS_NBIGINT(hcl, num)) xbuf[xlen++] = '-';
reverse_string (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 return hcl_makestring(hcl, xbuf, xlen, ngc);
hcl_freemem (hcl, t);
hcl_freemem (hcl, xbuf);
#endif
return s;
oops_einval: oops_einval:
hcl_seterrnum (hcl, HCL_EINVAL); hcl_seterrnum (hcl, HCL_EINVAL);

View File

@ -970,6 +970,15 @@ hcl_oop_t hcl_strtoint (
int radix 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_oop_t hcl_inttostr (
hcl_t* hcl, hcl_t* hcl,
hcl_oop_t num, hcl_oop_t num,
@ -977,7 +986,6 @@ hcl_oop_t hcl_inttostr (
int ngc int ngc
); );
/* ========================================================================= */ /* ========================================================================= */
/* print.c */ /* print.c */
/* ========================================================================= */ /* ========================================================================= */

View File

@ -236,6 +236,7 @@ void hcl_fini (hcl_t* hcl)
hcl_freemem (hcl, hcl->inttostr.xbuf.ptr); hcl_freemem (hcl, hcl->inttostr.xbuf.ptr);
hcl->inttostr.xbuf.ptr = HCL_NULL; hcl->inttostr.xbuf.ptr = HCL_NULL;
hcl->inttostr.xbuf.capa = 0; hcl->inttostr.xbuf.capa = 0;
hcl->inttostr.xbuf.len = 0;
} }
if (hcl->inttostr.t.ptr) if (hcl->inttostr.t.ptr)

View File

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

View File

@ -156,18 +156,16 @@ next:
case HCL_BRAND_PBIGINT: case HCL_BRAND_PBIGINT:
case HCL_BRAND_NBIGINT: case HCL_BRAND_NBIGINT:
{ {
hcl_oop_t str; hcl_oop_t tmp;
/* TODO: can i do this without memory allocation? */ /* -1 to drive hcl_inttostr() to not create a new string object.
str = hcl_inttostr(hcl, obj, 10, 1); /* inttostr with ngc on. not using object memory */ * not using the object memory. the result stays in the temporary
if (!str) return -1; * 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_ASSERT (hcl, (hcl_oop_t)tmp == hcl->_nil);
{ if (outbfmt(hcl, mask, "%.*js", hcl->inttostr.xbuf.len, hcl->inttostr.xbuf.ptr) <= -1) return -1;
hcl_freengcobj (hcl, str);
return -1;
}
hcl_freengcobj (hcl, str);
break; break;
} }

View File

@ -195,6 +195,7 @@ static hcl_oop_t string_to_num (hcl_t* hcl, hcl_oocs_t* str, int radixed)
ptr++; ptr++;
} }
#if 0
if (radixed) if (radixed)
{ {
HCL_ASSERT (hcl, ptr < end); 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++; ptr++;
} }
else base = 10; 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 */ /* TODO: handle floating point numbers ... etc */
if (negsign) base = -base; 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) 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)); hcl_setsynerr (hcl, HCL_SYNERR_VBARBANNED, TOKEN_LOC(hcl), TOKEN_NAME(hcl));
return -1; return -1;
} }
if (get_symbol_array_literal (hcl, &obj) <= -1) return -1; if (get_symbol_array_literal(hcl, &obj) <= -1) return -1;
break; break;
case HCL_IOTOK_NIL: case HCL_IOTOK_NIL:
@ -1899,12 +1924,12 @@ static int read_object (hcl_t* hcl)
case HCL_IOTOK_NUMLIT: case HCL_IOTOK_NUMLIT:
case HCL_IOTOK_RADNUMLIT: case HCL_IOTOK_RADNUMLIT:
obj = string_to_num(hcl, TOKEN_NAME(hcl), TOKEN_TYPE(hcl) == HCL_IOTOK_RADNUMLIT); obj = string_to_num(hcl, TOKEN_NAME(hcl), TOKEN_TYPE(hcl) == HCL_IOTOK_RADNUMLIT);
break; break;
/* /*
case HCL_IOTOK_REAL: case HCL_IOTOK_REAL:
obj = hcl_makerealnum (hcl, HCL_IOTOK_RVAL(hcl)); obj = hcl_makerealnum(hcl, HCL_IOTOK_RVAL(hcl));
break; break;
*/ */
@ -1923,7 +1948,7 @@ static int read_object (hcl_t* hcl)
hcl_pfbase_t* pfbase; hcl_pfbase_t* pfbase;
hcl_oop_t prim; 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) if (!pfbase)
{ {
/* TODO switch to syntax error */ /* TODO switch to syntax error */