Spherical forums

Creations => Programming => Topic started by: Fat Cerberus on February 12, 2016, 01:45:14 pm

Title: strnewf(): malloc + sprintf in one
Post by: Fat Cerberus on February 12, 2016, 01:45:14 pm
While working on SSJ, I wrote the following function:
Code: (c) [Select]
char*
strnewf(const char* fmt, ...)
{
va_list ap, apc;
char* buffer;
int   buf_size;

va_start(ap, fmt);
va_copy(apc, ap);
buf_size = vsnprintf(NULL, 0, fmt, apc) + 1;
va_end(apc);
buffer = malloc(buf_size);
va_copy(apc, ap);
vsnprintf(buffer, buf_size, fmt, apc);
va_end(apc);
va_end(ap);
return buffer;
}


Usage:
Code: (c) [Select]
char* string = strnewf("%s ate %d pigs", "maggie", 812);
/* do stuff with string... */
free(string);


It's quite useful when you need a formatted string on-the-fly but don't want to have to guess at the correct buffer size and risk a buffer overflow.
Title: Re: strnewf(): malloc + sprintf in one
Post by: Flying Jester on February 12, 2016, 04:43:46 pm
Isn't this already what `asprintf` does?
Title: Re: strnewf(): malloc + sprintf in one
Post by: Fat Cerberus on February 12, 2016, 05:09:03 pm
Huh, I never heard of asprintf before!  It looks like it's GNU-only though, it's not even a POSIX function (like strdup is).
Title: Re: strnewf(): malloc + sprintf in one
Post by: Flying Jester on February 12, 2016, 06:30:50 pm
BSD has an implementation, too, and I think there is a musl one as well.

I tend to take non-standard things like that and strcasecmp and the like from the BSD libc. Each file corresponds to one function or one small family of functions, and doesn't require many (if any) other files to work.
Title: Re: strnewf(): malloc + sprintf in one
Post by: Fat Cerberus on February 12, 2016, 07:13:42 pm
strcasecmp was at least easy to get in MSVC:
Code: (c) [Select]
#define strcasecmp stricmp


Same goes for strtok_r vs. strtok_s and a few other POSIX functions, they usually have reasonable drop-in replacements in the MS CRT.  asprintf is an exception though, MSVC has no equivalent to that as far as I'm aware.

Nice to see I reinvented the wheel without even intending to. :P