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_coll_sequence.h

Go to the documentation of this file.
00001 /* 
00002  * File:        comstl_collection_sequence.h (originally MOEnSeq.h, ::SynesisCom)
00003  *
00004  * Purpose:     STL sequence for COM collection 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_COLL_SEQUENCE
00046 #define COMSTL_INCL_H_COMSTL_COLL_SEQUENCE
00047 
00048 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00049 # define COMSTL_VER_H_COMSTL_COLL_SEQUENCE_MAJOR        3
00050 # define COMSTL_VER_H_COMSTL_COLL_SEQUENCE_MINOR        0
00051 # define COMSTL_VER_H_COMSTL_COLL_SEQUENCE_REVISION     1
00052 # define COMSTL_VER_H_COMSTL_COLL_SEQUENCE_EDIT         39
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 COMSTL_INCL_H_COMSTL_INTERFACE_TRAITS
00069 # include "comstl_interface_traits.h"
00070 #endif /* !COMSTL_INCL_H_COMSTL_INTERFACE_TRAITS */
00071 #ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00072 # include "stlsoft_iterator.h"
00073 #endif /* !STLSOFT_INCL_H_STLSOFT_ITERATOR */
00074 #include <algorithm>
00075 
00076 /* 
00077  * Namespace
00078  *
00079  * The COMSTL components are contained within the comstl namespace. This is
00080  * actually an alias for stlsoft::comstl_project,
00081  *
00082  * The definition matrix is as follows:
00083  *
00084  * _STLSOFT_NO_NAMESPACE    _COMSTL_NO_NAMESPACE    comstl definition
00085  * ---------------------    --------------------    -----------------
00086  *  not defined              not defined             = stlsoft::comstl_project
00087  *  not defined              defined                 not defined
00088  *  defined                  not defined             comstl
00089  *  defined                  defined                 not defined
00090  *
00091  */
00092 
00093 #ifndef _COMSTL_NO_NAMESPACE
00094 # if defined(_STLSOFT_NO_NAMESPACE) || \
00095      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00096 /* There is no stlsoft namespace, so must define ::comstl */
00097 namespace comstl
00098 {
00099 # else
00100 /* Define stlsoft::comstl_project */
00101 
00102 namespace stlsoft
00103 {
00104 
00105 namespace comstl_project
00106 {
00107 
00108 # endif /* _STLSOFT_NO_NAMESPACE */
00109 #endif /* !_COMSTL_NO_NAMESPACE */
00110 
00111 /* 
00112 
00117 
00118 /* 
00119  * Classes
00120  */
00121 
00182 template<   ss_typename_param_k CI                                      /* Collection interface */
00183         ,   ss_typename_param_k EI                                      /* Enumerator interface */
00184         ,   ss_typename_param_k V                                       /* Value type */
00185         ,   ss_typename_param_k VP                                      /* Value policy type */
00186         ,   ss_typename_param_k R   =   V const &                       /* Reference type */
00187         ,   ss_typename_param_k CP  =   degenerate_cloning_policy<EI>   /* Cloning policy type */
00188         ,   cs_size_t           Q   =   8                               /* Quanta */
00189         >
00190 class collection_sequence
00191 {
00192 public:
00194     typedef CI                                                          collection_interface_type;
00196     typedef EI                                                          enumerator_interface_type;
00198     typedef V                                                           value_type;
00200     typedef policy_adaptor<VP>                                          value_policy_type;
00202     typedef R                                                           reference_type;
00204     typedef CP                                                          cloning_policy_type;
00206     typedef ss_typename_type_k cloning_policy_type::iterator_tag_type   iterator_tag_type;
00208     enum                                                                { quanta = Q };
00210     typedef collection_sequence<CI, EI, V, VP, R, CP, Q>                class_type;
00212     typedef class_type                                                  sequence_type;
00214     typedef cs_size_t                                                   size_type;
00215 
00216 public:
00222     collection_sequence(collection_interface_type *i, cs_bool_t bAddRef, cs_size_t quant = 0)
00223         : m_i(i)
00224         , m_quanta(validate_quanta_(quant))
00225     {
00226         if(bAddRef)
00227         {
00228             m_i->AddRef();
00229         }
00230     }
00232     ~collection_sequence()
00233     {
00234         m_i->Release();
00235     }
00236 
00237 public:
00239     class iterator
00240         : public stlsoft_ns_qual(iterator_base)<iterator_tag_type, value_type, ss_ptrdiff_t, void, value_type>
00241     {
00242         typedef iterator    class_type;
00243     private:
00244         friend class collection_sequence<CI, EI, V, VP, R, CP, Q>;
00245 
00247         iterator(enumerator_interface_type *i, cs_size_t quant)
00248             : m_i(i)
00249             , m_acquired(0)
00250             , m_current(0)
00251             , m_quanta(quant)
00252         {
00253             // Default initialise all elements
00254             comstl_ns_qual_std(for_each)(&m_values[0], &m_values[m_quanta], value_policy_type::_init());
00255 
00256 //            m_i->AddRef();
00257 
00258             operator ++();
00259         }
00260     public:
00262         iterator()
00263             : m_i(0)
00264             , m_acquired(0)
00265             , m_current(0)
00266             , m_quanta(0)
00267         {
00268             // Default initialise all elements
00269             comstl_ns_qual_std(for_each)(&m_values[0], &m_values[m_quanta], value_policy_type::_init());
00270         }
00272         iterator(class_type const &rhs)
00273             : m_i(cloning_policy_type::clone(const_cast<interface_type *&>(rhs.m_i)))
00274             , m_acquired(rhs.m_acquired)
00275             , m_current(rhs.m_current)
00276             , m_quanta(rhs.m_quanta)
00277         {
00278             value_type          *begin      =   &m_values[0];
00279             value_type          *end        =   &m_values[m_quanta];
00280             value_type const    *src_begin  =   &rhs.m_values[0];
00281             value_type const    *src_end    =   &rhs.m_values[rhs.m_acquired];
00282 
00283             for(; src_begin != src_end; ++begin, ++src_begin)
00284             {
00285                 value_policy_type::init(begin);
00286                 value_policy_type::copy(begin, src_begin);
00287             }
00288 
00289 #if 1
00290             for(; begin != end; ++begin)
00291             {
00292                 value_policy_type::init(begin);
00293             }
00294 #else /* ? 0 */
00295             std::for_each(begin, end, s
00296 #endif /* 0 */
00297         }
00299         ~iterator()
00300         {
00301             // Clear all elements
00302             comstl_ns_qual_std(for_each)(&m_values[0], &m_values[m_acquired], value_policy_type::_clear());
00303 
00304             safe_release(m_i);
00305         }
00306 
00307     public:
00309         iterator &operator ++()
00310         {
00311             if(++m_current < m_acquired)
00312             {
00313                 // Do nothing
00314             }
00315             else if(NULL == m_i)
00316             {
00317                 comstl_message_assert("Attempting to increment an invalid iterator", 0 < m_acquired && m_acquired < m_quanta && m_current == m_acquired);
00318 
00319                 m_acquired = 0;
00320             }
00321             else
00322             {
00323                 comstl_message_assert("Attempting to increment an invalid iterator", NULL != m_i);
00324 
00325                 // Clear all elements
00326                 comstl_ns_qual_std(for_each)(&m_values[0], &m_values[m_acquired], value_policy_type::_clear());
00327 
00328                 // Reset enumeration
00329                 m_current = 0;
00330 
00331                 ULONG   cFetched    =   0;
00332                 HRESULT hr          =   m_i->Next(m_quanta, &m_values[0], &cFetched);
00333 
00334                 // We no longer checked for a FAILED(hr), since some iterators
00335                 // return invalid results. We rely on cFetched, which is the
00336                 // only reliable guide when marshalling anyway
00337 
00338                 m_acquired = cFetched;
00339 
00340                 if( hr == S_FALSE ||
00341                     m_acquired == 0)
00342                 {
00343                     release_set_null(m_i);
00344                 }
00345             }
00346 
00347             return *this;
00348         }
00349 
00350         void operator ++(int)
00351         {
00352             operator ++();
00353         }
00354 
00355     public:
00357         reference_type operator *()
00358         {
00359             return m_values[m_current];
00360         }
00361 
00362     public:
00364         cs_bool_t operator == (iterator const &rhs) const
00365         {
00366             // The only valid comparison is when they both represent the end
00367             // values.
00368 
00369             return m_acquired == 0 && m_i == 0 && rhs.m_i == 0;
00370         }
00372         cs_bool_t operator != (iterator const &rhs) const
00373         {
00374             return !operator == (rhs);
00375         }
00376 
00377     // Members
00378     private:
00379         enumerator_interface_type   *m_i;
00380         cs_size_t                   m_acquired;
00381         cs_size_t                   m_current;
00382         cs_size_t                   m_quanta;
00383         value_type                  m_values[quanta];
00384 
00385     // Not to be implemented
00386     private:
00387         class_type &operator =(class_type const&);
00388     };
00389 
00390 public:
00394     iterator begin() const
00395     {
00396         LPUNKNOWN   punkEnum;
00397         HRESULT     hr  =   m_i->get__NewEnum(&punkEnum);
00398 
00399         if(SUCCEEDED(hr))
00400         {
00401             enumerator_interface_type   *ei;
00402 
00403             hr = punkEnum->QueryInterface(IID_traits<enumerator_interface_type>::iid(), reinterpret_cast<void**>(&ei));
00404 
00405             punkEnum->Release();
00406 
00407             if(SUCCEEDED(hr))
00408             {
00409                 return iterator(ei, m_quanta);
00410             }
00411         }
00412 
00413         return iterator();
00414     }
00418     iterator end() const
00419     {
00420         return iterator();
00421     }
00422 
00427     size_type size() const
00428     {
00429         ULONG   count;
00430         HRESULT hr  =   m_i->get_Count(&count);
00431 
00432         return SUCCEEDED(hr) ? count : 0;
00433     }
00434 
00435 // Implementation
00436 private:
00437     static cs_size_t validate_quanta_(cs_size_t quant)
00438     {
00439         comstl_assert(quant <= quanta); // Could have named these things better!
00440 
00441         if( 0 == quant ||
00442             quant > quanta)
00443         {
00444             quant = quanta;
00445         }
00446 
00447         return quant;
00448     }
00449 
00450 // Members
00451 private:
00452     collection_interface_type   *m_i;
00453     cs_size_t const             m_quanta;
00454 
00455 // Implementation
00456 private:
00457     collection_sequence(class_type const &);
00458     collection_sequence const &operator =(class_type const &);
00459 };
00460 
00462 // Unit-testing
00463 
00464 #ifdef STLSOFT_UNITTEST
00465 
00466 namespace unittest
00467 {
00468     ss_bool_t test_comstl_coll_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", "coll_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_coll_sequence(test_comstl_coll_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_COLL_SEQUENCE */
00512 
00513 /* 

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