STLSoft - ... Robust, Lightweight, Cross-platform, Template Software ... ATLSTL - Template Software for the Active Template Library COMSTL - The Standard Template Library meets the Component Object Model .netSTL - Standard Template Library meets the Microsoft.NET Common Language Runtime InetSTL - The Standard Template Library meets WinInet MFCSTL - Template Software for the Microsoft Foundation Classes UNIXSTL - Template Software for the UNIX Operating System WinSTL - where the Standard Template Library meets the Win32 API

Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

comstl_enum_sequence.h

Go to the documentation of this file.
00001 /* 
00002  * File:        comstl_enum_sequence.h (originally MOEnSeq.h, ::SynesisCom)
00003  *
00004  * Purpose:     STL sequence for IEnumXXXX enumerator interfaces.
00005  *
00006  * Created:     17th September 1998
00007  * Updated:     11th September 2004
00008  *
00009  * Home:        http://stlsoft.org/
00010  *
00011  * Copyright (c) 1998-2004, Matthew Wilson and Synesis Software
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * - Redistributions of source code must retain the above copyright notice, this
00018  *   list of conditions and the following disclaimer.
00019  * - Redistributions in binary form must reproduce the above copyright notice,
00020  *   this list of conditions and the following disclaimer in the documentation
00021  *   and/or other materials provided with the distribution.
00022  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
00023  *   any contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036  * POSSIBILITY OF SUCH DAMAGE.
00037  *
00038  * 
00039 
00040 
00044 
00045 #ifndef COMSTL_INCL_H_COMSTL_ENUM_SEQUENCE
00046 #define COMSTL_INCL_H_COMSTL_ENUM_SEQUENCE
00047 
00048 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00049 # define COMSTL_VER_H_COMSTL_ENUM_SEQUENCE_MAJOR        3
00050 # define COMSTL_VER_H_COMSTL_ENUM_SEQUENCE_MINOR        0
00051 # define COMSTL_VER_H_COMSTL_ENUM_SEQUENCE_REVISION     1
00052 # define COMSTL_VER_H_COMSTL_ENUM_SEQUENCE_EDIT         164
00053 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00054 
00055 /* 
00056  * Includes
00057  */
00058 
00059 #ifndef COMSTL_INCL_H_COMSTL
00060 # include "comstl.h"                    // Include the COMSTL root header
00061 #endif /* !COMSTL_INCL_H_COMSTL */
00062 #ifndef COMSTL_INCL_H_COMSTL_REFCOUNT_FUNCTIONS
00063 # include "comstl_refcount_functions.h" // safe_release, release_set_null
00064 #endif /* !COMSTL_INCL_H_COMSTL_REFCOUNT_FUNCTIONS */
00065 #ifndef COMSTL_INCL_H_COMSTL_ENUMERATOR_POLICIES
00066 # include "comstl_enumerator_policies.h" // input_cloning_policy
00067 #endif /* !COMSTL_INCL_H_COMSTL_ENUMERATOR_POLICIES */
00068 #ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00069 # include "stlsoft_iterator.h"
00070 #endif /* !STLSOFT_INCL_H_STLSOFT_ITERATOR */
00071 #include <algorithm>
00072 
00073 /* 
00074  * Namespace
00075  *
00076  * The COMSTL components are contained within the comstl namespace. This is
00077  * actually an alias for stlsoft::comstl_project,
00078  *
00079  * The definition matrix is as follows:
00080  *
00081  * _STLSOFT_NO_NAMESPACE    _COMSTL_NO_NAMESPACE    comstl definition
00082  * ---------------------    --------------------    -----------------
00083  *  not defined              not defined             = stlsoft::comstl_project
00084  *  not defined              defined                 not defined
00085  *  defined                  not defined             comstl
00086  *  defined                  defined                 not defined
00087  *
00088  */
00089 
00090 #ifndef _COMSTL_NO_NAMESPACE
00091 # if defined(_STLSOFT_NO_NAMESPACE) || \
00092      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00093 /* There is no stlsoft namespace, so must define ::comstl */
00094 namespace comstl
00095 {
00096 # else
00097 /* Define stlsoft::comstl_project */
00098 
00099 namespace stlsoft
00100 {
00101 
00102 namespace comstl_project
00103 {
00104 
00105 # endif /* _STLSOFT_NO_NAMESPACE */
00106 #endif /* !_COMSTL_NO_NAMESPACE */
00107 
00108 /* 
00109 
00114 
00115 /* 
00116  * Classes
00117  */
00118 
00178 template<   ss_typename_param_k I                                       /* Interface */
00179         ,   ss_typename_param_k V                                       /* Value type */
00180         ,   ss_typename_param_k VP                                      /* Value policy type */
00181         ,   ss_typename_param_k R   =   V const &                       /* Reference type */
00182         ,   ss_typename_param_k CP  =   degenerate_cloning_policy<I>    /* Cloning policy type */
00183         ,   cs_size_t           Q   =   8                               /* Quanta */
00184         >
00185 class enumerator_sequence
00186 {
00187 public:
00189     typedef I                                                           interface_type;
00191     typedef V                                                           value_type;
00193     typedef policy_adaptor<VP>                                          value_policy_type;
00195     typedef R                                                           reference_type;
00197     typedef CP                                                          cloning_policy_type;
00199     typedef ss_typename_type_k cloning_policy_type::iterator_tag_type   iterator_tag_type;
00201     enum                                                                { quanta = Q };
00203     typedef enumerator_sequence<I, V, VP, R, CP, Q>                     class_type;
00204 
00205 public:
00211     enumerator_sequence(interface_type *i, cs_bool_t bAddRef, cs_size_t quant = 0)
00212         : m_i(i)
00213         , m_quanta(validate_quanta_(quant))
00214     {
00215         if(bAddRef)
00216         {
00217             m_i->AddRef();
00218         }
00219     }
00221     ~enumerator_sequence()
00222     {
00223         m_i->Release();
00224     }
00225 
00226 public:
00228     class iterator
00229         : public stlsoft_ns_qual(iterator_base)<iterator_tag_type, value_type, cs_ptrdiff_t, void, value_type>
00230     {
00231         typedef iterator    class_type;
00232     public:
00234         iterator(interface_type *i, cs_size_t quant)
00235             : m_i(i)
00236             , m_acquired(0)
00237             , m_current(0)
00238             , m_quanta(quant)
00239         {
00240             // Default initialise all elements
00241             comstl_ns_qual_std(for_each)(&m_values[0], &m_values[m_quanta], value_policy_type::_init());
00242 
00243             m_i->AddRef();
00244 
00245             operator ++();
00246         }
00248         iterator()
00249             : m_i(0)
00250             , m_acquired(0)
00251             , m_current(0)
00252             , m_quanta(0)
00253         {
00254             // Default initialise all elements
00255             comstl_ns_qual_std(for_each)(&m_values[0], &m_values[quanta], value_policy_type::_init());
00256         }
00258         iterator(class_type const &rhs)
00259             : m_i(cloning_policy_type::clone(const_cast<interface_type *&>(rhs.m_i)))
00260             , m_acquired(rhs.m_acquired)
00261             , m_current(rhs.m_current)
00262             , m_quanta(rhs.m_quanta)
00263         {
00264             value_type          *begin      =   &m_values[0];
00265             value_type          *end        =   &m_values[m_quanta];
00266             value_type const    *src_begin  =   &rhs.m_values[0];
00267             value_type const    *src_end    =   &rhs.m_values[rhs.m_acquired];
00268 
00269             for(; src_begin != src_end; ++begin, ++src_begin)
00270             {
00271                 value_policy_type::init(begin);
00272                 value_policy_type::copy(begin, src_begin);
00273             }
00274 
00275             for(; begin != end; ++begin)
00276             {
00277                 value_policy_type::init(begin);
00278             }
00279         }
00281         ~iterator()
00282         {
00283             // Clear all elements
00284             comstl_ns_qual_std(for_each)(&m_values[0], &m_values[m_acquired], value_policy_type::_clear());
00285 
00286             safe_release(m_i);
00287         }
00288 
00289     public:
00291         iterator &operator ++()
00292         {
00293             if(++m_current < m_acquired)
00294             {
00295                 // Do nothing
00296             }
00297             else if(NULL == m_i)
00298             {
00299                 comstl_message_assert("Attempting to increment an invalid iterator", 0 < m_acquired && m_acquired < m_quanta && m_current == m_acquired);
00300 
00301                 m_acquired = 0;
00302             }
00303             else
00304             {
00305                 comstl_message_assert("Attempting to increment an invalid iterator", NULL != m_i);
00306 
00307                 // Clear all elements
00308                 comstl_ns_qual_std(for_each)(&m_values[0], &m_values[m_acquired], value_policy_type::_clear());
00309 
00310                 // Reset enumeration
00311                 m_current = 0;
00312 
00313                 ULONG   cFetched    =   0;
00314                 HRESULT hr          =   m_i->Next(m_quanta, &m_values[0], &cFetched);
00315 
00316                 // We no longer checked for a FAILED(hr), since some iterators
00317                 // return invalid results. We rely on cFetched, which is the
00318                 // only reliable guide when marshalling anyway
00319 
00320                 m_acquired = cFetched;
00321 
00322                 if( hr == S_FALSE ||
00323                     m_acquired == 0)
00324                 {
00325                     release_set_null(m_i);
00326                 }
00327             }
00328 
00329             return *this;
00330         }
00331 
00332         void operator ++(int)
00333         {
00334             operator ++();
00335         }
00336 
00337     public:
00339         reference_type operator *()
00340         {
00341             return m_values[m_current];
00342         }
00343 
00344     public:
00346         cs_bool_t operator == (iterator const &rhs) const
00347         {
00348             // The only valid comparison is when they both represent the end
00349             // values.
00350 
00351             return m_acquired == 0 && m_i == 0 && rhs.m_i == 0;
00352         }
00354         cs_bool_t operator != (iterator const &rhs) const
00355         {
00356             return !operator == (rhs);
00357         }
00358 
00359     private:
00360         interface_type  *m_i;
00361         cs_size_t       m_acquired;
00362         cs_size_t       m_current;
00363         cs_size_t const m_quanta;
00364         value_type      m_values[quanta];
00365 
00366     // Not to be implemented
00367     private:
00368         class_type &operator =(class_type const&);
00369     };
00370 
00371 public:
00375     iterator begin() const
00376     {
00377         if(NULL != m_i)
00378         {
00379             m_i->Reset();
00380         }
00381 
00382         return iterator(m_i, m_quanta);
00383     }
00387     iterator end() const
00388     {
00389         return iterator();
00390     }
00391 
00392 // Implementation
00393 private:
00394     static cs_size_t validate_quanta_(cs_size_t quant)
00395     {
00396         comstl_assert(quant <= quanta); // Could have named these things better!
00397 
00398         if( 0 == quant ||
00399             quant > quanta)
00400         {
00401             quant = quanta;
00402         }
00403 
00404         return quant;
00405     }
00406 
00407 // Members
00408 private:
00409     interface_type  *m_i;
00410     cs_size_t const m_quanta;
00411 
00412 // Implementation
00413 private:
00414     enumerator_sequence(class_type const &);
00415     enumerator_sequence const &operator =(class_type const &);
00416 };
00417 
00418 
00422 template<   ss_typename_param_k I   /* Interface */
00423         ,   ss_typename_param_k V   /* Value type */
00424         ,   ss_typename_param_k VP  /* Value policy type */
00425         ,   ss_typename_param_k R   /* Reference type */
00426         ,   ss_typename_param_k CP  /* Cloning policy type */
00427         ,   cs_size_t           Q   /* Quanta */
00428         >
00429 class enum_simple_sequence
00430     : public enumerator_sequence<I, V, VP, R, CP, Q>
00431 {
00432 private:
00433     typedef enumerator_sequence<I, V, VP, R, CP, Q>     parent_class_type;
00434 public:
00436     typedef ss_typename_type_k parent_class_type::interface_type        interface_type;
00438     typedef ss_typename_type_k parent_class_type::value_type            value_type;
00440     typedef ss_typename_type_k parent_class_type::value_policy_type     value_policy_type;
00442     typedef ss_typename_type_k parent_class_type::reference_type        reference_type;
00444     typedef ss_typename_type_k parent_class_type::cloning_policy_type   cloning_policy_type;
00446     typedef ss_typename_type_k parent_class_type::iterator_tag_type     iterator_tag_type;
00448     typedef enum_simple_sequence<I, V, VP, R, CP, Q>                    class_type;
00449 
00450 public:
00455     enum_simple_sequence(interface_type *i, cs_bool_t bAddRef)
00456         : parent_class_type(i, bAddRef)
00457     {}
00458 };
00459 
00460 
00462 // Unit-testing
00463 
00464 #ifdef STLSOFT_UNITTEST
00465 
00466 namespace unittest
00467 {
00468     ss_bool_t test_comstl_enum_sequence(unittest_reporter *r)
00469     {
00470         using stlsoft::unittest::unittest_initialiser;
00471 
00472         ss_bool_t               bSuccess    =   true;
00473 
00474         unittest_initialiser    init(r, "COMSTL", "enum_sequence", __FILE__);
00475 
00476 #if 0
00477         if(<<TODO>>)
00478         {
00479             r->report("<<TODO>> failed ", __LINE__);
00480             bSuccess = false;
00481         }
00482 #endif /* 0 */
00483 
00484         return bSuccess;
00485     }
00486 
00487     unittest_registrar    unittest_comstl_enum_sequence(test_comstl_enum_sequence);
00488 
00489 } // namespace unittest
00490 
00491 #endif /* STLSOFT_UNITTEST */
00492 
00493 /* 
00494 
00496 
00497 /* 
00498 
00499 #ifndef _COMSTL_NO_NAMESPACE
00500 # if defined(_STLSOFT_NO_NAMESPACE) || \
00501      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00502 } // namespace comstl
00503 # else
00504 } // namespace stlsoft::comstl_project
00505 } // namespace stlsoft
00506 # endif /* _STLSOFT_NO_NAMESPACE */
00507 #endif /* !_COMSTL_NO_NAMESPACE */
00508 
00509 /* 
00510 
00511 #endif /* !COMSTL_INCL_H_COMSTL_ENUM_SEQUENCE */
00512 
00513 /* 

STLSoft Libraries documentation © Synesis Software Pty Ltd, 2001-2004