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

📄 enumerator_sequence.hpp

📁 新版本TR1的stl
💻 HPP
📖 第 1 页 / 共 3 页
字号:
        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, &copy);

                    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 &current() 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 + -