[glibmm] Add Glib::Environ and tests/glibmm_environ



commit b8343851afbe33b7ceb50893f9d7221cffce4dd1
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date:   Sun May 23 14:59:54 2021 +0200

    Add Glib::Environ and tests/glibmm_environ
    
    Fixes #89

 glib/glibmm.h                |  1 +
 glib/glibmm/environ.cc       | 58 +++++++++++++++++++++++++++
 glib/glibmm/environ.h        | 93 ++++++++++++++++++++++++++++++++++++++++++++
 glib/glibmm/filelist.am      |  2 +
 glib/glibmm/meson.build      |  1 +
 tests/Makefile.am            |  2 +
 tests/glibmm_environ/main.cc | 48 +++++++++++++++++++++++
 tests/meson.build            |  1 +
 8 files changed, 206 insertions(+)
---
diff --git a/glib/glibmm.h b/glib/glibmm.h
index 44e8cda1..5e3b278d 100644
--- a/glib/glibmm.h
+++ b/glib/glibmm.h
@@ -112,6 +112,7 @@
 #include <glibmm/datetime.h>
 #include <glibmm/dispatcher.h>
 #include <glibmm/enums.h>
+#include <glibmm/environ.h>
 #include <glibmm/error.h>
 #include <glibmm/exceptionhandler.h>
 #include <glibmm/fileutils.h>
diff --git a/glib/glibmm/environ.cc b/glib/glibmm/environ.cc
new file mode 100755
index 00000000..4586ef58
--- /dev/null
+++ b/glib/glibmm/environ.cc
@@ -0,0 +1,58 @@
+/* Copyright (C) 2021 The glibmm Development Team
+ *
+ * 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.1 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glibmm/environ.h>
+#include <glibmm/vectorutils.h>
+
+namespace Glib
+{
+
+Environ::Environ()
+: envp(g_get_environ(), &g_strfreev)
+{}
+
+Environ::Environ(const std::vector<std::string>& env_vec)
+: envp(g_new(char*, env_vec.size() + 1), &g_strfreev)
+{
+  for (unsigned int i = 0; i < env_vec.size(); ++i)
+    envp.get()[i] = g_strdup(env_vec[i].c_str());
+  envp.get()[env_vec.size()] = nullptr;
+}
+
+std::optional<std::string> Environ::get(StdStringView variable) const
+{
+  const char* value = g_environ_getenv(envp.get(), variable.c_str());
+  if (value)
+    return std::optional<std::string>(std::in_place, value);
+  return std::optional<std::string>();
+}
+
+void Environ::set(StdStringView variable, StdStringView value, bool overwrite)
+{
+  envp.reset(g_environ_setenv(envp.release(), variable.c_str(), value.c_str(), overwrite));
+}
+
+void Environ::unset(StdStringView variable)
+{
+  envp.reset(g_environ_unsetenv(envp.release(), variable.c_str()));
+}
+
+std::vector<std::string> Environ::to_vector() const
+{
+  return Glib::ArrayHandler<std::string>::array_to_vector(envp.get(), Glib::OWNERSHIP_NONE);
+}
+
+} // namespace Glib
diff --git a/glib/glibmm/environ.h b/glib/glibmm/environ.h
new file mode 100755
index 00000000..238ef532
--- /dev/null
+++ b/glib/glibmm/environ.h
@@ -0,0 +1,93 @@
+#ifndef _GLIBMM_ENVIRON_H
+#define _GLIBMM_ENVIRON_H
+/* Copyright (C) 2021 The glibmm Development Team
+ *
+ * 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.1 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glibmm/ustring.h>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace Glib
+{
+
+/** A convenience class for manipulating a copy of the environment variables.
+ *
+ * Useful for generating the @a envp parameter in calls to
+ * Glib::spawn_async_with_pipes(), Glib::spawn_async() and Glib::spawn_sync().
+ *
+ * If you want to change the environment itself (i.e. not a copy of it),
+ * see Glib::getenv(), Glib::setenv() and Glib::unsetenv().
+ *
+ * @newin{2,70}
+ */
+class Environ
+{
+public:
+  /** Constructs a list of environment variables for the current process.
+   *
+   * Each item in the list is of the form 'NAME=VALUE'.
+   */
+  GLIBMM_API Environ();
+
+  /** Constructs a %Glib::Environ instance from a vector.
+   *
+   * @param env_vec A vector with the environment variables. Each element in
+   *                the vector must be of the form 'NAME=VALUE'.
+   */
+  GLIBMM_API explicit Environ(const std::vector<std::string>& env_vec);
+
+  /** Gets the value of the environment variable @a variable.
+   *
+   * @param variable The environment variable to get, must not contain '='.
+   * @return The value of the environment variable, or an empty std::optional
+   *         if the environment variable is not set in this %Environ.
+   */
+  GLIBMM_API std::optional<std::string> get(StdStringView variable) const;
+
+  /// Same as get().
+  GLIBMM_API std::optional<std::string> operator[](StdStringView variable) const
+  { return get(variable); }
+
+  /** Sets the environment variable @a variable in the provided list to @a value.
+   *
+   * @param variable The environment variable to set, must not contain '='.
+   * @param value The value to set the variable to.
+   * @param overwrite Whether to change the variable if it already exists.
+   */
+  GLIBMM_API void set(StdStringView variable, StdStringView value, bool overwrite = true);
+
+  /** Removes the environment variable @a variable from the provided list.
+   *
+   * @param variable The environment variable to remove, must not contain '='.
+   */
+  GLIBMM_API void unset(StdStringView variable);
+
+  /** Get a vector with the environment variables.
+   *
+   * @return A vector with the environment variables. Each element in the vector
+   *         is of the form 'NAME=VALUE'.
+   */
+  GLIBMM_API std::vector<std::string> to_vector() const;
+
+private:
+  std::unique_ptr<char*, decltype(&g_strfreev)> envp;
+};
+
+} // namespace Glib
+
+#endif /* _GLIBMM_ENVIRON_H */
diff --git a/glib/glibmm/filelist.am b/glib/glibmm/filelist.am
index e606d5fd..6bd16f1c 100644
--- a/glib/glibmm/filelist.am
+++ b/glib/glibmm/filelist.am
@@ -8,6 +8,7 @@ glibmm_files_extra_cc =                 \
        class.cc                        \
        debug.cc                        \
        dispatcher.cc                   \
