]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add RFC 5234 abnf definitions
authorMarco Bettini <marco.bettini@open-xchange.com>
Mon, 18 May 2026 13:05:14 +0000 (13:05 +0000)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Thu, 2 Jul 2026 21:05:23 +0000 (21:05 +0000)
src/lib/Makefile.am
src/lib/abnf.h [new file with mode: 0644]

index 1e4b850fd55b3b90c29d287530f5fa2fa7d71a01..5f0cb181a0e92f2759980db569a057f317857c36 100644 (file)
@@ -263,6 +263,7 @@ liblib_la_SOURCES = \
        write-full.c
 
 headers = \
+       abnf.h \
        aqueue.h \
        array.h \
        array-decl.h \
diff --git a/src/lib/abnf.h b/src/lib/abnf.h
new file mode 100644 (file)
index 0000000..4db109f
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef ABNF_H
+#define ABNF_H
+
+/* RFC 5234 core rules that match a single character only. */
+
+#define ABNF_IS(name, chr) static inline bool abnf_is_##name(char ch) \
+{ return ch == (chr); }
+
+/* bool abnf_is_cr(char ch) and so on */
+ABNF_IS(cr, '\r')
+ABNF_IS(lf, '\n')
+ABNF_IS(dquote, '"')
+ABNF_IS(htab, '\t')
+ABNF_IS(sp, ' ')
+
+#undef ABNF_IS
+
+static inline bool abnf_is_ascii_ctrl(char ch)
+{
+       return (unsigned char)ch <= 0x1f || ch == 0x7f;
+}
+
+static inline bool abnf_is_wsp(char ch)
+{
+       return abnf_is_sp(ch) || abnf_is_htab(ch);
+}
+
+static inline bool abnf_is_ascii_alpha(char ch)
+{
+       return ((ch >= 'A' && ch <= 'Z') ||
+               (ch >= 'a' && ch <= 'z'));
+}
+
+static inline bool abnf_is_ascii_char(char ch)
+{
+       return ch >= 0x01 && (unsigned char)ch <= 0x7f;
+}
+
+static inline bool abnf_is_ascii_printable_char(char ch)
+{
+       return ch >= 0x20 && ch <= 0x7e;
+}
+
+static inline bool abnf_is_ascii_visible_char(char ch)
+{
+       return ch >= 0x21 && ch <= 0x7e;
+}
+
+static inline bool abnf_is_bit(char ch)
+{
+       return ch == '0' || ch == '1';
+}
+
+static inline bool abnf_is_digit(char ch)
+{
+       return ch >= '0' && ch <= '9';
+}
+
+static inline bool abnf_is_hexdig(char ch)
+{
+       /* This intentionally loosens RFC 5234 to accept lowercase too */
+       return abnf_is_digit(ch) ||
+              (ch >= 'A' && ch <= 'F') ||
+              (ch >= 'a' && ch <= 'f');
+}
+
+#define ABNF_CONTAINS_BODY(predicate) \
+       for (; *str != '\0'; ++str) \
+               if (predicate(*str)) \
+                       return TRUE; \
+       return FALSE;
+
+#define ABNF_IS_ONLY_BODY(predicate) \
+       for (; *str != '\0'; ++str) \
+               if (!(predicate(*str))) \
+                       return FALSE; \
+       return TRUE;
+
+#define ABNF_CONTAINS(name, predicate) \
+static inline bool name(const char *str) { ABNF_CONTAINS_BODY(predicate) }
+static inline bool abnf_contains(const char *str, bool (*predicate)(char))
+{
+       ABNF_CONTAINS_BODY(predicate)
+}
+#define ABNF_CONTAINS_GEN(name) ABNF_CONTAINS(abnf_contains_##name, abnf_is_##name)
+
+/* bool abnf_contains_cr(const char *str) and so on */
+ABNF_CONTAINS_GEN(cr)
+ABNF_CONTAINS_GEN(lf)
+ABNF_CONTAINS_GEN(dquote)
+ABNF_CONTAINS_GEN(htab)
+ABNF_CONTAINS_GEN(sp)
+ABNF_CONTAINS_GEN(ascii_ctrl)
+ABNF_CONTAINS_GEN(wsp)
+ABNF_CONTAINS_GEN(ascii_alpha)
+ABNF_CONTAINS_GEN(ascii_char)
+ABNF_CONTAINS_GEN(ascii_printable_char)
+ABNF_CONTAINS_GEN(ascii_visible_char)
+ABNF_CONTAINS_GEN(bit)
+ABNF_CONTAINS_GEN(digit)
+ABNF_CONTAINS_GEN(hexdig)
+
+#undef ABNF_CONTAINS_BODY
+#undef ABNF_CONTAINS_GEN
+#undef ABNF_CONTAINS
+
+#define ABNF_IS_ONLY(name, predicate) \
+static inline bool name(const char *str) { ABNF_IS_ONLY_BODY(predicate) }
+static inline bool abnf_is_only(const char *str, bool (*predicate)(char))
+{
+       ABNF_IS_ONLY_BODY(predicate)
+}
+#define ABNF_IS_ONLY_GEN(name)  ABNF_IS_ONLY(abnf_is_only_##name,   abnf_is_##name)
+
+/* bool abnf_is_only_cr(const char *str) and so on */
+ABNF_IS_ONLY_GEN(cr)
+ABNF_IS_ONLY_GEN(lf)
+ABNF_IS_ONLY_GEN(dquote)
+ABNF_IS_ONLY_GEN(htab)
+ABNF_IS_ONLY_GEN(sp)
+ABNF_IS_ONLY_GEN(ascii_ctrl)
+ABNF_IS_ONLY_GEN(wsp)
+ABNF_IS_ONLY_GEN(ascii_alpha)
+ABNF_IS_ONLY_GEN(ascii_char)
+ABNF_IS_ONLY_GEN(ascii_printable_char)
+ABNF_IS_ONLY_GEN(ascii_visible_char)
+ABNF_IS_ONLY_GEN(bit)
+ABNF_IS_ONLY_GEN(digit)
+ABNF_IS_ONLY_GEN(hexdig)
+
+#undef ABNF_IS_ONLY_BODY
+#undef ABNF_IS_ONLY_GEN
+#undef ABNF_IS_ONLY
+
+#endif