[m-dev.] diff: MR_make_string improvement

Peter Ross peter.ross at miscrit.be
Thu Aug 17 02:47:58 AEST 2000


On Thu, Aug 17, 2000 at 02:33:39AM +1000, Fergus Henderson wrote:
> 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);
> 		}
> 	}
> 

===================================================================


Estimated hours taken: 0.1

runtime/mercury_string.c:
	Simplify the logic of MR_make_string as suggested by Fergus
	Henderson <fjh at cs.mu.oz.au>.


Index: mercury_string.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_string.c,v
retrieving revision 1.6
diff -u -r1.6 mercury_string.c
--- mercury_string.c	2000/08/16 16:02:21	1.6
+++ mercury_string.c	2000/08/16 16:45:58
@@ -13,7 +13,7 @@
   #define vsnprintf	_vsnprintf
 #endif
 
-#define SIZE	4096
+#define BUFFER_SIZE	4096
 
 MR_String
 MR_make_string(MR_Code *proclabel, const char *fmt, ...) {
@@ -23,46 +23,42 @@
 	char		*p;
 
 #if defined(HAVE_VSNPRINTF) || defined(HAVE__VSNPRINTF)
-	int 		size = 2 * SIZE;
-	char		fixed[SIZE];
-	int		dynamically_allocated = FALSE;
+	int 		size = 2 * BUFFER_SIZE;
+	char		fixed[BUFFER_SIZE];
+	bool		dynamically_allocated = FALSE;
 	
-	va_start(ap, fmt);
-	n = vsnprintf(fixed, SIZE, fmt, ap);
-	va_end(ap);
-
 	/*
+	** 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.
 	*/
-	if (!(n > -1 && n < size)) {
-		p = MR_NEW_ARRAY(char, size);
+	p = fixed;
 
-		while (1) {
-			dynamically_allocated = TRUE;
+	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;
+		}
 
-			/* 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 */
-			}
+		/* 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);
 		}
-	} else {
-		p = fixed;
 	}
 
 #else

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