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:
		| @ -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 | ||||
| 		{ | ||||
|  | ||||
| @ -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; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
		Reference in New Issue
	
	Block a user