[libglnx] Add G_IN_SET, patch our internal users via spatch



commit 9a1b77ef96b4eb9a916a71e7a04055c4c5665dea
Author: Colin Walters <walters verbum org>
Date:   Tue Jun 13 16:22:09 2017 -0400

    Add G_IN_SET, patch our internal users via spatch
    
    I originally tried to get this into GLib:
    https://bugzilla.gnome.org/show_bug.cgi?id=783751
    
    But that looks like it's going to fail due to MSVC. Let's add it here at least
    so I can start using it tomorrow and not wait for the MSVC team to catch up.
    
    I renamed `glnx-alloca.h` to `glnx-macros.h` as a more natural collective
    home for things from systemd's `macro.h`.
    
    Finally, I used a Coccinelle spatch similar to the one referenced
    in the above BZ to patch our uses.

 Makefile-libglnx.am         |    8 ++-
 glnx-alloca.h               |   47 -----------------
 glnx-fdio.c                 |    7 +--
 glnx-fdio.h                 |    3 +-
 glnx-macros.h               |  115 +++++++++++++++++++++++++++++++++++++++++++
 glnx-xattrs.c               |    5 +-
 libglnx.h                   |    2 +-
 tests/test-libglnx-macros.c |   48 ++++++++++++++++++
 8 files changed, 178 insertions(+), 57 deletions(-)
---
diff --git a/Makefile-libglnx.am b/Makefile-libglnx.am
index 805a9d0..6df05ea 100644
--- a/Makefile-libglnx.am
+++ b/Makefile-libglnx.am
@@ -22,7 +22,7 @@ EXTRA_DIST += \
        $(NULL)
 
 libglnx_la_SOURCES = \
-       $(libglnx_srcpath)/glnx-alloca.h \
+       $(libglnx_srcpath)/glnx-macros.h \
        $(libglnx_srcpath)/glnx-backport-autocleanups.h \
        $(libglnx_srcpath)/glnx-backport-autoptr.h \
        $(libglnx_srcpath)/glnx-backports.h \
@@ -52,7 +52,7 @@ libglnx_la_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags)
 libglnx_la_LDFLAGS = -avoid-version -Bsymbolic-functions -export-symbols-regex "^glnx_" -no-undefined 
-export-dynamic 
 libglnx_la_LIBADD = $(libglnx_libs)
 
-libglnx_tests = test-libglnx-xattrs test-libglnx-fdio test-libglnx-errors
+libglnx_tests = test-libglnx-xattrs test-libglnx-fdio test-libglnx-errors test-libglnx-macros
 TESTS += $(libglnx_tests)
 
 check_PROGRAMS += $(libglnx_tests)
@@ -67,3 +67,7 @@ test_libglnx_fdio_LDADD = $(libglnx_libs) libglnx.la
 test_libglnx_errors_SOURCES = $(libglnx_srcpath)/tests/test-libglnx-errors.c
 test_libglnx_errors_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags)
 test_libglnx_errors_LDADD = $(libglnx_libs) libglnx.la
+
+test_libglnx_macros_SOURCES = $(libglnx_srcpath)/tests/test-libglnx-macros.c
+test_libglnx_macros_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags)
+test_libglnx_macros_LDADD = $(libglnx_libs) libglnx.la
diff --git a/glnx-fdio.c b/glnx-fdio.c
index 87e2dbb..e496828 100644
--- a/glnx-fdio.c
+++ b/glnx-fdio.c
@@ -37,7 +37,6 @@
 
 #include <glnx-fdio.h>
 #include <glnx-dirfd.h>
-#include <glnx-alloca.h>
 #include <glnx-errors.h>
 #include <glnx-xattrs.h>
 #include <glnx-backport-autoptr.h>
