NeoMutt  2021-02-05-666-ge300cd
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 
131 static size_t startswith(const char *str, const char *prefix, bool match_case)
132 {
133  if (!str || (str[0] == '\0') || !prefix || (prefix[0] == '\0'))
134  {
135  return 0;
136  }
137 
138  const char *saved_prefix = prefix;
139  for (; *str && *prefix; str++, prefix++)
140  {
141  if (*str == *prefix)
142  continue;
143 
144  if (!match_case && tolower(*str) == tolower(*prefix))
145  continue;
146 
147  return 0;
148  }
149 
150  return (*prefix == '\0') ? (prefix - saved_prefix) : 0;
151 }
152 
160 size_t mutt_str_startswith(const char *str, const char *prefix)
161 {
162  return startswith(str, prefix, true);
163 }
164 
172 size_t mutt_istr_startswith(const char *str, const char *prefix)
173 {
174  return startswith(str, prefix, false);
175 }
176 
188 int mutt_str_atol(const char *str, long *dst)
189 {
190  if (dst)
191  *dst = 0;
192 
193  if (!str || (*str == '\0')) /* no input: 0 */
194  return 0;
195 
196  char *e = NULL;
197  errno = 0;
198 
199  long res = strtol(str, &e, 10);
200  if (dst)
201  *dst = res;
202  if (((res == LONG_MIN) || (res == LONG_MAX)) && (errno == ERANGE))
203  return -2;
204  if (e && (*e != '\0'))
205  return -1;
206  return 0;
207 }
208 
222 int mutt_str_atos(const char *str, short *dst)
223 {
224  if (dst)
225  *dst = 0;
226 
227  long res = 0;
228  int rc = mutt_str_atol(str, &res);
229  if (rc < 0)
230  return rc;
231  if ((res < SHRT_MIN) || (res > SHRT_MAX))
232  return -2;
233 
234  if (dst)
235  *dst = (short) res;
236 
237  return 0;
238 }
239 
252 int mutt_str_atoi(const char *str, int *dst)
253 {
254  if (dst)
255  *dst = 0;
256 
257  long res = 0;
258  int rc = mutt_str_atol(str, &res);
259  if (rc < 0)
260  return rc;
261  if ((res < INT_MIN) || (res > INT_MAX))
262  return -2;
263 
264  if (dst)
265  *dst = (int) res;
266 
267  return 0;
268 }
269 
282 int mutt_str_atoui(const char *str, unsigned int *dst)
283 {
284  if (dst)
285  *dst = 0;
286 
287  unsigned long res = 0;
288  int rc = mutt_str_atoul(str, &res);
289  if (rc < 0)
290  return rc;
291  if (res > UINT_MAX)
292  return -2;
293 
294  if (dst)
295  *dst = (unsigned int) res;
296 
297  return rc;
298 }
299 
311 int mutt_str_atoul(const char *str, unsigned long *dst)
312 {
313  if (dst)
314  *dst = 0;
315 
316  if (!str || (*str == '\0')) /* no input: 0 */
317  return 0;
318 
319  char *e = NULL;
320  errno = 0;
321 
322  unsigned long res = strtoul(str, &e, 10);
323  if (dst)
324  *dst = res;
325  if ((res == ULONG_MAX) && (errno == ERANGE))
326  return -1;
327  if (e && (*e != '\0'))
328  return 1;
329  return 0;
330 }
331 
343 int mutt_str_atoull(const char *str, unsigned long long *dst)
344 {
345  if (dst)
346  *dst = 0;
347 
348  if (!str || (*str == '\0')) /* no input: 0 */
349  return 0;
350 
351  char *e = NULL;
352  errno = 0;
353 
354  unsigned long long res = strtoull(str, &e, 10);
355  if (dst)
356  *dst = res;
357  if ((res == ULLONG_MAX) && (errno == ERANGE))
358  return -1;
359  if (e && (*e != '\0'))
360  return 1;
361  return 0;
362 }
363 
370 char *mutt_str_dup(const char *str)
371 {
372  if (!str || (*str == '\0'))
373  return NULL;
374 
375  return strdup(str);
376 }
377 
385 char *mutt_str_cat(char *buf, size_t buflen, const char *s)
386 {
387  if (!buf || (buflen == 0) || !s)
388  return buf;
389 
390  char *p = buf;
391 
392  buflen--; /* Space for the trailing '\0'. */
393 
394  for (; (*buf != '\0') && buflen; buflen--)
395  buf++;
396  for (; *s && buflen; buflen--)
397  *buf++ = *s++;
398 
399  *buf = '\0';
400 
401  return p;
402 }
403 
414 char *mutt_strn_cat(char *d, size_t l, const char *s, size_t sl)
415 {
416  if (!d || (l == 0) || !s)
417  return d;
418 
419  char *p = d;
420 
421  l--; /* Space for the trailing '\0'. */
422 
423  for (; *d && l; l--)
424  d++;
425  for (; *s && l && sl; l--, sl--)
426  *d++ = *s++;
427 
428  *d = '\0';
429 
430  return p;
431 }
432 
446 char *mutt_str_replace(char **p, const char *s)
447 {
448  if (!p)
449  return NULL;
450  const char *tmp = *p;
451  *p = mutt_str_dup(s);
452  FREE(&tmp);
453  return *p;
454 }
455 
466 void mutt_str_append_item(char **str, const char *item, char sep)
467 {
468  if (!str || !item)
469  return;
470 
471  size_t sz = mutt_str_len(item);
472  size_t ssz = mutt_str_len(*str);
473 
474  mutt_mem_realloc(str, ssz + (((ssz > 0) && (sep != '\0')) ? 1 : 0) + sz + 1);
475  char *p = *str + ssz;
476  if ((ssz > 0) && (sep != '\0'))
477  *p++ = sep;
478  memcpy(p, item, sz + 1);
479 }
480 
490 void mutt_str_adjust(char **ptr)
491 {
492  if (!ptr || !*ptr)
493  return;
494  mutt_mem_realloc(ptr, strlen(*ptr) + 1);
495 }
496 
504 char *mutt_str_lower(char *str)
505 {
506  if (!str)
507  return NULL;
508 
509  char *p = str;
510 
511  while (*p)
512  {
513  *p = tolower((unsigned char) *p);
514  p++;
515  }
516 
517  return str;
518 }
519 
528 char *mutt_strn_copy(char *dest, const char *src, size_t len, size_t dsize)
529 {
530  if (!src || !dest || (len == 0) || (dsize == 0))
531  return dest;
532 
533  if (len > (dsize - 1))
534  len = dsize - 1;
535  memcpy(dest, src, len);
536  dest[len] = '\0';
537  return dest;
538 }
539 
548 char *mutt_strn_dup(const char *begin, size_t len)
549 {
550  if (!begin)
551  return NULL;
552 
553  char *p = mutt_mem_malloc(len + 1);
554  memcpy(p, begin, len);
555  p[len] = '\0';
556  return p;
557 }
558 
567 int mutt_str_cmp(const char *a, const char *b)
568 {
569  return strcmp(NONULL(a), NONULL(b));
570 }
571 
580 int mutt_istr_cmp(const char *a, const char *b)
581 {
582  return strcasecmp(NONULL(a), NONULL(b));
583 }
584 
593 bool mutt_strn_equal(const char *a, const char *b, size_t num)
594 {
595  return strncmp(NONULL(a), NONULL(b), num) == 0;
596 }
597 
607 int mutt_istrn_cmp(const char *a, const char *b, size_t num)
608 {
609  return strncasecmp(NONULL(a), NONULL(b), num);
610 }
611 
621 bool mutt_istrn_equal(const char *a, const char *b, size_t num)
622 {
623  return strncasecmp(NONULL(a), NONULL(b), num) == 0;
624 }
625 
637 const char *mutt_istrn_rfind(const char *haystack, size_t haystack_length, const char *needle)
638 {
639  if (!haystack || (haystack_length == 0) || !needle)
640  return NULL;
641 
642  int needle_length = strlen(needle);
643  const char *haystack_end = haystack + haystack_length - needle_length;
644 
645  for (const char *p = haystack_end; p >= haystack; --p)
646  {
647  for (size_t i = 0; i < needle_length; i++)
648  {
649  if ((tolower((unsigned char) p[i]) != tolower((unsigned char) needle[i])))
650  goto next;
651  }
652  return p;
653 
654  next:;
655  }
656  return NULL;
657 }
658 
664 size_t mutt_str_len(const char *a)
665 {
666  return a ? strlen(a) : 0;
667 }
668 
677 int mutt_str_coll(const char *a, const char *b)
678 {
679  return strcoll(NONULL(a), NONULL(b));
680 }
681 
689 const char *mutt_istr_find(const char *haystack, const char *needle)
690 {
691  if (!haystack)
692  return NULL;
693  if (!needle)
694  return haystack;
695 
696  const char *p = NULL, *q = NULL;
697 
698  while (*(p = haystack))
699  {
700  for (q = needle;
701  *p && *q && (tolower((unsigned char) *p) == tolower((unsigned char) *q));
702  p++, q++)
703  {
704  }
705  if ((*q == '\0'))
706  return haystack;
707  haystack++;
708  }
709  return NULL;
710 }
711 
719 char *mutt_str_skip_whitespace(const char *p)
720 {
721  if (!p)
722  return NULL;
723  SKIPWS(p);
724  return (char *) p;
725 }
726 
734 {
735  if (!s)
736  return;
737 
738  for (char *p = s + mutt_str_len(s) - 1; (p >= s) && IS_SPACE(*p); p--)
739  *p = '\0';
740 }
741 
749 size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
750 {
751  if (!dest || (dsize == 0))
752  return 0;
753  if (!src)
754  {
755  dest[0] = '\0';
756  return 0;
757  }
758 
759  char *dest0 = dest;
760  while ((--dsize > 0) && (*src != '\0'))
761  *dest++ = *src++;
762 
763  *dest = '\0';
764  return dest - dest0;
765 }
766 
776 char *mutt_str_skip_email_wsp(const char *s)
777 {
778  if (!s)
779  return NULL;
780 
781  for (; mutt_str_is_email_wsp(*s); s++)
782  ; // Do nothing
783 
784  return (char *) s;
785 }
786 
793 {
794  return c && strchr(" \t\r\n", c);
795 }
796 
806 size_t mutt_str_lws_len(const char *s, size_t n)
807 {
808  if (!s)
809  return 0;
810 
811  const char *p = s;
812  size_t len = n;
813 
814  if (n == 0)
815  return 0;
816 
817  for (; p < (s + n); p++)
818  {
819  if (!strchr(" \t\r\n", *p))
820  {
821  len = p - s;
822  break;
823  }
824  }
825 
826  if ((len != 0) && strchr("\r\n", *(p - 1))) /* LWS doesn't end with CRLF */
827  len = 0;
828  return len;
829 }
830 
840 size_t mutt_str_lws_rlen(const char *s, size_t n)
841 {
842  if (!s)
843  return 0;
844 
845  const char *p = s + n - 1;
846  size_t len = n;
847 
848  if (n == 0)
849  return 0;
850 
851  if (strchr("\r\n", *p)) /* LWS doesn't end with CRLF */
852  return 0;
853 
854  for (; p >= s; p--)
855  {
856  if (!strchr(" \t\r\n", *p))
857  {
858  len = s + n - 1 - p;
859  break;
860  }
861  }
862 
863  return len;
864 }
865 
873 {
874  if (!str)
875  return;
876 
877  char *w = str;
878 
879  for (; *str; str++)
880  {
881  if (*str == '\\')
882  {
883  if (!*++str)
884  break; /* error? */
885  *w++ = *str;
886  }
887  else if (*str != '\"')
888  {
889  if (w != str)
890  *w = *str;
891  w++;
892  }
893  }
894  *w = '\0';
895 }
896 
904 bool mutt_str_equal(const char *a, const char *b)
905 {
906  return (a == b) || (mutt_str_cmp(a, b) == 0);
907 }
908 
916 bool mutt_istr_equal(const char *a, const char *b)
917 {
918  return (a == b) || (mutt_istr_cmp(a, b) == 0);
919 }
920 
931 const char *mutt_str_next_word(const char *s)
932 {
933  if (!s)
934  return NULL;
935 
936  while (*s && !IS_SPACE(*s))
937  s++;
938  SKIPWS(s);
939  return s;
940 }
941 
953 const char *mutt_strn_rfind(const char *haystack, size_t haystack_length, const char *needle)
954 {
955  if (!haystack || (haystack_length == 0) || !needle)
956  return NULL;
957 
958  int needle_length = strlen(needle);
959  const char *haystack_end = haystack + haystack_length - needle_length;
960 
961  for (const char *p = haystack_end; p >= haystack; --p)
962  {
963  for (size_t i = 0; i < needle_length; i++)
964  {
965  if (p[i] != needle[i])
966  goto next;
967  }
968  return p;
969 
970  next:;
971  }
972  return NULL;
973 }
974 
981 bool mutt_str_is_ascii(const char *str, size_t len)
982 {
983  if (!str)
984  return true;
985 
986  for (; (*str != '\0') && (len > 0); str++, len--)
987  if ((*str & 0x80) != 0)
988  return false;
989 
990  return true;
991 }
992 
1004 const char *mutt_str_find_word(const char *src)
1005 {
1006  if (!src)
1007  return NULL;
1008 
1009  while (*src && strchr(" \t\n", *src))
1010  src++;
1011  while (*src && !strchr(" \t\n", *src))
1012  src++;
1013  return src;
1014 }
1015 
1024 const char *mutt_str_getenv(const char *name)
1025 {
1026  if (!name)
1027  return NULL;
1028 
1029  const char *val = getenv(name);
1030  if (val && (val[0] != '\0'))
1031  return val;
1032 
1033  return NULL;
1034 }
1035 
1046 bool mutt_str_inline_replace(char *buf, size_t buflen, size_t xlen, const char *rstr)
1047 {
1048  if (!buf || !rstr || (xlen >= buflen))
1049  return false;
1050 
1051  size_t slen = mutt_str_len(buf + xlen);
1052  size_t rlen = mutt_str_len(rstr);
1053 
1054  if ((slen + rlen) >= buflen)
1055  return false;
1056 
1057  memmove(buf + rlen, buf + xlen, slen + 1);
1058  memmove(buf, rstr, rlen);
1059 
1060  return true;
1061 }
1062 
1070 int mutt_istr_remall(char *str, const char *target)
1071 {
1072  int rc = 1;
1073  if (!str || !target)
1074  return rc;
1075 
1076  // Look through an ensure all instances of the substring are gone.
1077  while ((str = (char *) strcasestr(str, target)))
1078  {
1079  size_t target_len = mutt_str_len(target);
1080  memmove(str, str + target_len, 1 + strlen(str + target_len));
1081  rc = 0; // If we got here, then a substring existed and has been removed.
1082  }
1083 
1084  return rc;
1085 }
1086 
1087 #ifdef HAVE_VASPRINTF
1088 
1096 int mutt_str_asprintf(char **strp, const char *fmt, ...)
1097 {
1098  if (!strp || !fmt)
1099  return -1;
1100 
1101  va_list ap;
1102  int n;
1103 
1104  va_start(ap, fmt);
1105  n = vasprintf(strp, fmt, ap);
1106  va_end(ap);
1107 
1108  /* GNU libc man page for vasprintf(3) states that the value of *strp
1109  * is undefined when the return code is -1. */
1110  if (n < 0)
1111  {
1112  mutt_error(_("Out of memory")); /* LCOV_EXCL_LINE */
1113  mutt_exit(1); /* LCOV_EXCL_LINE */
1114  }
1115 
1116  if (n == 0)
1117  {
1118  /* NeoMutt convention is to use NULL for 0-length strings */
1119  FREE(strp);
1120  }
1121 
1122  return n;
1123 }
1124 #else
1125 /* Allocate a C-string large enough to contain the formatted string.
1126  * This is essentially malloc+sprintf in one.
1127  */
1128 int mutt_str_asprintf(char **strp, const char *fmt, ...)
1129 {
1130  if (!strp || !fmt)
1131  return -1;
1132 
1133  int rlen = 256;
1134 
1135  *strp = mutt_mem_malloc(rlen);
1136  while (true)
1137  {
1138  va_list ap;
1139  va_start(ap, fmt);
1140  const int n = vsnprintf(*strp, rlen, fmt, ap);
1141  va_end(ap);
1142  if (n < 0)
1143  {
1144  FREE(strp);
1145  return n;
1146  }
1147 
1148  if (n < rlen)
1149  {
1150  /* reduce space to just that which was used. note that 'n' does not
1151  * include the terminal nul char. */
1152  if (n == 0) /* convention is to use NULL for zero-length strings. */
1153  FREE(strp);
1154  else if (n != rlen - 1)
1155  mutt_mem_realloc(strp, n + 1);
1156  return n;
1157  }
1158  /* increase size and try again */
1159  rlen = n + 1;
1160  mutt_mem_realloc(strp, rlen);
1161  }
1162  /* not reached */
1163 }
1164 #endif /* HAVE_ASPRINTF */
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
int mutt_istr_cmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:580
int mutt_str_cmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:567
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:719
static size_t startswith(const char *str, const char *prefix, bool match_case)
Check whether a string starts with a prefix.
Definition: string.c:131
#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:252
Memory management wrappers.
#define S_ERR
Definition: string2.h:41
#define mutt_error(...)
Definition: logging.h:88
char * mutt_strn_cat(char *d, size_t l, const char *s, size_t sl)
Concatenate two strings.
Definition: string.c:414
void mutt_str_dequote_comment(char *str)
Un-escape characters in an email address comment.
Definition: string.c:872
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:621
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
int mutt_str_atol(const char *str, long *dst)
Convert ASCII string to a long.
Definition: string.c:188
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:806
int mutt_str_atos(const char *str, short *dst)
Convert ASCII string to a short.
Definition: string.c:222
int mutt_str_coll(const char *a, const char *b)
Collate two strings (compare using locale), safely.
Definition: string.c:677
Logging Dispatcher.
const char * mutt_istrn_rfind(const char *haystack, size_t haystack_length, const char *needle)
Find last instance of a substring, ignoring case.
Definition: string.c:637
String manipulation functions.
const char * mutt_str_getenv(const char *name)
Get an environment variable.
Definition: string.c:1024
#define mutt_array_size(x)
Definition: memory.h:33
Lookup table of error messages.
Definition: string.c:52
char * mutt_strn_dup(const char *begin, size_t len)
Duplicate a sub-string.
Definition: string.c:548
#define SKIPWS(ch)
Definition: string2.h:46
char * mutt_strn_copy(char *dest, const char *src, size_t len, size_t dsize)
Copy a sub-string into a buffer.
Definition: string.c:528
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
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:733
int mutt_istrn_cmp(const char *a, const char *b, size_t num)
Compare two strings ignoring case (to a maximum), safely.
Definition: string.c:607
bool mutt_str_is_ascii(const char *str, size_t len)
Is a string ASCII (7-bit)?
Definition: string.c:981
bool mutt_str_is_email_wsp(char c)
Is this a whitespace character (for an email header)
Definition: string.c:792
int mutt_istr_remall(char *str, const char *target)
Remove all occurrences of substring, ignoring case.
Definition: string.c:1070
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
void mutt_str_adjust(char **ptr)
Shrink-to-fit a string.
Definition: string.c:490
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
Leave the program NOW.
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:282
int mutt_str_atoull(const char *str, unsigned long long *dst)
Convert ASCII string to an unsigned long long.
Definition: string.c:343
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:172
char * mutt_str_cat(char *buf, size_t buflen, const char *s)
Concatenate two strings.
Definition: string.c:385
#define IS_SPACE(ch)
Definition: string2.h:38
void mutt_exit(int code)
Leave NeoMutt NOW.
Definition: main.c:279
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:840
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition: string.c:689
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
const char * err_str
Definition: string.c:55
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
Definition: string.c:504
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
int mutt_str_atoul(const char *str, unsigned long *dst)
Convert ASCII string to an unsigned long.
Definition: string.c:311
#define FREE(x)
Definition: memory.h:40
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:1046
const char * mutt_strn_rfind(const char *haystack, size_t haystack_length, const char *needle)
Find last instance of a substring.
Definition: string.c:953
int mutt_str_asprintf(char **strp, const char *fmt,...)
Definition: string.c:1128
void mutt_str_append_item(char **str, const char *item, char sep)
Add string to another separated by sep.
Definition: string.c:466
const char * mutt_str_next_word(const char *s)
Find the next word in a string.
Definition: string.c:931
const char * mutt_str_find_word(const char *src)
Find the end of a word (non-space)
Definition: string.c:1004
int err_num
Definition: string.c:54