+       environ.cc              \
        error.cc                        \
        exceptionhandler.cc             \
        extraclassinit.cc               \
@@ -40,6 +41,7 @@ glibmm_files_extra_h =                        \
        containerhandle_shared.h        \
        debug.h                         \
        dispatcher.h                    \
+       environ.h               \
        error.h                         \
        exceptionhandler.h              \
        extraclassinit.h                \
diff --git a/glib/glibmm/meson.build b/glib/glibmm/meson.build
index b736a3cf..29f55bdd 100644
--- a/glib/glibmm/meson.build
+++ b/glib/glibmm/meson.build
@@ -76,6 +76,7 @@ glibmm_extra_h_cc_basenames = [
   'class',
   'debug',
   'dispatcher',
+  'environ',
   'error',
   'exceptionhandler',
   'extraclassinit',
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9adab850..9887f204 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -29,6 +29,7 @@ check_PROGRAMS =                              \
        glibmm_base64/test                      \
        glibmm_binding/test     \
        glibmm_date/test                        \
+       glibmm_environ/test                     \
        glibmm_buildfilename/test               \
        glibmm_interface_implementation/test    \
        glibmm_interface_move/test                      \
@@ -97,6 +98,7 @@ glibmm_base64_test_SOURCES               = glibmm_base64/main.cc
 glibmm_binding_test_SOURCES              = glibmm_binding/main.cc
 glibmm_buildfilename_test_SOURCES        = glibmm_buildfilename/main.cc
 glibmm_date_test_SOURCES                 = glibmm_date/main.cc
+glibmm_environ_test_SOURCES              = glibmm_environ/main.cc
 
 glibmm_interface_implementation_test_SOURCES = glibmm_interface_implementation/main.cc
 glibmm_interface_implementation_test_LDADD = $(giomm_ldadd)
diff --git a/tests/glibmm_environ/main.cc b/tests/glibmm_environ/main.cc
new file mode 100755
index 00000000..c99e279d
--- /dev/null
+++ b/tests/glibmm_environ/main.cc
@@ -0,0 +1,48 @@
+#include <glibmm.h>
+#include <iostream>
+
+int
+main(int, char**)
+{
+  Glib::Environ env1;
+  Glib::Environ env2(env1.to_vector());
+  g_assert_true(env1.to_vector() == env2.to_vector());
+
+  // Empty environment.
+  const std::vector<std::string> empty_vector;
+  Glib::Environ env3(empty_vector);
+  g_assert_true(env3.to_vector().size() == 0);
+
+  auto path = env1.get("PATH");
+  if (!path)
+  {
+    // There ought to be a PATH. If there isn't, add one.
+    std::cout << "No PATH!" << std::endl;
+    env1.set("PATH", "/a/b/c");
+  }
+
+  path = env1["PATH"];
+  if (!path)
+  {
+    // Now there really must be a PATH.
+    std::cerr << "Still no PATH!" << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  const std::string name = "GLIBMM_TEST_VAR";
+  const std::string value = "This is a test value";
+  env1.set(name, value);
+  g_assert_true(env1[name] == value);
+  env1.set(name, "Second value", false);
+  g_assert_true(env1.get(name) == value);
+  env1.set(name, "Second value");
+  g_assert_true(env1.get(name) == "Second value");
+  env1.unset(name);
+  if (env1.get(name))
+  {
+    std::cerr << name << " not removed" << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  return EXIT_SUCCESS;
+}
diff --git a/tests/meson.build b/tests/meson.build
index 653ed878..4d1135dc 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -18,6 +18,7 @@ test_programs = [
   [['glibmm_buildfilename'], 'test', ['main.cc'], false],
   [['glibmm_bytearray'], 'test', ['main.cc'], false],
   [['glibmm_date'], 'test', ['main.cc'], false],
+  [['glibmm_environ'], 'test', ['main.cc'], false],
   [['glibmm_interface_implementation'], 'test', ['main.cc'], true],
   [['glibmm_interface_move'], 'test', ['main.cc'], false],
   [['glibmm_mainloop'], 'test', ['main.cc'], false],


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