Replace deprecated luaL_openlib() by luaL_register()
[apps/madmutt.git] / lib-lib / str.h
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or (at
5  *  your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful, but
8  *  WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15  *  MA 02110-1301, USA.
16  *
17  *  Copyright © 2006 Pierre Habouzit
18  */
19 /*
20  * Copyright notice from original mutt:
21  * Copyright (C) 2001 Thomas Roessler <roessler@does-not-exist.org>
22  */
23
24 #ifndef MUTT_LIB_LIB_STR_H
25 #define MUTT_LIB_LIB_STR_H
26
27 /** \defgroup mutt_strings Madmutt string API
28  *
29  * This module contains the prefered string API to be used in Madmutt.
30  *
31  * Those function reimplement many usual calls (strlen, strcpy, strcat, …)
32  * It's intended to provide a uniform and consistent API to deal with usual C
33  * strings.
34  *
35  * The strong point that have to be followed are:
36  *  - strings are always \c \\0 terminated, meaning that we don't have
37  *    stupid semantics à la strncpy.
38  *  - function try to always work on buffers with its size (including the
39  *    ending \c \\0) to prevent buffer overflows.
40  *  - string and buffers sizes are \c ssize_t, negative values are allowed and
41  *    supported.
42  *  - functions use a à la sprintf semantics (for those that produce strings)
43  *    meaning that they all return the len that could have fit in the buffer
44  *    if it would have been big enough. We never try to reallocate the
45  *    buffers, it's up to the caller if it's needed.
46  *
47  * Many of the function do no difference between \c NULL and \c "" and will
48  * behave the same when you pass either the former or the latter (m_strlen(),
49  * m_strcpy(), ... to cite a few).
50  */
51 /*@{*/
52
53 /** \file str.h
54  * \brief Madmutt string API header.
55  * \author Pierre Habouzit <madcoder@debian.org>
56  */
57
58 #define HUGE_STRING     5120   /**< \brief Huge buffers */
59 #define LONG_STRING     1024   /**< \brief Long buffers */
60 #define STRING          256    /**< \brief Usual buffers */
61
62 /** \brief replace \c NULL strings with emtpy strings */
63 #define NONULL(x)       (x ? x : "")
64 /** \brief safe isspace */
65 #define ISSPACE(c)      isspace((unsigned char)c)
66
67 /** \brief Convert ascii digits into ints.
68  *
69  * Convert ascii digits into its integer value in base 36.
70  * Non convertible values are converted to 255.
71  *
72  * Translating a digit \c c into its numerical value in base \c x is just doing:
73  * \code
74  *   return !(c & ~127) && __m_strdigits[c] < x ? __m_strdigits[c] : -1;
75  * \endcode
76  */
77 extern unsigned char const __m_strdigits[128];
78 /** \brief Convert an ascii base64 digit into ints.
79  *
80  * Convert an a char base64 digit into its int value.
81  * Used by base64val(). Unlike #__m_strdigits, the invalid values are set to
82  * -1 instead of 255.
83  */
84 extern signed char const __m_b64digits[128];
85
86 /** \brief Convert ints from 0&ndash;64 into the corresponding base64 digit. */
87 extern char const __m_b64chars[64];
88 /** \brief Convert ints from 0&ndash;36 into a base36 lowercase digit. */
89 extern char const __m_b36chars_lower[36];
90 /** \brief Convert ints from 0&ndash;36 into a base36 uppercase digit. */
91 extern char const __m_b36chars_upper[36];
92
93 /****************************************************************************/
94 /* conversions                                                              */
95 /****************************************************************************/
96
97 /** \brief Converts an octal digit into an int.
98  * \param[in]  c    the octal char
99  * \return
100  *   - 0&ndash;7 if c is a valid octal digit,
101  *   - -1 on error.
102  */
103 static inline int octval(int c) {
104     return !(c & ~127) && __m_strdigits[c] < 7 ? __m_strdigits[c] : -1;
105 }
106
107 /** \brief Converts an hexadecimal digit into an int.
108  * \param[in]  c    the hexadecimal char
109  * \return
110  *   - 0&ndash;15 if c is a valid hexadecimal digit,
111  *   - -1 on error.
112  */
113 static inline int hexval(int c) {
114     return !(c & ~127) && __m_strdigits[c] < 16 ? __m_strdigits[c] : -1;
115 }
116
117 /** \brief Converts a base64 digit into an int.
118  * \param[in]  c    the base64 char
119  * \return
120  *   - 0&ndash;15 if c is a valid base64 digit,
121  *   - -1 on error.
122  */
123 static inline int base64val(int c) {
124     return (c & ~127) ? -1 : __m_b64digits[c];
125 }
126
127 /** \brief Converts a string to lowercase.
128  * \param[in] p     the string, shall not be \c NULL.
129  * \return a pointer to the terminating \c \\0.
130  */
131 __attribute__((nonnull(1)))
132 static inline char *m_strtolower(char *p) {
133     for (; *p; p++)
134         *p = tolower((unsigned char)*p);
135     return p;
136 }
137
138 /** \brief Converts a lower case ascii char to upper case.
139  * \param[in]  c    the character.
140  * \return the upper case character.
141  */
142 static inline int ascii_toupper(int c) {
143     if ('a' <= c && c <= 'z')
144         return c & ~32;
145
146     return c;
147 }
148
149 /** \brief Converts a upper case ascii char to lower case.
150  * \param[in]  c    the character.
151  * \return the lower case character.
152  */
153 static inline int ascii_tolower(int c) {
154     if ('A' <= c && c <= 'Z')
155         return c | 32;
156
157     return c;
158 }
159
160 /****************************************************************************/
161 /* length related                                                           */
162 /****************************************************************************/
163
164 /** \brief Short hand to test if a string is empty or not.
165  * \param[in]  s    the string.
166  * \return \c true iff s is an empty string.
167  */
168 static inline int m_strisempty(const char *s) {
169     return !s || !*s;
170 }
171
172 /** \brief \c NULL resistant strlen.
173  *
174  * Unlinke it's libc sibling, m_strlen returns a ssize_t, and supports its
175  * argument beeing NULL.
176  *
177  * \param[in]  s    the string.
178  * \return the string length (or 0 if \c s is \c NULL).
179  */
180 static inline ssize_t m_strlen(const char *s) {
181     return s ? strlen(s) : 0;
182 }
183
184 /** \brief \c NULL resistant strnlen.
185  *
186  * Unlinke it's GNU libc sibling, m_strnlen returns a ssize_t, and supports
187  * its argument beeing NULL.
188  *
189  * The m_strnlen() function returns the number of characters in the string
190  * pointed to by \c s, not including the terminating \c \\0 character, but at
191  * most \c n. In doing this, m_strnlen() looks only at the first \c n
192  * characters at \c s and never beyond \c s+n.
193  *
194  * \param[in]  s    the string.
195  * \param[in]  n    the maximum length to return.
196  * \return \c m_strlen(s) if less than \c n, else \c n.
197  */
198 static inline ssize_t m_strnlen(const char *s, ssize_t n) {
199     if (s) {
200         const char *p = memchr(s, '\0', n);
201         return p ? p - s : n;
202     }
203     return 0;
204 }
205
206 ssize_t m_strwidth(const char *s);
207
208 /****************************************************************************/
209 /* comparisons                                                              */
210 /****************************************************************************/
211
212 /** \brief Tells whether s begins with p.
213  *
214  * \param[in]  s     the input string
215  * \param[in]  p     the prefix
216  * \param[out] pp    position in s
217  *
218  * \return 1 if a match is found, 0 otherwise.
219  */
220 static inline int m_strstart(const char *s, const char *p, const char **pp)
221 {
222     if (!s)
223         return 0;
224
225     while (*p) {
226         if (ascii_tolower(*s++) != ascii_tolower(*p++))
227             return 0;
228     }
229     if (pp)
230         *pp = s;
231     return 1;
232 }
233
234 /** \brief Tells whether s begins with p, case insensitive.
235  *
236  * \param[in]  s     the input string
237  * \param[in]  p     the prefix
238  * \param[out] pp    position in s
239  *
240  * \return 1 if a match is found, 0 otherwise.
241  */
242 static inline int m_strcasestart(const char *s, const char *p, const char **pp)
243 {
244     if (!s)
245         return 0;
246
247     while (*p) {
248         if (*s++ != *p++)
249             return 0;
250     }
251     if (pp)
252         *pp = s;
253     return 1;
254 }
255
256 /** \brief \c NULL resistant strcmp.
257  * \param[in]  a     the first string.
258  * \param[in]  b     the second string.
259  * \return <tt>strcmp(a, b)</tt>, and treats \c NULL strings like \c "" ones.
260  */
261 static inline int m_strcmp(const char *a, const char *b) {
262     return strcmp(NONULL(a), NONULL(b));
263 }
264
265 /** \brief \c NULL resistant strcasecmp.
266  * \param[in]  a     the first string.
267  * \param[in]  b     the second string.
268  * \return <tt>strcasecmp(a, b)</tt>, and treats \c NULL strings like \c ""
269  * ones.
270  */
271 static inline int m_strcasecmp(const char *a, const char *b) {
272     return strcasecmp(NONULL(a), NONULL(b));
273 }
274
275 /** \brief \c NULL resistant strncmp.
276  * \param[in]  a     the first string.
277  * \param[in]  b     the second string.
278  * \param[in]  n     the number of maximum chars to compare.
279  * \return <tt>strncmp(a, b, n)</tt>, and treats \c NULL strings like \c ""
280  * ones.
281  */
282 static inline int m_strncmp(const char *a, const char *b, ssize_t n) {
283     return strncmp(NONULL(a), NONULL(b), n);
284 }
285
286 /** \brief \c NULL resistant strncasecmp.
287  * \param[in]  a     the first string.
288  * \param[in]  b     the second string.
289  * \param[in]  n     the number of maximum chars to compare.
290  * \return <tt>strcasecmp(a, b, n)</tt>, and treats \c NULL strings like \c ""
291  * ones.
292  */
293 static inline int m_strncasecmp(const char *a, const char *b, ssize_t n) {
294     return strncasecmp(NONULL(a), NONULL(b), n);
295 }
296
297 int ascii_strcasecmp(const char *a, const char *b);
298 int ascii_strncasecmp(const char *a, const char *b, ssize_t n);
299
300 /****************************************************************************/
301 /* making copies                                                            */
302 /****************************************************************************/
303
304 /** \brief \c NULL resistant strdup.
305  *
306  * the m_strdup() function returns a pointer to a new string, which is a
307  * duplicate of \c s. Memory should be freed using p_delete().
308  *
309  * \warning when s is \c "", it returns NULL !
310  *
311  * \param[in]  s    the string to duplicate.
312  * \return a pointer to the duplicated string.
313  */
314 static inline char *m_strdup(const char *s) {
315     ssize_t len = m_strlen(s);
316     return len ? p_dup(s, len + 1) : NULL;
317 }
318
319 /** \brief Duplicate substrings.
320  * \deprecated API IS NOT GOOD, I WILL DEPRECATE IT IN A NEAR FUTURE.
321  */
322 static inline char *m_substrdup(const char *s, const char *end) {
323     return p_dupstr(s, end ? end - s : m_strlen(s));
324 }
325
326 /** \brief Replace an allocated string with another.
327  *
328  * Replace the string pointed by \c *p with a copy of the string \c s.
329  * \c *p must point to a buffer allocated with p_new() or one of its alias.
330  *
331  * \param[in,out]  p    a pointer on a string (<tt>char **</tt>)
332  * \param[in]      s    the string to copy into p.
333  * \return a pointer on the duplicated string (aka \c *p).
334  */
335 __attribute__((nonnull(1)))
336 static inline char *m_strreplace(char **p, const char *s) {
337     p_delete(p);
338     return (*p = m_strdup(s));
339 }
340
341 /** \brief Puts a char in a string buffer.
342  *
343  * Puts a char at position 0 of a string buffer of size \c n.
344  * Then \c \\0 terminate the buffer.
345  *
346  * \param[in]  dst   pointer to the buffer.
347  * \param[in]  n     size of that buffer (negative values allowed).
348  * \param[in]  c     the character to append.
349  * \return always return 1.
350  */
351 __attribute__((nonnull(1)))
352 static inline ssize_t m_strputc(char *dst, ssize_t n, int c) {
353     if (n > 1) {
354         dst[0] = c;
355         dst[1] = '\0';
356     }
357     return 1;
358 }
359
360 /** \brief Sets a portion of a string to a defined character, à la memset.
361  *
362  * \param[in]  dst  pointer to the buffer.
363  * \param[in]  n    size of that buffer, (negative values allowed).
364  * \param[in]  c    the char to use in the padding.
365  * \param[in]  len  length of the padding.
366  * \return MAX(0, len).
367  */
368 __attribute__((nonnull(1)))
369 static inline ssize_t m_strpad(char *dst, ssize_t n, int c, ssize_t len)
370 {
371     ssize_t dlen = MIN(n - 1, len);
372     if (dlen > 0) {
373         memset(dst, c, dlen);
374         dst[dlen] = '\0';
375     }
376     return MAX(0, len);
377 }
378
379 ssize_t m_strcpy(char *dst, ssize_t n, const char *src)
380     __attribute__((nonnull(1)));
381
382 ssize_t m_strncpy(char *dst, ssize_t n, const char *src, ssize_t l)
383     __attribute__((nonnull(1)));
384
385 /** \brief safe strcat.
386  *
387  * The m_strcat() function appends the string \c src at the end of the buffer
388  * \c dst if space is available.
389  *
390  * \param[in]  dst   destination buffer.
391  * \param[in]  n     size of the buffer, Negative sizes are allowed.
392  * \param[in]  src   the string to append.
393  * \return <tt>m_strlen(dst) + m_strlen(src)</tt>
394  */
395 static inline ssize_t m_strcat(char *dst, ssize_t n, const char *src) {
396     ssize_t dlen = m_strnlen(dst, n - 1);
397     return dlen + m_strcpy(dst + dlen, n - dlen, src);
398 }
399
400 /** \brief safe strncat.
401  *
402  * The m_strncat() function appends at most \c n chars from the string \c src
403  * at the end of the buffer \c dst if space is available.
404  *
405  * \param[in]  dst   destination buffer.
406  * \param[in]  n     size of the buffer, Negative sizes are allowed.
407  * \param[in]  src   the string to append.
408  * \param[in]  l     maximum number of chars of src to consider.
409  * \return the smallest value between <tt>m_strlen(dst) + m_strlen(src)</tt>
410  *         and <tt>m_strlen(dst) + l</tt>
411  */
412 static inline ssize_t
413 m_strncat(char *dst, ssize_t n, const char *src, ssize_t l) {
414     ssize_t dlen = m_strnlen(dst, n - 1);
415     return dlen + m_strncpy(dst + dlen, n - dlen, src, l);
416 }
417
418 /* flags for m_strformat() */
419 typedef enum {
420   M_FORMAT_FORCESUBJ   = (1 << 0),  /* print the subject even if unchanged */
421   M_FORMAT_TREE        = (1 << 1),  /* draw the thread tree */
422   M_FORMAT_MAKEPRINT   = (1 << 2),  /* make sure that all chars are printable */
423   M_FORMAT_OPTIONAL    = (1 << 3),
424   M_FORMAT_STAT_FILE   = (1 << 4),  /* used by mutt_attach_fmt */
425   M_FORMAT_INDEX       = (1 << 6),  /* this is a main index entry */
426 } format_flag;
427
428 typedef const char *
429 format_t(char *, ssize_t, char, const char *,
430          const char *, const char *, const char *, anytype, format_flag);
431
432 ssize_t m_strformat(char *, ssize_t, int, const char *,
433                     format_t *, anytype, format_flag);
434
435 /****************************************************************************/
436 /* parsing related                                                          */
437 /****************************************************************************/
438
439 __attribute__((nonnull(1)))
440 static inline const char *m_strchrnul(const char *s, int c) {
441     while (*s && *s != c)
442         s++;
443     return s;
444 }
445
446 __attribute__((nonnull(1)))
447 static inline const char *m_strnextsp(const char *s) {
448     while (*s && !isspace((unsigned char)*s))
449         s++;
450     return s;
451 }
452
453 __attribute__((nonnull(1)))
454 static inline const char *skipspaces(const char *s) {
455     while (isspace((unsigned char)*s))
456         s++;
457     return s;
458 }
459 __attribute__((nonnull(1)))
460 static inline char *vskipspaces(const char *s) {
461     return (char *)skipspaces(s);
462 }
463
464 char *m_strrtrim(char *s);
465
466 /****************************************************************************/
467 /* search                                                                   */
468 /****************************************************************************/
469
470 const char *
471 m_stristrn(const char *haystack, const char *needle, ssize_t nlen);
472
473 static inline const char *
474 m_stristr(const char *haystack, const char *needle) {
475     return m_stristrn(haystack, needle, m_strlen(needle));
476 }
477
478 /*@}*/
479 #endif /* MUTT_LIB_LIB_STR_H */