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:
parent
46a4bd1561
commit
2a0551df2d
81
lib/bigint.c
81
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);
|
||||
|
@ -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 */
|
||||
/* ========================================================================= */
|
||||
|
@ -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)
|
||||
|
@ -1017,6 +1017,7 @@ struct hcl_t
|
||||
{
|
||||
hcl_uch_t* ptr;
|
||||
hcl_oow_t capa;
|
||||
hcl_oow_t len;
|
||||
} xbuf;
|
||||
struct
|
||||
{
|
||||
|
18
lib/print.c
18
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;
|
||||
}
|
||||
|
||||
|
37
lib/read.c
37
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user