Implement const_iterators.

Note that they are not available in the base class.
This commit is contained in:
King_DuckZ 2020-04-13 17:17:02 +02:00
parent 351e84b04e
commit dfefed1516
5 changed files with 119 additions and 2 deletions

View file

@ -126,4 +126,19 @@ void EnvFake::clear() noexcept {
m_map_strong_cpy.clear(); m_map_strong_cpy.clear();
} }
auto EnvFake::begin() const -> const_iterator {
return m_map.cbegin();
}
auto EnvFake::cbegin() const -> const_iterator {
return m_map.cbegin();
}
auto EnvFake::end() const -> const_iterator {
return m_map.cend();
}
auto EnvFake::cend() const -> const_iterator {
return m_map.cend();
}
} //namespace duck } //namespace duck

View file

@ -25,6 +25,8 @@ namespace duck {
class EnvFake : public EnvBase { class EnvFake : public EnvBase {
typedef std::unordered_map<std::string_view, std::string_view> map_type; typedef std::unordered_map<std::string_view, std::string_view> map_type;
public: public:
typedef map_type::const_iterator const_iterator;
explicit EnvFake (bool starts_empty=false); explicit EnvFake (bool starts_empty=false);
~EnvFake() noexcept = default; ~EnvFake() noexcept = default;
@ -36,6 +38,11 @@ namespace duck {
virtual size_type size() const noexcept override; virtual size_type size() const noexcept override;
virtual void clear() noexcept override; virtual void clear() noexcept override;
const_iterator begin() const;
const_iterator cbegin() const;
const_iterator end() const;
const_iterator cend() const;
private: private:
std::unordered_map<std::string_view, std::unique_ptr<char[]>> m_map_strong_cpy; std::unordered_map<std::string_view, std::unique_ptr<char[]>> m_map_strong_cpy;
map_type m_map; map_type m_map;

View file

@ -27,7 +27,6 @@
#include <unordered_map> #include <unordered_map>
#include <memory> #include <memory>
#include <cassert> #include <cassert>
#include <utility>
#include <cstring> #include <cstring>
#if defined(__GNU_LIBRARY__) && ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) || __GLIBC__ > 2) #if defined(__GNU_LIBRARY__) && ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) || __GLIBC__ > 2)
@ -149,8 +148,56 @@ namespace {
} }
} }
} }
std::pair<std::string_view, std::string_view> to_pair (char* env_entry) noexcept {
std::string_view text(to_string_view(env_entry));
const auto eq_pos = text.find('=');
if (eq_pos == text.npos) {
assert(false);
return {"", ""};
}
return std::make_pair(
text.substr(0, eq_pos),
text.substr(eq_pos + 1)
);
}
} //unnamed namespace } //unnamed namespace
namespace detail {
EnvironIterator::EnvironIterator (char** env) noexcept :
m_curr(),
m_env(env),
m_dirty(true)
{
assert(m_env);
}
auto EnvironIterator::operator*() noexcept -> value_type& {
return *this->operator->();
}
auto EnvironIterator::operator->() noexcept -> value_type* {
if (m_dirty) {
m_curr = (m_env and *m_env ? to_pair(*m_env) : value_type());
m_dirty = false;
}
return &m_curr;
}
EnvironIterator EnvironIterator::operator++(int) noexcept {
EnvironIterator cpy(*this);
++(*this);
return cpy;
}
EnvironIterator EnvironIterator::operator--(int) noexcept {
EnvironIterator cpy(*this);
--(*this);
return cpy;
}
} //namespace detial
EnvReal::EnvReal() : EnvReal::EnvReal() :
m_name_buff(std::make_unique<char[]>(g_name_buff_len)), m_name_buff(std::make_unique<char[]>(g_name_buff_len)),
m_name_buff_len(g_name_buff_len) m_name_buff_len(g_name_buff_len)
@ -251,4 +298,21 @@ const char* EnvReal::raw_fetch_env (std::string_view name) const noexcept {
); );
} }
auto EnvReal::begin() const -> const_iterator {
return {::environ};
}
auto EnvReal::cbegin() const -> const_iterator {
return {::environ};
}
auto EnvReal::end() const -> const_iterator {
assert(*(::environ + this->size()) == nullptr);
return {::environ + this->size()};
}
auto EnvReal::cend() const -> const_iterator {
assert(*(::environ + this->size()) == nullptr);
return {::environ + this->size()};
}
} //namespace duck } //namespace duck

View file

@ -19,10 +19,36 @@
#include "env_base.hpp" #include "env_base.hpp"
#include <memory> #include <memory>
#include <utility>
namespace duck { namespace duck {
namespace detail {
class EnvironIterator {
public:
typedef std::pair<std::string_view, std::string_view> value_type;
EnvironIterator (char** env) noexcept;
value_type& operator*() noexcept;
value_type* operator->() noexcept;
bool operator== (const EnvironIterator& other) const { return m_env == other.m_env; }
bool operator!= (const EnvironIterator& other) const { return m_env != other.m_env; }
EnvironIterator& operator++() noexcept { ++m_env; m_dirty = true; return *this; }
EnvironIterator& operator--() noexcept { --m_env; m_dirty = true; return *this; }
EnvironIterator operator++(int) noexcept;
EnvironIterator operator--(int) noexcept;
private:
value_type m_curr;
char** m_env;
bool m_dirty;
};
} //namespace detail
class EnvReal : public EnvBase { class EnvReal : public EnvBase {
public: public:
typedef detail::EnvironIterator const_iterator;
EnvReal(); EnvReal();
virtual ~EnvReal() noexcept = default; virtual ~EnvReal() noexcept = default;
@ -34,6 +60,11 @@ namespace duck {
virtual size_type size() const noexcept override; virtual size_type size() const noexcept override;
virtual void clear() noexcept override; virtual void clear() noexcept override;
const_iterator begin() const;
const_iterator cbegin() const;
const_iterator end() const;
const_iterator cend() const;
private: private:
const char* raw_fetch_env (std::string_view name) const noexcept; const char* raw_fetch_env (std::string_view name) const noexcept;

View file

@ -33,7 +33,7 @@ namespace duck {
return str; return str;
} }
inline std::string_view to_string_view (const char* str) { inline std::string_view to_string_view (const char* str) noexcept {
return (str ? std::string_view{str} : std::string_view{""}); return (str ? std::string_view{str} : std::string_view{""});
} }