[m-dev.] diff: MR_make_string improvement

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Aug 17 02:33:39 AEST 2000


On 16-Aug-2000, Peter Ross <peter.ross at miscrit.be> wrote:
> Estimated hours taken: 0.5
> 
> runtime/mercury_string.c:
> 	Modify MR_make_string so that it first tries printing into a
> 	fixed size buffer.  Only if that buffer is not big enough do we
> 	allocate a buffer on the heap.

That looks OK, but there's room for improvement:

> +#define SIZE	4096

It would be better to use a more descriptive name than `SIZE'.

>  MR_String
>  MR_make_string(MR_Code *proclabel, const char *fmt, ...) {
>  	va_list		ap;
>  	MR_String	result;
>  	int 		n;
> +	char		*p;
>  
>  #if defined(HAVE_VSNPRINTF) || defined(HAVE__VSNPRINTF)
> +	int 		size = 2 * SIZE;
> +	char		fixed[SIZE];
> +	int		dynamically_allocated = FALSE;

That variable should have type `bool' rather than int.

> +	va_start(ap, fmt);
> +	n = vsnprintf(fixed, SIZE, fmt, ap);
> +	va_end(ap);
>  
> +	/*
> +	** If that didn't work, use a dynamically allocated array twice
> +	** the size of the fixed array and keep growing the array until
> +	** the string fits.
> +	*/
> +	if (!(n > -1 && n < size)) {
> +		p = MR_NEW_ARRAY(char, size);
> +
> +		while (1) {
> +			dynamically_allocated = TRUE;
> +
> +			/* Try to print in the allocated space. */
> +			va_start(ap, fmt);
> +			n = vsnprintf(p, size, fmt, ap);
> +			va_end(ap);
> +
> +			/* If that worked, return the string.  */
> +			if (n > -1 && n < size) {
> +				break;
> +			}
> +
> +			/* Else try again with more space.  */
> +			if (n > -1) {	/* glibc 2.1 */
> +				size = n + 1; /* precisely what is needed */
> +			} else {	/* glibc 2.0 */
> +				size *= 2;  /* twice the old size */
> +			}
>  
> +			MR_RESIZE_ARRAY(p, char, size);
>  		}
> +	} else {
> +		p = fixed;
>  	}

I think you can do that with a little less code duplication and
somewhat simpler (IMHO) logic:

	/*
	** On the first iteration, we try with a fixed-size buffer.
	** If that didn't work, use a dynamically allocated array twice
	** the size of the fixed array and keep growing the array until
	** the string fits.
	*/
	p = fixed;

	while (1) {
		/* Try to print in the allocated space. */
		va_start(ap, fmt);
		n = vsnprintf(p, size, fmt, ap);
		va_end(ap);

		/* If that worked, return the string.  */
		if (n > -1 && n < size) {
			break;
		}

		/* Else try again with more space.  */
		if (n > -1) {	/* glibc 2.1 */
			size = n + 1; /* precisely what is needed */
		} else {	/* glibc 2.0 */
			size *= 2;  /* twice the old size */
		}

		if (!dynamically_allocated) {
			p = MR_NEW_ARRAY(char, size);
			dynamically_allocated = TRUE;
		} else {
			MR_RESIZE_ARRAY(p, char, size);
		}
	}

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list