📄 environment_map.hpp
字号:
}
// TODO: Make this a discriminated feature declared in the cccap files
#if ( defined(STLSOFT_COMPILER_IS_BORLAND) && \
__BORLANDC__ >= 0x0560) || \
defined(STLSOFT_COMPILER_IS_DMC)
# if defined(_STLSOFT_NO_NAMESPACE) || \
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
/* There is no stlsoft namespace, so must define ::platformstl */
namespace platformstl
{
# else
/* Define stlsoft::platformstl_project */
namespace stlsoft
{
namespace platformstl_project
{
# endif /* _STLSOFT_NO_NAMESPACE */
#endif /* compiler */
////////////////////////////////////////////////////////////////////////////
// Unit-testing
#ifdef STLSOFT_UNITTEST
# include "./unittest/environment_map_unittest_.h"
#endif /* STLSOFT_UNITTEST */
/* /////////////////////////////////////////////////////////////////////////
* Implementation
*/
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
// environment_map::const_iterator
#ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
inline environment_map::const_iterator::const_iterator()
: m_it()
{}
inline environment_map::const_iterator::const_iterator(environment_map::snapshot::iterator it, environment_map::snapshot::ref_type snapshot)
: m_it(it)
, m_snapshot(snapshot)
{}
inline environment_map::const_iterator::const_iterator(environment_map::const_iterator::class_type const& rhs)
: m_it(rhs.m_it)
, m_snapshot(rhs.m_snapshot)
{}
inline environment_map::const_iterator::class_type &environment_map::const_iterator::operator ++()
{
++m_it;
return *this;
}
inline environment_map::const_iterator::class_type environment_map::const_iterator::operator ++(int)
{
class_type r(*this);
operator ++();
return r;
}
inline environment_map::const_reference environment_map::const_iterator::operator *() const
{
return *m_it;
}
inline environment_map::const_iterator::class_type &environment_map::const_iterator::operator --()
{
--m_it;
return *this;
}
inline environment_map::const_iterator::class_type environment_map::const_iterator::operator --(int)
{
class_type r(*this);
operator --();
return r;
}
inline ss_bool_t environment_map::const_iterator::equal(environment_map::const_iterator::class_type const& rhs) const
{
return m_it == rhs.m_it;
}
#endif /* PLATFORMSTL_ENVVAR_HAS_ENVIRON */
// environment_map
inline environment_map::environment_map()
{}
inline environment_map::second_type environment_map::operator [](char const* name) const
{
char const *value = traits_type::get_variable(name);
if(NULL == value)
{
STLSOFT_THROW_X(stlsoft_ns_qual_std(out_of_range)("variable does not exist"));
}
return value;
}
inline environment_map::second_type environment_map::operator [](environment_map::first_type const& name) const
{
return operator [](name.c_str());
}
inline ss_bool_t environment_map::lookup(char const* name, environment_map::second_type& value) const
{
char const *value_ = traits_type::get_variable(name);
return (NULL == value_) ? false : (value = value_, true);
}
inline ss_bool_t environment_map::lookup(environment_map::first_type const& name, environment_map::second_type& value) const
{
return lookup(name.c_str(), value);
}
inline void environment_map::refresh()
{
#ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
m_snapshot.close();
#endif /* PLATFORMSTL_ENVVAR_HAS_ENVIRON */
}
#ifdef PLATFORMSTL_ENVVAR_SET_SUPPORTED
inline void environment_map::insert(environment_map::first_type const& name, environment_map::second_type const& value)
{
// Preconditions
STLSOFT_MESSAGE_ASSERT("Name may not be empty", !name.empty());
STLSOFT_MESSAGE_ASSERT("Name may not contain '='", name.end() == std::find(name.begin(), name.end(), '='));
STLSOFT_MESSAGE_ASSERT("Empty value not allowed in insertion", !value.empty());
second_type *pstr = NULL;
if( 1 < m_snapshot.use_count() &&
m_snapshot->lookup(name, pstr))
{
// If it exists, then:
// 1. Reserve the appropriate amount of storage (which may throw,
// but doesn't need to be rolled back). If this succeeds, then
// it means that the insert() call cannot throw an exception.
pstr->reserve(value.size());
// 2. Insert into the host environment
if(0 != traits_type::set_variable(name.c_str(), value.c_str()))
{
STLSOFT_THROW_X(stlsoft_ns_qual_std(runtime_error)("Cannot set environment variable"));
}
// 3. Update the snapshot
m_snapshot->set(name, value);
}
else
{
// If it does not exist, then we add it first, and remove
// again if the set_variable() call fails to also put it
// in the host environment
if(1 < m_snapshot.use_count())
{
m_snapshot->insert(name, value);
}
if(0 != traits_type::set_variable(name.c_str(), value.c_str()))
{
if(1 < m_snapshot.use_count())
{
m_snapshot->erase(name);
}
STLSOFT_THROW_X(stlsoft_ns_qual_std(runtime_error)("Cannot set environment variable"));
}
}
}
inline void environment_map::insert(char const* name, char const* value)
{
// Preconditions
STLSOFT_ASSERT(NULL != name);
STLSOFT_MESSAGE_ASSERT("Name may not be empty", 0 != ::strlen(name));
STLSOFT_MESSAGE_ASSERT("Name may not contain '='", NULL == ::strchr(name, '='));
STLSOFT_MESSAGE_ASSERT("Null value not allowed in insertion", NULL != value);
STLSOFT_MESSAGE_ASSERT("Empty value not allowed in insertion", 0 != ::strlen(value));
insert(first_type(name), second_type(value));
}
#endif /* PLATFORMSTL_ENVVAR_SET_SUPPORTED */
#ifdef PLATFORMSTL_ENVVAR_ERASE_SUPPORTED
inline environment_map::size_type environment_map::erase(environment_map::first_type const& name)
{
// Preconditions
STLSOFT_MESSAGE_ASSERT("Name may not be empty", !name.empty());
STLSOFT_MESSAGE_ASSERT("Name may not contain '='", name.end() == std::find(name.begin(), name.end(), '='));
size_type b = 0;
if(0 != traits_type::erase_variable(name.c_str()))
{
#if 0
// Failure to erase might be if some external part of the
// process has already erased it.
//
// Hence, the somewhat crude measure to checking whether it
// still exists (rather than knowing what value(s) to check
// the return value of erase_variable() for).
if(NULL != traits_type::get_variable(name.c_str()))
#endif /* 0 */
{
STLSOFT_THROW_X(stlsoft_ns_qual_std(runtime_error)("Cannot erase environment variable"));
}
}
else
{
b = 1;
}
if(1 < m_snapshot.use_count())
{
if(m_snapshot->erase(name))
{
b = 1;
}
}
return b;
}
inline environment_map::size_type environment_map::erase(char const* name)
{
// Preconditions
STLSOFT_ASSERT(NULL != name);
STLSOFT_MESSAGE_ASSERT("Name may not be empty", 0 != ::strlen(name));
STLSOFT_MESSAGE_ASSERT("Name may not contain '='", NULL == ::strchr(name, '='));
return erase(first_type(name));
}
inline void environment_map::erase(environment_map::const_iterator it)
{
STLSOFT_MESSAGE_ASSERT("No snapshot assigned, so erase() is inappropriate; maybe premature call to clear()", 1 < m_snapshot.use_count());
#if 0
first_type const &name = (*it).first;
#else /* ? 0 */
first_type const &name = (*it.m_it).first; // Avoid CUR
#endif /* 0 */
if(0 != traits_type::erase_variable(name.c_str()))
{
#if 0
// Failure to erase might be if some external part of the
// process has already erased it.
//
// Hence, the somewhat crude measure to checking whether it
// still exists (rather than knowing what value(s) to check
// the return value of erase_variable() for).
if(NULL != traits_type::get_variable(name.c_str()))
#endif /* 0 */
{
STLSOFT_THROW_X(stlsoft_ns_qual_std(runtime_error)("Cannot erase environment variable"));
}
}
m_snapshot->erase(it.m_it);
}
#endif /* PLATFORMSTL_ENVVAR_ERASE_SUPPORTED */
#ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
inline environment_map::const_iterator environment_map::begin() const
{
check_refresh_snapshot_();
#if 0
snapshot::ref_type snapshot = m_snapshot; // Avoid a const_cast
return const_iterator(snapshot->begin(), m_snapshot);
#else /* ? 0 */
return const_iterator(m_snapshot->begin(), m_snapshot);
#endif /* 0 */
}
inline environment_map::const_iterator environment_map::end() const
{
check_refresh_snapshot_();
#if 0
snapshot::ref_type snapshot = m_snapshot; // Avoid a const_cast
return const_iterator(snapshot->end(), m_snapshot);
#else /* ? 0 */
return const_iterator(m_snapshot->end(), m_snapshot);
#endif /* 0 */
}
# if defined(STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT) && \
!defined(STLSOFT_COMPILER_IS_BORLAND)
inline environment_map::const_reverse_iterator environment_map::rbegin() const
{
return const_reverse_iterator(end());
}
inline environment_map::const_reverse_iterator environment_map::rend() const
{
return const_reverse_iterator(begin());
}
# endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
#endif /* PLATFORMSTL_ENVVAR_HAS_ENVIRON */
#ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
inline void environment_map::check_refresh_snapshot_() const
{
if(m_snapshot.use_count() < 2)
{
m_snapshot = snapshot::ref_type(new snapshot());
}
}
#endif /* PLATFORMSTL_ENVVAR_HAS_ENVIRON */
// environment_map::snapshot
# ifdef PLATFORMSTL_ENVVAR_HAS_ENVIRON
inline environment_map::snapshot::snapshot()
{
first_type name;
second_type value;
stlsoft::scoped_handle<char const**> env( traits_type::get_environ()
, &traits_type::release_environ);
{ for(char const** p = env.get(); NULL != *p; ++p)
{
stlsoft::split(*p, '=', name, value);
m_variables[name] = value;
}}
}
inline environment_map::snapshot::iterator environment_map::snapshot::begin()
{
return m_variables.begin();
}
inline environment_map::snapshot::iterator environment_map::snapshot::end()
{
return m_variables.end();
}
inline ss_bool_t environment_map::snapshot::erase(first_type const& name) throw()
{
variables_type_::iterator it = m_variables.find(name);
if(m_variables.end() != it)
{
m_variables.erase(it);
return true;
}
return false;
}
inline void environment_map::snapshot::erase(environment_map::snapshot::iterator it) throw()
{
m_variables.erase(it);
}
inline void environment_map::snapshot::insert(first_type const& name, second_type const& value)
{
# if 0
/// This is not strongly exception safe, ...
m_variables[name] = value;
# else /* ? 0 */
/// ... but this is.
m_variables.insert(value_type(name, value));
# endif /* 0 */
}
inline void environment_map::snapshot::set(first_type const& name, second_type const& value)
{
variables_type_::iterator it = m_variables.find(name);
STLSOFT_ASSERT(m_variables.end() != it);
STLSOFT_ASSERT((*it).second.capacity() >= value.size());
# ifdef _DEBUG
try
# endif /* _DEBUG */
{
(*it).second.assign(value);
}
# ifdef _DEBUG
catch(...)
{
STLSOFT_MESSAGE_ASSERT("Should never happen", 0);
throw; // Might as well pass on to precipitate unexpected()
}
# endif /* _DEBUG */
}
inline ss_bool_t environment_map::snapshot::lookup(first_type const& name, second_type *&pvalue) throw()
{
variables_type_::iterator it = m_variables.find(name);
if(m_variables.end() == it)
{
return false;
}
else
{
pvalue = &(*it).second;
return true;
}
}
# endif /* PLATFORMSTL_ENVVAR_HAS_ENVIRON */
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
/* ////////////////////////////////////////////////////////////////////// */
#if defined(_STLSOFT_NO_NAMESPACE) || \
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
} // namespace platformstl
#else
} // namespace platformstl_project
} // namespace stlsoft
#endif /* _STLSOFT_NO_NAMESPACE */
/* ////////////////////////////////////////////////////////////////////// */
#endif /* !PLATFORMSTL_INCL_PLATFORMSTL_SYSTEM_HPP_ENVIRONMENT_MAP */
/* ////////////////////////////////////////////////////////////////////// */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -