From 4db083cd6dd8675f83503ab172eef00b4e44e3a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorsten=20J=C3=B8rgen=20Ottosen?= Date: Tue, 23 Oct 2007 20:28:52 +0000 Subject: [PATCH] Shunsuke Sogame's MFC/ATL docs and tests [SVN r40381] --- doc/mfc_atl.html | 313 +++++++++++++++++++ doc/mfc_atl.rst | 232 ++++++++++++++ test/atl.cpp | 623 +++++++++++++++++++++++++++++++++++++ test/mfc.cpp | 789 +++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 1892 insertions(+), 65 deletions(-) create mode 100644 doc/mfc_atl.html create mode 100644 doc/mfc_atl.rst create mode 100644 test/atl.cpp diff --git a/doc/mfc_atl.html b/doc/mfc_atl.html new file mode 100644 index 0000000..5717cc8 --- /dev/null +++ b/doc/mfc_atl.html @@ -0,0 +1,313 @@ + + + + + + +Boost Range MFC/ATL Extension + + + + + + +
+

Boost Range MFC/ATL Extension

+ +++ + + + + + + + + + +
Author:Shunsuke Sogame
Contact:mb2act@yahoo.co.jp
Date:26th of May 2006
Copyright:Shunsuke Sogame 2005-2006. Use, modification and distribution is subject to the Boost Software License, Version 1.0 (see LICENSE_1_0.txt).
+
+

Overview

+

Boost.Range MFC/ATL Extension provides Boost.Range support for MFC/ATL collection and string types.

+
+CTypedPtrArray<CPtrArray, CList<CString> *> myArray;
+...
+BOOST_FOREACH (CList<CString> *theList, myArray)
+{
+    BOOST_FOREACH (CString& str, *theList)
+    {
+        boost::to_upper(str);
+        std::sort(boost::begin(str), boost::end(str));
+        ...
+    }
+}
+
+ +
+
+

Requirements

+ +
+
+

MFC Ranges

+

If the <boost/range/mfc.hpp> is included before or after Boost.Range headers, +the MFC collections and strings become models of Range. +The table below lists the Traversal Category and range_reference of MFC ranges.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RangeTraversal Categoryrange_reference<Range>::type
CArray<T,A>Random AccessT&
CList<T,A>BidirectionalT&
CMap<K,AK,M,AM>ForwardRange::CPair&
CTypedPtrArray<B,T*>Random AccessT* const
CTypedPtrList<B,T*>BidirectionalT* const
CTypedPtrMap<B,T*,V*>Forwardstd::pair<T*,V*> const
CByteArrayRandom AccessBYTE&
CDWordArrayRandom AccessDWORD&
CObArrayRandom AccessCObject* &
CPtrArrayRandom Accessvoid* &
CStringArrayRandom AccessCString&
CUIntArrayRandom AccessUINT&
CWordArrayRandom AccessWORD&
CObListBidirectionalCObject* &
CPtrListBidirectionalvoid* &
CStringListBidirectionalCString&
CMapPtrToWordForwardstd::pair<void*,WORD> const
CMapPtrToPtrForwardstd::pair<void*,void*> const
CMapStringToObForwardstd::pair<String,CObject*> const
CMapStringToStringForwardRange::CPair&
CMapWordToObForwardstd::pair<WORD,CObject*> const
CMapWordToPtrForwardstd::pair<WORD,void*> const
+

Other Boost.Range metafunctions are defined by the following. +Let Range be any type listed above and ReF be the same as range_reference<Range>::type. +range_value<Range>::type is the same as remove_reference<remove_const<Ref>::type>::type, +range_difference<Range>::type is the same as std::ptrdiff_t, and +range_pointer<Range>::type is the same as add_pointer<remove_reference<Ref>::type>::type. +As for const Range, see const Ranges.

+
+
+

ATL Ranges

+

If the <boost/range/atl.hpp> is included before or after Boost.Range headers, +the ATL collections and strings become models of Range. +The table below lists the Traversal Category and range_reference of ATL ranges.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RangeTraversal Categoryrange_reference<Range>::type
CAtlArray<E,ET>Random AccessE&
CAutoPtrArray<E>Random AccessE&
CInterfaceArray<I,pi>Random AccessCComQIPtr<I,pi>&
CAtlList<E,ET>BidirectionalE&
CAutoPtrList<E>BidirectionalE&
CHeapPtrList<E,A>BidirectionalE&
CInterfaceList<I,pi>BidirectionalCComQIPtr<I,pi>&
CAtlMap<K,V,KT,VT>ForwardRange::CPair&
CRBTree<K,V,KT,VT>BidirectionalRange::CPair&
CRBMap<K,V,KT,VT>BidirectionalRange::CPair&
CRBMultiMap<K,V,KT,VT>BidirectionalRange::CPair&
CSimpleStringT<B,b>Random AccessB&
CStringT<B,ST>Random AccessB&
CFixedStringT<S,n>Random Accessrange_reference<S>::type
CStringT<B,ST>Random AccessB&
CComBSTRRandom AccessOLECHAR&
CSimpleArray<T,TE>Random AccessT&
+

