Boost logo

Boost :

From: Michiel Salters (Michiel.Salters_at_[hidden])
Date: 2002-01-24 09:23:58


Comments inlined - I haven't looked at POSIX but more
from a C++ interface (user) view.

> -----Original Message-----
> From: mfdylan [mailto:dylan_at_[hidden]]
> Sent: Monday, January 21, 2002 6:28 AM
> To: boost_at_[hidden]
> Subject: [boost] environment variable access
>
> namespace env
> {
>
> typedef std::string string;

Why not "using std::string" ?
 
> bool get(const char* name, string& value)
> {
> assert(name);
> const char* v = getenv(name);
> return v ? (value = v, true) : false;
> }

Why provide a const char* name interface? Provide a std::string
name interface, and take advantage of the conversion from
const char* to string.
I guess you could return the empty string if v==0, that might make more
sense than leaving any old value.

> template <class T>
> bool get(const char* name, T& value)
> {
> assert(name);
> const char* v = getenv(name);
> if (!v) return false;
> std::stringstream s(v);
> return (s >> value);
> }

Same comments, except returning T( ) is not as clearcut.

> template <class T>
> bool get(const string& name, T& value)
> {
> return get(name.c_str(), value);
> }

The previous comment on name would make this version redundant.
 
> bool set(const string& name, const string& value)
> {
> // NB not thread-safe, need lock here
> static std::map<string, string> m_strings;
>
> m_strings[name] = name + '=' + value;
> putenv(m_strings[name].c_str());
> return true;
> }

What purpose is served by m_strings ? It seems to be a write-only
map. Furthermore, using m_strings[name] to get back a string you
had only one statement earlier is rather expensive.

> template <class T>
> bool set(const string& name, const T& value)
> {
> std::stringstream s;
> s << value;
> return set(name, s.str());
> }
 
> bool set(const char* name, const string& value)
> {
> assert(name);
> return set(string(name), value);
> }
>
> template <class T>
> bool set(const char* name, const T& value)
> {
> return set(string(name), value);
> }

These two aren't needed - implicit conversion of name.
 
> } // namespace env
>
> ///////////////////////
>
> Sample usage might be:
>
> std::string path;
> if (env::get("PATH", path))
> path += ':';
> env::set("PATH", path + my_directory);
> int level = 0;
> env::get("USER_LEVEL", level);
> env::set("USER_LEVEL", level + 1);
>
> The other alternative would be to treat it like an associative array:
>
> env["PATH"] = path + "my_directory";
> int level = env["USER_LEVEL"];
>
> but then you'd need another call (and function) to determine whether
> an environment variable was set at all, and to define some sensible
> behaviour when trying to access a non-existent variable, or when the
> conversion from string fails (throwing an exception I think is
> overkill, so I suppose setting an error state is the only other
> possibility).

I'm not sure you'd have to choose. You could have both interfaces, and
have [] throw if the variable isn't found . That seems entirely reasonable.

But I'm not sure if you want to go so far as to allow
env["USER_LEVEL"]++; // Trying to be handy.

Regards,
Michiel Salters


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk