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

View File

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