NeoMutt  2018-07-16 +2481-68dcde
Teaching an old dog new tricks
DOXYGEN
string.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <ctype.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include <stdarg.h>
35 #include <stdbool.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <strings.h>
40 #include "exit.h"
41 #include "logging.h"
42 #include "memory.h"
43 #include "message.h"
44 #include "string2.h"
45 #ifdef HAVE_SYSEXITS_H
46 #include <sysexits.h>
47 #endif
48 
52 struct SysExits
53 {
54  int err_num;
55  const char *err_str;
56 };
57 
58 static const struct SysExits sysexits[] = {
59 #ifdef EX_USAGE
60  { 0xff & EX_USAGE, "Bad usage." },
61 #endif
62 #ifdef EX_DATAERR
63  { 0xff & EX_DATAERR, "Data format error." },
64 #endif
65 #ifdef EX_NOINPUT
66  { 0xff & EX_NOINPUT, "Can't open input." },
67 #endif
68 #ifdef EX_NOUSER
69  { 0xff & EX_NOUSER, "User unknown." },
70 #endif
71 #ifdef EX_NOHOST
72  { 0xff & EX_NOHOST, "Host unknown." },
73 #endif
74 #ifdef EX_UNAVAILABLE
75  { 0xff & EX_UNAVAILABLE, "Service unavailable." },
76 #endif
77 #ifdef EX_SOFTWARE
78  { 0xff & EX_SOFTWARE, "Internal error." },
79 #endif
80 #ifdef EX_OSERR
81  { 0xff & EX_OSERR, "Operating system error." },
82 #endif
83 #ifdef EX_OSFILE
84  { 0xff & EX_OSFILE, "System file missing." },
85 #endif
86 #ifdef EX_CANTCREAT
87  { 0xff & EX_CANTCREAT, "Can't create output." },
88 #endif
89 #ifdef EX_IOERR
90  { 0xff & EX_IOERR, "I/O error." },
91 #endif
92 #ifdef EX_TEMPFAIL
93  { 0xff & EX_TEMPFAIL, "Deferred." },
94 #endif
95 #ifdef EX_PROTOCOL
96  { 0xff & EX_PROTOCOL, "Remote protocol error." },
97 #endif
98 #ifdef EX_NOPERM
99  { 0xff & EX_NOPERM, "Insufficient permission." },
100 #endif
101 #ifdef EX_CONFIG
102  { 0xff & EX_NOPERM, "Local configuration error." },
103 #endif
104  { S_ERR, "Exec error." },
105 };
106 
112 const char *mutt_str_sysexit(int err_num)
113 {
114  for (size_t i = 0; i < mutt_array_size(sysexits); i++)
115  {
116  if (err_num == sysexits[i].err_num)
117  return sysexits[i].err_str;
118  }
119 
120  return NULL;
121 }
122 
129 static inline bool char_cmp_identity(char a, char b)
130 {
131  return a == b;
132 }
133 
140 static inline bool char_cmp_lower(char a, char b)
141 {
142  return tolower((unsigned char) a) == tolower((unsigned char) b);
143 }
144 
148 typedef bool (*char_cmp)(char, char);
149 
156 {
157  return (cs == CASE_IGNORE) ? char_cmp_lower : char_cmp_identity;
158 }
159 
168 size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
169 {
170  if (!str || (str[0] == '\0') || !prefix || (prefix[0] == '\0'))
171  {
172  return 0;
173  }
174 
175  const char *saved_prefix = prefix;
176  for (char_cmp fn = get_char_cmp(cs); *str && *prefix; str++, prefix++)
177  {
178  if (!fn(*str, *prefix))
179  {
180  return 0;
181  }
182  }
183 
184  return (!*prefix) ? prefix - saved_prefix : 0;
185 }
186 
198 int mutt_str_atol(const char *str, long *dst)
199 {
200  if (dst)
201  *dst = 0;
202 
203  if (!str || !*str) /* no input: 0 */
204  return 0;
205 
206  char *e = NULL;
207  errno = 0;
208 
209  long res = strtol(str, &e, 10);
210  if (dst)
211  *dst = res;
212  if (((res == LONG_MIN) || (res == LONG_MAX)) && (errno == ERANGE))
213  return -2;
214  if (e && (*e != '\0'))
215  return -1;
216  return 0;
217 }
218 
232 int mutt_str_atos(const char *str, short *dst)
233 {
234  if (dst)
235  *dst = 0;
236 
237  long res = 0;
238  int rc = mutt_str_atol(str, &res);
239  if (rc < 0)
240  return rc;
241  if ((res < SHRT_MIN) || (res > SHRT_MAX))
242  return -2;
243 
244  if (dst)
245  *dst = (short) res;
246 
247  return 0;
248 }
249 
262 int mutt_str_atoi(const char *str, int *dst)
263 {
264  if (dst)
265  *dst = 0;
266 
267  long res = 0;
268  int rc = mutt_str_atol(str, &res);
269  if (rc < 0)
270  return rc;
271  if ((res < INT_MIN) || (res > INT_MAX))
272  return -2;
273 
274  if (dst)
275  *dst = (int) res;
276 
277  return 0;
278 }
279 
292 int mutt_str_atoui(const char *str, unsigned int *dst)
293 {
294  if (dst)
295  *dst = 0;
296 
297  unsigned long res = 0;
298  int rc = mutt_str_atoul(str, &res);
299  if (rc < 0)
300  return rc;
301  if (res > UINT_MAX)
302  return -2;
303 
304  if (dst)
305  *dst = (unsigned int) res;
306 
307  return rc;
308 }
309 
321 int mutt_str_atoul(const char *str, unsigned long *dst)
322 {
323  if (dst)
324  *dst = 0;
325 
326  if (!str || !*str) /* no input: 0 */
327  return 0;
328 
329  char *e = NULL;
330  errno = 0;
331 
332  unsigned long res = strtoul(str, &e, 10);
333  if (dst)
334  *dst = res;
335  if ((res == ULONG_MAX) && (errno == ERANGE))
336  return -1;
337  if (e && (*e != '\0'))
338  return 1;
339  return 0;
340 }
341 
353 int mutt_str_atoull(const char *str, unsigned long long *dst)
354 {
355  if (dst)
356  *dst = 0;
357 
358  if (!str || !*str) /* no input: 0 */
359  return 0;
360 
361  char *e = NULL;
362  errno = 0;
363 
364  unsigned long long res = strtoull(str, &e, 10);
365  if (dst)
366  *dst = res;
367  if ((res == ULLONG_MAX) && (errno == ERANGE))
368  return -1;
369  if (e && (*e != '\0'))
370  return 1;
371  return 0;
372 }
373 
380 char *mutt_str_strdup(const char *str)
381 {
382  if (!str || !*str)
383  return NULL;
384 
385  return strdup(str);
386 }
387 
395 char *mutt_str_strcat(char *buf, size_t buflen, const char *s)
396 {
397  if (!buf || (buflen == 0) || !s)
398  return buf;
399 
400  char *p = buf;
401 
402  buflen--; /* Space for the trailing '\0'. */
403 
404  for (; (*buf != '\0') && buflen; buflen--)
405  buf++;
406  for (; *s && buflen; buflen--)
407  *buf++ = *s++;
408 
409  *buf = '\0';
410 
411  return p;
412 }
413 
424 char *mutt_str_strncat(char *d, size_t l, const char *s, size_t sl)
425 {
426  if (!d || (l == 0) || !s)
427  return d;
428 
429  char *p = d;
430 
431  l--; /* Space for the trailing '\0'. */
432 
433  for (; *d && l; l--)
434  d++;
435  for (; *s && l && sl; l--, sl--)
436  *d++ = *s++;
437 
438  *d = '\0';
439 
440  return p;
441 }
442 
453 void mutt_str_replace(char **p, const char *s)
454 {
455  if (!p)
456  return;
457  FREE(p);
458  *p = mutt_str_strdup(s);
459 }
460 
471 void mutt_str_append_item(char **str, const char *item, char sep)
472 {
473  if (!str || !item)
474  return;
475 
476  size_t sz = mutt_str_strlen(item);
477  size_t ssz = mutt_str_strlen(*str);
478 
479  mutt_mem_realloc(str, ssz + (((ssz > 0) && (sep != '\0')) ? 1 : 0) + sz + 1);
480  char *p = *str + ssz;
481  if ((ssz > 0) && (sep != '\0'))
482  *p++ = sep;
483  memcpy(p, item, sz + 1);
484 }
485 
495 void mutt_str_adjust(char **p)
496 {
497  if (!p || !*p)
498  return;
499  mutt_mem_realloc(p, strlen(*p) + 1);
500 }
501 
509 char *mutt_str_strlower(char *s)
510 {
511  if (!s)
512  return NULL;
513 
514  char *p = s;
515 
516  while (*p)
517  {
518  *p = tolower((unsigned char) *p);
519  p++;
520  }
521 
522  return s;
523 }
524 
538 const char *mutt_str_strchrnul(const char *s, char c)
539 {
540  if (!s)
541  return NULL;
542 
543  for (; *s && (*s != c); s++)
544  ;
545  return s;
546 }
547 
556 char *mutt_str_substr_copy(const char *begin, const char *end, char *buf, size_t buflen)
557 {
558  if (!begin || !end || !buf || (buflen == 0))
559  return buf;
560 
561  size_t len = end - begin;
562  if (len > (buflen - 1))
563  len = buflen - 1;
564  memcpy(buf, begin, len);
565  buf[len] = '\0';
566  return buf;
567 }
568 
579 char *mutt_str_substr_dup(const char *begin, const char *end)
580 {
581  size_t len;
582  char *p = NULL;
583 
584  if (!begin)
585  {
586  mutt_debug(LL_DEBUG1, "%s: ERROR: 'begin' is NULL\n", __func__);
587  return NULL;
588  }
589 
590  if (end)
591  {
592  if (begin > end)
593  return NULL;
594  len = end - begin;
595  }
596  else
597  {
598  len = strlen(begin);
599  }
600 
601  p = mutt_mem_malloc(len + 1);
602  memcpy(p, begin, len);
603  p[len] = '\0';
604  return p;
605 }
606 
615 int mutt_str_strcmp(const char *a, const char *b)
616 {
617  return strcmp(NONULL(a), NONULL(b));
618 }
619 
628 int mutt_str_strcasecmp(const char *a, const char *b)
629 {
630  return strcasecmp(NONULL(a), NONULL(b));
631 }
632 
642 int mutt_str_strncmp(const char *a, const char *b, size_t l)
643 {
644  return strncmp(NONULL(a), NONULL(b), l);
645 }
646 
656 int mutt_str_strncasecmp(const char *a, const char *b, size_t l)
657 {
658  return strncasecmp(NONULL(a), NONULL(b), l);
659 }
660 
666 size_t mutt_str_strlen(const char *a)
667 {
668  return a ? strlen(a) : 0;
669 }
670 
679 int mutt_str_strcoll(const char *a, const char *b)
680 {
681  return strcoll(NONULL(a), NONULL(b));
682 }
683 
691 const char *mutt_str_stristr(const char *haystack, const char *needle)
692 {
693  if (!haystack)
694  return NULL;
695  if (!needle)
696  return haystack;
697 
698  const char *p = NULL, *q = NULL;
699 
700  while (*(p = haystack))
701  {
702  for (q = needle;
703  *p && *q && (tolower((unsigned char) *p) == tolower((unsigned char) *q));
704  p++, q++)
705  {
706  }
707  if (!*q)
708  return haystack;
709  haystack++;
710  }
711  return NULL;
712 }
713 
720 char *mutt_str_skip_whitespace(const char *p)
721 {
722  if (!p)
723  return NULL;
724  SKIPWS(p);
725  return (char *) p;
726 }
727 
735 {
736  if (!s)
737  return;
738 
739  for (char *p = s + mutt_str_strlen(s) - 1; (p >= s) && IS_SPACE(*p); p--)
740  *p = '\0';
741 }
742 
750 size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
751 {
752  if (!dest || (dsize == 0))
753  return 0;
754  if (!src)
755  {
756  dest[0] = '\0';
757  return 0;
758  }
759 
760  char *dest0 = dest;
761  while ((--dsize > 0) && (*src != '\0'))
762  *dest++ = *src++;
763 
764  *dest = '\0';
765  return dest - dest0;
766 }
767 
776 char *mutt_str_skip_email_wsp(const char *s)
777 {
778  if (!s)
779  return NULL;
780  return (char *) (s + strspn(s, EMAIL_WSP));
781 }
782 
789 {
790  return c && (strchr(EMAIL_WSP, c));
791 }
792 
801 size_t mutt_str_strnfcpy(char *dest, const char *src, size_t n, size_t dsize)
802 {
803  return mutt_str_strfcpy(dest, src, MIN(n + 1, dsize));
804 }
805 
815 size_t mutt_str_lws_len(const char *s, size_t n)
816 {
817  if (!s)
818  return 0;
819 
820  const char *p = s;
821  size_t len = n;
822 
823  if (n == 0)
824  return 0;
825 
826  for (; p < (s + n); p++)
827  {
828  if (!strchr(" \t\r\n", *p))
829  {
830  len = p - s;
831  break;
832  }
833  }
834 
835  if ((len != 0) && strchr("\r\n", *(p - 1))) /* LWS doesn't end with CRLF */
836  len = 0;
837  return len;
838 }
839 
849 size_t mutt_str_lws_rlen(const char *s, size_t n)
850 {
851  if (!s)
852  return 0;
853 
854  const char *p = s + n - 1;
855  size_t len = n;
856 
857  if (n == 0)
858  return 0;
859 
860  if (strchr("\r\n", *p)) /* LWS doesn't end with CRLF */
861  return 0;
862 
863  for (; p >= s; p--)
864  {
865  if (!strchr(" \t\r\n", *p))
866  {
867  len = s + n - 1 - p;
868  break;
869  }
870  }
871 
872  return len;
873 }
874 
882 {
883  if (!s)
884  return;
885 
886  char *w = s;
887 
888  for (; *s; s++)
889  {
890  if (*s == '\\')
891  {
892  if (!*++s)
893  break; /* error? */
894  *w++ = *s;
895  }
896  else if (*s != '\"')
897  {
898  if (w != s)
899  *w = *s;
900  w++;
901  }
902  }
903  *w = '\0';
904 }
905 
916 const char *mutt_str_next_word(const char *s)
917 {
918  if (!s)
919  return NULL;
920 
921  while (*s && !IS_SPACE(*s))
922  s++;
923  SKIPWS(s);
924  return s;
925 }
926 
938 const char *mutt_str_rstrnstr(const char *haystack, size_t haystack_length, const char *needle)
939 {
940  if (!haystack || (haystack_length == 0) || !needle)
941  return NULL;
942 
943  int needle_length = strlen(needle);
944  const char *haystack_end = haystack + haystack_length - needle_length;
945 
946  for (const char *p = haystack_end; p >= haystack; --p)
947  {
948  for (size_t i = 0; i < needle_length; i++)
949  {
950  if (p[i] != needle[i])
951  goto next;
952  }
953  return p;
954 
955  next:;
956  }
957  return NULL;
958 }
959 
973 int mutt_str_word_casecmp(const char *a, const char *b)
974 {
975  if (!b)
976  {
977  if (a)
978  return 1;
979  else
980  return 0;
981  }
982 
983  char tmp[128] = { 0 };
984 
985  int i;
986  for (i = 0; i < (sizeof(tmp) - 2); i++, b++)
987  {
988  if (!*b || IS_SPACE(*b))
989  {
990  tmp[i] = '\0';
991  break;
992  }
993  tmp[i] = *b;
994  }
995  tmp[i + 1] = '\0';
996 
997  return mutt_str_strcasecmp(a, tmp);
998 }
999 
1006 bool mutt_str_is_ascii(const char *str, size_t len)
1007 {
1008  if (!str)
1009  return true;
1010 
1011  for (; (*str != '\0') && (len > 0); str++, len--)
1012  if ((*str & 0x80) != 0)
1013  return false;
1014 
1015  return true;
1016 }
1017 
1029 const char *mutt_str_find_word(const char *src)
1030 {
1031  if (!src)
1032  return NULL;
1033 
1034  while (*src && strchr(" \t\n", *src))
1035  src++;
1036  while (*src && !strchr(" \t\n", *src))
1037  src++;
1038  return src;
1039 }
1040 
1049 const char *mutt_str_getenv(const char *name)
1050 {
1051  if (!name)
1052  return NULL;
1053 
1054  const char *val = getenv(name);
1055  if (val && (val[0] != '\0'))
1056  return val;
1057 
1058  return NULL;
1059 }
1060 
1071 bool mutt_str_inline_replace(char *buf, size_t buflen, size_t xlen, const char *rstr)
1072 {
1073  if (!buf || !rstr || (xlen >= buflen))
1074  return false;
1075 
1076  size_t slen = mutt_str_strlen(buf + xlen);
1077  size_t rlen = mutt_str_strlen(rstr);
1078 
1079  if ((slen + rlen) >= buflen)
1080  return false;
1081 
1082  memmove(buf + rlen, buf + xlen, slen + 1);
1083  memmove(buf, rstr, rlen);
1084 
1085  return true;
1086 }
1087 
1095 int mutt_str_remall_strcasestr(char *str, const char *target)
1096 {
1097  int rc = 1;
1098 
1099  // Look through an ensure all instances of the substring are gone.
1100  while ((str = (char *) mutt_str_strcasestr(str, target)))
1101  {
1102  size_t target_len = mutt_str_strlen(target);
1103  memmove(str, str + target_len, 1 + strlen(str + target_len));
1104  rc = 0; // If we got here, then a substring existed and has been removed.
1105  }
1106 
1107  return rc;
1108 }
1109 
1120 const char *mutt_str_strcasestr(const char *haystack, const char *needle)
1121 {
1122  if (!needle)
1123  return NULL;
1124 
1125  size_t haystack_len = mutt_str_strlen(haystack);
1126  size_t needle_len = mutt_str_strlen(needle);
1127 
1128  // Empty string exists at the front of a string. Check strstr if you don't believe me.
1129  if (needle_len == 0)
1130  return haystack;
1131 
1132  // Check size conditions. No point wasting CPU cycles.
1133  if ((haystack_len == 0) || (haystack_len < needle_len))
1134  return NULL;
1135 
1136  // Only check space that needle could fit in.
1137  // Conditional has + 1 to handle when the haystack and needle are the same length.
1138  for (size_t i = 0; i < (haystack_len - needle_len) + 1; i++)
1139  {
1140  for (size_t j = 0; j < needle_len; j++)
1141  {
1142  if (tolower((unsigned char) haystack[i + j]) != tolower((unsigned char) needle[j]))
1143  break;
1144 
1145  // If this statement is true, the needle has been found.
1146  if (j == (needle_len - 1))
1147  return haystack + i;
1148  }
1149  }
1150 
1151  return NULL;
1152 }
1153 
1154 #ifdef HAVE_VASPRINTF
1155 
1163 int mutt_str_asprintf(char **strp, const char *fmt, ...)
1164 {
1165  if (!strp || !fmt)
1166  return -1;
1167 
1168  va_list ap;
1169  int n;
1170 
1171  va_start(ap, fmt);
1172  n = vasprintf(strp, fmt, ap);
1173  va_end(ap);
1174 
1175  /* GNU libc man page for vasprintf(3) states that the value of *strp
1176  * is undefined when the return code is -1. */
1177  if (n < 0)
1178  {
1179  mutt_error(_("Out of memory")); /* LCOV_EXCL_LINE */
1180  mutt_exit(1); /* LCOV_EXCL_LINE */
1181  }
1182 
1183  if (n == 0)
1184  {
1185  /* NeoMutt convention is to use NULL for 0-length strings */
1186  FREE(strp);
1187  }
1188 
1189  return n;
1190 }
1191 #else
1192 /* Allocate a C-string large enough to contain the formatted string.
1193  * This is essentially malloc+sprintf in one.
1194  */
1195 int mutt_str_asprintf(char **strp, const char *fmt, ...)
1196 {
1197  if (!strp || !fmt)
1198  return -1;
1199 
1200  int rlen = 256;
1201 
1202  *strp = mutt_mem_malloc(rlen);
1203  while (true)
1204  {
1205  va_list ap;
1206  va_start(ap, fmt);
1207  const int n = vsnprintf(*strp, rlen, fmt, ap);
1208  va_end(ap);
1209  if (n < 0)
1210  {
1211  FREE(strp);
1212  return n;
1213  }
1214 
1215  if (n < rlen)
1216  {
1217  /* reduce space to just that which was used. note that 'n' does not
1218  * include the terminal nul char. */
1219  if (n == 0) /* convention is to use NULL for zero-length strings. */
1220  FREE(strp);
1221  else if (n != rlen - 1)
1222  mutt_mem_realloc(strp, n + 1);
1223  return n;
1224  }
1225  /* increase size and try again */
1226  rlen = n + 1;
1227  mutt_mem_realloc(strp, rlen);
1228  }
1229  /* not reached */
1230 }
1231 #endif /* HAVE_ASPRINTF */
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:720
int mutt_str_word_casecmp(const char *a, const char *b)
Find word a in word list b.
Definition: string.c:973
#define NONULL(x)
Definition: string2.h:37
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:262
const char * mutt_str_strchrnul(const char *s, char c)
Find first occurrence of character in string.
Definition: string.c:538
#define MIN(a, b)
Definition: memory.h:31
Memory management wrappers.
CaseSensitivity
Should a string&#39;s case matter when matching?
Definition: string2.h:65
#define S_ERR
Definition: string2.h:42
#define _(a)
Definition: message.h:28
int mutt_str_remall_strcasestr(char *str, const char *target)
Remove all occurrences of substring, ignoring case.
Definition: string.c:1095
void mutt_str_adjust(char **p)
Shrink-to-fit a string.
Definition: string.c:495
int mutt_str_atol(const char *str, long *dst)
Convert ASCII string to a long.
Definition: string.c:198
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
const char * mutt_str_strcasestr(const char *haystack, const char *needle)
Find a substring within a string without worrying about case.
Definition: string.c:1120
size_t mutt_str_lws_len(const char *s, size_t n)
Measure the linear-white-space at the beginning of a string.
Definition: string.c:815
#define EMAIL_WSP
Definition: string2.h:39
int mutt_str_atos(const char *str, short *dst)
Convert ASCII string to a short.
Definition: string.c:232
char * mutt_str_strncat(char *d, size_t l, const char *s, size_t sl)
Concatenate two strings.
Definition: string.c:424
Logging Dispatcher.
String manipulation functions.
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1049
#define mutt_array_size(x)
Definition: memory.h:33
Lookup table of error messages.
Definition: string.c:52
char * mutt_str_strlower(char *s)
convert all characters in the string to lowercase
Definition: string.c:509
bool(* char_cmp)(char, char)
Pointer to a function taking two characters and returning bool.
Definition: string.c:148
size_t mutt_str_strnfcpy(char *dest, const char *src, size_t n, size_t dsize)
Copy a limited string into a buffer (guaranteeing NUL-termination)
Definition: string.c:801
const char * name
Definition: pgpmicalg.c:45
#define SKIPWS(ch)
Definition: string2.h:47
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
Message logging.
const char * mutt_str_sysexit(int err_num)
Return a string matching an error code.
Definition: string.c:112
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:734
bool mutt_str_is_ascii(const char *str, size_t len)
Is a string ASCII (7-bit)?
Definition: string.c:1006
int mutt_str_strncasecmp(const char *a, const char *b, size_t l)
Compare two strings ignoring case (to a maximum), safely.
Definition: string.c:656
bool mutt_str_is_email_wsp(char c)
Is this a whitespace character (for an email header)
Definition: string.c:788
static bool char_cmp_lower(char a, char b)
Compare two characters ignoring case.
Definition: string.c:140
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
const char * mutt_str_stristr(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:691
static char_cmp get_char_cmp(enum CaseSensitivity cs)
Retrieve the correct function to compare characters according to a case sensitivity setting...
Definition: string.c:155
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
Leave the program NOW.
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:292
Ignore case when comparing strings.
Definition: string2.h:68
int mutt_str_atoull(const char *str, unsigned long long *dst)
Convert ASCII string to an unsigned long long.
Definition: string.c:353
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
void mutt_str_dequote_comment(char *s)
Un-escape characters in an email address comment.
Definition: string.c:881
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:453
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define IS_SPACE(ch)
Definition: string2.h:38
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:210
char * mutt_str_strcat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:395
size_t mutt_str_lws_rlen(const char *s, size_t n)
Measure the linear-white-space at the end of a string.
Definition: string.c:849
Log at debug level 1.
Definition: logging.h:56
const char * err_str
Definition: string.c:55
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
int mutt_str_strncmp(const char *a, const char *b, size_t l)
Compare two strings (to a maximum), safely.
Definition: string.c:642
#define mutt_error(...)
Definition: logging.h:84
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
int mutt_str_atoul(const char *str, unsigned long *dst)
Convert ASCII string to an unsigned long.
Definition: string.c:321
#define FREE(x)
Definition: memory.h:40
static bool char_cmp_identity(char a, char b)
Compare two characters.
Definition: string.c:129
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
bool mutt_str_inline_replace(char *buf, size_t buflen, size_t xlen, const char *rstr)
Replace the beginning of a string.
Definition: string.c:1071
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1195
void mutt_str_append_item(char **str, const char *item, char sep)
Add string to another separated by sep.
Definition: string.c:471
int mutt_str_strcoll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:679
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:579
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
const char * mutt_str_next_word(const char *s)
Find the next word in a string.
Definition: string.c:916
const char * mutt_str_find_word(const char *src)
Find the end of a word (non-space)
Definition: string.c:1029
int err_num
Definition: string.c:54
const char * mutt_str_rstrnstr(const char *haystack, size_t haystack_length, const char *needle)
Find last instance of a substring.
Definition: string.c:938
char * mutt_str_substr_copy(const char *begin, const char *end, char *buf, size_t buflen)
Copy a sub-string into a buffer.
Definition: string.c:556