⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 environment_map.hpp

📁 新版本TR1的stl
💻 HPP
📖 第 1 页 / 共 2 页
字号:
}

// 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 + -