NeoMutt  2020-04-24
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 typedef bool (*char_cmp)(char, char);
53 
57 struct SysExits
58 {
59  int err_num;
60  const char *err_str;
61 };
62 
63 static const struct SysExits sysexits[] = {
64 #ifdef EX_USAGE
65  { 0xff & EX_USAGE, "Bad usage." },
66 #endif
67 #ifdef EX_DATAERR
68  { 0xff & EX_DATAERR, "Data format error." },
69 #endif
70 #ifdef EX_NOINPUT
71  { 0xff & EX_NOINPUT, "Can't open input." },
72 #endif
73 #ifdef EX_NOUSER
74  { 0xff & EX_NOUSER, "User unknown." },
75 #endif
76 #ifdef EX_NOHOST
77  { 0xff & EX_NOHOST, "Host unknown." },
78 #endif
79 #ifdef EX_UNAVAILABLE
80  { 0xff & EX_UNAVAILABLE, "Service unavailable." },
81 #endif
82 #ifdef EX_SOFTWARE
83  { 0xff & EX_SOFTWARE, "Internal error." },
84 #endif
85 #ifdef EX_OSERR
86  { 0xff & EX_OSERR, "Operating system error." },
87 #endif
88 #ifdef EX_OSFILE
89  { 0xff & EX_OSFILE, "System file missing." },
90 #endif
91 #ifdef EX_CANTCREAT
92  { 0xff & EX_CANTCREAT, "Can't create output." },
93 #endif
94 #ifdef EX_IOERR
95  { 0xff & EX_IOERR, "I/O error." },
96 #endif
97 #ifdef EX_TEMPFAIL
98  { 0xff & EX_TEMPFAIL, "Deferred." },
99 #endif
100 #ifdef EX_PROTOCOL
101  { 0xff & EX_PROTOCOL, "Remote protocol error." },
102 #endif
103 #ifdef EX_NOPERM
104  { 0xff & EX_NOPERM, "Insufficient permission." },
105 #endif
106 #ifdef EX_CONFIG
107  { 0xff & EX_NOPERM, "Local configuration error." },
108 #endif
109  { S_ERR, "Exec error." },
110 };
111 
117 const char *mutt_str_sysexit(int err_num)
118 {
119  for (size_t i = 0; i < mutt_array_size(sysexits); i++)
120  {
121  if (err_num == sysexits[i].err_num)
122  return sysexits[i].err_str;
123  }
124 
125  return NULL;
126 }
127 
134 static inline bool char_cmp_identity(char a, char b)
135 {
136  return a == b;
137 }
138 
145 static inline bool char_cmp_lower(char a, char b)
146 {
147  return tolower((unsigned char) a) == tolower((unsigned char) b);
148 }
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 
455 void mutt_str_replace(char **p, const char *s)
456 {
457  if (!p)
458  return;
459  const char *tmp = *p;
460  *p = mutt_str_strdup(s);
461  FREE(&tmp);
462 }
463 
474 void mutt_str_append_item(char **str, const char *item, char sep)
475 {
476  if (!str || !item)
477  return;
478 
479  size_t sz = mutt_str_strlen(item);
480  size_t ssz = mutt_str_strlen(*str);
481 
482  mutt_mem_realloc(str, ssz + (((ssz > 0) && (sep != '\0')) ? 1 : 0) + sz + 1);
483  char *p = *str + ssz;
484  if ((ssz > 0) && (sep != '\0'))
485  *p++ = sep;
486  memcpy(p, item, sz + 1);
487 }
488 
498 void mutt_str_adjust(char **p)
499 {
500  if (!p || !*p)
501  return;
502  mutt_mem_realloc(p, strlen(*p) + 1);
503 }
504 
512 char *mutt_str_strlower(char *s)
513 {
514  if (!s)
515  return NULL;
516 
517  char *p = s;
518 
519  while (*p)
520  {
521  *p = tolower((unsigned char) *p);
522  p++;
523  }
524 
525  return s;
526 }
527 
536 char *mutt_str_strnlower(char *str, size_t num)
537 {
538  if (!str)
539  return NULL;
540 
541  for (size_t i = 0; i < num; i++)
542  {
543  if (str[i] == '\0')
544  break;
545  str[i] = tolower((unsigned char) str[i]);
546  }
547 
548  return str;
549 }
550 
564 const char *mutt_str_strchrnul(const char *s, char c)
565 {
566  if (!s)
567  return NULL;
568 
569  for (; *s && (*s != c); s++)
570  ;
571  return s;
572 }
573 
582 char *mutt_str_substr_copy(const char *begin, const char *end, char *buf, size_t buflen)
583 {
584  if (!begin || !end || !buf || (buflen == 0))
585  return buf;
586 
587  size_t len = end - begin;
588  if (len > (buflen - 1))
589  len = buflen - 1;
590  memcpy(buf, begin, len);
591  buf[len] = '\0';
592  return buf;
593 }
594 
605 char *mutt_str_substr_dup(const char *begin, const char *end)
606 {
607  size_t len;
608  char *p = NULL;
609 
610  if (!begin)
611  {
612  mutt_debug(LL_DEBUG1, "%s: ERROR: 'begin' is NULL\n", __func__);
613  return NULL;
614  }
615 
616  if (end)
617  {
618  if (begin > end)
619  return NULL;
620  len = end - begin;
621  }
622  else
623  {
624  len = strlen(begin);
625  }
626 
627  p = mutt_mem_malloc(len + 1);
628  memcpy(p, begin, len);
629  p[len] = '\0';
630  return p;
631 }
632 
641 int mutt_str_strcmp(const char *a, const char *b)
642 {
643  return strcmp(NONULL(a), NONULL(b));
644 }
645 
654 int mutt_str_strcasecmp(const char *a, const char *b)
655 {
656  return strcasecmp(NONULL(a), NONULL(b));
657 }
658 
668 int mutt_str_strncmp(const char *a, const char *b, size_t l)
669 {
670  return strncmp(NONULL(a), NONULL(b), l);
671 }
672 
682 int mutt_str_strncasecmp(const char *a, const char *b, size_t l)
683 {
684  return strncasecmp(NONULL(a), NONULL(b), l);
685 }
686 
692 size_t mutt_str_strlen(const char *a)
693 {
694  return a ? strlen(a) : 0;
695 }
696 
705 int mutt_str_strcoll(const char *a, const char *b)
706 {
707  return strcoll(NONULL(a), NONULL(b));
708 }
709 
717 const char *mutt_str_stristr(const char *haystack, const char *needle)
718 {
719  if (!haystack)
720  return NULL;
721  if (!needle)
722  return haystack;
723 
724  const char *p = NULL, *q = NULL;
725 
726  while (*(p = haystack))
727  {
728  for (q = needle;
729  *p && *q && (tolower((unsigned char) *p) == tolower((unsigned char) *q));
730  p++, q++)
731  {
732  }
733  if (!*q)
734  return haystack;
735  haystack++;
736  }
737  return NULL;
738 }
739 
746 char *mutt_str_skip_whitespace(const char *p)
747 {
748  if (!p)
749  return NULL;
750  SKIPWS(p);
751  return (char *) p;
752 }
753 
761 {
762  if (!s)
763  return;
764 
765  for (char *p = s + mutt_str_strlen(s) - 1; (p >= s) && IS_SPACE(*p); p--)
766  *p = '\0';
767 }
768 
776 size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
777 {
778  if (!dest || (dsize == 0))
779  return 0;
780  if (!src)
781  {
782  dest[0] = '\0';
783  return 0;
784  }
785 
786  char *dest0 = dest;
787  while ((--dsize > 0) && (*src != '\0'))
788  *dest++ = *src++;
789 
790  *dest = '\0';
791  return dest - dest0;
792 }
793 
802 char *mutt_str_skip_email_wsp(const char *s)
803 {
804  if (!s)
805  return NULL;
806  return (char *) (s + strspn(s, EMAIL_WSP));
807 }
808 
815 {
816  return c && (strchr(EMAIL_WSP, c));
817 }
818 
827 size_t mutt_str_strnfcpy(char *dest, const char *src, size_t n, size_t dsize)
828 {
829  return mutt_str_strfcpy(dest, src, MIN(n + 1, dsize));
830 }
831 
841 size_t mutt_str_lws_len(const char *s, size_t n)
842 {
843  if (!s)
844  return 0;
845 
846  const char *p = s;
847  size_t len = n;
848 
849  if (n == 0)
850  return 0;
851 
852  for (; p < (s + n); p++)
853  {
854  if (!strchr(" \t\r\n", *p))
855  {
856  len = p - s;
857  break;
858  }
859  }
860 
861  if ((len != 0) && strchr("\r\n", *(p - 1))) /* LWS doesn't end with CRLF */
862  len = 0;
863  return len;
864 }
865 
875 size_t mutt_str_lws_rlen(const char *s, size_t n)
876 {
877  if (!s)
878  return 0;
879 
880  const char *p = s + n - 1;
881  size_t len = n;
882 
883  if (n == 0)
884  return 0;
885 
886  if (strchr("\r\n", *p)) /* LWS doesn't end with CRLF */
887  return 0;
888 
889  for (; p >= s; p--)
890  {
891  if (!strchr(" \t\r\n", *p))
892  {
893  len = s + n - 1 - p;
894  break;
895  }
896  }
897 
898  return len;
899 }
900 
908 {
909  if (!s)
910  return;
911 
912  char *w = s;
913 
914  for (; *s; s++)
915  {
916  if (*s == '\\')
917  {
918  if (!*++s)
919  break; /* error? */
920  *w++ = *s;
921  }
922  else if (*s != '\"')
923  {
924  if (w != s)
925  *w = *s;
926  w++;
927  }
928  }
929  *w = '\0';
930 }
931 
942 const char *mutt_str_next_word(const char *s)
943 {
944  if (!s)
945  return NULL;
946 
947  while (*s && !IS_SPACE(*s))
948  s++;
949  SKIPWS(s);
950  return s;
951 }
952 
964 const char *mutt_str_rstrnstr(const char *haystack, size_t haystack_length, const char *needle)
965 {
966  if (!haystack || (haystack_length == 0) || !needle)
967  return NULL;
968 
969  int needle_length = strlen(needle);
970  const char *haystack_end = haystack + haystack_length - needle_length;
971 
972  for (const char *p = haystack_end; p >= haystack; --p)
973  {
974  for (size_t i = 0; i < needle_length; i++)
975  {
976  if (p[i] != needle[i])
977  goto next;
978  }
979  return p;
980 
981  next:;
982  }
983  return NULL;
984 }
985 
999 int mutt_str_word_casecmp(const char *a, const char *b)
1000 {
1001  if (!b)
1002  {
1003  if (a)
1004  return 1;
1005  return 0;
1006  }
1007 
1008  char tmp[128] = { 0 };
1009 
1010  int i;
1011  for (i = 0; i < (sizeof(tmp) - 2); i++, b++)
1012  {
1013  if (!*b || IS_SPACE(*b))
1014  {
1015  tmp[i] = '\0';
1016  break;
1017  }
1018  tmp[i] = *b;
1019  }
1020  tmp[i + 1] = '\0';
1021 
1022  return mutt_str_strcasecmp(a, tmp);
1023 }
1024 
1031 bool mutt_str_is_ascii(const char *str, size_t len)
1032 {
1033  if (!str)
1034  return true;
1035 
1036  for (; (*str != '\0') && (len > 0); str++, len--)
1037  if ((*str & 0x80) != 0)
1038  return false;
1039 
1040  return true;
1041 }
1042 
1054 const char *mutt_str_find_word(const char *src)
1055 {
1056  if (!src)
1057  return NULL;
1058 
1059  while (*src && strchr(" \t\n", *src))
1060  src++;
1061  while (*src && !strchr(" \t\n", *src))
1062  src++;
1063  return src;
1064 }
1065 
1074 const char *mutt_str_getenv(const char *name)
1075 {
1076  if (!name)
1077  return NULL;
1078 
1079  const char *val = getenv(name);
1080  if (val && (val[0] != '\0'))
1081  return val;
1082 
1083  return NULL;
1084 }
1085 
1096 bool mutt_str_inline_replace(char *buf, size_t buflen, size_t xlen, const char *rstr)
1097 {
1098  if (!buf || !rstr || (xlen >= buflen))
1099  return false;
1100 
1101  size_t slen = mutt_str_strlen(buf + xlen);
1102  size_t rlen = mutt_str_strlen(rstr);
1103 
1104  if ((slen + rlen) >= buflen)
1105  return false;
1106 
1107  memmove(buf + rlen, buf + xlen, slen + 1);
1108  memmove(buf, rstr, rlen);
1109 
1110  return true;
1111 }
1112 
1120 int mutt_str_remall_strcasestr(char *str, const char *target)
1121 {
1122  int rc = 1;
1123 
1124  // Look through an ensure all instances of the substring are gone.
1125  while ((str = (char *) mutt_str_strcasestr(str, target)))
1126  {
1127  size_t target_len = mutt_str_strlen(target);
1128  memmove(str, str + target_len, 1 + strlen(str + target_len));
1129  rc = 0; // If we got here, then a substring existed and has been removed.
1130  }
1131 
1132  return rc;
1133 }
1134 
1145 const char *mutt_str_strcasestr(const char *haystack, const char *needle)
1146 {
1147  if (!needle)
1148  return NULL;
1149 
1150  size_t haystack_len = mutt_str_strlen(haystack);
1151  size_t needle_len = mutt_str_strlen(needle);
1152 
1153  // Empty string exists at the front of a string. Check strstr if you don't believe me.
1154  if (needle_len == 0)
1155  return haystack;
1156 
1157  // Check size conditions. No point wasting CPU cycles.
1158  if ((haystack_len == 0) || (haystack_len < needle_len))
1159  return NULL;
1160 
1161  // Only check space that needle could fit in.
1162  // Conditional has + 1 to handle when the haystack and needle are the same length.
1163  for (size_t i = 0; i < (haystack_len - needle_len) + 1; i++)
1164  {
1165  for (size_t j = 0; j < needle_len; j++)
1166  {
1167  if (tolower((unsigned char) haystack[i + j]) != tolower((unsigned char) needle[j]))
1168  break;
1169 
1170  // If this statement is true, the needle has been found.
1171  if (j == (needle_len - 1))
1172  return haystack + i;
1173  }
1174  }
1175 
1176  return NULL;
1177 }
1178 
1179 #ifdef HAVE_VASPRINTF
1180 
1188 int mutt_str_asprintf(char **strp, const char *fmt, ...)
1189 {
1190  if (!strp || !fmt)
1191  return -1;
1192 
1193  va_list ap;
1194  int n;
1195 
1196  va_start(ap, fmt);
1197  n = vasprintf(strp, fmt, ap);
1198  va_end(ap);
1199 
1200  /* GNU libc man page for vasprintf(3) states that the value of *strp
1201  * is undefined when the return code is -1. */
1202  if (n < 0)
1203  {
1204  mutt_error(_("Out of memory")); /* LCOV_EXCL_LINE */
1205  mutt_exit(1); /* LCOV_EXCL_LINE */
1206  }
1207 
1208  if (n == 0)
1209  {
1210  /* NeoMutt convention is to use NULL for 0-length strings */
1211  FREE(strp);
1212  }
1213 
1214  return n;
1215 }
1216 #else
1217 /* Allocate a C-string large enough to contain the formatted string.
1218  * This is essentially malloc+sprintf in one.
1219  */
1220 int mutt_str_asprintf(char **strp, const char *fmt, ...)
1221 {
1222  if (!strp || !fmt)
1223  return -1;
1224 
1225  int rlen = 256;
1226 
1227  *strp = mutt_mem_malloc(rlen);
1228  while (true)
1229  {
1230  va_list ap;
1231  va_start(ap, fmt);
1232  const int n = vsnprintf(*strp, rlen, fmt, ap);
1233  va_end(ap);
1234  if (n < 0)
1235  {
1236  FREE(strp);
1237  return n;
1238  }
1239 
1240  if (n < rlen)
1241  {
1242  /* reduce space to just that which was used. note that 'n' does not
1243  * include the terminal nul char. */
1244  if (n == 0) /* convention is to use NULL for zero-length strings. */
1245  FREE(strp);
1246  else if (n != rlen - 1)
1247  mutt_mem_realloc(strp, n + 1);
1248  return n;
1249  }
1250  /* increase size and try again */
1251  rlen = n + 1;
1252  mutt_mem_realloc(strp, rlen);
1253  }
1254  /* not reached */
1255 }
1256 #endif /* HAVE_ASPRINTF */
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:746
int mutt_str_word_casecmp(const char *a, const char *b)
Find word a in word list b.
Definition: string.c:999
#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:564
#define MIN(a, b)
Definition: memory.h:31
Memory management wrappers.
char * mutt_str_strnlower(char *str, size_t num)
Convert some characters in the string to lowercase.
Definition: string.c:536
CaseSensitivity
Should a string&#39;s case matter when matching?
Definition: string2.h:65
#define S_ERR
Definition: string2.h:42
static int const char * fmt
Definition: acutest.h:488
vsnprintf(buffer, sizeof(buffer), fmt, args)
#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:1120
void mutt_str_adjust(char **p)
Shrink-to-fit a string.
Definition: string.c:498
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:692
const char * mutt_str_strcasestr(const char *haystack, const char *needle)
Find a substring within a string without worrying about case.
Definition: string.c:1145
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:841
#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:1074
#define mutt_array_size(x)
Definition: memory.h:33
Lookup table of error messages.
Definition: string.c:57
char * mutt_str_strlower(char *s)
Convert all characters in the string to lowercase.
Definition: string.c:512
bool(* char_cmp)(char, char)
Pointer to a function taking two characters and returning bool.
Definition: string.c:52
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:827
const char * name
Definition: pgpmicalg.c:46
va_start(args, fmt)
#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:117
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:760
bool mutt_str_is_ascii(const char *str, size_t len)
Is a string ASCII (7-bit)?
Definition: string.c:1031
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:682
bool mutt_str_is_email_wsp(char c)
Is this a whitespace character (for an email header)
Definition: string.c:814
static bool char_cmp_lower(char a, char b)
Compare two characters ignoring case.
Definition: string.c:145
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:717
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:776
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:802
void mutt_str_dequote_comment(char *s)
Un-escape characters in an email address comment.
Definition: string.c:907
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:455
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:138
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:875
Log at debug level 1.
Definition: logging.h:40
int n
Definition: acutest.h:492
const char * err_str
Definition: string.c:60
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:668
#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:654
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:134
#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:1096
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1220
void mutt_str_append_item(char **str, const char *item, char sep)
Add string to another separated by sep.
Definition: string.c:474
int mutt_str_strcoll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:705
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:605
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:641
const char * mutt_str_next_word(const char *s)
Find the next word in a string.
Definition: string.c:942
const char * mutt_str_find_word(const char *src)
Find the end of a word (non-space)
Definition: string.c:1054
int err_num
Definition: string.c:59
const char * mutt_str_rstrnstr(const char *haystack, size_t haystack_length, const char *needle)
Find last instance of a substring.
Definition: string.c:964
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:582
va_end(args)