jice wrote:
> On 21 fév, 11:46, Ido Yehieli <Ido.Yehi....RemoveThis@gmail.com> wrote:
>>
>> I can imagine you have a line of the sorts of "char buffer[256];"
>> somewhere in your code?
>> If you are using c99 you can take advantage of variable-length arrays:
>>
>> char buffer[snprintf(NULL, 0, your_string)];
>>
>> Or just dynamically allocate if you use c89.
>>
>> -Ido.
>
> To avoid calling vsnprintf twice for each printed string, I'm now
> using a resizable buffer :
>
> static char *TCOD_console_vsprint(const char *fmt, va_list ap) {
> static char *msg=NULL;
> static int buflen=0;
> bool ok=false;
> if (!msg) {
> buflen=512;
> msg=(char *)calloc(sizeof(char),buflen);
> }
> do {
> ok = (vsnprintf(msg,buflen,fmt,ap) != -1);
> if (!ok) {
> buflen*=2;
> free( msg );
> msg=(char *)calloc(sizeof(char),buflen);
> }
> } while (! ok);
> return msg;
> }
The problem with that code is that it doesn't really work with a valid
implementation of vsnprintf. According to the C99 the vsnprintf function
should return "the number of characters that would have been written had
[the buffer size] been sufficiently large, not counting the terminating
null character, or a negative value if an encoding error occurred." (I'm
guessing that an encoding error means invalid fmt string).
At least Microsoft Visual C++ libraries and older versions of glibc
implement the vsnprintf function incorrectly and return a negative value
if the buffer isn't big enough, and your code would work on them, but on
recent versions of glibc and other C libraries that have C99 conforming
vsnprintf your code will fail if the initial 512 chars isn't enough.
Here's a version of the function that should (untested, sorry) also work
with a C99 conforming vsnprintf:
static char *TCOD_console_vsprint(const char *fmt, va_list ap) {
static char *msg=NULL;
static int buflen=0;
int len;
bool ok=false;
if (!msg) {
buflen=512;
msg=(char *)calloc(sizeof(char),buflen);
}
len = vsnprintf(msg,buflen,fmt,ap);
if (len >= buflen) {
// buffer not big enough, glibc
buflen = len + 1; // null char not included in len
msg=(char *)calloc(sizeof(char),buflen);
vsnprintf(msg,buflen,fmt,ap);
return(msg);
} else if (len < 0) {
// buffer not big enough, MSVC
do {
buflen*=2;
free( msg );
msg=(char *)calloc(sizeof(char),buflen);
} while(vsnprintf(msg,buflen,fmt,ap) < 0);
}
return msg;
}
(I tried to imitate your coding style, but if it looks ugly to you, just
reformat it -- provided that it works at all
Hope this helps...
>> Stay informed about: libtcod 1.1 released