Str5 functions
Eric Sanchis
University of Toulouse Capitole
Few functions of the C standard library cumulate as many failures (trapped names, careless design, inconsistent behaviour, ambiguity, failing safety) as the functions dedicated (or supposedly dedicated) to the copy or concatenation of character strings.
The str5cpy() and str5cat() functions are designed to replace the three couples of functions strncpy()/strncat(), strlcpy()/strlcat() and strncpy_s()/strncat_s() dedicated to the copy/concatenation of strings while bringing clearness, consistency, robustness and facility of use which the preceding functions lack more or less.
The central point of the str5cpy() and str5cat() functions is their articulation around 5 parameters (and not 2 or 3) which will enable them to deal with the various checks (sources of many errors when they are not or badly done by the programmer) and which provide a truly significant return value indicating the action actually carried out.
int str5cpy( char * dst,
size_t dstsize,
const char * src,
size_t nb,
size_t mode ) ;
int str5cat( char * dst,
size_t dstsize,
const char * src,
size_t nb,
size_t mode ) ;
The two first parameters characterize the destination buffer:
dst: destination buffer
dstsize: size of the destination buffer
The two following parameters are related to the source string:
src: source string
nb: number of bytes of the source string to be copied/concatenated
The last parameter specifies if truncation is allowed:
mode: truncation allowed (TRUNC) or not allowed (NOTRUNC).
These functions are designed to force programmers to specify what they know (e.g. dstsize) and what they want (e.g. no truncation).
They return:
- a non negative integer after success:
OKNOTRUNC, no truncation was done during the copy/concatenation
OKTRUNC, an allowed truncation was done during the copy/concatenation
- and a negative integer after error:
EDSTPAR, a parameter related to the destination buffer is considered as incorrect
ESRCPAR, a parameter related to the source string is considered as incorrect
EMODPAR, mode is invalid
ETRUNC, dstzise is too small and truncation is not allowed.
The str5cpy() [cf. str5cpy.txt] function copies up to the first nb (not nul) characters from the source string pointed to by src to the destination buffer pointed to by dst and adds a terminating nul byte.
If srclen is the length of the string pointed to by src and srclen is less than nb, str5cpy() only writes the srclen characters of src and an additional nul byte to dst. Consequently, only min(nb,srclen) characters are considered, plus the terminating nul byte.
The copy is actually made if the size dstsize of the destination buffer is large enough (the returned value is OKNOTRUNC) or if the TRUNC mode is chosen (the returned value is OKTRUNC). The size dstsize of the destination buffer dst is large enough if
dstsize ≥ min(srclen,nb)+1
When dstsize is too small and the TRUNC mode is chosen, only dstsize-1 characters are copied and the string is terminated with a nul byte.
The destination buffer remains unchanged if one of these conditions is realized:
- dst is a NULL pointer or dstsize is equal to 0. The returned value is EDSTPAR
- src is a NULL pointer. The returned value is ESRCPAR
- dstsize is too small and the NOTRUNC mode is chosen. The returned value is ETRUNC
- the mode parameter is incorrect. The returned value is EMODPAR.
To sum up, str5cpy() stores a well-formed string into the buffer pointed to by dst and the return value is OKxxx or leaves this buffer unchanged and the return value is Exxx.
Examples
String copy becomes easy. For example, to prevent truncation:
char dst[DSTSIZE] ;
ret = str5cpy(dst,sizeof(dst),src,sizeof(dst),NOTRUNC) ;
switch( ret )
{
case ETRUNC : /* appropriate processing */
. . .
}
Programmers do not need to calculate the length of the src string: they only need to indicate the size of the destination buffer dst as fourth parameter. No extra nul byte will be added.
Or defining the macro strntcpy (nt: no trunc):
#define strntcpy(dst,dstsize,src) str5cpy(dst,dstsize,src,dstsize,NOTRUNC) ;
char dst[DSTSIZE] ;
if ( strntcpy(dst,sizeof(dst),src) < 0 )
{ . . . }
To copy the first n bytes of src:
ret = str5cpy(dst,sizeof(dst),src,n,NOTRUNC) ; /* or TRUNC */
The str5cat() [cf. str5cat.txt] function appends at most the first nb (not nul) bytes from src string to the dst string, overwriting the terminating nul byte of dst, and then adds a terminating nul byte.
Similarly to str5cpy(), str5cat() appends min(nb,srclen) characters of src and an additional nul byte to dst.
The concatenation is actually made if the remaining space in the destination buffer dst is large enough (the returned value is OKNOTRUNC) or if the TRUNC mode is chosen (the returned value is OKTRUNC).
If dstlen is the length of a well-formed string initially memorized into the destination buffer, it is possible to append up to dstsize-dstlen characters (nul byte included) to dst.
Let remain = dstsize-dstlen. The dst destination buffer is large enough if
remain > min(srclen,nb)
When there is not enough space and the TRUNC mode is chosen, only remain-1 characters are appended and the string is terminated with a nul byte.
The destination buffer remains unchanged if one of these conditions is realized:
- dst is a NULL pointer or is a bad-formed string or dstsize is equal to 0. The returned value is EDSTPAR
- src is a NULL pointer. The returned value is ESRCPAR
- the remaining space is too small and the NOTRUNC mode is chosen. The returned value is ETRUNC
- the mode parameter is incorrect. The returned value is EMODPAR
- there is no space left in the destination buffer (the string dst fully occupies the buffer) and the TRUNC mode is chosen. The returned value is OKTRUNC.
Examples
Concatenating string is as simple as copying:
char dst[DSTSIZE] ;
if ( str5cat(dst,sizeof(dst),src,sizeof(dst),TRUNC) == OKTRUNC )
{
/* truncation happened */
}
To concatenate the first n bytes of src:
ret = str5cat(dst,sizeof(dst),src,n,NOTRUNC) ; /* or TRUNC */
The behavior of str5cpy()/str5cat() functions is undefined if:
- dst and src overlap
- dstsize is different to 0 and does not correspond to the actual size of the destination buffer dst.
This document compares different functions with str5cpy()/str5cat().
Source code is here: str5.h , str5cpy.c , str5cat.c