/* ///////////////////////////////////////////////////////////////////////// * File: winstl/shell/drophandle_sequence.hpp * * Purpose: Contains the basic_drophandle_sequence template class, and ANSI * and Unicode specialisations thereof. * * Created: 13th November 2002 * Updated: 26th July 2012 * * Home: http://stlsoft.org/ * * Copyright (c) 2002-2012, Matthew Wilson and Synesis Software * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of * any contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * ////////////////////////////////////////////////////////////////////// */ /** \file winstl/shell/drophandle_sequence.hpp * * \brief [C++ only] Definition of the winstl::basic_drophandle_sequence * class template * (\ref group__library__windows_shell "Windows Shell" Library). */ #ifndef WINSTL_INCL_WINSTL_SHELL_HPP_DROPHANDLE_SEQUENCE #define WINSTL_INCL_WINSTL_SHELL_HPP_DROPHANDLE_SEQUENCE #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION # define WINSTL_VER_WINSTL_SHELL_HPP_DROPHANDLE_SEQUENCE_MAJOR 4 # define WINSTL_VER_WINSTL_SHELL_HPP_DROPHANDLE_SEQUENCE_MINOR 1 # define WINSTL_VER_WINSTL_SHELL_HPP_DROPHANDLE_SEQUENCE_REVISION 5 # define WINSTL_VER_WINSTL_SHELL_HPP_DROPHANDLE_SEQUENCE_EDIT 97 #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */ /* ///////////////////////////////////////////////////////////////////////// * Includes */ #ifndef WINSTL_INCL_WINSTL_H_WINSTL # include #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */ #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER # include #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */ #if defined(STLSOFT_CF_FRAME_STRING_SHIM_NOT_SUPPORTED) || \ ( defined(STLSOFT_COMPILER_IS_MSVC) && \ _MSC_VER < 1200) # ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR # include # endif /* !WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR */ # ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING # include # endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING */ #else /* ? STLSOFT_CF_FRAME_STRING_SHIM_NOT_SUPPORTED */ # ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_STATIC_STRING # include # endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_STATIC_STRING */ #endif /* STLSOFT_CF_FRAME_STRING_SHIM_NOT_SUPPORTED */ #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER # include #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */ #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_GENERATORS # include #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_GENERATORS */ #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS # include #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */ /* ///////////////////////////////////////////////////////////////////////// * Namespace */ #ifndef _WINSTL_NO_NAMESPACE # if defined(_STLSOFT_NO_NAMESPACE) || \ defined(STLSOFT_DOCUMENTATION_SKIP_SECTION) /* There is no stlsoft namespace, so must define ::winstl */ namespace winstl { # else /* Define stlsoft::winstl_project */ namespace stlsoft { namespace winstl_project { # endif /* _STLSOFT_NO_NAMESPACE */ #endif /* !_WINSTL_NO_NAMESPACE */ /* ///////////////////////////////////////////////////////////////////////// * Typedefs */ #ifdef _STLSOFT_DROPHANDLE_SEQUENCE_VALUE_TYPE # undef _STLSOFT_DROPHANDLE_SEQUENCE_VALUE_TYPE #endif /* _STLSOFT_DROPHANDLE_SEQUENCE_VALUE_TYPE */ #if defined(STLSOFT_CF_FRAME_STRING_SHIM_NOT_SUPPORTED) || \ ( defined(STLSOFT_COMPILER_IS_MSVC) && \ _MSC_VER < 1200) # define _STLSOFT_DROPHANDLE_SEQUENCE_VALUE_TYPE(C) stlsoft_ns_qual(basic_simple_string), processheap_allocator > #else /* ? STLSOFT_CF_FRAME_STRING_SHIM_NOT_SUPPORTED */ # define _STLSOFT_DROPHANDLE_SEQUENCE_VALUE_TYPE(C) stlsoft_ns_qual(basic_static_string) #endif /* STLSOFT_CF_FRAME_STRING_SHIM_NOT_SUPPORTED */ /* ///////////////////////////////////////////////////////////////////////// * Forward declarations */ #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION template class basic_drophandle_sequence; #endif /* STLSOFT_DOCUMENTATION_SKIP_SECTION */ /* ///////////////////////////////////////////////////////////////////////// * Classes */ #ifdef STLSOFT_DOCUMENTATION_SKIP_SECTION /** \brief Traits for accessing the correct drop-handle functions for a given character type * * \ingroup group__library__windows_shell * * drophandle_sequence_traits is a traits class for determining the correct * drop-handle structures and functions for a given character type. * * \param C The character type */ template struct drophandle_sequence_traits { /// Queries the information from the given drop handle /// /// \param hdrop The drop handle /// \param index The index of the requested item /// \param buffer The buffer within which to write the results /// \param cchBuffer The size of \c buffer in characters static ws_uint_t drag_query_file(HDROP hdrop, ws_uint_t index, C* buffer, ws_uint_t cchBuffer); }; #else template struct drophandle_sequence_traits; STLSOFT_TEMPLATE_SPECIALISATION struct drophandle_sequence_traits { static ws_uint_t drag_query_file(HDROP hdrop, ws_uint_t index, ws_char_a_t* buffer, ws_uint_t cchBuffer) { return DragQueryFileA(hdrop, index, buffer, cchBuffer); } }; STLSOFT_TEMPLATE_SPECIALISATION struct drophandle_sequence_traits { static ws_uint_t drag_query_file(HDROP hdrop, ws_uint_t index, ws_char_w_t* buffer, ws_uint_t cchBuffer) { return DragQueryFileW(hdrop, index, buffer, cchBuffer); } }; #endif /* STLSOFT_DOCUMENTATION_SKIP_SECTION */ // class basic_drophandle_sequence_const_iterator /** \brief Iterator for the basic_drophandle_sequence class * * \ingroup group__library__windows_shell * * \param C The character type * \param T The traits type. For translators that support default template arguments this defaults to drophandle_sequence_traits */ template< ss_typename_param_k C #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT , ss_typename_param_k T = drophandle_sequence_traits #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */ , ss_typename_param_k T /* = drophandle_sequence_traits */ #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */ > class basic_drophandle_sequence_const_iterator : public stlsoft_ns_qual(iterator_base) { public: /// The character type typedef C char_type; /// The traits type typedef T traits_type; /// The string type typedef _STLSOFT_DROPHANDLE_SEQUENCE_VALUE_TYPE(C) string_type; /// The current parameterisation of the type typedef basic_drophandle_sequence_const_iterator class_type; /// The value type typedef string_type value_type; /// The index type typedef ws_uint_t index_type; // Construction protected: /// Create an iterator based on the given drop handle ss_explicit_k basic_drophandle_sequence_const_iterator(HDROP hdrop, index_type index); public: // Default constructor basic_drophandle_sequence_const_iterator(); /// Copy constructor basic_drophandle_sequence_const_iterator(class_type const& rhs); /// Copy assignment operator basic_drophandle_sequence_const_iterator& operator =(class_type const& rhs); // Operators public: /// Pre-increment operator class_type& operator ++(); /// Pre-decrement operator class_type& operator --(); /// Post-increment operator class_type operator ++(int); /// Post-decrement operator class_type operator --(int); /// Dereference const value_type operator *() const; /// Evaluates whether \c this and \c rhs are equivalent ws_bool_t equal(class_type const& rhs) const; #if 0 private: value_type *operator ->(); value_type const *operator ->() const; #endif /* 0 */ // Implementation private: static index_type sentinel_(); // Members private: friend class basic_drophandle_sequence; HDROP m_hdrop; index_type m_index; }; // class basic_drophandle_sequence /** \brief This class wraps an STL-like sequence interface over a Win32 drop handle * * \ingroup group__library__windows_shell * * \param C The character type * \param T The traits type. For translators that support default template arguments this defaults to drophandle_sequence_traits */ template< ss_typename_param_k C #ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT , ss_typename_param_k T = drophandle_sequence_traits #else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */ , ss_typename_param_k T /* = drophandle_sequence_traits */ #endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */ > class basic_drophandle_sequence : public stlsoft_ns_qual(stl_collection_tag) { public: /// \brief The character type typedef C char_type; /// \brief The traits type typedef T traits_type; /// \brief The current parameterisation of the type typedef basic_drophandle_sequence class_type; /// \brief The non-mutating (const) iterator type typedef basic_drophandle_sequence_const_iterator const_iterator; /// \brief The value type typedef ss_typename_type_k const_iterator::value_type value_type; /// \brief The difference type typedef ws_ptrdiff_t difference_type; #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT) && \ !defined(STLSOFT_COMPILER_IS_BORLAND) /// \brief The non-mutating (const) reverse iterator type typedef #if !defined(STLSOFT_COMPILER_IS_BORLAND) ss_typename_type_k #endif /* compiler */ stlsoft_ns_qual(const_reverse_iterator_generator)< const_iterator , value_type , value_type // By-Value Temporary reference category , void // By-Value Temporary reference category , difference_type >::type const_reverse_iterator; #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */ // Construction public: /// \brief Construct a sequence based on the contents of the given drop handle ss_explicit_k basic_drophandle_sequence(HDROP hdrop, ws_bool_t bOwnHandle = true); /// \brief Release any resources aquired ~basic_drophandle_sequence() stlsoft_throw_0(); // Attributes public: /// \brief The number of elements in the sequence ws_size_t size() const; /// \brief Indicates whether the sequence is empty ws_bool_t empty() const; // Iteration public: /// \brief Begins the iteration /// /// \return An iterator representing the start of the sequence const_iterator begin() const; /// \brief Ends the iteration /// /// \return An iterator representing the end of the sequence const_iterator end() const; #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT) && \ !defined(STLSOFT_COMPILER_IS_BORLAND) /// \brief Begins the reverse iteration /// /// \return An iterator representing the start of the reverse sequence const_reverse_iterator rbegin() const; /// \brief Ends the reverse iteration /// /// \return An iterator representing the end of the reverse sequence const_reverse_iterator rend() const; #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */ // Members private: HDROP m_hdrop; const ws_bool_t m_bOwnHandle; // Implementation private: // Not to be implemented private: basic_drophandle_sequence(class_type const&); class_type& operator =(class_type const&); }; /* Typedefs to commonly encountered types. */ /** \brief Specialisation of the basic_drophandle_sequence template for the ANSI character type \c char * * \ingroup group__library__shell */ typedef basic_drophandle_sequence > drophandle_sequence_a; /** \brief Specialisation of the basic_drophandle_sequence template for the Unicode character type \c wchar_t * * \ingroup group__library__shell */ typedef basic_drophandle_sequence > drophandle_sequence_w; /** \brief Specialisation of the basic_drophandle_sequence template for the ANSI character type \c char * * \ingroup group__library__shell */ typedef basic_drophandle_sequence > drophandle_sequence; //////////////////////////////////////////////////////////////////////////// // Operators template< ss_typename_param_k C , ss_typename_param_k T > inline ws_bool_t operator ==( basic_drophandle_sequence_const_iterator const& lhs , basic_drophandle_sequence_const_iterator const& rhs) { return lhs.equal(rhs); } template< ss_typename_param_k C , ss_typename_param_k T > inline ws_bool_t operator !=( basic_drophandle_sequence_const_iterator const& lhs , basic_drophandle_sequence_const_iterator const& rhs) { return !lhs.equal(rhs); } //////////////////////////////////////////////////////////////////////////// #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION // basic_drophandle_sequence_const_iterator template< ss_typename_param_k C , ss_typename_param_k T > inline /* static */ ss_typename_type_ret_k basic_drophandle_sequence_const_iterator::index_type basic_drophandle_sequence_const_iterator::sentinel_() { return 0x7fffffff; } template< ss_typename_param_k C , ss_typename_param_k T > inline /* ss_explicit_k */ basic_drophandle_sequence_const_iterator::basic_drophandle_sequence_const_iterator(HDROP hdrop, ss_typename_type_k basic_drophandle_sequence_const_iterator::index_type index) : m_hdrop(hdrop) , m_index(index) {} template< ss_typename_param_k C , ss_typename_param_k T > inline basic_drophandle_sequence_const_iterator::basic_drophandle_sequence_const_iterator() : m_hdrop(0) , m_index(sentinel_()) {} template< ss_typename_param_k C , ss_typename_param_k T > inline basic_drophandle_sequence_const_iterator::basic_drophandle_sequence_const_iterator(ss_typename_type_k basic_drophandle_sequence_const_iterator::class_type const& rhs) : m_hdrop(rhs.m_hdrop) , m_index(rhs.m_index) {} template< ss_typename_param_k C , ss_typename_param_k T > inline ss_typename_type_ret_k basic_drophandle_sequence_const_iterator::class_type& basic_drophandle_sequence_const_iterator::operator =(ss_typename_type_k basic_drophandle_sequence_const_iterator::class_type const& rhs) { m_hdrop = rhs.m_hdrop; m_index = rhs.m_index; return *this; } template< ss_typename_param_k C , ss_typename_param_k T > inline ss_typename_type_ret_k basic_drophandle_sequence_const_iterator::class_type& basic_drophandle_sequence_const_iterator::operator ++() { WINSTL_MESSAGE_ASSERT("Incrementing the end iterator", m_index != sentinel_()); ws_uint_t const res = traits_type::drag_query_file(m_hdrop, static_cast(m_index + 1), NULL, 0); if(res == 0) { // Failed, so become 'end' m_index = sentinel_(); } else { // Fine, so increment to next ++m_index; } return *this; } template< ss_typename_param_k C , ss_typename_param_k T > inline ss_typename_type_ret_k basic_drophandle_sequence_const_iterator::class_type& basic_drophandle_sequence_const_iterator::operator --() { // If currently at 'end' .... if(m_index == sentinel_()) { // ... then determine the new end ... m_index = static_cast(traits_type::drag_query_file(m_hdrop, static_cast(0xFFFFFFFF), NULL, 0)); if(m_index == 0xFFFFFFFF) { // ... failed. Must set to end again! m_index = sentinel_(); } else { // ... decrement from end --m_index; } } else { // ... decrement from current position --m_index; } return *this; } template< ss_typename_param_k C , ss_typename_param_k T > inline ss_typename_type_ret_k basic_drophandle_sequence_const_iterator::class_type basic_drophandle_sequence_const_iterator::operator ++(int) { class_type ret(*this); operator ++(); return ret; } template< ss_typename_param_k C , ss_typename_param_k T > inline ss_typename_type_ret_k basic_drophandle_sequence_const_iterator::class_type basic_drophandle_sequence_const_iterator::operator --(int) { class_type ret(*this); operator --(); return ret; } template< ss_typename_param_k C , ss_typename_param_k T > inline const ss_typename_type_k basic_drophandle_sequence_const_iterator::value_type basic_drophandle_sequence_const_iterator::operator *() const { WINSTL_MESSAGE_ASSERT("Dereferencing the end iterator", m_index != sentinel_()); ws_uint_t cch = traits_type::drag_query_file(m_hdrop, static_cast(m_index), NULL, 0); stlsoft_ns_qual(auto_buffer) sz(1 + cch); if( 0 == sz.size() || 0 == (cch = traits_type::drag_query_file(m_hdrop, static_cast(m_index), &sz[0], ws_uint_t(sz.size())))) { sz[0] = '\0'; } return value_type(sz.data()); } template< ss_typename_param_k C , ss_typename_param_k T > inline ws_bool_t basic_drophandle_sequence_const_iterator::equal(ss_typename_type_k basic_drophandle_sequence_const_iterator::class_type const& rhs) const { WINSTL_MESSAGE_ASSERT("Comparing iterators from different sequences", (m_hdrop == NULL || rhs.m_hdrop == NULL || m_hdrop == rhs.m_hdrop)); return m_index == rhs.m_index; } // basic_drophandle_sequence template inline basic_drophandle_sequence::basic_drophandle_sequence(HDROP hdrop, ws_bool_t bOwnHandle /* = true */) : m_hdrop(hdrop) , m_bOwnHandle(bOwnHandle) {} template inline basic_drophandle_sequence::~basic_drophandle_sequence() stlsoft_throw_0() { if(m_bOwnHandle) { ::DragFinish(m_hdrop); } } template inline ws_size_t basic_drophandle_sequence::size() const { return traits_type::drag_query_file(m_hdrop, static_cast(0xFFFFFFFF), NULL, 0); } template inline ws_bool_t basic_drophandle_sequence::empty() const { return size() == 0; } template inline ss_typename_type_ret_k basic_drophandle_sequence::const_iterator basic_drophandle_sequence::begin() const { ws_uint_t const res = traits_type::drag_query_file(m_hdrop, 0, NULL, 0); return const_iterator(m_hdrop, (res == 0) ? const_iterator::sentinel_() : 0); } template inline ss_typename_type_ret_k basic_drophandle_sequence::const_iterator basic_drophandle_sequence::end() const { return const_iterator(m_hdrop, const_iterator::sentinel_()); } #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT) && \ !defined(STLSOFT_COMPILER_IS_BORLAND) template inline ss_typename_type_ret_k basic_drophandle_sequence::const_reverse_iterator basic_drophandle_sequence::rbegin() const { return const_reverse_iterator(end()); } template inline ss_typename_type_ret_k basic_drophandle_sequence::const_reverse_iterator basic_drophandle_sequence::rend() const { return const_reverse_iterator(begin()); } #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */ #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */ //////////////////////////////////////////////////////////////////////////// // Unit-testing #ifdef STLSOFT_UNITTEST # include "./unittest/drophandle_sequence_unittest_.h" #endif /* STLSOFT_UNITTEST */ /* ////////////////////////////////////////////////////////////////////// */ #ifndef _WINSTL_NO_NAMESPACE # if defined(_STLSOFT_NO_NAMESPACE) || \ defined(STLSOFT_DOCUMENTATION_SKIP_SECTION) } // namespace winstl # else } // namespace winstl_project } // namespace stlsoft # endif /* _STLSOFT_NO_NAMESPACE */ #endif /* !_WINSTL_NO_NAMESPACE */ /* ////////////////////////////////////////////////////////////////////// */ #endif /* WINSTL_INCL_WINSTL_SHELL_HPP_DROPHANDLE_SEQUENCE */ /* ///////////////////////////// end of file //////////////////////////// */