Other Boost.Range metafunctions are defined by the following. +Let Range be any type listed above and ReF be the same as range_reference<Range>::type. +range_value<Range>::type is the same as remove_reference<Ref>::type, +range_difference<Range>::type is the same as std::ptrdiff_t, and +range_pointer<Range>::type is the same as add_pointer<remove_reference<Ref>::type>::type. +As for const Range, see const Ranges.

+
+
+

const Ranges

+

range_reference<const Range>::type is defined by the following algorithm. +Let Range be any type listed above and ReF be the same as range_reference<Range>::type.

+
+if (Range is CObArray || Range is CObList)
+    return CObject const * &
+else if (Range is CPtrArray || Range is CPtrList)
+    return void const * &
+else if (there is a type X such that X& is the same as ReF)
+    return X const &
+else if (there is a type X such that X* const is the same as ReF)
+    return X const * const
+else
+    return ReF
+
+

Other Boost.Range metafunctions are defined by the following. +range_value<const Range>::type is the same as range_value<Range>::type, +range_difference<const Range>::type is the same as std::ptrdiff_t, and +range_pointer<const Range>::type is the same as add_pointer<remove_reference<range_reference<const Range>::type>::type>::type.

+
+ +
+ + + diff --git a/doc/mfc_atl.rst b/doc/mfc_atl.rst new file mode 100644 index 0000000..3dcd8fe --- /dev/null +++ b/doc/mfc_atl.rst @@ -0,0 +1,232 @@ + +++++++++++++++++++++++++++++++++ + |Boost| Range MFC/ATL Extension +++++++++++++++++++++++++++++++++ + +.. |Boost| image:: http://www.boost.org/libs/ptr_container/doc/boost.png + + + +:Author: Shunsuke Sogame +:Contact: mb2act@yahoo.co.jp +:date: 26th of May 2006 +:copyright: Shunsuke Sogame 2005-2006. Use, modification and distribution is subject to the Boost Software License, Version 1.0 (see LICENSE_1_0.txt__). + +__ http://www.boost.org/LICENSE_1_0.txt + + + +======== +Overview +======== + +Boost.Range MFC/ATL Extension provides `Boost.Range`_ support for MFC/ATL collection and string types. + + +.. parsed-literal:: + + CTypedPtrArray \*> myArray; + ... + BOOST_FOREACH (CList \*theList, myArray) + { + BOOST_FOREACH (CString& str, \*theList) + { + boost::to_upper(str); + std::sort(boost::begin(str), boost::end(str)); + ... + } + } + + + +* `Requirements`_ +* `MFC Ranges`_ +* `ATL Ranges`_ +* `const Ranges`_ +* `References`_ + + + +============ +Requirements +============ + +- `Boost C++ Libraries Version 1.34.0`__ or later (no compilation required) +- Visual C++ 7.1 or Visual C++ 8.0 + +__ Boost_ + + + +========== +MFC Ranges +========== + +If the ```` is included before or after `Boost.Range`_ headers, +the MFC collections and strings become models of Range. +The table below lists the Traversal Category and ``range_reference`` of MFC ranges. + + +============================= ================== ======================================= +``Range`` Traversal Category ``range_reference::type`` +============================= ================== ======================================= +``CArray`` Random Access ``T&`` +----------------------------- ------------------ --------------------------------------- +``CList`` Bidirectional ``T&`` +----------------------------- ------------------ --------------------------------------- +``CMap`` Forward ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CTypedPtrArray`` Random Access ``T* const`` +----------------------------- ------------------ --------------------------------------- +``CTypedPtrList`` Bidirectional ``T* const`` +----------------------------- ------------------ --------------------------------------- +``CTypedPtrMap`` Forward ``std::pair const`` +----------------------------- ------------------ --------------------------------------- +``CByteArray`` Random Access ``BYTE&`` +----------------------------- ------------------ --------------------------------------- +``CDWordArray`` Random Access ``DWORD&`` +----------------------------- ------------------ --------------------------------------- +``CObArray`` Random Access ``CObject* &`` +----------------------------- ------------------ --------------------------------------- +``CPtrArray`` Random Access ``void* &`` +----------------------------- ------------------ --------------------------------------- +``CStringArray`` Random Access ``CString&`` +----------------------------- ------------------ --------------------------------------- +``CUIntArray`` Random Access ``UINT&`` +----------------------------- ------------------ --------------------------------------- +``CWordArray`` Random Access ``WORD&`` +----------------------------- ------------------ --------------------------------------- +``CObList`` Bidirectional ``CObject* &`` +----------------------------- ------------------ --------------------------------------- +``CPtrList`` Bidirectional ``void* &`` +----------------------------- ------------------ --------------------------------------- +``CStringList`` Bidirectional ``CString&`` +----------------------------- ------------------ --------------------------------------- +``CMapPtrToWord`` Forward ``std::pair const`` +----------------------------- ------------------ --------------------------------------- +``CMapPtrToPtr`` Forward ``std::pair const`` +----------------------------- ------------------ --------------------------------------- +``CMapStringToOb`` Forward ``std::pair const`` +----------------------------- ------------------ --------------------------------------- +``CMapStringToString`` Forward ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CMapWordToOb`` Forward ``std::pair const`` +----------------------------- ------------------ --------------------------------------- +``CMapWordToPtr`` Forward ``std::pair const`` +============================= ================== ======================================= + + +Other `Boost.Range`_ metafunctions are defined by the following. +Let ``Range`` be any type listed above and ``ReF`` be the same as ``range_reference::type``. +``range_value::type`` is the same as ``remove_reference::type>::type``, +``range_difference::type`` is the same as ``std::ptrdiff_t``, and +``range_pointer::type`` is the same as ``add_pointer::type>::type``. +As for ``const Range``, see `const Ranges`_. + + + +========== +ATL Ranges +========== + +If the ```` is included before or after `Boost.Range`_ headers, +the ATL collections and strings become models of Range. +The table below lists the Traversal Category and ``range_reference`` of ATL ranges. + + +============================= ================== ======================================= +``Range`` Traversal Category ``range_reference::type`` +============================= ================== ======================================= +``CAtlArray`` Random Access ``E&`` +----------------------------- ------------------ --------------------------------------- +``CAutoPtrArray`` Random Access ``E&`` +----------------------------- ------------------ --------------------------------------- +``CInterfaceArray`` Random Access ``CComQIPtr&`` +----------------------------- ------------------ --------------------------------------- +``CAtlList`` Bidirectional ``E&`` +----------------------------- ------------------ --------------------------------------- +``CAutoPtrList`` Bidirectional ``E&`` +----------------------------- ------------------ --------------------------------------- +``CHeapPtrList`` Bidirectional ``E&`` +----------------------------- ------------------ --------------------------------------- +``CInterfaceList`` Bidirectional ``CComQIPtr&`` +----------------------------- ------------------ --------------------------------------- +``CAtlMap`` Forward ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CRBTree`` Bidirectional ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CRBMap`` Bidirectional ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CRBMultiMap`` Bidirectional ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CSimpleStringT`` Random Access ``B&`` +----------------------------- ------------------ --------------------------------------- +``CStringT`` Random Access ``B&`` +----------------------------- ------------------ --------------------------------------- +``CFixedStringT`` Random Access ``range_reference::type`` +----------------------------- ------------------ --------------------------------------- +``CStringT`` Random Access ``B&`` +----------------------------- ------------------ --------------------------------------- +``CComBSTR`` Random Access ``OLECHAR&`` +----------------------------- ------------------ --------------------------------------- +``CSimpleArray`` Random Access ``T&`` +============================= ================== ======================================= + + +Other `Boost.Range`_ metafunctions are defined by the following. +Let ``Range`` be any type listed above and ``ReF`` be the same as ``range_reference::type``. +``range_value::type`` is the same as ``remove_reference::type``, +``range_difference::type`` is the same as ``std::ptrdiff_t``, and +``range_pointer::type`` is the same as ``add_pointer::type>::type``. +As for ``const Range``, see `const Ranges`_. + + + +============ +const Ranges +============ + +``range_reference::type`` is defined by the following algorithm. +Let ``Range`` be any type listed above and ``ReF`` be the same as ``range_reference::type``. + + +.. parsed-literal:: + + if (Range is CObArray || Range is CObList) + return CObject const \* & + else if (Range is CPtrArray || Range is CPtrList) + return void const \* & + else if (there is a type X such that X& is the same as ReF) + return X const & + else if (there is a type X such that X* const is the same as ReF) + return X const \* const + else + return ReF + + +Other `Boost.Range`_ metafunctions are defined by the following. +``range_value::type`` is the same as ``range_value::type``, +``range_difference::type`` is the same as ``std::ptrdiff_t``, and +``range_pointer::type`` is the same as ``add_pointer::type>::type>::type``. + + + +========== +References +========== +- `Boost.Range`_ +- `MFC Collections`__ +- `ATL Collection Classes`__ + +__ http://msdn2.microsoft.com/en-us/library/942860sh.aspx +__ http://msdn2.microsoft.com/en-US/library/15e672bd.aspx + + + +.. _Boost C++ Libraries: http://www.boost.org/ +.. _Boost: `Boost C++ Libraries`_ +.. _Boost.Range: http://www.boost.org/libs/range/ +.. _forward: http://www.boost.org/libs/range/doc/range.html#forward_range +.. _bidirectional: http://www.boost.org/libs/range/doc/range.html#forward_range +.. _random access: http://www.boost.org/libs/range/doc/range.html#random_access_range + diff --git a/test/atl.cpp b/test/atl.cpp new file mode 100644 index 0000000..50905b1 --- /dev/null +++ b/test/atl.cpp @@ -0,0 +1,623 @@ + + +// Boost.Range ATL Extension +// +// Copyright Shunsuke Sogame 2005-2006. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +// #include + +#include +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS +#define _ATL_NO_AUTOMATIC_NAMESPACE + +#define BOOST_LIB_NAME boost_test_exec_monitor +#include + +#define BOOST_RANGE_DETAIL_MICROSOFT_TEST +#include // can be placed first + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + + +#include // for ATL3 CSimpleArray/CSimpleValArray +#if !(_ATL_VER < 0x0700) + #include + #include + #include + #include +#endif + + +namespace brdm = boost::range_detail_microsoft; + + +#if !(_ATL_VER < 0x0700) + + +template< class ArrayT, class SampleRange > +bool test_init_auto_ptr_array(ArrayT& arr, SampleRange& sample) +{ + typedef typename boost::range_iterator::type iter_t; + + for (iter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) { + arr.Add(*it); // moves ownership + } + + return boost::distance(arr) == boost::distance(sample); +} + + +template< class ListT, class SampleRange > +bool test_init_auto_ptr_list(ListT& lst, SampleRange& sample) +{ + typedef typename boost::range_iterator::type iter_t; + typedef typename boost::range_value::type val_t; + + for (iter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) { + lst.AddTail(*it); // moves ownership + } + + return boost::distance(lst) == boost::distance(sample); +} + + +// Workaround: +// CRBTree provides no easy access function, but yes, it is the range! +// +template< class AtlMapT, class KeyT, class MappedT > +bool test_atl_map_has(AtlMapT& map, const KeyT& k, const MappedT m) +{ + typedef typename boost::range_iterator::type iter_t; + + for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) { + if (it->m_key == k && it->m_value == m) + return true; + } + + return false; +} + + +template< class AtlMapT, class MapT > +bool test_atl_map(AtlMapT& map, const MapT& sample) +{ + typedef typename boost::range_iterator::type iter_t; + typedef typename boost::range_const_iterator::type siter_t; + + bool result = true; + + result = result && (boost::distance(map) == boost::distance(sample)); + if (!result) + return false; + + { + for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) { + result = result && brdm::test_find_key_and_mapped(sample, std::make_pair(it->m_key, it->m_value)); + } + } + + { + for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) { + result = result && (test_atl_map_has)(map, it->first, it->second); + } + } + + return result; +} + + +template< class MapT, class SampleMap > +bool test_init_atl_multimap(MapT& map, const SampleMap& sample) +{ + typedef typename boost::range_const_iterator::type iter_t; + + for (iter_t it = boost::const_begin(sample), last = boost::const_end(sample); it != last; ++it) { + map.Insert(it->first, it->second); + } + + return boost::distance(map) == boost::distance(sample); +} + + +// arrays +// + +template< class Range > +void test_CAtlArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CAtlArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class ValT, class Range > +void test_CAutoPtrArray(Range& sample) +{ + typedef ValT val_t; + + typedef ATL::CAutoPtrArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter *> >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter const*> >::value )); + + rng_t rng; + BOOST_CHECK( ::test_init_auto_ptr_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class I, class Range > +void test_CInterfaceArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CInterfaceArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter * >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter const* >::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// lists +// + +template< class Range > +void test_CAtlList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CAtlList rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class ValT, class Range > +void test_CAutoPtrList(Range& sample) +{ + typedef ValT val_t; + + typedef ATL::CAutoPtrList rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, boost::indirect_iterator< brdm::list_iterator > > >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, boost::indirect_iterator< brdm::list_iterator const> > >::value )); + + rng_t rng; + BOOST_CHECK( ::test_init_auto_ptr_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class ValT, class Range > +void test_CHeapPtrList(const Range& sample) +{ + typedef ValT val_t; + + typedef ATL::CHeapPtrList rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, boost::indirect_iterator< brdm::list_iterator > > >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, boost::indirect_iterator< brdm::list_iterator const> > >::value )); + + rng_t rng; + BOOST_CHECK( ::test_init_auto_ptr_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class I, class Range > +void test_CInterfaceList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CInterfaceList rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator > >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator const> >::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// strings +// + +template< class Range > +void test_CSimpleStringT(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef typename boost::mpl::if_< boost::is_same, + ATL::CAtlStringA, + ATL::CAtlStringW + >::type derived_t; + + typedef ATL::CSimpleStringT rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + derived_t drng; + rng_t& rng = drng; + BOOST_CHECK( brdm::test_init_string(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + // BOOST_CHECK( brdm::test_emptiness(rng) ); no default constructible +} + + +template< int n, class Range > +void test_CFixedStringT(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef typename boost::mpl::if_< boost::is_same, + ATL::CAtlStringA, + ATL::CAtlStringW + >::type base_t; + + typedef ATL::CFixedStringT rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_string(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CStringT(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef typename boost::mpl::if_< boost::is_same, + ATL::CAtlStringA, // == CStringT + ATL::CAtlStringW // == CStringT + >::type rng_t; + + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_string(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CStaticString(const Range& sample) +{ +#if !defined(BOOST_RANGE_ATL_NO_TEST_UNDOCUMENTED_RANGE) + { + typedef ATL::CStaticString rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng("hello static string"); + BOOST_CHECK( *(boost::begin(rng)+4) == 'o' ); + BOOST_CHECK( *(boost::end(rng)-3) == 'i' ); + } + + { + typedef ATL::CStaticString rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng(L"hello static string"); + BOOST_CHECK( *(boost::begin(rng)+4) == L'o' ); + BOOST_CHECK( *(boost::end(rng)-3) == L'i' ); + } +#endif + + (void)sample; // unused +} + + +#endif // !(_ATL_VER < 0x0700) + + +template< class Range > +void test_CComBSTR(const Range& sample) +{ + typedef ATL::CComBSTR rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng(OLESTR("hello CComBSTR range!")); + BOOST_CHECK( brdm::test_equals(rng, std::string("hello CComBSTR range!")) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); + + (void)sample; // unused +} + + +// simples +// + +template< class Range > +void test_CSimpleArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CSimpleArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CSimpleMap(const Range& sample) +{ +#if !defined(BOOST_RANGE_ATL_NO_TEST_UNDOCUMENTED_RANGE) + + typedef ATL::CSimpleMap rng_t; + + rng_t rng; + rng.Add(3, 3.0); + rng.Add(4, 2.0); + + BOOST_CHECK( boost::begin(rng)->get<0>() == 3.0 ); + BOOST_CHECK( (boost::end(rng)-1)->get<1>() == 2.0 ); + +#endif + + (void)sample; // unused +} + + +template< class Range > +void test_CSimpleValArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CSimpleArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// maps +// + +template< class MapT > +void test_CAtlMap(const MapT& sample) +{ + typedef typename MapT::key_type k_t; + typedef typename MapT::mapped_type m_t; + + typedef ATL::CAtlMap rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_atl_map(rng, sample) ); +} + + +template< class MapT > +void test_CRBTree(const MapT& sample) +{ + typedef typename MapT::key_type k_t; + typedef typename MapT::mapped_type m_t; + + typedef ATL::CRBMap derived_t; + typedef ATL::CRBTree rng_t; + + derived_t drng; + rng_t& rng = drng; + + boost::function_requires< boost::BidirectionalRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(drng, sample) ); + BOOST_CHECK( ::test_atl_map(rng, sample) ); +} + + +template< class MapT > +void test_CRBMap(const MapT& sample) +{ + typedef typename MapT::key_type k_t; + typedef typename MapT::mapped_type m_t; + + typedef ATL::CRBMap rng_t; + + rng_t rng; + boost::function_requires< boost::BidirectionalRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_atl_map(rng, sample) ); +} + + +template< class MapT > +void test_CRBMultiMap(const MapT& sample) +{ + typedef typename MapT::key_type k_t; + typedef typename MapT::mapped_type m_t; + + typedef ATL::CRBMultiMap rng_t; + + rng_t rng; + boost::function_requires< boost::BidirectionalRangeConcept >(); + BOOST_CHECK( ::test_init_atl_multimap(rng, sample) ); + BOOST_CHECK( ::test_atl_map(rng, sample) ); +} + + +// main test +// + +void test_atl() +{ + + // ordinary ranges + // + { + std::string sample("rebecca judy and mary whiteberry chat monchy"); +#if !(_ATL_VER < 0x0700) + ::test_CAtlArray(sample); + ::test_CAtlList(sample); + ::test_CSimpleStringT(sample); + ::test_CFixedStringT<44>(sample); + ::test_CStringT(sample); + ::test_CStaticString(sample); +#endif + ::test_CComBSTR(sample); + ::test_CSimpleArray(sample); + ::test_CSimpleMap(sample); + ::test_CSimpleValArray(sample); + } + + + { + std::wstring sample(L"rebecca judy and mary whiteberry chat monchy"); +#if !(_ATL_VER < 0x0700) + ::test_CAtlArray(sample); + ::test_CAtlList(sample); + ::test_CSimpleStringT(sample); + ::test_CFixedStringT<44>(sample); + ::test_CStringT(sample); + ::test_CStaticString(sample); +#endif + ::test_CComBSTR(sample); + ::test_CSimpleArray(sample); + ::test_CSimpleMap(sample); + ::test_CSimpleValArray(sample); + } + + // pointer ranges + // +#if !(_ATL_VER < 0x0700) + { + typedef ATL::CAutoPtr ptr_t; + ptr_t + ptr0(new int(3)), ptr1(new int(4)), ptr2(new int(5)), ptr3(new int(4)), + ptr4(new int(1)), ptr5(new int(2)), ptr6(new int(4)), ptr7(new int(0)); + + ptr_t ptrs[8] = { + ptr0, ptr1, ptr2, ptr3, ptr4, ptr5, ptr6, ptr7 + }; + + boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+8); + ::test_CAutoPtrArray(workaround); + } + + { + typedef ATL::CAutoPtr ptr_t; + ptr_t + ptr0(new int(3)), ptr1(new int(4)), ptr2(new int(5)), ptr3(new int(4)), + ptr4(new int(1)), ptr5(new int(2)), ptr6(new int(4)), ptr7(new int(0)); + + ptr_t ptrs[8] = { + ptr0, ptr1, ptr2, ptr3, ptr4, ptr5, ptr6, ptr7 + }; + + boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+8); + ::test_CAutoPtrList(workaround); + } + + { + typedef ATL::CHeapPtr ptr_t; + ptr_t ptrs[5]; { + ptrs[0].AllocateBytes(sizeof(int)); + ptrs[1].AllocateBytes(sizeof(int)); + ptrs[2].AllocateBytes(sizeof(int)); + ptrs[3].AllocateBytes(sizeof(int)); + ptrs[4].AllocateBytes(sizeof(int)); + } + + boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+5); + ::test_CHeapPtrList(workaround); + } + + + { + typedef ATL::CComQIPtr ptr_t; + ptr_t ptrs[8]; + + boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+8); + ::test_CInterfaceArray(workaround); + ::test_CInterfaceList(workaround); + } +#endif + + // maps + // + { +#if !(_ATL_VER < 0x0700) + std::map sample; { + sample[0] = "hello"; + sample[1] = "range"; + sample[2] = "atl"; + sample[3] = "mfc"; + sample[4] = "collections"; + } + + ::test_CAtlMap(sample); + ::test_CRBTree(sample); + ::test_CRBMap(sample); + ::test_CRBMultiMap(sample); +#endif + } + + +} // test_atl + + +#include +using boost::unit_test::test_suite; + + +test_suite * +init_unit_test_suite(int argc, char* argv[]) +{ + test_suite *test = BOOST_TEST_SUITE("ATL Range Test Suite"); + test->add(BOOST_TEST_CASE(&test_atl)); + + (void)argc, (void)argv; // unused + return test; +} diff --git a/test/mfc.cpp b/test/mfc.cpp index c429993..29f2234 100755 --- a/test/mfc.cpp +++ b/test/mfc.cpp @@ -1,86 +1,745 @@ -// Boost.Range library -// -// Copyright Thorsten Ottosen 2003-2004. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see http://www.boost.org/libs/range/ + + +// Boost.Range MFC Extension // +// Copyright Shunsuke Sogame 2005-2006. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) -#define _MSL_USING_NAMESPACE 1 -#include +#include // must be here -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -# pragma warn -8091 // supress warning in Boost.Test -# pragma warn -8057 // unused argument argc/argv in Boost.Test -#endif - -#define BOOST_RANGE_ENABLE_MFC -#define BOOST_RANGE_ENABLE_MCF_CARRAY - -/* -#define WIN32 -#define _WINDOWS -#define _MBCS -#define _AFXDLL -#define _ATL_DLL -*/ - -///Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_MBCS" /D "_AFXDLL" /D "_ATL_DLL" /Gm /EHsc /RTC1 -// /MDd /Zc:wchar_t /Yu"stdafx.h" /Fp"Debug/Foo.pch" /Fo"Debug/" /Fd"Debug/vc70.pdb" /W3 /nologo /c /Wp64 /ZI /TP - -#include -#include -#include +// #include #include -#include +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS +#define _ATL_NO_AUTOMATIC_NAMESPACE + +#define BOOST_LIB_NAME boost_test_exec_monitor +#include + +#define BOOST_RANGE_DETAIL_MICROSOFT_TEST +#include // can be placed first -void check_mfc() +#include +#include +// #include +#include +#include +#include +#include +#include + + +#include +#include +#include + +#if !(_ATL_VER < 0x0700) + #include + #include + #include +#endif + + +namespace brdm = boost::range_detail_microsoft; + + +// helpers +// + +template< class MfcMapT, class MapT > +bool test_mfc_map(MfcMapT& map, const MapT& sample) { - CString s = "hello world"; - BOOST_CHECK( boost::begin( s ) + boost::size( s ) == boost::end( s ) ); - BOOST_CHECK( boost::size( s ) == boost::size( "hello world" ) ); - BOOST_CHECK( !boost::empty( s ) ); - const CString cs( s ); - BOOST_CHECK( boost::begin( cs ) + boost::size( cs ) == boost::end( cs ) ); - BOOST_CHECK( boost::size( cs ) == boost::size( "hello world" ) ); - BOOST_CHECK( !boost::empty( cs ) ); - - CArray a; - BOOST_CHECK( boost::empty( a ) ); - a.Add( 5 ); - a.Add( 10 ); - BOOST_CHECK( boost::begin( a ) + boost::size( a ) == boost::end( a ) ); - BOOST_CHECK( boost::size( a ) == 2 ); - BOOST_CHECK( !boost::empty( a ) ); - const CArray& ca = a; - BOOST_CHECK( boost::begin( ca ) + boost::size( ca ) == boost::end( ca ) ); - BOOST_CHECK( boost::size( ca ) == 2 ); - BOOST_CHECK( !boost::empty( ca ) ); - + typedef typename boost::range_iterator::type iter_t; + typedef typename boost::range_const_iterator::type siter_t; + + bool result = true; + + result = result && (boost::distance(map) == boost::distance(sample)); + if (!result) + return false; + + { + for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) { + result = result && brdm::test_find_key_and_mapped(sample, *it); + } + } + + { + for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) { + result = result && (map[it->first] == it->second); + } + } + + return result; } +template< class MfcMapT, class MapT > +bool test_mfc_cpair_map(MfcMapT& map, const MapT& sample) +{ + typedef typename boost::range_iterator::type iter_t; + typedef typename boost::range_const_iterator::type siter_t; + + bool result = true; + + result = result && (boost::distance(map) == boost::distance(sample)); + if (!result) + return false; + + { + for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) { + result = result && brdm::test_find_key_and_mapped(sample, std::make_pair(it->key, it->value)); + } + } + + { + for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) { + result = result && (map[it->first] == it->second); + } + } + + return result; +} + + +// arrays +// +template< class Range > +void test_CByteArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CByteArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CDWordArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CDWordArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CObArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CObArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter >::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CPtrArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CPtrArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter >::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CStringArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CStringArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CUIntArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CUIntArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CWordArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CWordArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// lists +// + +template< class Range > +void test_CObList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CObList rng_t; + + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator >::value )); +#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#else + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#endif + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CPtrList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CPtrList rng_t; + + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator >::value )); +#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#else + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#endif + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CStringList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CStringList rng_t; + + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator >::value )); +#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#else + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#endif + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// maps +// + +template< class MapT > +void test_CMapPtrToWord(const MapT& sample) +{ + typedef ::CMapPtrToWord rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapPtrToPtr(const MapT& sample) +{ + typedef ::CMapPtrToPtr rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapStringToOb(const MapT& sample) +{ + typedef ::CMapStringToOb rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapStringToPtr(const MapT& sample) +{ + typedef ::CMapStringToPtr rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapStringToString(const MapT& sample) +{ + typedef ::CMapStringToString rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); +#if !defined(BOOST_RANGE_MFC_NO_CPAIR) + BOOST_CHECK( ::test_mfc_cpair_map(rng, sample) ); +#endif + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapWordToOb(const MapT& sample) +{ + typedef ::CMapWordToOb rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapWordToPtr(const MapT& sample) +{ + typedef ::CMapWordToPtr rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// templates +// + +template< class Range > +void test_CArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CArray rng_t; // An old MFC needs the second template argument. + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CList rng_t; + + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator >::value )); +#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#else + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#endif + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMap(const MapT& sample) +{ + typedef typename MapT::key_type k_t; + typedef typename MapT::mapped_type m_t; + + typedef ::CMap rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); +#if !defined(BOOST_RANGE_MFC_NO_CPAIR) + BOOST_CHECK( ::test_mfc_cpair_map(rng, sample) ); +#endif + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +void test_CTypedPtrArray() +{ + typedef ::CTypedPtrArray< ::CPtrArray, int * > rng_t; + boost::function_requires< boost::RandomAccessRangeConcept >(); + + rng_t rng; + int o1, o2, o3, o4, o5; + int *data[] = { &o1, &o2, &o3, &o4, &o5 }; + BOOST_CHECK( brdm::test_init_array(rng, boost::make_iterator_range(data, data+5)) ); + + BOOST_CHECK( *(boost::begin(rng) + 2) == &o3 ); + BOOST_CHECK( *(boost::end(rng) - 1) == &o5 ); + + // BOOST_CHECK( brdm::test_random_access(rng) ); this range is not mutable + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +void test_CTypedPtrList() +{ + typedef ::CTypedPtrList< ::CObList, ::CObList * > rng_t; + boost::function_requires< boost::BidirectionalRangeConcept >(); + + rng_t rng; + + ::CObList o1, o2, o3, o4, o5; + ::CObList *data[] = { &o1, &o2, &o3, &o4, &o5 }; + BOOST_CHECK( brdm::test_init_list(rng, data) ); + + boost::range_iterator::type it = boost::begin(rng); + std::advance(it, 1); + BOOST_CHECK( *it == &o2 ); + std::advance(it, 2); + BOOST_CHECK( *it == &o4 ); + + // BOOST_CHECK( brdm::test_bidirectional(rng) ); this range is not mutable + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +void test_CTypedPtrMap() +{ + typedef ::CTypedPtrMap< ::CMapStringToPtr, ::CString, int *> rng_t; + boost::function_requires< boost::ForwardRangeConcept >(); + + rng_t rng; + ::CString o0(_T('a')), o1(_T('c')), o2(_T('f')), o3(_T('q')), o4(_T('g')); + int d0, d1, d2, d3, d4; + std::map< ::CString, int * > data; + data[o0] = &d0, data[o1] = &d1, data[o2] = &d2, data[o3] = &d3, data[o4] = &d4; + + BOOST_CHECK( brdm::test_init_map(rng, data) ); + BOOST_CHECK( ::test_mfc_map(rng, data) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// strings +// +#if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING) + + template< class Range > + void test_CString(const Range& sample) + { + typedef typename boost::range_value::type val_t; + + typedef ::CString rng_t; // An old MFC needs the second template argument. + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_string(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); + } + +#endif + + +struct CPerson +{ + void hello_range() { }; +}; + + +void test_mfc() +{ +#if 0 + // overview + // + { + CTypedPtrArray *> myArray; + // ... + BOOST_FOREACH (CList *theList, myArray) + { + BOOST_FOREACH (CString& str, *theList) + { + boost::to_upper(str); + std::sort(boost::begin(str), boost::end(str)); + // ... + } + } + } +#endif + + // arrays + // + { + BYTE data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 }; + + ::test_CByteArray(boost::make_iterator_range(data, data+22)); + } + + { + DWORD data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 }; + + test_CDWordArray(boost::make_iterator_range(data, data+22)); + } + + { + ::CObArray o1, o2, o3, o4, o5; + ::CObject *data[] = { &o1, &o2, &o3, &o4, &o5 }; + + ::test_CObArray(boost::make_iterator_range(data, data+5)); + } + + { + ::CPtrArray o1, o2, o3, o4, o5; + void *data[] = { &o1, &o2, &o3, &o4, &o5 }; + + ::test_CPtrArray(boost::make_iterator_range(data, data+5)); + } + + { + ::CString data[] = { + ::CString(_T('0')), ::CString(_T('1')), ::CString(_T('2')), ::CString(_T('3')), + ::CString(_T('4')), ::CString(_T('5')), ::CString(_T('6')), ::CString(_T('7')) + }; + + ::test_CStringArray(boost::make_iterator_range(data, data+8)); + } + + { + ::CUIntArray rng; + UINT data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 }; + + ::test_CUIntArray(boost::make_iterator_range(data, data+22)); + } + + { + ::CWordArray rng; + WORD data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 }; + + ::test_CWordArray(boost::make_iterator_range(data, data+22)); + } + + + // lists + // + { + ::CObList rng; + ::CObList o1, o2, o3, o4, o5; + ::CObject *data[] = { &o1, &o2, &o3, &o4, &o5 }; + + ::test_CObList(boost::make_iterator_range(data, data+5)); + } + + { + ::CPtrList rng; + ::CPtrList o1, o2, o3, o4, o5; + void *data[] = { &o1, &o2, &o3, &o4, &o5 }; + + ::test_CPtrList(boost::make_iterator_range(data, data+5)); + } + + { + ::CString data[] = { + ::CString(_T('0')), ::CString(_T('1')), ::CString(_T('2')), ::CString(_T('3')), + ::CString(_T('4')), ::CString(_T('5')), ::CString(_T('6')), ::CString(_T('7')) + }; + + ::test_CStringList(boost::make_iterator_range(data, data+8)); + } + + + // maps + // + { + std::map data; + int o0, o1, o2, o3, o4; + data[&o0] = 15, data[&o1] = 14, data[&o2] = 3, data[&o3] = 6, data[&o4] = 1; + + ::test_CMapPtrToWord(data); + } + + { + std::map data; + int o0, o1, o2, o3, o4; + data[&o0] = &o3, data[&o1] = &o2, data[&o2] = &o1, data[&o3] = &o0, data[&o4] = &o4; + + ::test_CMapPtrToPtr(data); + } + + { + std::map< ::CString, CObject * > data; + CObArray o0, o1, o2, o3, o4; + data[ ::CString('0') ] = &o0, data[ ::CString('1') ] = &o1, data[ ::CString('2') ] = &o2, + data[ ::CString('3') ] = &o3, data[ ::CString('4') ] = &o4; + + ::test_CMapStringToOb(data); + } + + { + std::map< ::CString, void * > data; + CObArray o0, o1, o2, o3, o4; + data[ ::CString('0') ] = &o0, data[ ::CString('1') ] = &o1, data[ ::CString('2') ] = &o2, + data[ ::CString('3') ] = &o3, data[ ::CString('4') ] = &o4; + + ::test_CMapStringToPtr(data); + } + + { + std::map< ::CString, ::CString > data; + CString o0('a'), o1('b'), o2('c'), o3('d'), o4('e'); + data[ ::CString('0') ] = o0, data[ ::CString('1') ] = o1, data[ ::CString('2') ] = o2, + data[ ::CString('3') ] = o3, data[ ::CString('4') ] = o4; + + ::test_CMapStringToString(data); + } + + { + std::map< WORD, CObject * > data; + ::CDWordArray o0, o1, o2, o3, o4; + data[21] = &o3, data[52] = &o2, data[12] = &o1, data[76] = &o0, data[54] = &o4; + + ::test_CMapWordToOb(data); + } + + { + std::map< WORD, void * > data; + ::CDWordArray o0, o1, o2, o3, o4; + data[21] = &o3, data[52] = &o2, data[12] = &o1, data[76] = &o0, data[54] = &o4; + + ::test_CMapWordToPtr(data); + } + + // templates + // + { + std::string data("0987654321qwertyuiop"); + ::test_CArray(data); + ::test_CList(data); + } + + { + std::wstring data(L"asdfghjklzxcvbnm"); + ::test_CArray(data); + ::test_CList(data); + } + + { + std::map< int, std::string > data; + data[0] = "abcde", data[1] = "ajfie", data[2] = "lij", data[3] = "abc", data[4] = "ioiu"; + + ::test_CMap(data); + } + + + // typed + // + { + ::test_CTypedPtrArray(); + ::test_CTypedPtrList(); + ::test_CTypedPtrMap(); + } + + + // strings + // +#if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING) + { + std::string data("123456789 abcdefghijklmn"); + ::test_CString(data); + } +#endif + + +} // test_mfc + #include using boost::unit_test::test_suite; -test_suite* init_unit_test_suite( int argc, char* argv[] ) +test_suite * +init_unit_test_suite(int argc, char* argv[]) { - test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); - - test->add( BOOST_TEST_CASE( &check_mfc ) ); + test_suite *test = BOOST_TEST_SUITE("MFC Range Test Suite"); + test->add(BOOST_TEST_CASE(&test_mfc)); + (void)argc, (void)argv; // unused return test; } - - - - - -