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:
KWSys Upstream 2016-07-15 08:40:41 -04:00 committed by Brad King
parent f7d23e6753
commit bbb3216a2c
2 changed files with 166 additions and 71 deletions

View File

@ -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;

View File

@ -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;