mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-14 21:35:49 +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,20 +13,35 @@
|
|||||||
#define vsnprintf _vsnprintf
|
#define vsnprintf _vsnprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SIZE 4096
|
||||||
|
|
||||||
MR_String
|
MR_String
|
||||||
MR_make_string(MR_Code *proclabel, const char *fmt, ...) {
|
MR_make_string(MR_Code *proclabel, const char *fmt, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
MR_String result;
|
MR_String result;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
#if defined(HAVE_VSNPRINTF) || defined(HAVE__VSNPRINTF)
|
|
||||||
/* Guess that 100 bytes should be sufficient */
|
|
||||||
int size = 100;
|
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
|
#if defined(HAVE_VSNPRINTF) || defined(HAVE__VSNPRINTF)
|
||||||
|
int size = 2 * SIZE;
|
||||||
|
char fixed[SIZE];
|
||||||
|
int dynamically_allocated = FALSE;
|
||||||
|
|
||||||
|
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);
|
p = MR_NEW_ARRAY(char, size);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
dynamically_allocated = TRUE;
|
||||||
|
|
||||||
/* Try to print in the allocated space. */
|
/* Try to print in the allocated space. */
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
n = vsnprintf(p, size, fmt, ap);
|
n = vsnprintf(p, size, fmt, ap);
|
||||||
@@ -46,16 +61,22 @@ MR_make_string(MR_Code *proclabel, const char *fmt, ...) {
|
|||||||
|
|
||||||
MR_RESIZE_ARRAY(p, char, size);
|
MR_RESIZE_ARRAY(p, char, size);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
p = fixed;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
** It is possible for this buffer to overflow and
|
** It is possible for this buffer to overflow and
|
||||||
** then bad things may happen
|
** then bad things may happen
|
||||||
*/
|
*/
|
||||||
char p[40960];
|
char fixed[40960];
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
n = vsprintf(p, fmt, ap);
|
n = vsprintf(fixed, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
p = fixed;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MR_allocate_aligned_string_msg(result, strlen(p),
|
MR_allocate_aligned_string_msg(result, strlen(p),
|
||||||
@@ -63,7 +84,9 @@ MR_make_string(MR_Code *proclabel, const char *fmt, ...) {
|
|||||||
strcpy(result, p);
|
strcpy(result, p);
|
||||||
|
|
||||||
#ifdef HAVE_VSNPRINTF
|
#ifdef HAVE_VSNPRINTF
|
||||||
|
if (dynamically_allocated) {
|
||||||
MR_free(p);
|
MR_free(p);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
Reference in New Issue
Block a user