More string and buffer functions.
[apps/madmutt.git] / lib-lib / str.h
index 3133585..f9ef19f 100644 (file)
@@ -94,6 +94,16 @@ extern char const __m_b36chars_upper[36];
 /* conversions                                                              */
 /****************************************************************************/
 
+/** \brief Converts an octal digit into an int.
+ * \param[in]  c    the octal char
+ * \return
+ *   - 0–7 if c is a valid octal digit,
+ *   - -1 on error.
+ */
+static inline int octval(int c) {
+    return !(c & ~127) && __m_strdigits[c] < 7 ? __m_strdigits[c] : -1;
+}
+
 /** \brief Converts an hexadecimal digit into an int.
  * \param[in]  c    the hexadecimal char
  * \return
@@ -193,10 +203,56 @@ static inline ssize_t m_strnlen(const char *s, ssize_t n) {
     return 0;
 }
 
+ssize_t m_strwidth(const char *s);
+
 /****************************************************************************/
 /* comparisons                                                              */
 /****************************************************************************/
 
+/** \brief Tells whether s begins with p.
+ *
+ * \param[in]  s     the input string
+ * \param[in]  p     the prefix
+ * \param[out] pp    position in s
+ *
+ * \return 1 if a match is found, 0 otherwise.
+ */
+static inline int m_strstart(const char *s, const char *p, const char **pp)
+{
+    if (!s)
+        return 0;
+
+    while (*p) {
+        if (ascii_tolower(*s++) != ascii_tolower(*p++))
+            return 0;
+    }
+    if (pp)
+        *pp = s;
+    return 1;
+}
+
+/** \brief Tells whether s begins with p, case insensitive.
+ *
+ * \param[in]  s     the input string
+ * \param[in]  p     the prefix
+ * \param[out] pp    position in s
+ *
+ * \return 1 if a match is found, 0 otherwise.
+ */
+static inline int m_strcasestart(const char *s, const char *p, const char **pp)
+{
+    if (!s)
+        return 0;
+
+    while (*p) {
+        if (*s++ != *p++)
+            return 0;
+    }
+    if (pp)
+        *pp = s;
+    return 1;
+}
+
 /** \brief \c NULL resistant strcmp.
  * \param[in]  a     the first string.
  * \param[in]  b     the second string.
@@ -301,6 +357,25 @@ static inline ssize_t m_strputc(char *dst, ssize_t n, int c) {
     return 1;
 }
 
+/** \brief Sets a portion of a string to a defined character, à la memset.
+ *
+ * \param[in]  dst  pointer to the buffer.
+ * \param[in]  n    size of that buffer, (negative values allowed).
+ * \param[in]  c    the char to use in the padding.
+ * \param[in]  len  length of the padding.
+ * \return MAX(0, len).
+ */
+__attribute__((nonnull(1)))
+static inline ssize_t m_strpad(char *dst, ssize_t n, int c, ssize_t len)
+{
+    ssize_t dlen = MIN(n - 1, len);
+    if (dlen > 0) {
+        memset(dst, c, dlen);
+        dst[dlen] = '\0';
+    }
+    return MAX(0, len);
+}
+
 ssize_t m_strcpy(char *dst, ssize_t n, const char *src)
     __attribute__((nonnull(1)));
 
@@ -340,27 +415,48 @@ m_strncat(char *dst, ssize_t n, const char *src, ssize_t l) {
     return dlen + m_strncpy(dst + dlen, n - dlen, src, l);
 }
 
+/* flags for m_strformat() */
+typedef enum {
+  M_FORMAT_FORCESUBJ   = (1 << 0),  /* print the subject even if unchanged */
+  M_FORMAT_TREE        = (1 << 1),  /* draw the thread tree */
+  M_FORMAT_MAKEPRINT   = (1 << 2),  /* make sure that all chars are printable */
+  M_FORMAT_OPTIONAL    = (1 << 3),
+  M_FORMAT_STAT_FILE   = (1 << 4),  /* used by mutt_attach_fmt */
+  M_FORMAT_INDEX       = (1 << 6),  /* this is a main index entry */
+} format_flag;
+
+typedef const char *
+format_t(char *, ssize_t, char, const char *,
+         const char *, const char *, const char *, anytype, format_flag);
+
+ssize_t m_strformat(char *, ssize_t, int, const char *,
+                    format_t *, anytype, format_flag);
+
 /****************************************************************************/
 /* parsing related                                                          */
 /****************************************************************************/
 
+__attribute__((nonnull(1)))
 static inline const char *m_strchrnul(const char *s, int c) {
     while (*s && *s != c)
         s++;
     return s;
 }
 
+__attribute__((nonnull(1)))
 static inline const char *m_strnextsp(const char *s) {
     while (*s && !isspace((unsigned char)*s))
         s++;
     return s;
 }
 
+__attribute__((nonnull(1)))
 static inline const char *skipspaces(const char *s) {
-    while (*s && isspace((unsigned char)*s))
+    while (isspace((unsigned char)*s))
         s++;
     return s;
 }
+__attribute__((nonnull(1)))
 static inline char *vskipspaces(const char *s) {
     return (char *)skipspaces(s);
 }