Listing 8 reg_key_sequence_const_iterator

// Extract from winstl_reg_key_sequence.h


template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
class basic_reg_key_sequence_const_iterator
  : public stlsoft::iterator_base<winstl::bidirectional_iterator_tag, 
                                  V, ws_ptrdiff_t, void *, V>
{
public:
  typedef C                                                 char_type;
  typedef T                                                 traits_type;
  typedef V                                                 value_type;
  typedef A                                                 allocator_type;
  typedef basic_reg_key_sequence_const_iterator class_type;
  typedef ws_typename_type_k traits_type::size_type         size_type;
  typedef ws_typename_type_k traits_type::difference_type   difference_type;
  typedef ws_typename_type_k traits_type::string_type       string_type;
  typedef ws_sint32_t                                       index_type;
  typedef ws_typename_type_k traits_type::hkey_type         hkey_type;

// Construction
protected:
  basic_reg_key_sequence_const_iterator( hkey_type          hkey
                                       , index_type         index
                                       , string_type const  &sub_key_name);
  basic_reg_key_sequence_const_iterator(hkey_type hkey);
public:
  basic_reg_key_sequence_const_iterator();
  basic_reg_key_sequence_const_iterator(class_type const &rhs);
  ~basic_reg_key_sequence_const_iterator() winstl_throw_0();

  basic_reg_key_sequence_const_iterator &operator =(class_type const &rhs);

// Operators
public:
  class_type &operator ++();
  class_type &operator --();
  const class_type operator ++(int);
  const class_type operator --(int);
  const value_type operator *() const;
  ws_bool_t operator ==(class_type const &rhs) const;
  ws_bool_t operator !=(class_type const &rhs) const;

// Implementation
protected:
  static index_type _sentinel();

// Members
protected:
  friend class basic_reg_key_sequence<C, T, A>;

  hkey_type   m_hkey;   // Registry key
  index_type  m_index;  // Iteration index
  string_type m_name;   // The value name
};


template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline ws_typename_type_k index_type 
    basic_reg_key_sequence_const_iterator<C, T, V, A>::_sentinel()
{
  return 0x7fffffff;
}


template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline basic_reg_key_sequence_const_iterator<C, T, V, A>::
    basic_reg_key_sequence_const_iterator()
  : m_hkey(NULL)
  , m_index(_sentinel())
{
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline basic_reg_key_sequence_const_iterator<C, T, V, A>::
    basic_reg_key_sequence_const_iterator(hkey_type hkey,
                        index_type index, 
                        string_type const &sub_key_name)
  : m_hkey(&l)
  , m_index(index)
  , m_name(sub_key_name)
{
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline basic_reg_key_sequence_const_iterator<C, T, V, A>::
    basic_reg_key_sequence_const_iterator(hkey_type hkey)
  : m_hkey(hkey)
  , m_index(_sentinel())
{
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline basic_reg_key_sequence_const_iterator<C, T, V, A>::
    basic_reg_key_sequence_const_iterator(class_type const &rhs)
  : m_hkey(rhs.m_hkey)
  , m_index(rhs.m_index)  // This is valid, since the index is
                          // transferrable  between iterators
  , m_name(rhs.m_name)
{
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline ws_typename_type_k class_type 
    &basic_reg_key_sequence_const_iterator<C, T, V, A>::
      operator =(class_type const &rhs)
{
  // For efficiency, we don't do self-assignment test, and
  // assume (reasonably) that m_name will be self-protecting

  m_hkey  = rhs.m_hkey;
  m_index = rhs.m_index;
  m_name  = rhs.m_name;

  return *this;
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline basic_reg_key_sequence_const_iterator<C, T, V, A>::
    ~basic_reg_key_sequence_const_iterator() winstl_throw_0()
{
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline ws_typename_type_k class_type 
  &basic_reg_key_sequence_const_iterator<C, T, V, A>::operator ++()
{
  // Grab enough for the first item
  size_type cch_key_name  = 0;
  ws_long_t res = traits_type::reg_query_info(m_hkey, NULL,
                              NULL, NULL, &cch_key_name, NULL,
                              NULL, NULL, NULL, NULL, NULL);

  if(res == 0)
  {
    auto_buffer<char_type, allocator_type>  buffer(++cch_key_name);

    res = traits_type::reg_enum_key(m_hkey, ++m_index, buffer, 
                                    &cch_key_name, NULL, NULL, NULL);

    if(res == 0)
    {
      m_name = static_cast<char_type const *>(buffer);
    }
    else
    {
      m_index = _sentinel();
    }
  }
  else
  {
    m_index = _sentinel();
  }

  return *this;
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline ws_typename_type_k class_type 
    &basic_reg_key_sequence_const_iterator<C, T, V, A>::operator --()
{
  // Grab enough for the first item
  size_type cch_key_name  = 0;
  ws_uint_t c_sub_keys;
  ws_long_t res     = traits_type::reg_query_info(m_hkey, NULL, NULL,
                                    &c_sub_keys, &cch_key_name, NULL,
                                    NULL, NULL, NULL, NULL, NULL);

  if(res == 0)
  {
    auto_buffer<char_type, allocator_type>  buffer(++cch_key_name);

    // If the iterator is currently at the "end()", ...
    if(m_index == _sentinel())
    {
      // ... then set the index to be one past the end
      m_index = c_sub_keys;
    }

    // Move back one position, and get the key name
    res = traits_type::reg_enum_key(m_hkey, --m_index, buffer,
                                &cch_key_name, NULL, NULL, NULL);

    if(res == 0)
    {
      m_name = static_cast<char_type const *>(buffer);
    }
    else
    {
      m_index = _sentinel();
    }
  }
  else
  {
    m_index = _sentinel();
  }

  return *this;
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline const ws_typename_type_k class_type 
    basic_reg_key_sequence_const_iterator<C, T, V, A>::operator ++(int)
{
  class_type  ret(*this);

  operator ++();

  return ret;
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline const ws_typename_type_k class_type 
    basic_reg_key_sequence_const_iterator<C, T, V, A>::operator --(int)
{
  class_type  ret(*this);

  operator --();

  return ret;
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline const ws_typename_type_k value_type 
    basic_reg_key_sequence_const_iterator<C, T, V, A>::operator *() const
{
  return value_type(m_hkey, m_name);
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline ws_bool_t basic_reg_key_sequence_const_iterator<C, T, V, A>::
    operator ==(class_type const &rhs) const
{
  winstl_message_assert("Comparing reg_key_sequence iterators from different sequences!", m_hkey == rhs.m_hkey);

  return m_index == rhs.m_index;
}

template< ws_typename_param_k C
        , ws_typename_param_k T
        , ws_typename_param_k V
        , ws_typename_param_k A
        >
inline ws_bool_t basic_reg_key_sequence_const_iterator<C, T, V, A>::
    operator !=(class_type const &rhs) const
{
  return ! operator ==(rhs);
}