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
|
||||
struct SystemToolsPathCaseCmp
|
||||
{
|
||||
|
@ -406,6 +472,9 @@ struct SystemToolsPathCaseCmp
|
|||
class SystemToolsPathCaseMap:
|
||||
public std::map<std::string, std::string,
|
||||
SystemToolsPathCaseCmp> {};
|
||||
|
||||
class SystemToolsEnvMap :
|
||||
public std::map<std::string,std::string> {};
|
||||
#endif
|
||||
|
||||
// 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)
|
||||
{
|
||||
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)
|
||||
|
@ -468,16 +549,23 @@ const char* SystemTools::GetEnv(const std::string& key)
|
|||
|
||||
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);
|
||||
if(v)
|
||||
{
|
||||
result = v;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__GLIBC__)
|
||||
# define KWSYS_PUTENV_NAME /* putenv("A") removes A. */
|
||||
#elif defined(_WIN32)
|
||||
# define KWSYS_PUTENV_EMPTY /* putenv("A=") removes A. */
|
||||
bool SystemTools::HasEnv(const char* key)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
const std::wstring wkey = Encoding::ToWide(key);
|
||||
const wchar_t* v = _wgetenv(wkey.c_str());
|
||||
#else
|
||||
const char* v = getenv(key);
|
||||
#endif
|
||||
return v != 0;
|
||||
}
|
||||
|
||||
bool SystemTools::HasEnv(const std::string& key)
|
||||
{
|
||||
return SystemTools::HasEnv(key.c_str());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if KWSYS_CXX_HAS_UNSETENV
|
||||
/* unsetenv("A") removes A from the environment.
|
||||
|
@ -511,18 +609,15 @@ static int kwsysUnPutEnv(const std::string& env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(KWSYS_PUTENV_EMPTY) || defined(KWSYS_PUTENV_NAME)
|
||||
/* putenv("A=") or putenv("A") removes A from the environment. */
|
||||
#elif defined(__CYGWIN__) || defined(__GLIBC__)
|
||||
/* 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)
|
||||
{
|
||||
int err = 0;
|
||||
size_t pos = env.find('=');
|
||||
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;
|
||||
# endif
|
||||
char local_buf[256];
|
||||
char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf;
|
||||
if(!buf)
|
||||
|
@ -530,20 +625,11 @@ static int kwsysUnPutEnv(const std::string& env)
|
|||
return -1;
|
||||
}
|
||||
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;
|
||||
if(putenv(buf) < 0 && errno != EINVAL)
|
||||
{
|
||||
err = errno;
|
||||
}
|
||||
# endif
|
||||
if(buf != local_buf)
|
||||
{
|
||||
free(buf);
|
||||
|
@ -556,6 +642,30 @@ static int kwsysUnPutEnv(const std::string& env)
|
|||
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
|
||||
/* Manipulate the "environ" global directly. */
|
||||
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 */
|
||||
# endif
|
||||
|
||||
/* Order by environment key only (VAR from VAR=VALUE). */
|
||||
struct kwsysEnvCompare
|
||||
class kwsysEnv: public kwsysEnvSet
|
||||
{
|
||||
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:
|
||||
typedef std::set<const char*, kwsysEnvCompare> derived;
|
||||
~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);
|
||||
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)
|
||||
{
|
||||
Free oldEnv(this->Release(env));
|
||||
static_cast<void>(oldEnv);
|
||||
#if defined(_WIN32)
|
||||
const std::wstring wEnv = Encoding::ToWide(env);
|
||||
wchar_t* newEnv = _wcsdup(wEnv.c_str());
|
||||
#else
|
||||
char* newEnv = strdup(env);
|
||||
#endif
|
||||
Free oldEnv(this->Release(newEnv));
|
||||
this->insert(newEnv);
|
||||
#if defined(_WIN32)
|
||||
return _wputenv(newEnv) == 0;
|
||||
#else
|
||||
return putenv(newEnv) == 0;
|
||||
#endif
|
||||
}
|
||||
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));
|
||||
static_cast<void>(oldEnv);
|
||||
#endif
|
||||
return kwsysUnPutEnv(env) == 0;
|
||||
}
|
||||
};
|
||||
|
@ -5371,6 +5459,7 @@ static unsigned int SystemToolsManagerCount;
|
|||
SystemToolsTranslationMap *SystemTools::TranslationMap;
|
||||
#ifdef _WIN32
|
||||
SystemToolsPathCaseMap *SystemTools::PathCaseMap;
|
||||
SystemToolsEnvMap *SystemTools::EnvMap;
|
||||
#endif
|
||||
#ifdef __CYGWIN__
|
||||
SystemToolsTranslationMap *SystemTools::Cyg2Win32Map;
|
||||
|
@ -5421,6 +5510,7 @@ void SystemTools::ClassInitialize()
|
|||
SystemTools::TranslationMap = new SystemToolsTranslationMap;
|
||||
#ifdef _WIN32
|
||||
SystemTools::PathCaseMap = new SystemToolsPathCaseMap;
|
||||
SystemTools::EnvMap = new SystemToolsEnvMap;
|
||||
#endif
|
||||
#ifdef __CYGWIN__
|
||||
SystemTools::Cyg2Win32Map = new SystemToolsTranslationMap;
|
||||
|
@ -5480,6 +5570,7 @@ void SystemTools::ClassFinalize()
|
|||
delete SystemTools::TranslationMap;
|
||||
#ifdef _WIN32
|
||||
delete SystemTools::PathCaseMap;
|
||||
delete SystemTools::EnvMap;
|
||||
#endif
|
||||
#ifdef __CYGWIN__
|
||||
delete SystemTools::Cyg2Win32Map;
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace @KWSYS_NAMESPACE@
|
|||
|
||||
class SystemToolsTranslationMap;
|
||||
class SystemToolsPathCaseMap;
|
||||
class SystemToolsEnvMap;
|
||||
|
||||
/** \class SystemToolsManager
|
||||
* \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 bool GetEnv(const char* 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
|
||||
of the form var=value */
|
||||
|
@ -989,6 +992,7 @@ private:
|
|||
static SystemToolsTranslationMap *TranslationMap;
|
||||
#ifdef _WIN32
|
||||
static SystemToolsPathCaseMap *PathCaseMap;
|
||||
static SystemToolsEnvMap *EnvMap;
|
||||
#endif
|
||||
#ifdef __CYGWIN__
|
||||
static SystemToolsTranslationMap *Cyg2Win32Map;
|
||||
|
|
Loading…
Reference in New Issue