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 #ifndef COMSTL_INCL_H_COMSTL
00060 # include "comstl.h"
00061 #endif
00062 #ifndef COMSTL_INCL_H_COMSTL_REFCOUNT_FUNCTIONS
00063 # include "comstl_refcount_functions.h"
00064 #endif
00065 #ifndef COMSTL_INCL_H_COMSTL_ENUMERATOR_POLICIES
00066 # include "comstl_enumerator_policies.h"
00067 #endif
00068 #ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00069 # include "stlsoft_iterator.h"
00070 #endif
00071 #include <algorithm>
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 #ifndef _COMSTL_NO_NAMESPACE
00091 # if defined(_STLSOFT_NO_NAMESPACE) || \
00092 defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00093
00094 namespace comstl
00095 {
00096 # else
00097
00098
00099 namespace stlsoft
00100 {
00101
00102 namespace comstl_project
00103 {
00104
00105 # endif
00106 #endif
00107
00108
00109
00114
00115
00116
00117
00118
00178 template< ss_typename_param_k I
00179 , ss_typename_param_k V
00180 , ss_typename_param_k VP
00181 , ss_typename_param_k R = V const &
00182 , ss_typename_param_k CP = degenerate_cloning_policy<I>
00183 , cs_size_t Q = 8
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
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
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
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
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
00308 comstl_ns_qual_std(for_each)(&m_values[0], &m_values[m_acquired], value_policy_type::_clear());
00309
00310
00311 m_current = 0;
00312
00313 ULONG cFetched = 0;
00314 HRESULT hr = m_i->Next(m_quanta, &m_values[0], &cFetched);
00315
00316
00317
00318
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
00349
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
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
00393 private:
00394 static cs_size_t validate_quanta_(cs_size_t quant)
00395 {
00396 comstl_assert(quant <= quanta);
00397
00398 if( 0 == quant ||
00399 quant > quanta)
00400 {
00401 quant = quanta;
00402 }
00403
00404 return quant;
00405 }
00406
00407
00408 private:
00409 interface_type *m_i;
00410 cs_size_t const m_quanta;
00411
00412
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
00423 , ss_typename_param_k V
00424 , ss_typename_param_k VP
00425 , ss_typename_param_k R
00426 , ss_typename_param_k CP
00427 , cs_size_t Q
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
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
00483
00484 return bSuccess;
00485 }
00486
00487 unittest_registrar unittest_comstl_enum_sequence(test_comstl_enum_sequence);
00488
00489 }
00490
00491 #endif
00492
00493
00494
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 #endif
00508
00509
00510
00511
00512
00513