Merge branch 'upstream' into stable
[gnulib.git] / lib / stpncpy.c
1 /* Copyright (C) 1993, 1995-1997, 2002-2003, 2005-2007 Free Software Foundation, Inc.
2
3    NOTE: The canonical source of this file is maintained with the GNU C Library.
4    Bugs can be reported to bug-glibc@gnu.org.
5
6    This program is free software: you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 3 of the License, or any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19 /* This is almost copied from strncpy.c, written by Torbjorn Granlund.  */
20
21 #include <config.h>
22
23 /* Specification.  */
24 #include <string.h>
25
26 #ifndef weak_alias
27 # define __stpncpy stpncpy
28 #endif
29
30 /* Copy no more than N bytes of SRC to DST, returning a pointer past the
31    last non-NUL byte written into DST.  */
32 char *
33 __stpncpy (char *dest, const char *src, size_t n)
34 {
35   char c;
36   char *s = dest;
37
38   if (n >= 4)
39     {
40       size_t n4 = n >> 2;
41
42       for (;;)
43         {
44           c = *src++;
45           *dest++ = c;
46           if (c == '\0')
47             break;
48           c = *src++;
49           *dest++ = c;
50           if (c == '\0')
51             break;
52           c = *src++;
53           *dest++ = c;
54           if (c == '\0')
55             break;
56           c = *src++;
57           *dest++ = c;
58           if (c == '\0')
59             break;
60           if (--n4 == 0)
61             goto last_chars;
62         }
63       n -= dest - s;
64       goto zero_fill;
65     }
66
67  last_chars:
68   n &= 3;
69   if (n == 0)
70     return dest;
71
72   for (;;)
73     {
74       c = *src++;
75       --n;
76       *dest++ = c;
77       if (c == '\0')
78         break;
79       if (n == 0)
80         return dest;
81     }
82
83  zero_fill:
84   while (n-- > 0)
85     dest[n] = '\0';
86
87   return dest - 1;
88 }
89 #ifdef weak_alias
90 weak_alias (__stpncpy, stpncpy)
91 #endif