Reload strlist and iplist resource-files only when needed.
[apps/pfixtools.git] / common / str.c
1 /******************************************************************************/
2 /*          pfixtools: a collection of postfix related tools                  */
3 /*          ~~~~~~~~~                                                         */
4 /*  ________________________________________________________________________  */
5 /*                                                                            */
6 /*  Redistribution and use in source and binary forms, with or without        */
7 /*  modification, are permitted provided that the following conditions        */
8 /*  are met:                                                                  */
9 /*                                                                            */
10 /*  1. Redistributions of source code must retain the above copyright         */
11 /*     notice, this list of conditions and the following disclaimer.          */
12 /*  2. Redistributions in binary form must reproduce the above copyright      */
13 /*     notice, this list of conditions and the following disclaimer in the    */
14 /*     documentation and/or other materials provided with the distribution.   */
15 /*  3. The names of its contributors may not be used to endorse or promote    */
16 /*     products derived from this software without specific prior written     */
17 /*     permission.                                                            */
18 /*                                                                            */
19 /*  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND   */
20 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE     */
21 /*  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR        */
22 /*  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS    */
23 /*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR    */
24 /*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF      */
25 /*  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  */
26 /*  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN   */
27 /*  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)   */
28 /*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF    */
29 /*  THE POSSIBILITY OF SUCH DAMAGE.                                           */
30 /******************************************************************************/
31
32 /*
33  * Copyright © 2006 Pierre Habouzit
34  */
35
36 /** \addtogroup mutt_strings */
37 /*@{*/
38
39 /** \file str.c
40  * \brief Madmutt string API module implementation.
41  * \author Pierre Habouzit <madcoder@debian.org>
42  */
43
44 #include "str.h"
45
46 #ifndef __doxygen_skip__
47 #define XX 255
48 unsigned char const __m_strdigits[128] = {
49     XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
50     XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
51     XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
52      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, XX, XX, XX, XX, XX, XX,
53     XX, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
54     25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, XX, XX, XX, XX, XX,
55     XX, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
56     25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, XX, XX, XX, XX, XX,
57 };
58 #undef XX
59
60 #define XX -1
61 signed char const __m_b64digits[128] = {
62     XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
63     XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
64     XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, 62, XX, XX, XX, 63,
65     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, XX, XX, XX, XX, XX, XX,
66     XX,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
67     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, XX, XX, XX, XX, XX,
68     XX, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
69     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, XX, XX, XX, XX, XX
70 };
71 #undef XX
72
73 char const __m_b64chars[64] = {
74     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
75     'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
76     'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
77     't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
78     '8', '9', '+', '/'
79 };
80
81 char const __m_b36chars_lower[36] = {
82     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
83     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
84     'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
85     'u', 'v', 'w', 'x', 'y', 'z'
86 };
87
88 char const __m_b36chars_upper[36] = {
89     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
90     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
91     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
92     'U', 'V', 'W', 'X', 'Y', 'Z'
93 };
94 #endif
95
96 /** \brief safe strcpy.
97  *
98  * Copies at most <tt>n-1</tt> characters from \c src into \c dst, always
99  * adding a final \c \\0 in \c dst.
100  *
101  * \param[in]  dst      destination buffer.
102  * \param[in]  n        size of the buffer. Negative sizes are allowed.
103  * \param[in]  src      source string.
104  *
105  * \return \c src \e length. If this value is \>= \c n then the copy was
106  *         truncated.
107  */
108 ssize_t m_strcpy(char *dst, ssize_t n, const char *src)
109 {
110     ssize_t len = m_strlen(src);
111
112     if (n > 0) {
113         ssize_t dlen = MIN(n - 1, len);
114         memcpy(dst, src, dlen);
115         dst[dlen] = '\0';
116     }
117
118     return len;
119 }
120
121 /** \brief safe limited strcpy.
122  *
123  * Copies at most min(<tt>n-1</tt>, \c l) characters from \c src into \c dst,
124  * always adding a final \c \\0 in \c dst.
125  *
126  * \param[in]  dst      destination buffer.
127  * \param[in]  n        size of the buffer. Negative sizes are allowed.
128  * \param[in]  src      source string.
129  * \param[in]  l        maximum number of chars to copy.
130  *
131  * \return minimum of  \c src \e length and \c l.
132  */
133 ssize_t m_strncpy(char *dst, ssize_t n, const char *src, ssize_t l)
134 {
135     ssize_t len = m_strnlen(src, l);
136
137     if (n > 0) {
138         ssize_t dlen = MIN(n - 1, len);
139         memcpy(dst, src, dlen);
140         dst[dlen] = '\0';
141     }
142
143     return len;
144 }
145
146 char *m_strrtrim(char *s)
147 {
148     ssize_t len = m_strlen(s);
149
150     while (len > 1 && isspace((unsigned char)s[len - 1]))
151         s[--len] = '\0';
152
153     return s + len;
154 }
155
156 const char *m_stristrn(const char *haystack, const char *needle, ssize_t nlen)
157 {
158     int nc;
159
160     if (!nlen)
161         return haystack;
162
163     nc = tolower(*needle);
164     for (;;) {
165         int c = tolower(*haystack);
166
167         if (c != nc) {
168             if (c == '\0')
169                 return NULL;
170         } else {
171             ssize_t i;
172
173             /* compare the rest of needle */
174             for (i = 1;; i++) {
175                 if (i == nlen)
176                     return haystack;
177                 if (c == '\0')
178                     return NULL;
179                 c = tolower(haystack[i]);
180                 if (c != tolower(needle[i]))
181                     break;
182             }
183         }
184
185         haystack++;
186     }
187 }
188
189 /** \brief \c NULL resistant strcasecmp.
190  * \param[in]  a     the first string.
191  * \param[in]  b     the second string.
192  * \return <tt>strcasecmp(a, b)</tt>, and treats \c NULL strings like \c ""
193  *         ones, as if we were in the C locale.
194  */
195 int ascii_strcasecmp(const char *a, const char *b)
196 {
197     if (a == b)
198         return 0;
199     if (!a)
200         return -1;
201     if (!b)
202         return 1;
203
204     while (*a || *b) {
205         int i;
206         if ((i = ascii_tolower(*a++) - ascii_tolower(*b++)))
207             return i;
208     }
209
210     return 0;
211 }
212
213 /** \brief \c NULL resistant strncasecmp.
214  * \param[in]  a     the first string.
215  * \param[in]  b     the second string.
216  * \param[in]  n     the number of maximum chars to compare.
217  * \return <tt>strncasecmp(a, b)</tt>, and treats \c NULL strings like \c ""
218  *         ones, as if we were in the C locale.
219  */
220 int ascii_strncasecmp(const char *a, const char *b, ssize_t n)
221 {
222     if (a == b)
223         return 0;
224     if (!a)
225         return -1;
226     if (!b)
227         return 1;
228
229     while ((*a || *b) && n > 0) {
230         int i;
231         if ((i = ascii_tolower(*a++) - ascii_tolower(*b++)))
232             return i;
233         n--;
234     }
235
236     return 0;
237 }
238
239 /*@}*/