sprintf into newly mallocated memory block

F

Francois Grieu

Hello,

I'm tring to implement a function that behaves like sprintf,
but returns what it produce into newly mallocated memory block.


I opened ISO/IEC 9899:1999, found

int vsnprintf(char * restrict s, size_t n,
const char * restrict format,
va_list arg);

[note: my purchased copy of the standard has a typo, says vsprintf]

My goal can be achieved using this function: it can be passed NULL
in s and 0 in n, and then will preflight format and arg to determine
the output length, which let us know the size to malloc, then make
a second call to the function this time producing output.

Unfortunately, on many target platform vsnprintf is not implemented.

MS C runtime has _vsnprintf, which does not allow the above
(NULL in s and 0 in n cause a runtime exception).
However it is still usable by iteration: start with some arbitrary
output size likely suitable in the context, try that, if it does
not fit, double the size and try again until it works, finally trim
the block to approriate size. This likely is more efficient, as
most of the time only one parsing occurs.

Any idea for platforms without any form of vsnprintf?

Or any pointer to a compact standard-compliant implementation of the
"printf" parsing gear, which seems a lot of work?


Francois Grieu
 
S

santosh

Francois said:
Hello,

I'm tring to implement a function that behaves like sprintf,
but returns what it produce into newly mallocated memory block.

It's probable that I don't understand your requirements sufficiently,
but, won't a simple wrapper around sprintf() do?
 
F

Francois Grieu

"santosh said:
It's probable that I don't understand your requirements sufficiently,
but, won't a simple wrapper around sprintf() do?

I would like to implement xprintf and be able to use it as

char *x = xprintf(x,"%9999u %s",5,s);
/* here strlen(x) would be strlen(x)+10000 */
free(x);

To implement xprintf using vsprintf, xprintf would need to estimate
a safe size for the malloc size, here at least strlen(x)+10001.


Francois Grieu
 
G

Guest

Francois said:
I would like to implement xprintf and be able to use it as

char *x = xprintf(x,"%9999u %s",5,s);
/* here strlen(x) would be strlen(x)+10000 */
free(x);

You're passing an uninitialised pointer to your xprintf function. There
are two possibilities for a working interface:
1- char *x = xprintf("%9999u %s", 5, s);
2- char *x; xprintf(&x, "%9999u %s", 5, s);
To implement xprintf using vsprintf, xprintf would need to estimate
a safe size for the malloc size, here at least strlen(x)+10001.

You could take a look at GNU's asprintf function, included in gnulib,
which does just this. It's meant to be portable, though not strictly
conforming. If you need it to be, you can probably modify it.

http://savannah.gnu.org/projects/gnulib/

I believe FreeBSD also implements asprintf, so you could also look at
that if you have a problem with GNU's licensing terms.
 
J

Jeffrey Stedfast

Harald said:
You're passing an uninitialised pointer to your xprintf function. There
are two possibilities for a working interface:
1- char *x = xprintf("%9999u %s", 5, s);
2- char *x; xprintf(&x, "%9999u %s", 5, s);


You could take a look at GNU's asprintf function, included in gnulib,
which does just this. It's meant to be portable, though not strictly
conforming. If you need it to be, you can probably modify it.

http://savannah.gnu.org/projects/gnulib/

I believe FreeBSD also implements asprintf, so you could also look at
that if you have a problem with GNU's licensing terms.

There existed a simpler implementation in glib a while back (looks like
current versions just wrap gnulib now):

http://svn.gnome.org/viewcvs/glib/branches/glib-2-2/glib/gstrfuncs.c?view=markup

(this is the latest version I could find before they switched to
wrapping gnulib afaict)

take a look at g_strdup_printf() - the bit to calculate how much memory
you'll need to malloc in order to print the format/args is in
g_printf_string_upper_bound() (you'll see it called in g_strdup_vprintf)

Jeff
 
F

Francois Grieu

"Harald van Dijk said:
You're passing an uninitialised pointer to your xprintf function.

Must be gremlins dancing on keyboard :)
I wanted to write: implement xprintf and be able to use it as
char *x = xprintf("%9999u %s",5,s);
/* here strlen(x) would be strlen(x)+10000 */
free(x);

You could take a look at GNU's asprintf function, included in gnulib,
which does just this. It's meant to be portable, though not strictly
conforming. If you need it to be, you can probably modify it.
http://savannah.gnu.org/projects/gnulib/

Thanks.

Francois Grieu
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top