00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #ifndef COMSTL_INCL_H_COMSTL
00070 # include "comstl.h"
00071 #endif
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
00077
00078 #if 0
00079 #ifndef COMSTL_INCL_H_COMSTL_REFCOUNT_FUNCTIONS
00080 # include "comstl_refcount_functions.h"
00081 #endif
00082 #ifndef COMSTL_INCL_H_COMSTL_ENUMERATOR_POLICIES
00083 # include "comstl_enumerator_policies.h"
00084 #endif
00085 #ifndef COMSTL_INCL_H_COMSTL_INTERFACE_TRAITS
00086 # include "comstl_interface_traits.h"
00087 #endif
00088 #endif
00089 #ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00090 # include "stlsoft_iterator.h"
00091 #endif
00092 #ifdef STLSOFT_UNITTEST
00093 # include <algorithm>
00094 #endif
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 #ifndef _COMSTL_NO_NAMESPACE
00114 # if defined(_STLSOFT_NO_NAMESPACE) || \
00115 defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00116
00117 namespace comstl
00118 {
00119 # else
00120
00121
00122 namespace stlsoft
00123 {
00124
00125 namespace comstl_project
00126 {
00127
00128 # endif
00129 #endif
00130
00131
00132
00137
00138
00139
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
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
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
00205
00206 public:
00207 ss_explicit_k safearray_sequence(LPCSAFEARRAY array);
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
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
00247
00248 public:
00250 size_type size() const;
00252 bool empty() const;
00253
00254 public:
00255
00256
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
00267 private:
00268 class_type &operator =(class_type const &);
00269 };
00270
00272
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
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
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 }
00348
00349 #endif
00350
00352
00353
00354 template <ss_typename_param_k T>
00355 inline 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 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)
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
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
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
00455
00456
00457
00458
00459
00460
00461
00462 #endif
00463
00464
00465
00466
00467
00468