---
.gitignore | 1 +
common/include/Makefile.am | 6 +++
common/include/ascii-ctype.h | 75 ++++++++++++++++++++++++++
common/include/test-ascii-ctype.c | 88 +++++++++++++++++++++++++++++++
4 files changed, 170 insertions(+)
diff --git a/.gitignore b/.gitignore
index f42737131d..90eeadb793 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,6 +34,7 @@ Makefile.in
/bash-completion/nbdinfo
/bash-completion/nbdublk
/common/include/test-array-size
+/common/include/test-ascii-ctype
/common/include/test-checked-overflow
/common/include/test-ispowerof2
/common/utils/test-human-size
diff --git a/common/include/Makefile.am b/common/include/Makefile.am
index fa2633c25a..04553a367d 100644
--- a/common/include/Makefile.am
+++ b/common/include/Makefile.am
@@ -20,6 +20,7 @@ include $(top_srcdir)/subdir-rules.mk
EXTRA_DIST = \
ansi-colours.h \
array-size.h \
+ ascii-ctype.h \
byte-swapping.h \
checked-overflow.h \
compiler-macros.h \
@@ -35,6 +36,7 @@ EXTRA_DIST = \
TESTS = \
test-array-size \
+ test-ascii-ctype \
test-checked-overflow \
test-ispowerof2 \
$(NULL)
@@ -44,6 +46,10 @@ test_array_size_SOURCES = test-array-size.c array-size.h
test_array_size_CPPFLAGS = -I$(srcdir)
test_array_size_CFLAGS = $(WARNINGS_CFLAGS)
+test_ascii_ctype_SOURCES = test-ascii-ctype.c ascii-ctype.h
+test_ascii_ctype_CPPFLAGS = -I$(srcdir)
+test_ascii_ctype_CFLAGS = $(WARNINGS_CFLAGS)
+
test_checked_overflow_SOURCES = test-checked-overflow.c checked-overflow.h
test_checked_overflow_CPPFLAGS = -I$(srcdir)
test_checked_overflow_CFLAGS = $(WARNINGS_CFLAGS)
diff --git a/common/include/ascii-ctype.h b/common/include/ascii-ctype.h
new file mode 100644
index 0000000000..a55dee11b8
--- /dev/null
+++ b/common/include/ascii-ctype.h
@@ -0,0 +1,75 @@
+/* nbdkit
+ * Copyright (C) 2013-2020 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Normal ctype functions are affected by the current locale. For
+ * example isupper() might recognize Ä in some but not all locales.
+ * These functions match only 7 bit ASCII characters.
+ */
+
+#ifndef NBDKIT_ASCII_CTYPE_H
+#define NBDKIT_ASCII_CTYPE_H
+
+#define ascii_isalnum(c) (ascii_isalpha (c) || ascii_isdigit (c))
+
+#define ascii_isalpha(c) \
+ (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A'
&& (c) <= 'Z'))
+
+#define ascii_isdigit(c) \
+ ((c) >= '0' && (c) <= '9')
+
+#define ascii_isspace(c) \
+ ((c) == '\t' || (c) == '\n' || (c) == '\f' || (c) ==
'\r' || (c) == ' ')
+
+#define ascii_isupper(c) \
+ ((c) >= 'A' && (c) <= 'Z')
+
+#define ascii_islower(c) \
+ ((c) >= 'a' && (c) <= 'z')
+
+/* See also hexdigit.h */
+#define ascii_isxdigit(c) \
+ ((c) == '0' || (c) == '1' || (c) == '2' || (c) == '3'
|| (c) == '4' || \
+ (c) == '5' || (c) == '6' || (c) == '7' || (c) == '8'
|| (c) == '9' || \
+ (c) == 'a' || (c) == 'b' || (c) == 'c' ||
\
+ (c) == 'd' || (c) == 'e' || (c) == 'f' ||
\
+ (c) == 'A' || (c) == 'B' || (c) == 'C' ||
\
+ (c) == 'D' || (c) == 'E' || (c) == 'F')
+
+#define ascii_tolower(c) \
+ (ascii_isupper ((c)) ? (c) + 32 : (c))
+
+#define ascii_toupper(c) \
+ (ascii_islower ((c)) ? (c) - 32 : (c))
+
+#define ascii_isprint(c) ((c) >= 32 && (c) <= 126)
+
+#endif /* NBDKIT_ASCII_CTYPE_H */
diff --git a/common/include/test-ascii-ctype.c b/common/include/test-ascii-ctype.c
new file mode 100644
index 0000000000..4fbb0259f8
--- /dev/null
+++ b/common/include/test-ascii-ctype.c
@@ -0,0 +1,88 @@
+/* nbdkit
+ * Copyright (C) 2020 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of Red Hat nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#undef NDEBUG /* Keep test strong even for nbdkit built without assertions */
+#include <assert.h>
+
+#include "ascii-ctype.h"
+
+int
+main (void)
+{
+ assert (ascii_isspace (' '));
+ assert (ascii_isspace ('\t'));
+ assert (ascii_isspace ('\n'));
+ assert (! ascii_isspace ('a'));
+
+ assert (ascii_isalpha ('a'));
+ assert (ascii_isalpha ('Z'));
+ assert (ascii_isalpha ('z'));
+ assert (! ascii_isalpha (' '));
+ assert (! ascii_isalpha ('0'));
+ { const char *s = "Ä"; assert (! ascii_isalpha (s[0])); }
+ { const char *s = "®"; assert (! ascii_isalpha (s[0])); }
+
+ assert (ascii_isdigit ('0'));
+ assert (ascii_isdigit ('9'));
+ { const char *s = "Ø"; assert (! ascii_isdigit (s[0])); } /* U+00D8 */
+ { const char *s = "9"; assert (! ascii_isdigit (s[0])); } /* U+FF19 */
+
+ assert (ascii_islower ('a'));
+ assert (ascii_islower ('z'));
+ assert (! ascii_islower ('Z'));
+ { const char *s = "Ä"; assert (! ascii_islower (s[0])); }
+
+ assert (ascii_isupper ('A'));
+ assert (ascii_isupper ('Z'));
+ assert (! ascii_isupper ('z'));
+ { const char *s = "Ä"; assert (! ascii_isupper (s[0])); }
+
+ assert (ascii_tolower ('A') == 'a');
+ assert (ascii_tolower ('Z') == 'z');
+ assert (ascii_tolower ('a') == 'a');
+ assert (ascii_tolower ('z') == 'z');
+ assert (ascii_tolower ('0') == '0');
+ { const char *s = "Ä"; assert (ascii_tolower (s[0]) == s[0]); }
+
+ assert (ascii_toupper ('a') == 'A');
+ assert (ascii_toupper ('z') == 'Z');
+ assert (ascii_toupper ('A') == 'A');
+ assert (ascii_toupper ('Z') == 'Z');
+ assert (ascii_toupper ('0') == '0');
+ { const char *s = "à"; assert (ascii_toupper (s[0]) == s[0]); }
+
+ exit (EXIT_SUCCESS);
+}
--
2.39.0