snprintf.c
- a portable implementation of snprintf,
including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf

snprintf is a routine to convert numeric and string arguments to formatted strings. It is similar to sprintf(3) provided in a system's C library, yet it requires an additional argument - the buffer size - and it guarantees never to store anything beyond the given buffer, regardless of the format or arguments to be formatted. Some newer operating systems do provide snprintf in their C library, but many do not or do provide an inadequate (slow or idiosyncratic) version, which calls for a portable implementation of this routine.

Author

Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
Copyright ©: Mark Martinec

Terms and conditions ...

This program is free software; you can redistribute it and/or modify it under the terms of the Frontier Artistic License which comes with this Kit.

Features

Supported formats and data types

This snprintf only supports format specifiers: s, c, d, o, u, x, X, p (and synonyms: i, D, U, O - see below) with flags: '-', '+', ' ', '0' and '#'. An asterisk is supported for field width as well as precision.

Data type modifiers 'h' (short int), 'l' (long int) and 'll' (long long int) are supported.

NOTE:

If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the data type modifier 'll' is recognized but treated the same as 'l', which may cause argument value truncation! Defining SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also handles data type modifier 'll'. long long int is a language extension which may not be portable.

Conversion of numeric data (formats d, o, u, x, X, p) with data type modifiers (none or h, l, ll) is left to the system routine sprintf, but all handling of flags, field width and precision as well as c and s formats is done very carefully by this portable routine. If a string precision (truncation) is specified (e.g. %.8s) it is guaranteed the string beyond the specified precision will not be referenced.

Data type modifiers h, l and ll are ignored for c and s formats (data types wint_t and wchar_t are not supported).

The following common synonyms for conversion characters are supported:

The following is specifically not supported:

It is permitted for str_m to be zero, and it is permitted to specify NULL pointer for resulting string argument if str_m is zero (as per ISO C9X).

The return value is the number of characters which would be generated for the given input, excluding the trailing null. If this value is greater or equal to str_m, not all characters from the result have been stored in str. If str_m is greater than zero it is guaranteed the resulting string will be null-terminated.

NOTE that this matches the ISO C9X and GNU C library 2.1, but is different from some older implementations!

Routines asprintf and vasprintf return a pointer (in the ptr argument) to a buffer sufficiently large to hold the resulting string. This pointer should be passed to free(3) to release the allocated storage when it is no longer needed. If sufficient space cannot be allocated, these functions will return -1 and set ptr to be a NULL pointer. These two routines are a GNU C library extensions (glibc).

Routines asnprintf and vasnprintf are similar to asprintf and vasprintf, yet, like snprintf and vsnprintf counterparts, will write at most str_m-1 characters into the allocated output string, the last character in the allocated buffer then gets the terminating null. If the formatted string length (the return value) is greater than or equal to the str_m argument, the resulting string was truncated and some of the formatted characters were discarded. These routines present a handy way to limit the amount of allocated memory to some sane value.

Availability

http://www.ijs.si/software/snprintf/

Revision history

Version 1.3 fixes a runaway loop problem from 1.2. Please upgrade.

1999-06-30 V1.3 Mark Martinec <mark.martinec@ijs.si>
- fixed runaway loop (eventually crashing when str_l wraps beyond 2*31) while copying format string without conversion specifiers to a buffer that is too short (thanks to Edwin Young <edwiny@autonomy.com> for spotting the problem);
- added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) to snprintf.h
2000-02-14 V2.0 (never released) Mark Martinec <mark.martinec@ijs.si>
- relaxed license terms: The Artistic License now applies. You may still apply the GNU GENERAL PUBLIC LICENSE as was distributed with previous versions, if you prefer;
- changed REVISION HISTORY dates to use ISO 8601 date format;
- added vsnprintf (patch also independently proposed by Caolán McNamara 2000-05-04, and Keith M Willenson 2000-06-01)
2000-06-27 V2.1 Mark Martinec <mark.martinec@ijs.si>
- removed POSIX check for str_m < 1; value 0 for str_m is allowed by ISO C9X (and GNU C library 2.1) (pointed out on 2000-05-04 by Caolán McNamara, caolan@ csn dot ul dot ie). Besides relaxed license this change in standards adherence is the main reason to bump up the major version number;
- added nonstandard routines asnprintf, vasnprintf, asprintf, vasprintf that dynamically allocate storage for the resulting string; these routines are not compiled by default, see comments where NEED_V?ASN?PRINTF macros are defined;
- autoconf contributed by Caolán McNamara

Other implementations of snprintf

I am aware of some other (more or less) portable implementations of snprintf. I do not claim they are free software - please refer to their respective copyright and licensing terms. If you know of other versions please let me know.

In retrospect, it appears that a lot of effort was wasted by many people for not being aware of what others are doing. Sigh.

Also of interest: The Approved Base Working Group Resolution for XSH5, Ref: bwg98-006, Topic: snprintf.


mm
Last updated: July 18, 2000