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.
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.
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,
17 * Copyright © 2006 Pierre Habouzit
20 * Copyright notice from original mutt:
21 * Copyright (C) 2001 Thomas Roessler <roessler@does-not-exist.org>
24 #ifndef MUTT_LIB_LIB_STR_H
25 #define MUTT_LIB_LIB_STR_H
27 /** \defgroup mutt_strings Madmutt string API
29 * This module contains the prefered string API to be used in Madmutt.
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
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
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.
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).
54 * \brief Madmutt string API header.
55 * \author Pierre Habouzit <madcoder@debian.org>
58 #define HUGE_STRING 5120 /**< \brief Huge buffers */
59 #define LONG_STRING 1024 /**< \brief Long buffers */
60 #define STRING 256 /**< \brief Usual buffers */
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)
67 /** \brief Convert ascii digits into ints.
69 * Convert ascii digits into its integer value in base 36.
70 * Non convertible values are converted to 255.
72 * Translating a digit \c c into its numerical value in base \c x is just doing:
74 * return !(c & ~127) && __m_strdigits[c] < x ? __m_strdigits[c] : -1;
77 extern unsigned char const __m_strdigits[128];
78 /** \brief Convert an ascii base64 digit into ints.
80 * Convert an a char base64 digit into its int value.
81 * Used by base64val(). Unlike #__m_strdigits, the invalid values are set to
84 extern signed char const __m_b64digits[128];
86 /** \brief Convert ints from 0–64 into the corresponding base64 digit. */
87 extern char const __m_b64chars[64];
88 /** \brief Convert ints from 0–36 into a base36 lowercase digit. */
89 extern char const __m_b36chars_lower[36];
90 /** \brief Convert ints from 0–36 into a base36 uppercase digit. */
91 extern char const __m_b36chars_upper[36];
93 /****************************************************************************/
95 /****************************************************************************/
97 /** \brief Converts an octal digit into an int.
98 * \param[in] c the octal char
100 * - 0–7 if c is a valid octal digit,
103 static inline int octval(int c) {
104 return !(c & ~127) && __m_strdigits[c] < 7 ? __m_strdigits[c] : -1;
107 /** \brief Converts an hexadecimal digit into an int.
108 * \param[in] c the hexadecimal char
110 * - 0–15 if c is a valid hexadecimal digit,
113 static inline int hexval(int c) {
114 return !(c & ~127) && __m_strdigits[c] < 16 ? __m_strdigits[c] : -1;
117 /** \brief Converts a base64 digit into an int.
118 * \param[in] c the base64 char
120 * - 0–15 if c is a valid base64 digit,
123 static inline int base64val(int c) {
124 return (c & ~127) ? -1 : __m_b64digits[c];
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.
131 __attribute__((nonnull(1)))
132 static inline char *m_strtolower(char *p) {
134 *p = tolower((unsigned char)*p);
138 /** \brief Converts a lower case ascii char to upper case.
139 * \param[in] c the character.
140 * \return the upper case character.
142 static inline int ascii_toupper(int c) {
143 if ('a' <= c && c <= 'z')
149 /** \brief Converts a upper case ascii char to lower case.
150 * \param[in] c the character.
151 * \return the lower case character.
153 static inline int ascii_tolower(int c) {
154 if ('A' <= c && c <= 'Z')
160 /****************************************************************************/
162 /****************************************************************************/
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.
168 static inline int m_strisempty(const char *s) {
172 /** \brief \c NULL resistant strlen.
174 * Unlinke it's libc sibling, m_strlen returns a ssize_t, and supports its
175 * argument beeing NULL.
177 * \param[in] s the string.
178 * \return the string length (or 0 if \c s is \c NULL).
180 static inline ssize_t m_strlen(const char *s) {
181 return s ? strlen(s) : 0;
184 /** \brief \c NULL resistant strnlen.
186 * Unlinke it's GNU libc sibling, m_strnlen returns a ssize_t, and supports
187 * its argument beeing NULL.
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.
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.
198 static inline ssize_t m_strnlen(const char *s, ssize_t n) {
200 const char *p = memchr(s, '\0', n);
201 return p ? p - s : n;
206 ssize_t m_strwidth(const char *s);
208 /****************************************************************************/
210 /****************************************************************************/
212 /** \brief Tells whether s begins with p.
214 * \param[in] s the input string
215 * \param[in] p the prefix
216 * \param[out] pp position in s
218 * \return 1 if a match is found, 0 otherwise.
220 static inline int m_strstart(const char *s, const char *p, const char **pp)
226 if (ascii_tolower(*s++) != ascii_tolower(*p++))
234 /** \brief Tells whether s begins with p, case insensitive.
236 * \param[in] s the input string
237 * \param[in] p the prefix
238 * \param[out] pp position in s
240 * \return 1 if a match is found, 0 otherwise.
242 static inline int m_strcasestart(const char *s, const char *p, const char **pp)
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.
261 static inline int m_strcmp(const char *a, const char *b) {
262 return strcmp(NONULL(a), NONULL(b));
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 ""
271 static inline int m_strcasecmp(const char *a, const char *b) {
272 return strcasecmp(NONULL(a), NONULL(b));
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 ""
282 static inline int m_strncmp(const char *a, const char *b, ssize_t n) {
283 return strncmp(NONULL(a), NONULL(b), n);
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 ""
293 static inline int m_strncasecmp(const char *a, const char *b, ssize_t n) {
294 return strncasecmp(NONULL(a), NONULL(b), n);
297 int ascii_strcasecmp(const char *a, const char *b);
298 int ascii_strncasecmp(const char *a, const char *b, ssize_t n);
300 /****************************************************************************/
302 /****************************************************************************/
304 /** \brief \c NULL resistant strdup.
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().
309 * \warning when s is \c "", it returns NULL !
311 * \param[in] s the string to duplicate.
312 * \return a pointer to the duplicated string.
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;
319 /** \brief Duplicate substrings.
320 * \deprecated API IS NOT GOOD, I WILL DEPRECATE IT IN A NEAR FUTURE.
322 static inline char *m_substrdup(const char *s, const char *end) {
323 return p_dupstr(s, end ? end - s : m_strlen(s));
326 /** \brief Replace an allocated string with another.
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.
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).
335 __attribute__((nonnull(1)))
336 static inline char *m_strreplace(char **p, const char *s) {
338 return (*p = m_strdup(s));
341 /** \brief Puts a char in a string buffer.
343 * Puts a char at position 0 of a string buffer of size \c n.
344 * Then \c \\0 terminate the buffer.
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.
351 __attribute__((nonnull(1)))
352 static inline ssize_t m_strputc(char *dst, ssize_t n, int c) {
360 /** \brief Sets a portion of a string to a defined character, à la memset.
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).
368 __attribute__((nonnull(1)))
369 static inline ssize_t m_strpad(char *dst, ssize_t n, int c, ssize_t len)
371 ssize_t dlen = MIN(n - 1, len);
373 memset(dst, c, dlen);
379 ssize_t m_strcpy(char *dst, ssize_t n, const char *src)
380 __attribute__((nonnull(1)));
382 ssize_t m_strncpy(char *dst, ssize_t n, const char *src, ssize_t l)
383 __attribute__((nonnull(1)));
385 /** \brief safe strcat.
387 * The m_strcat() function appends the string \c src at the end of the buffer
388 * \c dst if space is available.
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>
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);
400 /** \brief safe strncat.
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.
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>
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);
418 /* flags for m_strformat() */
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 */
429 format_t(char *, ssize_t, char, const char *,
430 const char *, const char *, const char *, anytype, format_flag);
432 ssize_t m_strformat(char *, ssize_t, int, const char *,
433 format_t *, anytype, format_flag);
435 /****************************************************************************/
436 /* parsing related */
437 /****************************************************************************/
439 __attribute__((nonnull(1)))
440 static inline const char *m_strchrnul(const char *s, int c) {
441 while (*s && *s != c)
446 __attribute__((nonnull(1)))
447 static inline const char *m_strnextsp(const char *s) {
448 while (*s && !isspace((unsigned char)*s))
453 __attribute__((nonnull(1)))
454 static inline const char *skipspaces(const char *s) {
455 while (isspace((unsigned char)*s))
459 __attribute__((nonnull(1)))
460 static inline char *vskipspaces(const char *s) {
461 return (char *)skipspaces(s);
464 char *m_strrtrim(char *s);
466 /****************************************************************************/
468 /****************************************************************************/
471 m_stristrn(const char *haystack, const char *needle, ssize_t nlen);
473 static inline const char *
474 m_stristr(const char *haystack, const char *needle) {
475 return m_stristrn(haystack, needle, m_strlen(needle));
479 #endif /* MUTT_LIB_LIB_STR_H */