📄 enumerator_sequence.hpp
字号:
public:
typedef enumeration_context class_type;
typedef V value_type;
typedef CP cloning_policy_type;
/// @}
/// \name Construction
/// @{
private:
/// \brief Copying constructor
///
/// This constructor copies the state of rhs, and is given a new
/// cloned enumerator instance pointer.
enumeration_context(interface_type *i, class_type const& rhs)
: m_enumerator(i)
, m_acquired(rhs.m_acquired)
, m_current(rhs.m_current)
, m_quanta(rhs.m_quanta)
, m_refCount(1)
, m_previousBlockTotal(rhs.m_previousBlockTotal)
{
COMSTL_ASSERT(rhs.m_acquired <= m_quanta);
// Initialise all elements first, so that if a copy() throws an exception
// all is cleared up simply.
init_elements_(m_quanta);
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
try
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
{
value_type *begin = &m_values[0];
value_type *end = &m_values[0] + m_quanta;
value_type const *src_begin = &rhs.m_values[0];
value_type const *src_end = &rhs.m_values[0] + rhs.m_acquired;
// Copy each element up to the common extent ...
for(; src_begin != src_end; ++begin, ++src_begin)
{
value_policy_type::copy(begin, src_begin);
}
COMSTL_ASSERT(begin <= end);
STLSOFT_SUPPRESS_UNUSED(end);
}
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
catch(...)
{
// Must clear everything up here, since the enumeration_context will
// not be destroyed (because it is not fully constructed).
clear_elements_();
throw;
}
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
COMSTL_ASSERT(is_valid());
COMSTL_ASSERT(this->index() == rhs.index());
}
public:
/// \brief Sharing constructor
///
/// The iterator is
enumeration_context(interface_type *i, size_type quanta, bool_type bFirst)
: m_enumerator(bFirst ? (i->AddRef(), i) : cloning_policy_type::share(i))
, m_acquired(0)
, m_current(0)
, m_quanta(quanta)
, m_refCount(1)
, m_previousBlockTotal(0)
{
COMSTL_ASSERT(quanta <= STLSOFT_NUM_ELEMENTS(m_values));
init_elements_(m_quanta);
// Note: We don't add a reference here, because share() increments the reference count.
acquire_next_();
COMSTL_ASSERT(is_valid());
}
~enumeration_context() stlsoft_throw_0()
{
++m_refCount;
COMSTL_ASSERT(is_valid());
--m_refCount;
clear_elements_();
if(NULL != m_enumerator)
{
m_enumerator->Release();
}
}
void AddRef()
{
++m_refCount;
}
void Release()
{
if(0 == --m_refCount)
{
delete this;
}
}
static class_type *make_clone(class_type *ctxt)
{
if(NULL == ctxt)
{
return NULL;
}
else
{
COMSTL_ASSERT(NULL != ctxt->m_enumerator); // Must always have one, so can test its cloneability
interface_type *copy;
const bool bTrueClone = cloning_policy_type::clone(ctxt->m_enumerator, ©);
if(!bTrueClone)
{
COMSTL_ASSERT(NULL == copy);
// Either forward_cloning_policy/input_cloning_policy that failed, or input_cloning_policy
//
// No reference will have been taken on m_ctxt->m_enumerator
//
// Just add ref on context, and return
ctxt->AddRef();
return ctxt;
}
else
{
COMSTL_ASSERT(NULL != copy);
// Either forward_cloning_policy that succeeded, or degenerate_cloning_policy that succeeded
//
//
class_type *newCtxt;
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
try
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
{
newCtxt = new class_type(copy, *ctxt);
if(NULL == newCtxt)
{
copy->Release();
}
}
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
catch(...)
{
copy->Release();
throw;
}
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
return newCtxt;
}
}
}
/// @}
/// \name Iteration
/// @{
public:
void advance() stlsoft_throw_0()
{
COMSTL_ASSERT(NULL != m_enumerator);
// Four possibilities here:
//
// 1. Called when in an invalid state. This is determined by:
// -
// -
// -
// 2. next iteration point is within the number acquired
// 3. need to acquire more elements from IEnumXXXX::Next()
// 1.
COMSTL_MESSAGE_ASSERT("Attempting to increment an invalid iterator: m_refCount < 1", 0 < m_refCount);
COMSTL_MESSAGE_ASSERT("Attempting to increment an invalid iterator: 0 == m_acquired", 0 != m_acquired);
COMSTL_MESSAGE_ASSERT("Attempting to increment an invalid iterator: m_current >= m_acquired", m_current < m_acquired);
COMSTL_MESSAGE_ASSERT("Attempting to increment an invalid iterator: m_acquired > m_quanta", m_acquired <= m_quanta);
COMSTL_MESSAGE_ASSERT("Attempting to increment an invalid iterator: m_quanta > dimensionof(m_values)", m_quanta <= STLSOFT_NUM_ELEMENTS(m_values));
if(++m_current < m_acquired)
{
// 2.
// Do nothing
}
else
{
COMSTL_MESSAGE_ASSERT("Attempting to increment an invalid iterator", NULL != m_enumerator);
clear_elements_();
// Reset enumeration
m_current = 0;
acquire_next_();
}
}
value_type ¤t() stlsoft_throw_0()
{
COMSTL_ASSERT(!empty());
return m_values[m_current];
}
size_type index() const stlsoft_throw_0()
{
return m_previousBlockTotal + m_current;
}
bool empty() const stlsoft_throw_0()
{
return 0 == m_acquired /* && NULL == m_enumerator */;
}
/// @}
/// \name Invariant
/// @{
public:
bool_type is_valid() const
{
if(m_refCount < 1)
{
#ifdef STLSOFT_UNITTEST
fprintf(err, "invalid reference count (%ld) \n", m_refCount);
#endif /* STLSOFT_UNITTEST */
return false;
}
if( NULL == m_enumerator &&
0 == m_quanta)
{
if(0 != m_acquired)
{
#ifdef STLSOFT_UNITTEST
fprintf(err, "m_acquired == %lu when m_quanta == 0\n", m_acquired);
#endif /* STLSOFT_UNITTEST */
return false;
}
if(0 != m_current)
{
#ifdef STLSOFT_UNITTEST
fprintf(err, "m_current == %lu when m_quanta == 0\n", m_current);
#endif /* STLSOFT_UNITTEST */
return false;
}
if(0 != m_quanta)
{
return false;
}
}
else
{
if(m_acquired < m_current)
{
#ifdef STLSOFT_UNITTEST
fprintf(err, "m_acquired (%lu) not less than m_current (%lu)\n", m_acquired, m_current);
#endif /* STLSOFT_UNITTEST */
return false;
}
if(m_quanta < m_current)
{
#ifdef STLSOFT_UNITTEST
fprintf(err, "m_quanta (%lu) not less than m_current (%lu)\n", m_quanta, m_current);
#endif /* STLSOFT_UNITTEST */
return false;
}
if(m_quanta < m_acquired)
{
#ifdef STLSOFT_UNITTEST
fprintf(err, "m_quanta (%lu) not less than m_acquired (%lu)\n", m_quanta, m_acquired);
#endif /* STLSOFT_UNITTEST */
return false;
}
}
return true;
}
/// @}
/// \name Implementation
/// @{
private:
void acquire_next_() stlsoft_throw_0()
{
// COMSTL_ASSERT(0 == m_acquired);
COMSTL_ASSERT(0 == m_current);
ULONG cFetched = 0;
m_enumerator->Next(m_quanta, &m_values[0], &cFetched);
m_acquired = cFetched;
m_previousBlockTotal += cFetched;
// We no longer checked for a FAILED(hr), since some enumerators
// return invalid results. We rely on cFetched, which is the
// only reliable guide when marshalling anyway
}
void clear_elements_() stlsoft_throw_0()
{
COMSTL_ASSERT(m_acquired <= STLSOFT_NUM_ELEMENTS(m_values));
typedef ss_typename_type_k value_policy_type::clear_element clear_t;
comstl_ns_qual_std(for_each)(&m_values[0], &m_values[0] + m_acquired, clear_t());
}
void init_elements_(size_type n) stlsoft_throw_0()
{
COMSTL_ASSERT(n <= STLSOFT_NUM_ELEMENTS(m_values));
typedef ss_typename_type_k value_policy_type::init_element init_t;
comstl_ns_qual_std(for_each)(&m_values[0], &m_values[0] + n, init_t());
}
/// @}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -