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

Go to the documentation of this file.
00001 /* 
00002  * File:        comstl_safearray_sequence.h (originally MOEnSeq.h, ::SynesisCom)
00003  *
00004  * Purpose:     STL sequence for COM collection interfaces.
00005  *
00006  * Created:     17th April 2004
00007  * Updated:     11th September 2004
00008  *
00009  * Home:        http://stlsoft.org/
00010  *
00011  * Copyright (c) 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_SAFEARRAY_SEQUENCE
00046 #define COMSTL_INCL_H_COMSTL_SAFEARRAY_SEQUENCE
00047 
00048 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00049 # define COMSTL_VER_H_COMSTL_SAFEARRAY_SEQUENCE_MAJOR       2
00050 # define COMSTL_VER_H_COMSTL_SAFEARRAY_SEQUENCE_MINOR       0
00051 # define COMSTL_VER_H_COMSTL_SAFEARRAY_SEQUENCE_REVISION    1
00052 # define COMSTL_VER_H_COMSTL_SAFEARRAY_SEQUENCE_EDIT        19
00053 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00054 
00055 /* 
00056  * Compatibility
00057  */
00058 
00059 /*
00060 [Incompatibilies-start]
00061 __STLSOFT_COMPILER_IS_MSVC: _MSC_VER<1200
00062 [Incompatibilies-end]
00063  */
00064 
00065 /* 
00066  * Includes
00067  */
00068 
00069 #ifndef COMSTL_INCL_H_COMSTL
00070 # include "comstl.h"                    // Include the COMSTL root header
00071 #endif /* !COMSTL_INCL_H_COMSTL */
00072 
00073 #if defined(__STLSOFT_COMPILER_IS_MSVC) && \
00074     _MSC_VER < 1200
00075 # error comstl_safearray_sequence.h is not compatible with Visual C++ 5.0 or earlier
00076 #endif /* _MSC_VER < 1200 */
00077 
00078 #if 0
00079     #ifndef COMSTL_INCL_H_COMSTL_REFCOUNT_FUNCTIONS
00080     # include "comstl_refcount_functions.h" // safe_release, release_set_null
00081     #endif /* !COMSTL_INCL_H_COMSTL_REFCOUNT_FUNCTIONS */
00082     #ifndef COMSTL_INCL_H_COMSTL_ENUMERATOR_POLICIES
00083     # include "comstl_enumerator_policies.h" // input_cloning_policy
00084     #endif /* !COMSTL_INCL_H_COMSTL_ENUMERATOR_POLICIES */
00085     #ifndef COMSTL_INCL_H_COMSTL_INTERFACE_TRAITS
00086     # include "comstl_interface_traits.h"
00087     #endif /* !COMSTL_INCL_H_COMSTL_INTERFACE_TRAITS */
00088 #endif /* 0 */
00089 #ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00090 # include "stlsoft_iterator.h"
00091 #endif /* !STLSOFT_INCL_H_STLSOFT_ITERATOR */
00092 #ifdef STLSOFT_UNITTEST
00093 # include <algorithm>
00094 #endif /* STLSOFT_UNITTEST */
00095 
00096 /* 
00097  * Namespace
00098  *
00099  * The COMSTL components are contained within the comstl namespace. This is
00100  * actually an alias for stlsoft::comstl_project,
00101  *
00102  * The definition matrix is as follows:
00103  *
00104  * _STLSOFT_NO_NAMESPACE    _COMSTL_NO_NAMESPACE    comstl definition
00105  * ---------------------    --------------------    -----------------
00106  *  not defined              not defined             = stlsoft::comstl_project
00107  *  not defined              defined                 not defined
00108  *  defined                  not defined             comstl
00109  *  defined                  defined                 not defined
00110  *
00111  */
00112 
00113 #ifndef _COMSTL_NO_NAMESPACE
00114 # if defined(_STLSOFT_NO_NAMESPACE) || \
00115      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00116 /* There is no stlsoft namespace, so must define ::comstl */
00117 namespace comstl
00118 {
00119 # else
00120 /* Define stlsoft::comstl_project */
00121 
00122 namespace stlsoft
00123 {
00124 
00125 namespace comstl_project
00126 {
00127 
00128 # endif /* _STLSOFT_NO_NAMESPACE */
00129 #endif /* !_COMSTL_NO_NAMESPACE */
00130 
00131 /* 
00132 
00137 
00138 /* 
00139  * Classes
00140  */
00141 
00143 class variant_type_exception
00144     : public std::exception
00145 {};
00146 
00148 template <ss_typename_param_k T>
00149 class safearray_sequence
00150 {
00151 private:
00152     typedef SAFEARRAY const                                                 *LPCSAFEARRAY;
00153 public:
00155     typedef T                                                               value_type;
00157     typedef safearray_sequence<T>                                           class_type;
00159     typedef cs_size_t                                                       size_type;
00161     typedef ptrdiff_t                                                       difference_type;
00163     typedef value_type                                                      &reference;
00165     typedef value_type const                                                &const_reference;
00167     typedef value_type                                                      *pointer;
00169     typedef value_type const                                                *const_pointer;
00171     typedef
00172 #if !defined(__STLSOFT_COMPILER_IS_BORLAND)
00173          ss_typename_type_k
00174 #endif /* __STLSOFT_COMPILER_IS_BORLAND */
00175                        pointer_iterator <   value_type
00176                                         ,   pointer
00177                                         ,   reference
00178                                         >::iterator_type                    iterator;
00180     typedef
00181 #if !defined(__STLSOFT_COMPILER_IS_BORLAND)
00182          ss_typename_type_k
00183 #endif /* __STLSOFT_COMPILER_IS_BORLAND */
00184                        pointer_iterator <   value_type const
00185                                         ,   const_pointer
00186                                         ,   const_reference
00187                                         >::iterator_type                    const_iterator;
00188 
00190 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00191     typedef stlsoft_ns_qual(reverse_iterator_base)      <   iterator
00192                                                         ,   value_type
00193                                                         ,   reference
00194                                                         ,   pointer
00195                                                         ,   difference_type
00196                                                         >                   reverse_iterator;
00197 
00198     typedef stlsoft_ns_qual(const_reverse_iterator_base)<   const_iterator
00199                                                         ,   value_type const
00200                                                         ,   const_reference
00201                                                         ,   const_pointer
00202                                                         ,   difference_type
00203                                                         >                   const_reverse_iterator;
00204 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00205 
00206 public:
00207     ss_explicit_k safearray_sequence(LPCSAFEARRAY array); // throw variant_type_exception
00208 
00209 public:
00213     const_iterator          begin() const;
00217     const_iterator          end() const;
00218 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00222     const_reverse_iterator  rbegin() const;
00226     const_reverse_iterator  rend() const;
00227 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00228 
00232     iterator                begin();
00236     iterator                end();
00237 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00241     reverse_iterator        rbegin();
00245     reverse_iterator        rend();
00246 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00247 
00248 public:
00250     size_type       size() const;
00252     bool            empty() const;
00253 
00254 public:
00255 //  void            **access_data();    // Should RAII this
00256 //  void            unaccess_data();
00257 
00258 private:
00259     static bool     type_is_compatible_(LPCSAFEARRAY array);
00260     static DWORD    calc_size_(LPCSAFEARRAY array);
00261 
00262 private:
00263     LPCSAFEARRAY    m_sa;
00264     DWORD const     m_cItems;
00265 
00266 // Not to be implemented
00267 private:
00268     class_type &operator =(class_type const &);
00269 };
00270 
00272 // Unit-testing
00273 
00274 #ifdef STLSOFT_UNITTEST
00275 
00276 namespace unittest
00277 {
00278     ss_bool_t test_comstl_safearray_sequence(unittest_reporter *r)
00279     {
00280         using stlsoft::unittest::unittest_initialiser;
00281 
00282         ss_bool_t               bSuccess    =   true;
00283 
00284         unittest_initialiser    init(r, "COMSTL", "safearray_sequence", __FILE__);
00285 
00286         /* Create a safe-array. */
00287         SAFEARRAYBOUND  bounds[2] =
00288         {
00289                 {   10,     0   }
00290             ,   {   5,      0   }
00291         };
00292         LPSAFEARRAY     psa =   ::SafeArrayCreate(VT_I4, stlsoft_num_elements(bounds), bounds);
00293 
00294         if(NULL == psa)
00295         {
00296             r->report("failed to create array", __LINE__);
00297             bSuccess = false;
00298         }
00299         else
00300         {
00301             void            *pv;
00302             HRESULT         hr  =   ::SafeArrayAccessData(psa, &pv);
00303 
00304             if(FAILED(hr))
00305             {
00306                 r->report("failed to access array data", __LINE__);
00307                 bSuccess = false;
00308             }
00309             else
00310             {
00311                 long            *pl =   static_cast<long*>(pv);
00312                 cs_size_t       l;
00313                 long            total;
00314 
00315                 for(l = 0, total = 0; l < bounds[0].cElements * bounds[1].cElements; ++l)
00316                 {
00317                     pl[l] = l;
00318                     total += l;
00319                 }
00320                 ::SafeArrayUnaccessData(psa);
00321 
00322                 comstl::safearray_sequence<long>    array(psa);
00323 
00324                 if(stlsoft_ns_qual_std(accumulate)(array.begin(), array.end(), static_cast<long>(0)) != total)
00325                 {
00326                     r->report("array contents (forward iteration) test failed ", __LINE__);
00327                     bSuccess = false;
00328                 }
00329 
00330 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00331                 if(stlsoft_ns_qual_std(accumulate)(array.rbegin(), array.rend(), static_cast<long>(0)) != total)
00332                 {
00333                     r->report("array contents (reverse iteration) test failed ", __LINE__);
00334                     bSuccess = false;
00335                 }
00336 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00337             }
00338 
00339             ::SafeArrayDestroy(psa);
00340         }
00341 
00342         return bSuccess;
00343     }
00344 
00345     unittest_registrar    unittest_comstl_safearray_sequence(test_comstl_safearray_sequence);
00346 
00347 } // namespace unittest
00348 
00349 #endif /* STLSOFT_UNITTEST */
00350 
00352 // Implementation
00353 
00354 template <ss_typename_param_k T>
00355 inline /* static */ bool safearray_sequence<T>::type_is_compatible_(LPCSAFEARRAY array)
00356 {
00357     return sizeof(value_type) == array->cbElements;
00358 }
00359 
00360 template <ss_typename_param_k T>
00361 inline /* static */ DWORD safearray_sequence<T>::calc_size_(LPCSAFEARRAY array)
00362 {
00363     DWORD   cItems  =   1;
00364 
00365     for(USHORT dim = 0; dim < array->cDims; ++dim)
00366     {
00367         cItems *= array->rgsabound[dim].cElements;
00368     }
00369 
00370     return cItems;
00371 }
00372 
00373 template <ss_typename_param_k T>
00374 inline safearray_sequence<T>::safearray_sequence(LPCSAFEARRAY array) // throw variant_type_exception
00375     : m_sa(array)
00376     , m_cItems(calc_size_(array))
00377 {
00378     if(!type_is_compatible_(array))
00379     {
00380         throw variant_type_exception();
00381     }
00382 }
00383 
00384 template <ss_typename_param_k T>
00385 inline ss_typename_type_k safearray_sequence<T>::const_iterator safearray_sequence<T>::begin() const
00386 {
00387     return static_cast<pointer>(m_sa->pvData);
00388 }
00389 
00390 template <ss_typename_param_k T>
00391 inline ss_typename_type_k safearray_sequence<T>::const_iterator safearray_sequence<T>::end() const
00392 {
00393     return static_cast<pointer>(m_sa->pvData) + size();
00394 }
00395 
00396 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00397 template <ss_typename_param_k T>
00398 inline ss_typename_type_k safearray_sequence<T>::const_reverse_iterator safearray_sequence<T>::rbegin() const
00399 {
00400     return const_reverse_iterator(end());
00401 }
00402 
00403 template <ss_typename_param_k T>
00404 inline ss_typename_type_k safearray_sequence<T>::const_reverse_iterator safearray_sequence<T>::rend() const
00405 {
00406     return const_reverse_iterator(begin());
00407 }
00408 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00409 
00410 template <ss_typename_param_k T>
00411 inline ss_typename_type_k safearray_sequence<T>::iterator safearray_sequence<T>::begin()
00412 {
00413     return static_cast<pointer>(m_sa->pvData);
00414 }
00415 
00416 template <ss_typename_param_k T>
00417 inline ss_typename_type_k safearray_sequence<T>::iterator safearray_sequence<T>::end()
00418 {
00419     return static_cast<pointer>(m_sa->pvData) + size();
00420 }
00421 
00422 #if defined(__STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT)
00423 template <ss_typename_param_k T>
00424 inline ss_typename_type_k safearray_sequence<T>::reverse_iterator safearray_sequence<T>::rbegin()
00425 {
00426     return reverse_iterator(end());
00427 }
00428 
00429 template <ss_typename_param_k T>
00430 inline ss_typename_type_k safearray_sequence<T>::reverse_iterator safearray_sequence<T>::rend()
00431 {
00432     return reverse_iterator(begin());
00433 }
00434 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00435 
00436 template <ss_typename_param_k T>
00437 inline ss_typename_type_k safearray_sequence<T>::size_type safearray_sequence<T>::size() const
00438 {
00439     return m_cItems;
00440 }
00441 
00442 template <ss_typename_param_k T>
00443 inline bool safearray_sequence<T>::empty() const
00444 {
00445     return 0 != size();
00446 }
00447 
00448 /* 
00449 
00451 
00452 /* 
00453 
00454 #ifndef _COMSTL_NO_NAMESPACE
00455 # if defined(_STLSOFT_NO_NAMESPACE) || \
00456      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00457 } // namespace comstl
00458 # else
00459 } // namespace stlsoft::comstl_project
00460 } // namespace stlsoft
00461 # endif /* _STLSOFT_NO_NAMESPACE */
00462 #endif /* !_COMSTL_NO_NAMESPACE */
00463 
00464 /* 
00465 
00466 #endif /* !COMSTL_INCL_H_COMSTL_SAFEARRAY_SEQUENCE */
00467 
00468 /* 

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