Home / strlcpy

strlcpy

strlcpy とそれっぽい実装の比較

まずは本家? OpenBSD の 2004/08/07 のものから。少しスタイルなんかを変えてある。

--- strlcpy.c ---

 1: /*
 2:  * Copy src to string dst of size siz.  At most siz-1 characters
 3:  * will be copied.  Always NUL terminates (unless siz == 0).
 4:  * Returns strlen(src); if retval >= siz, truncation occurred.
 5:  */
 6: size_t
 7: strlcpy(char *dst, const char *src, size_t siz)
 8: {
 9:           char *d = dst;
10:     const char *s = src;
11:     size_t n = siz;
12: 
13:     /* Copy as many bytes as will fit */
14:     if (n != 0 && --n != 0)
15:     {
16:         do
17:         {
18:             if ((*d++ = *s++) == '\0')
19:                 break;
20:         }
21:         while (--n != 0);
22:     }
23: 
24:     /* Not enough room in dst, add NUL and traverse rest of src */
25:     if (n == 0)
26:     {
27:         if (siz != 0)
28:             *d = '\0';     /* NUL-terminate dst */
29:         while (*s++)
30:             continue;
31:     }
32: 
33:     return s - src - 1;    /* count does not include NUL */
34: }

なかなか玄人っぽい実装で、素人目には文字列コピーには見えないかも知れない。
前半(L14〜22)はコピー処理で、ここを抜けるのは n == 0 指定文字数-1だけコピーしたが、元の文字列全てをコピーしていない状況が1つ。その場合、後半(L25〜31)で NUL 終端して元の文字列ポインタをカウントアップし、元の文字数を返す。
 もう1つのケースは、指定サイズより早く(短く)元の文字列が終わっている場合。その場合、元の文字列ポインタは終端まで進み、コピー先も終端されているので、そのまま元の文字数を返す事になる。
 ちょっと気になったのは、サイズに 0 を指定しても元の文字数を返している事。どういう使い方が想定されているか良く判らないが、strlen の代用にはなっているなぁ...



別の実装として、たまたま見かけたのが VLC 0.8.6f の vlc_strlcpy。比較し易いように引数名を strlcpy に合わせて変えたりしている。

--- extras/libc.c ---

363: /**
364:  * Copy a string to a sized buffer. The result is always nul-terminated
365:  * (contrary to strncpy()).
366:  *
367:  * @param dest destination buffer
368:  * @param src string to be copied
369:  * @param len maximum number of characters to be copied plus one for the
370:  * terminating nul.
371:  *
372:  * @return strlen(src)
373:  */
374: #ifndef HAVE_STRLCPY
375: extern size_t vlc_strlcpy (char *dst, const char *src, size_t siz)
376: {
377:     size_t len;
378: 
379:     for (len = 1; (len < siz) && *src; len++)
380:         *dst++ = *src++;
381: 
382:     if (siz)
383:         *dst = '\0';
384: 
385:     while (*src++)
386:         len++;
387: 
388:     return len - 1;
389: }
390: #endif

strlcpy と等価なんだけども随分すっきりして見える。と思ったら意外に難しい動きをする。元の文字数を返す為に len 変数が用いられ、while が常に実行される。巧妙で拡張するには手を入れにくいかも知れない...


こうやって見ると、戻り値は strcpy や strncpy のように dst ポインタを返すのが易しい実装になると思うし、コピー後に strlen(src) が欲しい状況が今ひとつ良く判らないが、適切なバッファサイズか確かめる為かも知れない。

strncpy との比較で言えば、strncpy はコピー先サイズより文字列が短い場合に、残りを 0 で埋めるが、strlcpy はそうはしない。


Home / strlcpy
http://usskim.web.fc2.com/
inserted by FC2 system