Migrate universal variables to env_var_t structure. Encapsulate

universal variable storage into a class for better testability.
This commit is contained in:
ridiculousfish 2014-04-25 16:09:26 -07:00
parent bb0b82a110
commit a475dd15e6
7 changed files with 147 additions and 93 deletions

29
env.cpp
View file

@ -80,20 +80,6 @@ extern char **environ;
*/
extern char **__environ;
/**
A variable entry. Stores the value of a variable and whether it
should be exported. Obviously, it needs to be allocated large
enough to fit the value string.
*/
struct var_entry_t
{
wcstring val; /**< The value of the variable */
bool exportv; /**< Whether the variable should be exported */
var_entry_t() : exportv(false) { }
};
typedef std::map<wcstring, var_entry_t> var_table_t;
bool g_log_forks = false;
bool g_use_posix_spawn = false; //will usually be set to true
@ -824,7 +810,7 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode)
env_universal_barrier();
}
if (env_universal_get(key))
if (! env_universal_get(key).missing())
{
bool exportv;
if (var_mode & ENV_EXPORT)
@ -1071,9 +1057,9 @@ env_var_t env_get_string(const wcstring &key)
env_universal_barrier();
}
const wchar_t *item = env_universal_get(key);
env_var_t item = env_universal_get(key);
if (!item || (wcscmp(item, ENV_NULL)==0))
if (item.missing() || (wcscmp(item.c_str(), ENV_NULL)==0))
{
return env_var_t::missing_var();
}
@ -1087,7 +1073,6 @@ env_var_t env_get_string(const wcstring &key)
bool env_exist(const wchar_t *key, int mode)
{
env_node_t *env;
const wchar_t *item = NULL;
CHECK(key, false);
@ -1151,9 +1136,7 @@ bool env_exist(const wchar_t *key, int mode)
env_universal_barrier();
}
item = env_universal_get(key);
if (item != NULL)
if (! env_universal_get(key).missing())
{
if (mode & ENV_EXPORT)
{
@ -1419,9 +1402,9 @@ static void update_export_array_if_necessary(bool recalc)
for (i=0; i<uni.size(); i++)
{
const wcstring &key = uni.at(i);
const wchar_t *val = env_universal_get(key);
const env_var_t val = env_universal_get(key);
if (wcscmp(val, ENV_NULL))
if (! val.missing() && wcscmp(val.c_str(), ENV_NULL))
{
// Note that std::map::insert does NOT overwrite a value already in the map,
// which we depend on here

13
env.h
View file

@ -242,5 +242,18 @@ extern int g_fork_count;
extern bool g_use_posix_spawn;
/**
A variable entry. Stores the value of a variable and whether it
should be exported.
*/
struct var_entry_t
{
wcstring val; /**< The value of the variable */
bool exportv; /**< Whether the variable should be exported */
var_entry_t() : exportv(false) { }
};
typedef std::map<wcstring, var_entry_t> var_table_t;
#endif

View file

@ -38,6 +38,7 @@
#include "wutil.h"
#include "env_universal_common.h"
#include "env_universal.h"
#include "env.h"
/**
Maximum number of times to try to get a new fishd socket
@ -345,10 +346,10 @@ int env_universal_read_all()
}
}
const wchar_t *env_universal_get(const wcstring &name)
env_var_t env_universal_get(const wcstring &name)
{
if (!s_env_univeral_inited)
return NULL;
return env_var_t::missing_var();
return env_universal_common_get(name);
}
@ -462,14 +463,15 @@ int env_universal_remove(const wchar_t *name)
CHECK(name, 1);
res = !env_universal_common_get(name);
wcstring name_str = name;
res = env_universal_common_get(name_str).missing();
debug(3,
L"env_universal_remove( \"%ls\" )",
name);
if (is_dead())
{
env_universal_common_remove(wcstring(name));
env_universal_common_remove(name_str);
}
else
{

View file

@ -8,6 +8,7 @@
#include <wchar.h>
#include "env_universal_common.h"
#include "env.h"
/**
Data about the universal variable server.
@ -29,7 +30,7 @@ void env_universal_destroy();
/**
Get the value of a universal variable
*/
const wchar_t *env_universal_get(const wcstring &name);
env_var_t env_universal_get(const wcstring &name);
/**
Get the export flag of the variable with the specified

View file

@ -86,28 +86,13 @@
*/
#define ENV_UNIVERSAL_EOF 0x102
/**
A variable entry. Stores the value of a variable and whether it
should be exported. Obviously, it needs to be allocated large
enough to fit the value string.
*/
typedef struct var_uni_entry
{
bool exportv; /**< Whether the variable should be exported */
wcstring val; /**< The value of the variable */
var_uni_entry():exportv(false), val() { }
}
var_uni_entry_t;
static void parse_message(wchar_t *msg,
connection_t *src);
/**
The table of all universal variables
*/
typedef std::map<wcstring, var_uni_entry_t> env_var_table_t;
env_var_table_t env_universal_var;
static env_universal_t s_env_universal_var;
/**
Callback function, should be called on all events
@ -269,7 +254,7 @@ void read_message(connection_t *src)
*/
void env_universal_common_remove(const wcstring &name)
{
env_universal_var.erase(name);
s_env_universal_var.remove(name);
}
/**
@ -291,10 +276,8 @@ void env_universal_common_set(const wchar_t *key, const wchar_t *val, bool expor
{
CHECK(key,);
CHECK(val,);
var_uni_entry_t &entry = env_universal_var[key];
entry.exportv=exportv;
entry.val = val;
s_env_universal_var.set(key, val, exportv);
if (callback)
{
@ -601,60 +584,26 @@ message_t *create_message(fish_message_type_t type,
/**
Put exported or unexported variables in a string list
*/
void env_universal_common_get_names(wcstring_list_t &lst,
bool show_exported,
bool show_unexported)
void env_universal_common_get_names(wcstring_list_t &lst, bool show_exported, bool show_unexported)
{
env_var_table_t::const_iterator iter;
for (iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
{
const wcstring &key = iter->first;
const var_uni_entry_t &e = iter->second;
if ((e.exportv && show_exported) || (! e.exportv && show_unexported))
{
lst.push_back(key);
}
}
wcstring_list_t names = s_env_universal_var.get_names(show_exported, show_unexported);
lst.insert(lst.end(), names.begin(), names.end());
}
const wchar_t *env_universal_common_get(const wcstring &name)
env_var_t env_universal_common_get(const wcstring &name)
{
env_var_table_t::const_iterator result = env_universal_var.find(name);
if (result != env_universal_var.end())
{
const var_uni_entry_t &e = result->second;
return const_cast<wchar_t*>(e.val.c_str());
}
return NULL;
return s_env_universal_var.get(name);
}
bool env_universal_common_get_export(const wcstring &name)
{
env_var_table_t::const_iterator result = env_universal_var.find(name);
if (result != env_universal_var.end())
{
const var_uni_entry_t &e = result->second;
return e.exportv;
}
return false;
return s_env_universal_var.get_export(name);
}
void enqueue_all(connection_t *c)
{
env_var_table_t::const_iterator iter;
for (iter = env_universal_var.begin(); iter != env_universal_var.end(); ++iter)
{
const wcstring &key = iter->first;
const var_uni_entry_t &entry = iter->second;
message_t *msg = create_message(entry.exportv ? SET_EXPORT : SET, key.c_str(), entry.val.c_str());
msg->count=1;
c->unsent.push(msg);
}
s_env_universal_var.enqueue_all(c);
try_send_all(c);
}
@ -679,3 +628,81 @@ void connection_destroy(connection_t *c)
}
}
}
env_universal_t::env_universal_t()
{
VOMIT_ON_FAILURE(pthread_mutex_init(&lock, NULL));
}
env_universal_t::~env_universal_t()
{
pthread_mutex_destroy(&lock);
}
env_var_t env_universal_t::get(const wcstring &name) const
{
env_var_t result = env_var_t::missing_var();
var_table_t::const_iterator where = vars.find(name);
if (where != vars.end())
{
result = where->second.val;
}
return result;
}
bool env_universal_t::get_export(const wcstring &name) const
{
bool result = false;
var_table_t::const_iterator where = vars.find(name);
if (where != vars.end())
{
result = where->second.exportv;
}
return result;
}
void env_universal_t::set(const wcstring &key, const wcstring &val, bool exportv)
{
scoped_lock locker(lock);
var_entry_t *entry = &vars[key];
entry->val = val;
entry->exportv = exportv;
}
void env_universal_t::remove(const wcstring &key)
{
scoped_lock locker(lock);
vars.erase(key);
}
wcstring_list_t env_universal_t::get_names(bool show_exported, bool show_unexported) const
{
wcstring_list_t result;
scoped_lock locker(lock);
var_table_t::const_iterator iter;
for (iter = vars.begin(); iter != vars.end(); ++iter)
{
const wcstring &key = iter->first;
const var_entry_t &e = iter->second;
if ((e.exportv && show_exported) || (! e.exportv && show_unexported))
{
result.push_back(key);
}
}
return result;
}
void env_universal_t::enqueue_all(connection_t *c) const
{
scoped_lock locker(lock);
var_table_t::const_iterator iter;
for (iter = vars.begin(); iter != vars.end(); ++iter)
{
const wcstring &key = iter->first;
const var_entry_t &entry = iter->second;
message_t *msg = create_message(entry.exportv ? SET_EXPORT : SET, key.c_str(), entry.val.c_str());
msg->count=1;
c->unsent.push(msg);
}
}

View file

@ -5,6 +5,7 @@
#include <queue>
#include <string>
#include "util.h"
#include "env.h"
/**
The set command
@ -176,7 +177,7 @@ void env_universal_common_remove(const wcstring &key);
This function operate agains the local copy of all universal
variables, it does not communicate with any other process.
*/
const wchar_t *env_universal_common_get(const wcstring &name);
env_var_t env_universal_common_get(const wcstring &name);
/**
Get the export flag of the variable with the specified
@ -199,4 +200,32 @@ void enqueue_all(connection_t *c);
*/
void connection_destroy(connection_t *c);
/** Class representing universal variables */
class env_universal_t
{
var_table_t vars;
mutable pthread_mutex_t lock;
public:
env_universal_t();
~env_universal_t();
/* Get the value of the variable with the specified name */
env_var_t get(const wcstring &name) const;
/* Returns whether the variable with the given name is exported, or false if it does not exist */
bool get_export(const wcstring &name) const;
/* Sets a variable */
void set(const wcstring &key, const wcstring &val, bool exportv);
/* Removes a variable */
void remove(const wcstring &name);
/* Gets variable names */
wcstring_list_t get_names(bool show_exported, bool show_unexported) const;
/* Writes variables to the connection */
void enqueue_all(connection_t *c) const;
};
#endif

View file

@ -720,8 +720,7 @@ static env_var_t fishd_env_get(const char *key)
else
{
const wcstring wkey = str2wcstring(key);
const wchar_t *tmp = env_universal_common_get(wkey);
return tmp ? env_var_t(tmp) : env_var_t::missing_var();
return env_universal_common_get(wkey);
}
}