KWSys 2016-07-15 (f396bf43)
Code extracted from: http://public.kitware.com/KWSys.git at commit f396bf43fc8a3e475e703acb99d629d123dbd003 (master). Upstream Shortlog ----------------- Brad King (2): e43689db SystemTools: Factor out environment storage class 2aa7dd82 SystemTools: Do not free buffer passed to putenv("A=") on Windows Dāvis Mosāns (4): 19c31914 SystemTools: Abstract environment storage character type 61301786 SystemTools: Tweak GetEnv/PutEnv implementation layout 85920d53 SystemTools: Teach GetEnv/PutEnv to use correct encoding on Windows f396bf43 SystemTools: Add HasEnv function
This commit is contained in:
parent
f7d23e6753
commit
bbb3216a2c
233
SystemTools.cxx
233
SystemTools.cxx
|
@ -388,6 +388,72 @@ class SystemToolsTranslationMap :
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Type of character storing the environment. */
|
||||||
|
#if defined(_WIN32)
|
||||||
|
typedef wchar_t envchar;
|
||||||
|
#else
|
||||||
|
typedef char envchar;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Order by environment key only (VAR from VAR=VALUE). */
|
||||||
|
struct kwsysEnvCompare
|
||||||
|
{
|
||||||
|
bool operator() (const envchar* l, const envchar* r) const
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
const wchar_t* leq = wcschr(l, L'=');
|
||||||
|
const wchar_t* req = wcschr(r, L'=');
|
||||||
|
size_t llen = leq? (leq-l) : wcslen(l);
|
||||||
|
size_t rlen = req? (req-r) : wcslen(r);
|
||||||
|
if(llen == rlen)
|
||||||
|
{
|
||||||
|
return wcsncmp(l,r,llen) < 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return wcscmp(l,r) < 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
const char* leq = strchr(l, '=');
|
||||||
|
const char* req = strchr(r, '=');
|
||||||
|
size_t llen = leq? (leq-l) : strlen(l);
|
||||||
|
size_t rlen = req? (req-r) : strlen(r);
|
||||||
|
if(llen == rlen)
|
||||||
|
{
|
||||||
|
return strncmp(l,r,llen) < 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return strcmp(l,r) < 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class kwsysEnvSet: public std::set<const envchar*, kwsysEnvCompare>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class Free
|
||||||
|
{
|
||||||
|
const envchar* Env;
|
||||||
|
public:
|
||||||
|
Free(const envchar* env): Env(env) {}
|
||||||
|
~Free() { free(const_cast<envchar*>(this->Env)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
const envchar* Release(const envchar* env)
|
||||||
|
{
|
||||||
|
const envchar* old = 0;
|
||||||
|
iterator i = this->find(env);
|
||||||
|
if(i != this->end())
|
||||||
|
{
|
||||||
|
old = *i;
|
||||||
|
this->erase(i);
|
||||||
|
}
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
struct SystemToolsPathCaseCmp
|
struct SystemToolsPathCaseCmp
|
||||||
{
|
{
|
||||||
|
@ -406,6 +472,9 @@ struct SystemToolsPathCaseCmp
|
||||||
class SystemToolsPathCaseMap:
|
class SystemToolsPathCaseMap:
|
||||||
public std::map<std::string, std::string,
|
public std::map<std::string, std::string,
|
||||||
SystemToolsPathCaseCmp> {};
|
SystemToolsPathCaseCmp> {};
|
||||||
|
|
||||||
|
class SystemToolsEnvMap :
|
||||||
|
public std::map<std::string,std::string> {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// adds the elements of the env variable path to the arg passed in
|
// adds the elements of the env variable path to the arg passed in
|
||||||
|
@ -458,7 +527,19 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env)
|
||||||
|
|
||||||
const char* SystemTools::GetEnv(const char* key)
|
const char* SystemTools::GetEnv(const char* key)
|
||||||
{
|
{
|
||||||
return getenv(key);
|
const char *v = 0;
|
||||||
|
#if defined(_WIN32)
|
||||||
|
std::string env;
|
||||||
|
if (SystemTools::GetEnv(key, env))
|
||||||
|
{
|
||||||
|
std::string& menv = (*SystemTools::EnvMap)[key];
|
||||||
|
menv = env;
|
||||||
|
v = menv.c_str();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
v = getenv(key);
|
||||||
|
#endif
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* SystemTools::GetEnv(const std::string& key)
|
const char* SystemTools::GetEnv(const std::string& key)
|
||||||
|
@ -468,16 +549,23 @@ const char* SystemTools::GetEnv(const std::string& key)
|
||||||
|
|
||||||
bool SystemTools::GetEnv(const char* key, std::string& result)
|
bool SystemTools::GetEnv(const char* key, std::string& result)
|
||||||
{
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
const std::wstring wkey = Encoding::ToWide(key);
|
||||||
|
const wchar_t* wv = _wgetenv(wkey.c_str());
|
||||||
|
if (wv)
|
||||||
|
{
|
||||||
|
result = Encoding::ToNarrow(wv);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
const char* v = getenv(key);
|
const char* v = getenv(key);
|
||||||
if(v)
|
if(v)
|
||||||
{
|
{
|
||||||
result = v;
|
result = v;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
#endif
|
||||||
{
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SystemTools::GetEnv(const std::string& key, std::string& result)
|
bool SystemTools::GetEnv(const std::string& key, std::string& result)
|
||||||
|
@ -485,13 +573,23 @@ bool SystemTools::GetEnv(const std::string& key, std::string& result)
|
||||||
return SystemTools::GetEnv(key.c_str(), result);
|
return SystemTools::GetEnv(key.c_str(), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
bool SystemTools::HasEnv(const char* key)
|
||||||
|
{
|
||||||
#if defined(__CYGWIN__) || defined(__GLIBC__)
|
#if defined(_WIN32)
|
||||||
# define KWSYS_PUTENV_NAME /* putenv("A") removes A. */
|
const std::wstring wkey = Encoding::ToWide(key);
|
||||||
#elif defined(_WIN32)
|
const wchar_t* v = _wgetenv(wkey.c_str());
|
||||||
# define KWSYS_PUTENV_EMPTY /* putenv("A=") removes A. */
|
#else
|
||||||
|
const char* v = getenv(key);
|
||||||
#endif
|
#endif
|
||||||
|
return v != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SystemTools::HasEnv(const std::string& key)
|
||||||
|
{
|
||||||
|
return SystemTools::HasEnv(key.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if KWSYS_CXX_HAS_UNSETENV
|
#if KWSYS_CXX_HAS_UNSETENV
|
||||||
/* unsetenv("A") removes A from the environment.
|
/* unsetenv("A") removes A from the environment.
|
||||||
|
@ -511,18 +609,15 @@ static int kwsysUnPutEnv(const std::string& env)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(KWSYS_PUTENV_EMPTY) || defined(KWSYS_PUTENV_NAME)
|
#elif defined(__CYGWIN__) || defined(__GLIBC__)
|
||||||
/* putenv("A=") or putenv("A") removes A from the environment. */
|
/* putenv("A") removes A from the environment. It must not put the
|
||||||
|
memory in the environment because it does not have any "=" syntax. */
|
||||||
static int kwsysUnPutEnv(const std::string& env)
|
static int kwsysUnPutEnv(const std::string& env)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
size_t pos = env.find('=');
|
size_t pos = env.find('=');
|
||||||
size_t const len = pos == env.npos ? env.size() : pos;
|
size_t const len = pos == env.npos ? env.size() : pos;
|
||||||
# ifdef KWSYS_PUTENV_EMPTY
|
|
||||||
size_t const sz = len + 2;
|
|
||||||
# else
|
|
||||||
size_t const sz = len + 1;
|
size_t const sz = len + 1;
|
||||||
# endif
|
|
||||||
char local_buf[256];
|
char local_buf[256];
|
||||||
char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf;
|
char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf;
|
||||||
if(!buf)
|
if(!buf)
|
||||||
|
@ -530,20 +625,11 @@ static int kwsysUnPutEnv(const std::string& env)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
strncpy(buf, env.c_str(), len);
|
strncpy(buf, env.c_str(), len);
|
||||||
# ifdef KWSYS_PUTENV_EMPTY
|
|
||||||
buf[len] = '=';
|
|
||||||
buf[len+1] = 0;
|
|
||||||
if(putenv(buf) < 0)
|
|
||||||
{
|
|
||||||
err = errno;
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
buf[len] = 0;
|
buf[len] = 0;
|
||||||
if(putenv(buf) < 0 && errno != EINVAL)
|
if(putenv(buf) < 0 && errno != EINVAL)
|
||||||
{
|
{
|
||||||
err = errno;
|
err = errno;
|
||||||
}
|
}
|
||||||
# endif
|
|
||||||
if(buf != local_buf)
|
if(buf != local_buf)
|
||||||
{
|
{
|
||||||
free(buf);
|
free(buf);
|
||||||
|
@ -556,6 +642,30 @@ static int kwsysUnPutEnv(const std::string& env)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
/* putenv("A=") places "A=" in the environment, which is as close to
|
||||||
|
removal as we can get with the putenv API. We have to leak the
|
||||||
|
most recent value placed in the environment for each variable name
|
||||||
|
on program exit in case exit routines access it. */
|
||||||
|
|
||||||
|
static kwsysEnvSet kwsysUnPutEnvSet;
|
||||||
|
|
||||||
|
static int kwsysUnPutEnv(std::string const& env)
|
||||||
|
{
|
||||||
|
std::wstring wEnv = Encoding::ToWide(env);
|
||||||
|
size_t const pos = wEnv.find('=');
|
||||||
|
size_t const len = pos == wEnv.npos ? wEnv.size() : pos;
|
||||||
|
wEnv.resize(len+1, L'=');
|
||||||
|
wchar_t* newEnv = _wcsdup(wEnv.c_str());
|
||||||
|
if(!newEnv)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
kwsysEnvSet::Free oldEnv(kwsysUnPutEnvSet.Release(newEnv));
|
||||||
|
kwsysUnPutEnvSet.insert(newEnv);
|
||||||
|
return _wputenv(newEnv);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* Manipulate the "environ" global directly. */
|
/* Manipulate the "environ" global directly. */
|
||||||
static int kwsysUnPutEnv(const std::string& env)
|
static int kwsysUnPutEnv(const std::string& env)
|
||||||
|
@ -623,68 +733,46 @@ bool SystemTools::UnPutEnv(const std::string& env)
|
||||||
# pragma warning disable 444 /* base has non-virtual destructor */
|
# pragma warning disable 444 /* base has non-virtual destructor */
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* Order by environment key only (VAR from VAR=VALUE). */
|
class kwsysEnv: public kwsysEnvSet
|
||||||
struct kwsysEnvCompare
|
|
||||||
{
|
{
|
||||||
bool operator() (const char* l, const char* r) const
|
|
||||||
{
|
|
||||||
const char* leq = strchr(l, '=');
|
|
||||||
const char* req = strchr(r, '=');
|
|
||||||
size_t llen = leq? (leq-l) : strlen(l);
|
|
||||||
size_t rlen = req? (req-r) : strlen(r);
|
|
||||||
if(llen == rlen)
|
|
||||||
{
|
|
||||||
return strncmp(l,r,llen) < 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return strcmp(l,r) < 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class kwsysEnv: public std::set<const char*, kwsysEnvCompare>
|
|
||||||
{
|
|
||||||
class Free
|
|
||||||
{
|
|
||||||
const char* Env;
|
|
||||||
public:
|
|
||||||
Free(const char* env): Env(env) {}
|
|
||||||
~Free() { free(const_cast<char*>(this->Env)); }
|
|
||||||
};
|
|
||||||
public:
|
public:
|
||||||
typedef std::set<const char*, kwsysEnvCompare> derived;
|
|
||||||
~kwsysEnv()
|
~kwsysEnv()
|
||||||
{
|
{
|
||||||
for(derived::iterator i = this->begin(); i != this->end(); ++i)
|
for(iterator i = this->begin(); i != this->end(); ++i)
|
||||||
{
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
const std::string s = Encoding::ToNarrow(*i);
|
||||||
|
kwsysUnPutEnv(s.c_str());
|
||||||
|
#else
|
||||||
kwsysUnPutEnv(*i);
|
kwsysUnPutEnv(*i);
|
||||||
free(const_cast<char*>(*i));
|
#endif
|
||||||
|
free(const_cast<envchar*>(*i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const char* Release(const char* env)
|
|
||||||
{
|
|
||||||
const char* old = 0;
|
|
||||||
derived::iterator i = this->find(env);
|
|
||||||
if(i != this->end())
|
|
||||||
{
|
|
||||||
old = *i;
|
|
||||||
this->erase(i);
|
|
||||||
}
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
bool Put(const char* env)
|
bool Put(const char* env)
|
||||||
{
|
{
|
||||||
Free oldEnv(this->Release(env));
|
#if defined(_WIN32)
|
||||||
static_cast<void>(oldEnv);
|
const std::wstring wEnv = Encoding::ToWide(env);
|
||||||
|
wchar_t* newEnv = _wcsdup(wEnv.c_str());
|
||||||
|
#else
|
||||||
char* newEnv = strdup(env);
|
char* newEnv = strdup(env);
|
||||||
|
#endif
|
||||||
|
Free oldEnv(this->Release(newEnv));
|
||||||
this->insert(newEnv);
|
this->insert(newEnv);
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return _wputenv(newEnv) == 0;
|
||||||
|
#else
|
||||||
return putenv(newEnv) == 0;
|
return putenv(newEnv) == 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
bool UnPut(const char* env)
|
bool UnPut(const char* env)
|
||||||
{
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
const std::wstring wEnv = Encoding::ToWide(env);
|
||||||
|
Free oldEnv(this->Release(wEnv.c_str()));
|
||||||
|
#else
|
||||||
Free oldEnv(this->Release(env));
|
Free oldEnv(this->Release(env));
|
||||||
static_cast<void>(oldEnv);
|
#endif
|
||||||
return kwsysUnPutEnv(env) == 0;
|
return kwsysUnPutEnv(env) == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -5371,6 +5459,7 @@ static unsigned int SystemToolsManagerCount;
|
||||||
SystemToolsTranslationMap *SystemTools::TranslationMap;
|
SystemToolsTranslationMap *SystemTools::TranslationMap;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SystemToolsPathCaseMap *SystemTools::PathCaseMap;
|
SystemToolsPathCaseMap *SystemTools::PathCaseMap;
|
||||||
|
SystemToolsEnvMap *SystemTools::EnvMap;
|
||||||
#endif
|
#endif
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
SystemToolsTranslationMap *SystemTools::Cyg2Win32Map;
|
SystemToolsTranslationMap *SystemTools::Cyg2Win32Map;
|
||||||
|
@ -5421,6 +5510,7 @@ void SystemTools::ClassInitialize()
|
||||||
SystemTools::TranslationMap = new SystemToolsTranslationMap;
|
SystemTools::TranslationMap = new SystemToolsTranslationMap;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SystemTools::PathCaseMap = new SystemToolsPathCaseMap;
|
SystemTools::PathCaseMap = new SystemToolsPathCaseMap;
|
||||||
|
SystemTools::EnvMap = new SystemToolsEnvMap;
|
||||||
#endif
|
#endif
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
SystemTools::Cyg2Win32Map = new SystemToolsTranslationMap;
|
SystemTools::Cyg2Win32Map = new SystemToolsTranslationMap;
|
||||||
|
@ -5480,6 +5570,7 @@ void SystemTools::ClassFinalize()
|
||||||
delete SystemTools::TranslationMap;
|
delete SystemTools::TranslationMap;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
delete SystemTools::PathCaseMap;
|
delete SystemTools::PathCaseMap;
|
||||||
|
delete SystemTools::EnvMap;
|
||||||
#endif
|
#endif
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
delete SystemTools::Cyg2Win32Map;
|
delete SystemTools::Cyg2Win32Map;
|
||||||
|
|
|
@ -53,6 +53,7 @@ namespace @KWSYS_NAMESPACE@
|
||||||
|
|
||||||
class SystemToolsTranslationMap;
|
class SystemToolsTranslationMap;
|
||||||
class SystemToolsPathCaseMap;
|
class SystemToolsPathCaseMap;
|
||||||
|
class SystemToolsEnvMap;
|
||||||
|
|
||||||
/** \class SystemToolsManager
|
/** \class SystemToolsManager
|
||||||
* \brief Use to make sure SystemTools is initialized before it is used
|
* \brief Use to make sure SystemTools is initialized before it is used
|
||||||
|
@ -843,6 +844,8 @@ public:
|
||||||
static const char* GetEnv(const std::string& key);
|
static const char* GetEnv(const std::string& key);
|
||||||
static bool GetEnv(const char* key, std::string& result);
|
static bool GetEnv(const char* key, std::string& result);
|
||||||
static bool GetEnv(const std::string& key, std::string& result);
|
static bool GetEnv(const std::string& key, std::string& result);
|
||||||
|
static bool HasEnv(const char* key);
|
||||||
|
static bool HasEnv(const std::string& key);
|
||||||
|
|
||||||
/** Put a string into the environment
|
/** Put a string into the environment
|
||||||
of the form var=value */
|
of the form var=value */
|
||||||
|
@ -989,6 +992,7 @@ private:
|
||||||
static SystemToolsTranslationMap *TranslationMap;
|
static SystemToolsTranslationMap *TranslationMap;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static SystemToolsPathCaseMap *PathCaseMap;
|
static SystemToolsPathCaseMap *PathCaseMap;
|
||||||
|
static SystemToolsEnvMap *EnvMap;
|
||||||
#endif
|
#endif
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
static SystemToolsTranslationMap *Cyg2Win32Map;
|
static SystemToolsTranslationMap *Cyg2Win32Map;
|
||||||
|
|
Loading…
Reference in New Issue