/* Header for environment manipulation library.
   Copyright (C) 1989-2017 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#if !defined (ENVIRON_H)
#define ENVIRON_H 1

#include <vector>
#include <set>

/* Class that represents the environment variables as seen by the
   inferior.  */

class gdb_environ
{
public:
  /* Regular constructor and destructor.  */
  gdb_environ ()
  {
    /* Make sure that the vector contains at least a NULL element.
       If/when we add more variables to it, NULL will always be the
       last element.  */
    m_environ_vector.push_back (NULL);
  }

  ~gdb_environ ()
  {
    clear ();
  }

  /* Move constructor.  */
  gdb_environ (gdb_environ &&e)
    : m_environ_vector (std::move (e.m_environ_vector)),
      m_user_set_env (std::move (e.m_user_set_env)),
      m_user_unset_env (std::move (e.m_user_unset_env))
  {
    /* Make sure that the moved-from vector is left at a valid
       state (only one NULL element).  */
    e.m_environ_vector.clear ();
    e.m_environ_vector.push_back (NULL);
    e.m_user_set_env.clear ();
    e.m_user_unset_env.clear ();
  }

  /* Move assignment.  */
  gdb_environ &operator= (gdb_environ &&e);

  /* Create a gdb_environ object using the host's environment
     variables.  */
  static gdb_environ from_host_environ ();

  /* Clear the environment variables stored in the object.  */
  void clear ();

  /* Return the value in the environment for the variable VAR.  The
     returned pointer is only valid as long as the gdb_environ object
     is not modified.  */
  const char *get (const char *var) const;

  /* Store VAR=VALUE in the environment.  */
  void set (const char *var, const char *value);

  /* Unset VAR in environment.  */
  void unset (const char *var);

  /* Return the environment vector represented as a 'char **'.  */
  char **envp () const;

  /* Return the user-set environment vector.  */
  const std::set<std::string> &user_set_env () const;

  /* Return the user-unset environment vector.  */
  const std::set<std::string> &user_unset_env () const;

private:
  /* Unset VAR in environment.  If UPDATE_UNSET_LIST is true, then
     also update M_USER_UNSET_ENV to reflect the unsetting of the
     environment variable.  */
  void unset (const char *var, bool update_unset_list);

  /* A vector containing the environment variables.  */
  std::vector<char *> m_environ_vector;

  /* The environment variables explicitly set by the user.  */
  std::set<std::string> m_user_set_env;

  /* The environment variables explicitly unset by the user.  */
  std::set<std::string> m_user_unset_env;
};

#endif /* defined (ENVIRON_H) */
