X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-lib%2Fstr.h;h=8c793fb77d2578626a299d71d65631d13a534ed3;hp=4ef9d485914c2579d4f2b669475688286bef8041;hb=4dbc0e4a9d573611d4f521400a2e16f47c176639;hpb=1c16e9623a9fb6a15bb284a6f7322b583ebc06a7 diff --git a/lib-lib/str.h b/lib-lib/str.h index 4ef9d48..8c793fb 100644 --- a/lib-lib/str.h +++ b/lib-lib/str.h @@ -16,16 +16,113 @@ * * Copyright © 2006 Pierre Habouzit */ +/* + * Copyright notice from original mutt: + * Copyright (C) 2001 Thomas Roessler + */ #ifndef MUTT_LIB_LIB_STR_H #define MUTT_LIB_LIB_STR_H -#include -#include "../lib/str.h" +/** \defgroup mutt_strings Madmutt string API + * + * This module contains the prefered string API to be used in Madmutt. + * + * Those function reimplement many usual calls (strlen, strcpy, strcat, …) + * It's intended to provide a uniform and consistent API to deal with usual C + * strings. + * + * The strong point that have to be followed are: + * - strings are always \c '\\0' terminated, meaning that we don't have + * stupid semantics à la strncpy. + * - function try to always work on buffers with its size (including the + * ending \c '\\0') to prevent buffer overflows. + * - string and buffers sizes are \c ssize_t, negative values are allowed and + * supported. + * - functions use a à la sprintf semantics (for those that produce strings) + * meaning that they all return the len that could have fit in the buffer + * if it would have been big enough. We never try to reallocate the + * buffers, it's up to the caller if it's needed. + */ +/*@{*/ + +/** \file str.h + * \brief Madmutt string API header. + * \author Pierre Habouzit + */ + +#define HUGE_STRING 5120 /**< \brief Huge buffers */ +#define LONG_STRING 1024 /**< \brief Long buffers */ +#define STRING 256 /**< \brief Usual buffers */ + +#define NONULL(x) (x ? x : "") /**< \brief replace \c NULL strings + with emtpy strings */ +#define ISSPACE(c) isspace((unsigned char)c) /**< \brief safe isspace */ + +/** \brief Convert ascii digits into ints. + * + * Convert ascii digits into its integer value in base 36. + * Non convertible values are converted to 255. + * + * Translating a digit \c c into its numerical value in base \c x is just doing: + * \code + * return (c & ~127) && __m_strdigits[c] < x ? __m_strdigits[c] : -1; + * \endcode + */ +extern unsigned char const __m_strdigits[128]; +/** \brief Convert an ascii base64 digit into ints. + * + * Convert an a char base64 digit into its int value. + * Used by base64val(). Unlike #__m_strdigits, the invalid values are set to + * -1 instead of 255. + */ +extern signed char const __m_b64digits[128]; + +/** \brief Convert ints from 0–64 into the corresponding base64 digit. */ +extern char const __m_b64chars[64]; +/** \brief Convert ints from 0–36 into a base36 lowercase digit. */ +extern char const __m_b36chars_lower[36]; +/** \brief Convert ints from 0–36 into a base36 uppercase digit. */ +extern char const __m_b36chars_upper[36]; + +/****************************************************************************/ +/* conversions */ +/****************************************************************************/ + +static inline int hexval(int c) { + return !(c & ~127) && __m_strdigits[c] < 16 ? __m_strdigits[c] : -1; +} + +static inline int base64val(int c) { + return (c & ~127) ? -1 : __m_b64digits[c]; +} + +static inline void m_strtolower(char *p) { + for (; *p; p++) + *p = tolower((unsigned char)*p); +} + +static inline int ascii_toupper(int c) { + if ('a' <= c && c <= 'z') + return c & ~32; + + return c; +} + +static inline int ascii_tolower(int c) { + if ('A' <= c && c <= 'Z') + return c | 32; -#include "mem.h" + return c; +} + +/****************************************************************************/ +/* length related */ +/****************************************************************************/ -#define NONULL(x) (x?x:"") +static inline int m_strisempty(const char *s) { + return !s || !*s; +} static inline ssize_t m_strlen(const char *s) { return s ? strlen(s) : 0; @@ -36,17 +133,60 @@ static inline ssize_t m_strnlen(const char *s, ssize_t n) { return p ? p - s : n; } -static inline char *m_strdup(const char *s) { - return p_dupstr(s, m_strlen(s)); -} +/****************************************************************************/ +/* comparisons */ +/****************************************************************************/ static inline int m_strcmp(const char *a, const char *b) { return strcmp(NONULL(a), NONULL(b)); } +static inline int m_strcasecmp(const char *a, const char *b) { + return strcasecmp(NONULL(a), NONULL(b)); +} + +static inline int m_strncmp(const char *a, const char *b, ssize_t n) { + return strncmp(NONULL(a), NONULL(b), n); +} + +static inline int m_strncasecmp(const char *a, const char *b, ssize_t n) { + return strncasecmp(NONULL(a), NONULL(b), n); +} + +int ascii_strcasecmp(const char *a, const char *b); +int ascii_strncasecmp(const char *a, const char *b, ssize_t n); + +/****************************************************************************/ +/* making copies */ +/****************************************************************************/ + +static inline char *m_strdup(const char *s) { + ssize_t len = m_strlen(s); + return len ? p_dup(s, len + 1) : NULL; +} + +static inline char *m_substrdup(const char *s, const char *end) { + return p_dupstr(s, end ? end - s : m_strlen(s)); +} + +static inline char *m_strreplace(char **p, const char *s) { + p_delete(p); + return (*p = m_strdup(s)); +} -ssize_t m_strcpy(char *dst, ssize_t n, const char *src); -ssize_t m_strncpy(char *dst, ssize_t n, const char *src, ssize_t l); +static inline ssize_t m_strputc(char *dst, ssize_t n, int c) { + if (n > 1) { + dst[0] = c; + dst[1] = '\0'; + } + return 1; +} + +ssize_t m_strcpy(char *dst, ssize_t n, const char *src) + __attribute__((nonnull(1))); + +ssize_t m_strncpy(char *dst, ssize_t n, const char *src, ssize_t l) + __attribute__((nonnull(1))); static inline ssize_t m_strcat(char *dst, ssize_t n, const char *src) { ssize_t dlen = m_strnlen(dst, n - 1); @@ -59,4 +199,44 @@ m_strncat(char *dst, ssize_t n, const char *src, ssize_t l) { return dlen + m_strncpy(dst + dlen, n - dlen, src, l); } +/****************************************************************************/ +/* parsing related */ +/****************************************************************************/ + +static inline const char *m_strchrnul(const char *s, int c) { + while (*s && *s != c) + s++; + return s; +} + +static inline const char *m_strnextsp(const char *s) { + while (*s && !isspace((unsigned char)*s)) + s++; + return s; +} + +static inline const char *skipspaces(const char *s) { + while (*s && isspace((unsigned char)*s)) + s++; + return s; +} +static inline char *vskipspaces(const char *s) { + return (char *)skipspaces(s); +} + +char *m_strrtrim(char *s); + +/****************************************************************************/ +/* search */ +/****************************************************************************/ + +const char * +m_stristrn(const char *haystack, const char *needle, ssize_t nlen); + +static inline const char * +m_stristr(const char *haystack, const char *needle) { + return m_stristrn(haystack, needle, m_strlen(needle)); +} + +/*@}*/ #endif /* MUTT_LIB_LIB_STR_H */