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  

stlsoft_searchspec_sequence.h

Go to the documentation of this file.
00001 /* 
00002  * File:        stlsoft_searchspec_sequence.h
00003  *
00004  * Purpose:     Contains the searchspec_sequence template class, and ANSI
00005  *              and Unicode specialisations thereof.
00006  *
00007  * Notes:       1. The original implementation of the class had the const_iterator
00008  *              and value_type as nested classes. Unfortunately, Visual C++ 5 &
00009  *              6 both had either compilation or linking problems so these are
00010  *              regretably now implemented as independent classes.
00011  *
00012  *              2. This class was described in detail in the article
00013  *              "Adapting Windows Enumeration Models to STL Iterator Concepts"
00014  *              (http://www.windevnet.com/documents/win0303a/), in the March
00015  *              2003 issue of Windows Developer Network (http://windevnet.com).
00016  *
00017  * Created:     1st May 2004
00018  * Updated:     11th September 2004
00019  *
00020  * Home:        http://stlsoft.org/
00021  *
00022  * Copyright (c) 2004, Matthew Wilson and Synesis Software
00023  * All rights reserved.
00024  *
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions are met:
00027  *
00028  * - Redistributions of source code must retain the above copyright notice, this
00029  *   list of conditions and the following disclaimer.
00030  * - Redistributions in binary form must reproduce the above copyright notice,
00031  *   this list of conditions and the following disclaimer in the documentation
00032  *   and/or other materials provided with the distribution.
00033  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
00034  *   any contributors may be used to endorse or promote products derived from
00035  *   this software without specific prior written permission.
00036  *
00037  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00038  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00039  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00040  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00041  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00042  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00043  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00044  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00045  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00046  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00047  * POSSIBILITY OF SUCH DAMAGE.
00048  *
00049  * 
00050 
00051 
00055 
00056 #ifndef STLSOFT_INCL_H_STLSOFT_SEARCHSPEC_SEQUENCE
00057 #define STLSOFT_INCL_H_STLSOFT_SEARCHSPEC_SEQUENCE
00058 
00059 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00060 # define STLSOFT_VER_H_STLSOFT_SEARCHSPEC_SEQUENCE_MAJOR        2
00061 # define STLSOFT_VER_H_STLSOFT_SEARCHSPEC_SEQUENCE_MINOR        0
00062 # define STLSOFT_VER_H_STLSOFT_SEARCHSPEC_SEQUENCE_REVISION     1
00063 # define STLSOFT_VER_H_STLSOFT_SEARCHSPEC_SEQUENCE_EDIT         17
00064 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00065 
00066 /* 
00067  * Includes
00068  */
00069 
00070 #ifndef STLSOFT_INCL_H_STLSOFT
00071 # include "stlsoft.h"                       // Include the STLSOFT root header
00072 #endif /* !STLSOFT_INCL_H_STLSOFT */
00073 //#if defined(__STLSOFT_COMPILER_IS_BORLAND)
00074 # ifndef STLSOFT_INCL_H_STLSOFT_SIMPLE_STRING
00075 #  include "stlsoft_simple_string.h"        // stlsoft::basic_simple_string
00076 # endif /* !STLSOFT_INCL_H_STLSOFT_SIMPLE_STRING */
00077 //#else /* ? compiler */
00078 //# ifndef STLSOFT_INCL_H_STLSOFT_STATIC_STRING
00079 //#  include "stlsoft_static_string.h"        // stlsoft::basic_static_string
00080 //# endif /* !STLSOFT_INCL_H_STLSOFT_STATIC_STRING */
00081 //#endif /* compiler */
00082 #ifndef STLSOFT_INCL_H_STLSOFT_STRING_TOKENISER
00083 # include "stlsoft_string_tokeniser.h"
00084 #endif /* !STLSOFT_INCL_H_STLSOFT_STRING_TOKENISER */
00085 
00086 //#include <stlsoft_string_access.h>
00087 
00088 
00089 #ifndef __STLSOFT_COMPILER_IS_WATCOM
00090 # ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00091 #  include "stlsoft_iterator.h"          // iterator_base
00092 # endif /* !STLSOFT_INCL_H_STLSOFT_ITERATOR */
00093 #endif /* __STLSOFT_COMPILER_IS_WATCOM */
00094 
00095 /* 
00096  * Pre-processor
00097  *
00098  * Definition of the
00099  */
00100 
00101 /* 
00102  * Namespace
00103  */
00104 
00105 #ifndef _STLSOFT_NO_NAMESPACE
00106 namespace stlsoft
00107 {
00108 #endif /* _STLSOFT_NO_NAMESPACE */
00109 
00110 /* 
00111 
00114 
00118 
00123 
00124 /* 
00125  * Functions
00126  */
00127 
00128 template <ss_typename_param_k T>
00129 inline void call_set_null(T *&pt, void (T::*F)())
00130 {
00131     stlsoft_assert(NULL != pt);
00132 
00133     (pt->*F)();
00134 
00135     pt = NULL;
00136 }
00137 
00138 /* 
00139  * Classes
00140  */
00141 
00143 template <ss_typename_param_k S>
00144 class searchspec_sequence
00145 {
00146 public:
00148     typedef S                                                           find_sequence_type;
00150     typedef searchspec_sequence<S>                                      class_type;
00151 private:
00152     typedef searchspec_sequence<S>                                      outer_class_type;
00153     typedef ss_typename_type_k find_sequence_type::traits_type          traits_type;
00154 public:
00156     typedef ss_typename_type_k find_sequence_type::char_type            char_type;
00158     typedef ss_typename_type_k find_sequence_type::value_type           value_type;
00160     typedef ss_typename_type_k find_sequence_type::size_type            size_type;
00162     typedef ss_typename_type_k find_sequence_type::const_reference      const_reference;
00164     class                                                               const_iterator;
00165 private:
00166 //#if defined(__STLSOFT_COMPILER_IS_BORLAND)
00167     typedef basic_simple_string<char_type>                              string_type;
00168 //#else /* ? compiler */
00169     // TODO: Have all filesystem_traits that have a fixed length derive from a tag type, so that we can parameterise
00170     // based on that. Then reinstante the string type discrimination based on the traits
00171 //    typedef basic_static_string<char_type, traits_type::maxPathLength>  string_type;
00172 //#endif /* compiler */
00173     typedef string_tokeniser<string_type, char>                         tokeniser_type;
00174 
00175 public:
00182     searchspec_sequence(char_type const *searchSpec, char_type delimiter)
00183         : m_rootDir(get_root_dir())
00184         , m_searchSpec(searchSpec)
00185         , m_delimiter(delimiter)
00186         , m_flags(0)
00187     {}
00195     searchspec_sequence(char_type const *searchSpec, char_type delimiter, ss_int_t flags)
00196         : m_rootDir(get_root_dir())
00197         , m_searchSpec(searchSpec)
00198         , m_delimiter(delimiter)
00199         , m_flags(flags)
00200     {}
00206     searchspec_sequence(char_type const *rootDir, char_type const *searchSpec, char_type delimiter)
00207         : m_rootDir(rootDir)
00208         , m_searchSpec(searchSpec)
00209         , m_delimiter(delimiter)
00210         , m_flags(0)
00211     {}
00218     searchspec_sequence(char_type const *rootDir, char_type const *searchSpec, char_type delimiter, ss_int_t flags)
00219         : m_rootDir(rootDir)
00220         , m_searchSpec(searchSpec)
00221         , m_delimiter(delimiter)
00222         , m_flags(flags)
00223     {}
00224 
00225 private:
00226     struct search_state
00227     {
00228         string_type                                             m_rootDir;
00229         ss_int_t                                                m_flags;
00230         tokeniser_type                                          m_tokens;
00231         ss_typename_type_k tokeniser_type::const_iterator       m_tokensNext;
00232         ss_typename_type_k tokeniser_type::const_iterator       m_tokensEnd;
00233         find_sequence_type                                      *m_entries;
00234         ss_typename_type_k find_sequence_type::const_iterator   m_entriesNext;
00235         ss_typename_type_k find_sequence_type::const_iterator   m_entriesEnd;
00236         ss_sint32_t                                             m_cRefs;
00237 
00238     private:
00239         search_state(char_type const *rootDir, char_type const *searchSpec, char_type delimiter, ss_int_t flags)
00240             : m_rootDir(rootDir)
00241             , m_flags(flags)
00242             , m_tokens(searchSpec, delimiter)
00243             , m_tokensNext(m_tokens.begin())
00244             , m_tokensEnd(m_tokens.end())
00245 #if defined(__STLSOFT_COMPILER_IS_VECTORC)
00246             , m_entries(new find_sequence_type(m_rootDir.c_str(), (*m_tokensNext).c_str(), m_flags))
00247 #else /* ? compiler */
00248             , m_entries(new find_sequence_type(c_str_ptr(m_rootDir), c_str_ptr(*m_tokensNext), m_flags))
00249 #endif /* compiler */
00250             , m_entriesNext(m_entries->begin())
00251             , m_entriesEnd(m_entries->end())
00252             , m_cRefs(1)
00253         {
00254             while(m_entriesNext == m_entriesEnd)
00255             {
00256                 ++m_tokensNext;
00257 
00258                 if(m_tokensNext == m_tokensEnd)
00259                 {
00260                     break;
00261                 }
00262                 else
00263                 {
00264                     stlsoft_assert(NULL != m_entries);
00265 
00266                     stlsoft_destroy_instance_fn(m_entries);
00267 #if defined(__STLSOFT_COMPILER_IS_VECTORC)
00268                     m_entries = new(m_entries) find_sequence_type(m_rootDir.c_str(), (*m_tokensNext).c_str(), m_flags);
00269 #else /* ? compiler */
00270                     m_entries = new(m_entries) find_sequence_type(c_str_ptr(m_rootDir), c_str_ptr(*m_tokensNext), m_flags);
00271 #endif /* compiler */
00272 
00273                     m_entriesEnd    =   m_entries->end();
00274                     m_entriesNext   =   m_entries->begin();
00275                 }
00276             }
00277         }
00278 
00279 #if defined(__STLSOFT_COMPILER_IS_MSVC) && \
00280 _MSC_VER < 1300
00281         friend class const_iterator;
00282 #endif /* compiler */
00283 
00284     public:
00285         static search_state *create(char_type const *rootDir, char_type const *searchSpec, char_type delimiter, ss_int_t flags)
00286         {
00287             search_state *ss = new search_state(rootDir, searchSpec, delimiter, flags);
00288 
00289             if(ss->m_tokensNext == ss->m_tokensEnd)
00290             {
00291                 delete ss;
00292 
00293                 ss = NULL;
00294             }
00295 
00296             return ss;
00297         }
00298 
00299     public:
00300         bool next()
00301         {
00302             if(m_tokensNext == m_tokensEnd)
00303             {
00304                 return false;
00305             }
00306 
00307             stlsoft_assert(m_tokensNext != m_tokensEnd);
00308             stlsoft_assert(NULL != m_entries || m_tokensNext == m_tokensEnd);
00309 
00310             // We are doing two enumerations here.
00311             //
00312             // The outer enumeration is over the tokens, the
00313             // inner is over the file entries.
00314 
00315             ++m_entriesNext;
00316 
00317             while(m_entriesNext == m_entriesEnd)
00318             {
00319                 ++m_tokensNext;
00320 
00321                 if(m_tokensNext == m_tokensEnd)
00322                 {
00323                     return false;
00324                 }
00325                 else
00326                 {
00327                     stlsoft_assert(NULL != m_entries);
00328 
00329                     stlsoft_destroy_instance_fn(m_entries);
00330 #if defined(__STLSOFT_COMPILER_IS_VECTORC)
00331                     m_entries = new(m_entries) find_sequence_type(m_rootDir.c_str(), (*m_tokensNext).c_str(), m_flags);
00332 #else /* ? compiler */
00333                     m_entries = new(m_entries) find_sequence_type(c_str_ptr(m_rootDir), c_str_ptr(*m_tokensNext), m_flags);
00334 #endif /* compiler */
00335 
00336                     m_entriesEnd    =   m_entries->end();
00337                     m_entriesNext   =   m_entries->begin();
00338                 }
00339             }
00340 
00341             return true;
00342         }
00343 
00344         void Release()
00345         {
00346             if(0 == --m_cRefs)
00347             {
00348                 delete this;
00349             }
00350         }
00351 #if defined(__STLSOFT_COMPILER_IS_GCC)
00352 protected:
00353 #else /* ? __STLSOFT_COMPILER_IS_GCC */
00354 private:
00355 #endif /* __STLSOFT_COMPILER_IS_GCC */
00356         ~search_state()
00357         {
00358             delete m_entries;
00359         }
00360     };
00361 
00362 public:
00364     class const_iterator
00365     {
00366     private:
00367         typedef const_iterator      class_type;
00368 
00369     private:
00370         friend class searchspec_sequence<S>;
00371 
00372         const_iterator(char_type const *rootDir, char_type const *searchSpec, char_type delimiter, ss_int_t flags)
00373             : m_searchState(search_state::create(rootDir, searchSpec, delimiter, flags))
00374         {}
00375 
00376     public:
00378         const_iterator()
00379             : m_searchState(NULL)
00380         {}
00382         ~const_iterator()
00383         {
00384             if(NULL != m_searchState)
00385             {
00386                 m_searchState->Release();
00387             }
00388         }
00389 
00391         const_iterator(class_type const &rhs)
00392             : m_searchState(rhs.m_searchState)
00393         {
00394             if(NULL != m_searchState)
00395             {
00396                 ++m_searchState->m_cRefs;
00397             }
00398         }
00399 
00400         class_type &operator =(class_type const &rhs)
00401         {
00402             if(NULL != m_searchState)
00403             {
00404                 m_searchState->Release();
00405             }
00406 
00407             m_searchState = rhs.m_searchState;
00408 
00409             if(NULL != m_searchState)
00410             {
00411                 ++m_searchState->m_cRefs;
00412             }
00413 
00414             return *this;
00415         }
00416 
00417     public:
00418         class_type &operator ++()
00419         {
00420             stlsoft_assert(NULL != m_searchState);
00421 
00422             if(!m_searchState->next())
00423             {
00424 #if defined(__STLSOFT_COMPILER_IS_MSVC) && \
00425 _MSC_VER < 1300
00426                 m_searchState->Release();
00427 
00428                 m_searchState = NULL;
00429 #else /* ? compiler */
00430                 call_set_null(m_searchState, &search_state::Release);
00431 #endif /* compiler */
00432             }
00433 
00434             return *this;
00435         }
00436 
00437         class_type operator ++(int)
00438         {
00439             class_type  ret(*this);
00440 
00441             operator ++();
00442 
00443             return ret;
00444         }
00445 
00447         const value_type operator *() const
00448         {
00449             stlsoft_assert(NULL != m_searchState);
00450 
00451             return *m_searchState->m_entriesNext;
00452         }
00453 
00454         ss_bool_t operator ==(class_type const &rhs) const
00455         {
00456             // Only evaluate the same when both are at their ends
00457             return (NULL == m_searchState) && (NULL == rhs.m_searchState);
00458         }
00459         ss_bool_t operator !=(class_type const &rhs) const
00460         {
00461             return !operator ==(rhs);
00462         }
00463 
00464     private:
00465         search_state    *m_searchState;
00466     };
00467 
00468 public:
00472     const_iterator begin() const
00473     {
00474 #if defined(__STLSOFT_COMPILER_IS_VECTORC)
00475         return const_iterator(m_rootDir.c_str(), (m_searchSpec).c_str(), m_delimiter, m_flags);
00476 #else /* ? compiler */
00477         return const_iterator(c_str_ptr(m_rootDir), c_str_ptr(m_searchSpec), m_delimiter, m_flags);
00478 #endif /* compiler */
00479     }
00483     const_iterator end() const
00484     {
00485         return const_iterator();
00486     }
00487 
00488 public:
00490     ss_bool_t empty() const
00491     {
00492         return begin() == end();
00493     }
00494 
00495 // Implementation
00496 private:
00498     static char_type const *get_root_dir()
00499     {
00500         static char_type s_rootDir[2] = { '.', '\0' };
00501 
00502         return s_rootDir;
00503     }
00504 
00505 // Members
00506 private:
00507     string_type m_rootDir;
00508     string_type m_searchSpec;
00509     char_type   m_delimiter;
00510     ss_int_t    m_flags;
00511 };
00512 
00514 // Shims
00515 
00516 template <ss_typename_param_k S>
00517 inline ss_bool_t is_empty(searchspec_sequence<S> const &s)
00518 {
00519     return s.empty();
00520 }
00521 
00523 // Unit-testing
00524 
00525 #ifdef STLSOFT_UNITTEST
00526 
00527 namespace unittest
00528 {
00529     ss_bool_t test_stlsoft_searchspec_sequence(unittest_reporter *r)
00530     {
00531         ss_bool_t               bSuccess    =   true;
00532 
00533         unittest_initialiser    init(r, "STLSoft", "searchspec_sequence", __FILE__);
00534 
00535 #if 0
00536         if(<<TODO>>)
00537         {
00538             r->report("<<TODO>> failed ", __LINE__);
00539             bSuccess = false;
00540         }
00541 #endif /* 0 */
00542 
00543         return bSuccess;
00544     }
00545 
00546     unittest_registrar    unittest_stlsoft_searchspec_sequence(test_stlsoft_searchspec_sequence);
00547 
00548 } // namespace unittest
00549 
00550 #endif /* STLSOFT_UNITTEST */
00551 
00553 // Implementation
00554 
00555 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00556 
00557 
00558 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00559 
00560 /* 
00561 
00563 
00564 /* 
00565 
00566 #ifndef _STLSOFT_NO_NAMESPACE
00567 } // namespace stlsoft
00568 #endif /* _STLSOFT_NO_NAMESPACE */
00569 
00570 /* 
00571 
00572 #endif /* STLSOFT_INCL_H_STLSOFT_SEARCHSPEC_SEQUENCE */
00573 
00574 /* 

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