@@ -65,7 +64,7 @@ glnx_renameat2_noreplace (int olddirfd, const char *oldpath,
 #ifndef ENABLE_WRPSEUDO_COMPAT
   if (renameat2 (olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE) < 0)
     {
-      if (errno == EINVAL || errno == ENOSYS)
+      if (G_IN_SET(errno, EINVAL, ENOSYS))
         {
           /* Fall through */
         }
@@ -119,7 +118,7 @@ glnx_renameat2_exchange (int olddirfd, const char *oldpath,
     return 0;
   else
     {
-      if (errno == ENOSYS || errno == EINVAL)
+      if (G_IN_SET(errno, ENOSYS, EINVAL))
         {
           /* Fall through */
         }
@@ -195,7 +194,7 @@ glnx_open_tmpfile_linkable_at (int dfd,
    * in full. */
 #if defined(O_TMPFILE) && !defined(DISABLE_OTMPFILE) && !defined(ENABLE_WRPSEUDO_COMPAT)
   fd = openat (dfd, subpath, O_TMPFILE|flags, 0600);
-  if (fd == -1 && !(errno == ENOSYS || errno == EISDIR || errno == EOPNOTSUPP))
+  if (fd == -1 && !(G_IN_SET(errno, ENOSYS, EISDIR, EOPNOTSUPP)))
     return glnx_throw_errno_prefix (error, "open(O_TMPFILE)");
   if (fd != -1)
     {
diff --git a/glnx-fdio.h b/glnx-fdio.h
index e52c823..95574bd 100644
--- a/glnx-fdio.h
+++ b/glnx-fdio.h
@@ -35,6 +35,7 @@
 #include <libgen.h>
 #undef basename
 
+#include <glnx-macros.h>
 #include <glnx-errors.h>
 
 G_BEGIN_DECLS
@@ -189,7 +190,7 @@ glnx_try_fallocate (int      fd,
 
   if (fallocate (fd, 0, offset, size) < 0)
     {
-      if (errno == ENOSYS || errno == EOPNOTSUPP)
+      if (G_IN_SET(errno, ENOSYS, EOPNOTSUPP))
         ; /* Ignore */
       else
         return glnx_throw_errno_prefix (error, "fallocate");
diff --git a/glnx-macros.h b/glnx-macros.h
new file mode 100644
index 0000000..87c25ca
--- /dev/null
+++ b/glnx-macros.h
@@ -0,0 +1,115 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Colin Walters <walters verbum org>
+ * With original source from systemd:
+ * Copyright 2010 Lennart Poettering
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#pragma once
+
+#include <stdlib.h>
+#include <string.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/* Taken from https://github.com/systemd/systemd/src/basic/string-util.h
+ * at revision v228-666-gcf6c8c4
+ */
+#define glnx_strjoina(a, ...)                                           \
+        ({                                                              \
+                const char *_appendees_[] = { a, __VA_ARGS__ };         \
+                char *_d_, *_p_;                                        \
+                int _len_ = 0;                                          \
+                unsigned _i_;                                           \
+                for (_i_ = 0; _i_ < G_N_ELEMENTS(_appendees_) && _appendees_[_i_]; _i_++) \
+                        _len_ += strlen(_appendees_[_i_]);              \
+                _p_ = _d_ = alloca(_len_ + 1);                          \
+                for (_i_ = 0; _i_ < G_N_ELEMENTS(_appendees_) && _appendees_[_i_]; _i_++) \
+                        _p_ = stpcpy(_p_, _appendees_[_i_]);            \
+                *_p_ = 0;                                               \
+                _d_;                                                    \
+        })
+
+#ifndef G_IN_SET
+
+/* Infrastructure for `G_IN_SET`; this code is copied from
+ * systemd's macro.h - please treat that version as canonical
+ * and submit patches first to systemd.
+ */
+#define _G_INSET_CASE_F(X) case X:
+#define _G_INSET_CASE_F_1(CASE, X) _G_INSET_CASE_F(X)
+#define _G_INSET_CASE_F_2(CASE, X, ...)  CASE(X) _G_INSET_CASE_F_1(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_3(CASE, X, ...)  CASE(X) _G_INSET_CASE_F_2(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_4(CASE, X, ...)  CASE(X) _G_INSET_CASE_F_3(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_5(CASE, X, ...)  CASE(X) _G_INSET_CASE_F_4(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_6(CASE, X, ...)  CASE(X) _G_INSET_CASE_F_5(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_7(CASE, X, ...)  CASE(X) _G_INSET_CASE_F_6(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_8(CASE, X, ...)  CASE(X) _G_INSET_CASE_F_7(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_9(CASE, X, ...)  CASE(X) _G_INSET_CASE_F_8(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_10(CASE, X, ...) CASE(X) _G_INSET_CASE_F_9(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_11(CASE, X, ...) CASE(X) _G_INSET_CASE_F_10(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_12(CASE, X, ...) CASE(X) _G_INSET_CASE_F_11(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_13(CASE, X, ...) CASE(X) _G_INSET_CASE_F_12(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_14(CASE, X, ...) CASE(X) _G_INSET_CASE_F_13(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_15(CASE, X, ...) CASE(X) _G_INSET_CASE_F_14(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_16(CASE, X, ...) CASE(X) _G_INSET_CASE_F_15(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_17(CASE, X, ...) CASE(X) _G_INSET_CASE_F_16(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_18(CASE, X, ...) CASE(X) _G_INSET_CASE_F_17(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_19(CASE, X, ...) CASE(X) _G_INSET_CASE_F_18(CASE, __VA_ARGS__)
+#define _G_INSET_CASE_F_20(CASE, X, ...) CASE(X) _G_INSET_CASE_F_19(CASE, __VA_ARGS__)
+
+#define _G_INSET_GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) 
NAME
+#define _G_INSET_FOR_EACH_MAKE_CASE(...) \
+  
_G_INSET_GET_CASE_F(__VA_ARGS__,_G_INSET_CASE_F_20,_G_INSET_CASE_F_19,_G_INSET_CASE_F_18,_G_INSET_CASE_F_17,_G_INSET_CASE_F_16,_G_INSET_CASE_F_15,_G_INSET_CASE_F_14,_G_INSET_CASE_F_13,_G_INSET_CASE_F_12,_G_INSET_CASE_F_11,
 \
+                               
_G_INSET_CASE_F_10,_G_INSET_CASE_F_9,_G_INSET_CASE_F_8,_G_INSET_CASE_F_7,_G_INSET_CASE_F_6,_G_INSET_CASE_F_5,_G_INSET_CASE_F_4,_G_INSET_CASE_F_3,_G_INSET_CASE_F_2,_G_INSET_CASE_F_1)
 \
+                   (_G_INSET_CASE_F,__VA_ARGS__)
+
+/* Note: claiming the name here even though it isn't upstream yet
+ * https://bugzilla.gnome.org/show_bug.cgi?id=783751
+ */
+/**
+ * G_IN_SET:
+ * @x: Integer (or smaller) sized value
+ * @...: Elements to compare
+ *
+ * It's quite common to test whether or not `char` values or Unix @errno (among) others
+ * are members of a small set.  Normally one has to choose to either use `if (x == val || x == otherval ...)`
+ * or a `switch` statement.  This macro is useful to reduce duplication in the first case,
+ * where one can write simply `if (G_IN_SET (x, val, otherval))`, and avoid the verbosity
+ * that the `switch` statement requires.
+ */
+#define G_IN_SET(x, ...)                          \
+        ({                                      \
+                gboolean _g_inset_found = FALSE;            \
+                /* If the build breaks in the line below, you need to extend the case macros */ \
+                static G_GNUC_UNUSED char _static_assert__macros_need_to_be_extended[20 - 
sizeof((int[]){__VA_ARGS__})/sizeof(int)]; \
+                switch(x) {                     \
+                _G_INSET_FOR_EACH_MAKE_CASE(__VA_ARGS__) \
+                        _g_inset_found = TRUE;          \
+                        break;                  \
+                default:                        \
+                        break;                  \
+                }                               \
+                _g_inset_found;                 \
+        })
+
+#endif /* ifndef G_IN_SET */
+
+
+G_END_DECLS
diff --git a/glnx-xattrs.c b/glnx-xattrs.c
index 3c1a9c5..3ade89c 100644
--- a/glnx-xattrs.c
+++ b/glnx-xattrs.c
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <stdio.h>
 
+#include <glnx-macros.h>
 #include <glnx-xattrs.h>
 #include <glnx-errors.h>
 #include <glnx-local-alloc.h>
@@ -249,7 +250,7 @@ glnx_dfd_name_get_all_xattrs (int            dfd,
                               GCancellable  *cancellable,
                               GError       **error)
 {
-  if (dfd == AT_FDCWD || dfd == -1)
+  if (G_IN_SET(dfd, AT_FDCWD, -1))
     {
       return get_xattrs_impl (name, -1, out_xattrs, cancellable, error);
     }
@@ -306,7 +307,7 @@ glnx_dfd_name_set_all_xattrs (int            dfd,
                               GCancellable  *cancellable,
                               GError       **error)
 {
-  if (dfd == AT_FDCWD || dfd == -1)
+  if (G_IN_SET(dfd, AT_FDCWD, -1))
     {
       return set_all_xattrs_for_path (name, xattrs, cancellable, error);
     }
diff --git a/libglnx.h b/libglnx.h
index a5b23d0..494810d 100644
--- a/libglnx.h
+++ b/libglnx.h
@@ -24,7 +24,7 @@
 
 G_BEGIN_DECLS
 
-#include <glnx-alloca.h>
+#include <glnx-macros.h>
 #include <glnx-local-alloc.h>
 #include <glnx-backport-autocleanups.h>
 #include <glnx-backports.h>
diff --git a/tests/test-libglnx-macros.c b/tests/test-libglnx-macros.c
new file mode 100644
index 0000000..d16c100
--- /dev/null
+++ b/tests/test-libglnx-macros.c
@@ -0,0 +1,48 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "libglnx.h"
+#include <glib.h>
+#include <stdlib.h>
+#include <gio/gio.h>
+#include <string.h>
+
+static void
+test_inset (void)
+{
+  g_assert (G_IN_SET (7, 7));
+  g_assert (G_IN_SET (7, 42, 7));
+  g_assert (G_IN_SET (7, 7,42,3,9));
+  g_assert (G_IN_SET (42, 7,42,3,9));
+  g_assert (G_IN_SET (3, 7,42,3,9));
+  g_assert (G_IN_SET (9, 7,42,3,9));
+  g_assert (!G_IN_SET (8, 7,42,3,9));
+  g_assert (!G_IN_SET (-1, 7,42,3,9));
+  g_assert (G_IN_SET ('x', 'a', 'x', 'c'));
+  g_assert (!G_IN_SET ('y', 'a', 'x', 'c'))
+}
+
+int main (int argc, char **argv)
+{
+  g_test_init (&argc, &argv, NULL);
+  g_test_add_func ("/inset", test_inset);
+  return g_test_run();
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]