*** empty log message ***
[dana/urxvt.git] / src / strings.C
1 /*--------------------------------*-C-*---------------------------------*
2  * File:        strings.C
3  *----------------------------------------------------------------------*
4  *
5  * All portions of code are copyright by their respective author/s.
6  * Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com>
7  * Copyright (c) 2004      Marc Lehmann <pcg@goof.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *----------------------------------------------------------------------*/
23
24 #include "../config.h"          /* NECESSARY */
25 #include "rxvt.h"               /* NECESSARY */
26
27 #ifndef NO_STRINGS
28 /*----------------------------------------------------------------------*/
29 /*
30  * a replacement for strcasecmp () to avoid linking an entire library.
31  * Mark Olesen added this in 2.15 but for which OS & library? - Geoff Wing
32  */
33 int
34 strcasecmp (const char *s1, const char *s2)
35 {
36   for ( ; tolower (*s1) == tolower (*s2); s1++, s2++)
37     if (!*s1)
38       return 0;
39   return (int) (tolower (*s1) - tolower (*s2));
40 }
41
42 int
43 strncasecmp (const char *s1, const char *s2, size_t n)
44 {
45   for ( ; n-- && (tolower (*s1) == tolower (*s2)); s1++, s2++)
46     if (!*s1)
47       return 0;
48   if (n == 0)
49     return 0;
50   return (int) (tolower (*s1) - tolower (*s2));
51 }
52
53 char           *
54 strcpy (char *d, const char *s)
55 {
56   char          *r = d;
57
58   for ( ; (*r++ = *s++) != '\0'; ) ;
59   return d;
60 }
61
62 char           *
63 strncpy (char *d, const char *s, size_t len)
64 {
65   char          *r = d;
66
67   if (len)
68     for ( ; len; len--)
69       if ((*r++ = *s++) == '\0')
70         {
71           for ( ; --len; )
72             *r++ = '\0';
73           break;
74         }
75   return d;
76 }
77
78 int
79 strcmp (const char *s1, const char *s2)
80 {
81   for ( ; (*s1 == *s2++); )
82     if (*s1++ == '\0')
83       return 0;
84   return (int) ((unsigned char) *s1 - (unsigned char) *--s2);
85 }
86
87 int
88 strncmp (const char *s1, const char *s2, size_t len)
89 {
90   if (len)
91     {
92       for ( ; len-- && (*s1++ == *s2++); ) ;
93       if (++len)
94         return (int) ((unsigned char) *--s1 - (unsigned char) *--s2);
95     }
96   return 0;
97 }
98
99 char           *
100 strcat (char *s1, const char *s2)
101 {
102   char           *r = s1;
103
104   if (*r != '\0')
105     for ( ; *++r != '\0'; ) ;
106   for ( ; (*r++ = *s2++) != '\0'; ) ;
107
108   return s1;
109 }
110
111 char           *
112 strncat (char *s1, const char *s2, size_t len)
113 {
114   char           *r = s1;
115
116   if (*r != '\0')
117     for ( ; *++r != '\0'; ) ;
118   for ( ; len-- && ((*r++ = *s2++) != '\0'); ) ;
119   *r = '\0';
120
121   return s1;
122 }
123
124 size_t
125 strlen (const char *s)
126 {
127   size_t         len = 0;
128
129   for ( ; *s++ != '\0'; len++) ;
130   return len;
131 }
132
133 char           *
134 strdup (const char *s)
135 {
136   size_t         len = strlen (s) + 1;
137   char          *c;
138
139   if ((c = malloc (len)) != NULL)
140     memcpy (c, s, len);
141   return c;
142 }
143
144 char           *
145 index (const char *s, int c)
146 {
147   return strchr (s, c);
148 }
149
150 char           *
151 strchr (const char *s, int c)
152 {
153   char          *p = NULL;
154
155   for (;;)
156     {
157       if (*s == (char)c)
158         {
159           p = (char *)s;
160           break;
161         }
162       if (*s++ == '\0')
163         break;
164     }
165   return p;
166
167 }
168
169 char           *
170 rindex (const char *s, int c)
171 {
172   return strrchr (s, c);
173 }
174
175 char           *
176 strrchr (const char *s, int c)
177 {
178   char          *p = NULL;
179
180   for (;;)
181     {
182       if (*s == (char)c)
183         p = (char *)s;
184       if (*s++ == '\0')
185         break;
186     }
187   return p;
188 }
189
190 void           *
191 memcpy (void *s1, const void *s2, size_t len)
192 {
193   /* has extra stack and time but less code space */
194   return memmove (s1, s2, len);
195 }
196
197 /*--------------------------------------------------------------------------*
198  * Possibly faster memmove () by Geoff Wing <mason@primenet.com.au>
199  *--------------------------------------------------------------------------*/
200 void           *
201 memmove (void *d, const void *s, size_t len)
202 {
203   u_intp_t        i;
204   unsigned char  *dst = (unsigned char *)d;
205   const unsigned char *src = (const unsigned char *)s;
206
207   if (len && d != s)
208     {
209       if ((u_intp_t)d < (u_intp_t)s)
210         {
211           /* forwards */
212           i = (- (u_intp_t)dst) & (SIZEOF_INT_P - 1);
213           if (len >= 16 && i == ((- (u_intp_t)src) & (SIZEOF_INT_P - 1)))
214             {
215               /* speed up since src & dst are offset correctly */
216               len -= (size_t)i;
217               for ( ; i--; )
218                 *dst++ = *src++;
219               for (i = (u_intp_t) (len / SIZEOF_INT_P); i--; )
220                 * ((u_intp_t *)dst)++ = * ((const u_intp_t *)src)++;
221               len &= (SIZEOF_INT_P - 1);
222             }
223           for ( ; len--; )
224             *dst++ = *src++;
225         }
226       else
227         {
228           /* backwards */
229           dst += len;
230           src += len;
231           i = ((u_intp_t)dst) & (SIZEOF_INT_P - 1);
232           if (len >= 16 && i == (((u_intp_t)src) & (SIZEOF_INT_P - 1)))
233             {
234               /* speed up since src & dst are offset correctly */
235               len -= (size_t)i;
236               for ( ; i--; )
237                 *--dst = *--src;
238               for (i = (u_intp_t) (len / SIZEOF_INT_P); i--; )
239                 *-- ((u_intp_t *)dst) = *-- ((const u_intp_t *)src);
240               len &= (SIZEOF_INT_P - 1);
241             }
242           for ( ; len--; )
243             *--dst = *--src;
244         }
245     }
246   return d;
247 }
248
249 /*--------------------------------------------------------------------------*
250  * Possibly faster memset () by Geoff Wing <mason@primenet.com.au>
251  * presumptions:
252  *   1) intp_t write the best
253  *   2) SIZEOF_INT_P == power of 2
254  *--------------------------------------------------------------------------*/
255
256 void
257 bzero (void *b, size_t len)
258 {
259   memset (b, 0, len);
260 }
261
262 void           *
263 memset (void *p, int c1, size_t len)
264 {
265   u_intp_t        i, val;
266   unsigned char   c = (unsigned char) c1;
267   unsigned char  *lp = (unsigned char *) p;
268
269   if (len)
270     {
271       if (len >= 16)
272         { /* < 16 probably not worth all the calculations */
273           /* write out preceding characters so we align on an integer boundary */
274           if ((i = ((- (u_intp_t)p) & (SIZEOF_INT_P - 1))))
275             {
276               len -= (size_t)i;
277               for (; i--;)
278                 *lp++ = c;
279             }
280
281           /* do the fast writing */
282           val = (c << 8) + c;
283 #if SIZEOF_INT_P >= 4
284           val |= (val << 16);
285 #endif
286 #if SIZEOF_INT_P >= 8
287           val |= (val << 32);
288 #endif
289 #if SIZEOF_INT_P == 16
290           val |= (val << 64);
291 #endif
292           for (i = (u_intp_t) (len / SIZEOF_INT_P); i--;)
293             * ((u_intp_t *)lp)++ = val;
294           len &= (SIZEOF_INT_P - 1);
295         }
296       /* write trailing characters */
297       for (; len--;)
298         *lp++ = c;
299     }
300   return p;
301 }
302 #endif
303 /*----------------------- end-of-file (C source) -----------------------*/