mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-12 20:34:19 +00:00
Modify MR_make_string so that it first tries printing into a
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.
This commit is contained in:
@@ -13,49 +13,70 @@
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#define SIZE 4096
|
||||
|
||||
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)
|
||||
/* Guess that 100 bytes should be sufficient */
|
||||
int size = 100;
|
||||
char *p;
|
||||
int size = 2 * SIZE;
|
||||
char fixed[SIZE];
|
||||
int dynamically_allocated = FALSE;
|
||||
|
||||
p = MR_NEW_ARRAY(char, size);
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(fixed, SIZE, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
while (1) {
|
||||
/* Try to print in the allocated space. */
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(p, 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);
|
||||
|
||||
/* If that worked, return the string. */
|
||||
if (n > -1 && n < size) {
|
||||
break;
|
||||
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 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;
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
** It is possible for this buffer to overflow and
|
||||
** then bad things may happen
|
||||
*/
|
||||
char p[40960];
|
||||
char fixed[40960];
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = vsprintf(p, fmt, ap);
|
||||
n = vsprintf(fixed, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
p = fixed;
|
||||
#endif
|
||||
|
||||
MR_allocate_aligned_string_msg(result, strlen(p),
|
||||
@@ -63,7 +84,9 @@ MR_make_string(MR_Code *proclabel, const char *fmt, ...) {
|
||||
strcpy(result, p);
|
||||
|
||||
#ifdef HAVE_VSNPRINTF
|
||||
MR_free(p);
|
||||
if (dynamically_allocated) {
|
||||
MR_free(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user