Mail Archives: djgpp-workers/2003/05/10/11:40:56
I don't know if these are planned for inclusion in 2.04 - I
recommend they be. At any rate, following is my implementation of
them, with a built in regression test by using -dTESTING. The
strlcpy code is a bit tricky and minimized.
They are also available as a package at:
<http://cbfalconer.home.att.net/download/>
/* ------- file strlcpy.h ------- */
#ifndef strlcpy_h_
#define strlcpy_h_
#ifdef __cplusplus
extern "C" {
#endif
/* Implementation of strlcpy and strlcat
See http://www.courtesan.com/todd/papers/strlcpy.html
These routines are explicitly designed to move no
data and simply return the projected size of the
final strings when called with sz == 0.
In addition they treat src == NULL as an empty string
strlcat expects that the sz parameter is greater than
the size of the dst string. If not, the treatment is
exactly the same as if a sz value of 0 was used.
NOTE: these routines are deliberately designed to
not require any assistance from the standard
libraries. This makes them more useful in any
embedded systems that must minimize the load size.
Public domain, by C.B. Falconer
bug reports to mailto:cbfalconer AT worldnet DOT att DOT net
*/
#include <stddef.h>
size_t strlcpy(char *dst, const char *src, size_t sz);
size_t strlcat(char *dst, const char *src, size_t sz);
#ifdef __cplusplus
}
#endif
#endif
/* ------- End file strlcpy.h ------- */
/* ------- file strlcpy.c ------- */
/* Implementation of strlcpy and strlcat
See http://www.courtesan.com/todd/papers/strlcpy.html
These routines are explicitly designed to move no
data and simply return the projected size of the
final strings when called with sz == 0.
In addition they treat src == NULL as an empty string
strlcat expects that the sz parameter is greater than
the size of the dst string. If not, the treatment is
exactly the same as if a sz value of 0 was used.
*/
#include "strlcpy.h"
/* NOTE: these routines are deliberately designed to
not require any assistance from the standard
libraries. This makes them more useful in any
embedded systems that must minimize the load size.
Public domain, by C.B. Falconer
bug reports to mailto:cbfalconer AT worldnet DOT att DOT net
*/
/* ---------------------- */
size_t strlcpy(char *dst, const char *src, size_t sz)
{
const char *start = src;
if (src && sz--) {
while ((*dst++ = *src))
if (sz--) src++;
else {
*(--dst) = '\0';
break;
}
}
if (src) {
while (*src++) continue;
return src - start - 1;
}
else if (sz) *dst = '\0';
return 0;
} /* strlcpy */
/* ---------------------- */
size_t strlcat(char *dst, const char *src, size_t sz)
{
char *start = dst;
while (*dst++) /* assumes sz >= strlen(dst) */
if (sz) sz--; /* i.e. well formed string */
dst--;
return dst - start + strlcpy(dst, src, sz);
} /* strlcat */
/* ---------------------- */
#ifdef TESTING
#include <stdio.h>
typedef size_t (*op)(char *, const char *, size_t);
#define FLD 16
/* ---------------------- */
static void putleftinfld(const char *str, int field, int quote)
{
int used;
static const char *nullstr = "(NULL)";
if (!str) str = nullstr;
if (quote) used = printf("\"%s\"", str);
else used = printf("%s", str);
while (used++ < field) putchar(' ');
} /* putleftinfld */
/* ---------------------- */
static void dotest(op fn, char *s1, char *s2, size_t sz)
{
unsigned long lgh;
putleftinfld(s1, FLD, 1); putleftinfld(s2, FLD, 1);
if (fn == strlcat) printf(" cat ");
else if (fn == strlcpy) printf(" cpy ");
else printf(" ??? ");
lgh = fn(s1, s2, sz);
printf("%3lu %3lu \"%s\"\n", (unsigned long)sz, lgh, s1);
} /* dotest */
/* ---------------------- */
int main(void)
{
char *str1 = "string1";
char str2[10] = "";
char str3[5] = "";
char str4[] = "";
puts("Testing lgh = stringop(dest, source, sz)\n");
putleftinfld(" dest", FLD, 0);
putleftinfld(" source", FLD, 0);
puts(" opn sz lgh result");
putleftinfld(" ====", FLD, 0);
putleftinfld(" ======", FLD, 0);
puts(" === == === ======");
dotest(strlcpy, str2, str1, sizeof str2);
dotest(strlcpy, str3, str1, sizeof str3);
dotest(strlcpy, str4, str1, sizeof str4);
dotest(strlcat, str2, str1, sizeof str2);
dotest(strlcpy, str2, "x ", sizeof str2);
dotest(strlcat, str2, str1, sizeof str2);
dotest(strlcpy, str2, "x ", sizeof str2);
dotest(strlcat, str2, str1, 0);
dotest(strlcpy, str2, str1, 0);
dotest(strlcat, str2, "longer string", 0);
dotest(strlcpy, str2, NULL, sizeof str2);
dotest(strlcpy, str2, "x ", sizeof str2);
dotest(strlcat, str2, NULL, sizeof str2);
return 0;
} /* main */
#endif
/* ------- End file strlcpy.c ------- */
And the regression test results:
Testing lgh = stringop(dest, source, sz)
dest source opn sz lgh result
==== ====== === == === ======
"" "string1" cpy 10 7 "string1"
"" "string1" cpy 5 7 "stri"
"" "string1" cpy 1 7 ""
"string1" "string1" cat 10 14 "string1st"
"string1st" "x " cpy 10 2 "x "
"x " "string1" cat 10 9 "x string1"
"x string1" "x " cpy 10 2 "x "
"x " "string1" cat 0 9 "x "
"x " "string1" cpy 0 7 "x "
"x " "longer string" cat 0 15 "x "
"x " "(NULL)" cpy 10 0 ""
"" "x " cpy 10 2 "x "
"x " "(NULL)" cat 10 2 "x "
--
Chuck F (cbfalconer AT yahoo DOT com) (cbfalconer AT worldnet DOT att DOT net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
- Raw text -