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  

unixstl_glob_sequence.h

Go to the documentation of this file.
00001 /* 
00002  * File:        unixstl_glob_sequence.h (formerly unixstl_findfile_sequence.h)
00003  *
00004  * Purpose:     glob_sequence class.
00005  *
00006  * Created:     15th January 2002
00007  * Updated:     11th September 2004
00008  *
00009  * Home:        http://stlsoft.org/
00010  *
00011  * Copyright (c) 2002-2004, Matthew Wilson and Synesis Software
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * - Redistributions of source code must retain the above copyright notice, this
00018  *   list of conditions and the following disclaimer.
00019  * - Redistributions in binary form must reproduce the above copyright notice,
00020  *   this list of conditions and the following disclaimer in the documentation
00021  *   and/or other materials provided with the distribution.
00022  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
00023  *   any contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036  * POSSIBILITY OF SUCH DAMAGE.
00037  *
00038  * 
00039 
00040 
00044 
00045 #ifndef UNIXSTL_INCL_H_UNIXSTL_GLOB_SEQUENCE
00046 #define UNIXSTL_INCL_H_UNIXSTL_GLOB_SEQUENCE
00047 
00048 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00049 # define UNIXSTL_VER_H_UNIXSTL_GLOB_SEQUENCE_MAJOR      3
00050 # define UNIXSTL_VER_H_UNIXSTL_GLOB_SEQUENCE_MINOR      0
00051 # define UNIXSTL_VER_H_UNIXSTL_GLOB_SEQUENCE_REVISION   1
00052 # define UNIXSTL_VER_H_UNIXSTL_GLOB_SEQUENCE_EDIT       77
00053 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00054 
00055 /* 
00056  * Includes
00057  */
00058 
00059 #ifndef UNIXSTL_INCL_H_UNIXSTL
00060 # include "unixstl.h"                   // Include the UNIXSTL root header
00061 #endif /* !UNIXSTL_INCL_H_UNIXSTL */
00062 #ifndef UNIXSTL_INCL_H_UNIXSTL_FILESYSTEM_TRAITS
00063 # include "unixstl_filesystem_traits.h" // filesystem_traits
00064 #endif /* !UNIXSTL_INCL_H_UNIXSTL_FILESYSTEM_TRAITS */
00065 #ifndef UNIXSTL_INCL_H_UNIXSTL_FILE_PATH_BUFFER
00066 # include "unixstl_file_path_buffer.h"  // basic_file_path_buffer
00067 #endif /* !UNIXSTL_INCL_H_UNIXSTL_FILE_PATH_BUFFER */
00068 #ifndef STLSOFT_INCL_H_STLSOFT_ITERATOR
00069 # include "stlsoft_iterator.h"          // pointer_iterator, reverse_iterator_base
00070 #endif /* !STLSOFT_INCL_H_STLSOFT_ITERATOR */
00071 #ifndef STLSOFT_INCL_H_STLSOFT_AUTO_BUFFER
00072 # include "stlsoft_auto_buffer.h"       // auto_buffer
00073 #endif /* !STLSOFT_INCL_H_STLSOFT_AUTO_BUFFER */
00074 #ifndef STLSOFT_INCL_H_STLSOFT_MALLOC_ALLOCATOR
00075 # include "stlsoft_malloc_allocator.h"  // malloc_allocator
00076 #endif /* !STLSOFT_INCL_H_STLSOFT_MALLOC_ALLOCATOR */
00077 #include <sys/types.h>
00078 #include <sys/stat.h>                   // stat()
00079 #include <errno.h>
00080 #include <glob.h>                       // glob(), globfree()
00081 #include <algorithm>                    // std::sort
00082 #include <utility>                      // std::swap
00083 
00084 /* 
00085  * Namespace
00086  *
00087  * The UNIXSTL components are contained within the unixstl namespace. This is
00088  * actually an alias for stlsoft::unixstl_project,
00089  *
00090  * The definition matrix is as follows:
00091  *
00092  * _STLSOFT_NO_NAMESPACE    _UNIXSTL_NO_NAMESPACE   unixstl definition
00093  * ---------------------    ---------------------   -----------------
00094  *  not defined              not defined             = stlsoft::unixstl_project
00095  *  not defined              defined                 not defined
00096  *  defined                  not defined             unixstl
00097  *  defined                  defined                 not defined
00098  *
00099  */
00100 
00101 /* No STLSoft namespaces means no UNIXSTL namespaces */
00102 #ifdef _STLSOFT_NO_NAMESPACES
00103 # define _UNIXSTL_NO_NAMESPACES
00104 #endif /* _STLSOFT_NO_NAMESPACES */
00105 
00106 /* No UNIXSTL namespaces means no unixstl namespace */
00107 #ifdef _UNIXSTL_NO_NAMESPACES
00108 # define _UNIXSTL_NO_NAMESPACE
00109 #endif /* _UNIXSTL_NO_NAMESPACES */
00110 
00111 #ifndef _UNIXSTL_NO_NAMESPACE
00112 # if defined(_STLSOFT_NO_NAMESPACE) || \
00113      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00114 /* There is no stlsoft namespace, so must define ::unixstl */
00115 namespace unixstl
00116 {
00117 # else
00118 /* Define stlsoft::unixstl_project */
00119 
00120 namespace stlsoft
00121 {
00122 
00123 namespace unixstl_project
00124 {
00125 
00126 # endif /* _STLSOFT_NO_NAMESPACE */
00127 #endif /* !_UNIXSTL_NO_NAMESPACE */
00128 
00129 /* 
00130 
00133 
00137 
00142 
00143 /* 
00144  * Classes
00145  */
00146 
00147 #ifdef __STLSOFT_CF_EXCEPTION_SUPPORT
00151 class glob_sequence_exception
00152 #if defined(__STLSOFT_COMPILER_IS_DMC)
00153     : public std::exception
00154 #else /* ? compiler */
00155     : public unixstl_ns_qual_std(exception)
00156 #endif /* compiler */
00157 {
00160 public:
00161 #if defined(__STLSOFT_COMPILER_IS_DMC)
00162     typedef std::exception                  parent_class_type;
00163 #else /* ? compiler */
00164     typedef unixstl_ns_qual_std(exception)  parent_class_type;
00165 #endif /* compiler */
00166     typedef glob_sequence_exception         class_type;
00168 
00171 public:
00172     ss_explicit_k glob_sequence_exception(us_int_t globStatus, us_int_t errno_) unixstl_throw_0()
00173         : m_globStatus(globStatus)
00174         , m_errno(errno_)
00175     {}
00177 
00180 public:
00181 #if defined(__STLSOFT_COMPILER_IS_DMC)
00182     char const  *what() const throw()
00183 #else /* ? compiler */
00184     char const  *what() const unixstl_throw_0()
00185 #endif /* compiler */
00186     {
00187         return "glob_sequence failure";
00188     }
00189 
00190     us_int_t get_globstatus() const unixstl_throw_0()
00191     {
00192         return m_globStatus;
00193     }
00194     us_int_t get_errno() const unixstl_throw_0()
00195     {
00196         return m_errno;
00197     }
00199 
00200 // Members
00201 private:
00202     us_int_t const  m_globStatus;
00203     us_int_t const  m_errno;
00204 
00205 // Not to be implemented
00206 private:
00207     class_type &operator =(class_type const &);
00208 };
00209 
00210 #endif /* __STLSOFT_CF_EXCEPTION_SUPPORT */
00211 
00216 
00217 class glob_sequence
00218 {
00221 public:
00222     // This class
00223     typedef glob_sequence                                                   class_type;
00225     typedef us_char_a_t                                                     char_type;
00226     // The traits type
00227     typedef filesystem_traits<char_type>                                    traits_type;
00229     typedef char_type const                                                 *value_type;
00231     typedef value_type const                                                &const_reference;
00233     typedef value_type const                                                *const_pointer;
00235     typedef us_size_t                                                       size_type;
00237     typedef us_ptrdiff_t                                                    difference_type;
00238 
00240     typedef stlsoft_ns_qual(pointer_iterator)<   value_type const
00241                                              ,   const_pointer
00242                                              ,   const_reference
00243                                              >::iterator_type               const_iterator;
00244 
00245 #ifdef __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT
00246 
00247     typedef stlsoft_ns_qual(reverse_iterator_base)  <   const_iterator
00248                                                     ,   value_type
00249                                                     ,   const_reference
00250                                                     ,   const_pointer
00251                                                     ,   difference_type
00252                                                     >                       const_reverse_iterator;
00253 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00254 
00255 
00258 public:
00259     enum
00260     {
00261             includeDots     =   0x0008  
00262         ,   directories     =   0x0010  
00263         ,   files           =   0x0020  
00264         ,   noSort          =   0x0100  
00265         ,   markDirs        =   0x0200  
00266         ,   absolutePath    =   0x0400  
00267         ,
00268     };
00270 
00273 public:
00284     ss_explicit_k glob_sequence(char_type const *pattern, us_uint_t flags = noSort);
00285 
00297     glob_sequence(char_type const *directory, char_type const *pattern, us_uint_t flags = noSort);
00298 
00299     // Releases any acquired resources
00300     ~glob_sequence() unixstl_throw_0();
00302 
00305 public:
00307     us_size_t size() const;
00308 
00310     us_bool_t empty() const;
00311 
00315     const value_type operator [](size_type index) const;
00317 
00320 public:
00324     const_iterator  begin() const;
00328     const_iterator  end() const;
00329 
00330 #ifdef __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT
00334     const_reverse_iterator  rbegin() const;
00338     const_reverse_iterator  rend() const;
00339 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00340 
00341 
00342 // Implementation
00343 private:
00344     static us_uint_t validate_flags_(us_uint_t flags);
00345 
00346     // Returns true if pch == "" or "/" (or "\\"), false otherwise
00347     static us_bool_t is_end_of_path_elements_(char_type const *pch, difference_type index);
00348 
00349     static us_bool_t is_dots_maybe_slashed_(char_type const *s, us_bool_t &bTwoDots);
00350 
00351     us_size_t init_glob_(char_type const *directory, char_type const *pattern);
00352 
00353 // Members
00354 private:
00355     typedef stlsoft_ns_qual(auto_buffer)<char_type*, stlsoft_ns_qual(malloc_allocator)<char_type*>, 32> buffer_type;
00356 
00357     us_uint_t const m_flags;
00358     char_type const **m_base;
00359     us_size_t       m_cItems;
00360     buffer_type     m_buffer;
00361     glob_t          m_glob;
00362 
00363 // Not to be implemented
00364 private:
00365     glob_sequence(class_type const &);
00366     class_type const &operator =(class_type const &);
00367 };
00368 
00370 // Unit-testing
00371 
00372 #ifdef STLSOFT_UNITTEST
00373 
00374 namespace unittest
00375 {
00376     ss_bool_t test_unixstl_glob_sequence(unittest_reporter *r)
00377     {
00378         using stlsoft::unittest::unittest_initialiser;
00379 
00380         ss_bool_t               bSuccess    =   true;
00381 
00382         unittest_initialiser    init(r, "UNIXSTL", "glob_sequence", __FILE__);
00383 
00384 #if defined(WIN32) || \
00385     defined(_WIN32)
00386         glob_sequence   seq("*.*");
00387 #else /* ? WIN32 */
00388         glob_sequence   seq("*");
00389 #endif /* WIN32 */
00390 
00391         if(seq.empty() != (0 == seq.size()))
00392         {
00393             r->report("glob_sequence empty() and size() contradict ", __LINE__);
00394             bSuccess = false;
00395         }
00396 
00397         us_size_t   total_forward   =   0;
00398         us_size_t   total_backward  =   0;
00399 
00400         glob_sequence::const_iterator           b_f =   seq.begin();
00401         for(; b_f != seq.end(); ++b_f)
00402         {
00403             total_forward += strlen(*b_f);
00404         }
00405 
00406         glob_sequence::const_reverse_iterator   b_b =   seq.rbegin();
00407         for(; b_b != seq.rend(); ++b_b)
00408         {
00409             total_backward += strlen(*b_b);
00410         }
00411 
00412         if(total_forward != total_backward)
00413         {
00414             r->report("glob_sequence forward and backward ranges contradict ", __LINE__);
00415             bSuccess = false;
00416         }
00417 
00418         return bSuccess;
00419     }
00420 
00421     unittest_registrar    unittest_unixstl_glob_sequence(test_unixstl_glob_sequence);
00422 
00423 } // namespace unittest
00424 
00425 #endif /* STLSOFT_UNITTEST */
00426 
00427 /* 
00428  * Implementation
00429  */
00430 
00431 inline /* ss_explicit_k */ glob_sequence::glob_sequence(glob_sequence::char_type const *pattern, us_uint_t flags /* = noSort */)
00432     : m_flags(validate_flags_(flags))
00433     , m_buffer(1)
00434 {
00435     m_cItems = init_glob_(NULL, pattern);
00436 
00437     unixstl_assert((0 == m_cItems) || (NULL != m_base));
00438 }
00439 
00440 inline glob_sequence::glob_sequence(glob_sequence::char_type const *directory, glob_sequence::char_type const *pattern, us_uint_t flags /* = noSort */)
00441     : m_flags(validate_flags_(flags))
00442     , m_buffer(1)
00443 {
00444     m_cItems = init_glob_(directory, pattern);
00445 
00446     unixstl_assert((0 == m_cItems) || (NULL != m_base));
00447 }
00448 
00449 inline glob_sequence::~glob_sequence() unixstl_throw_0()
00450 {
00451     unixstl_assert((0 == m_cItems) || (NULL != m_base));
00452 
00453     if(NULL != m_base)
00454     {
00455         globfree(&m_glob);
00456     }
00457 }
00458 
00459 inline us_size_t glob_sequence::size() const
00460 {
00461     return m_cItems;
00462 }
00463 
00464 inline us_bool_t glob_sequence::empty() const
00465 {
00466     return 0 == size();
00467 }
00468 
00469 inline glob_sequence::value_type const glob_sequence::operator [](glob_sequence::size_type index) const
00470 {
00471     unixstl_message_assert("index access out of range in glob_sequence", index < 1 + size());   // Has to be +1, since legitimate to take address of one-past-the-end
00472 
00473     return m_base[index];
00474 }
00475 
00476 inline glob_sequence::const_iterator glob_sequence::begin() const
00477 {
00478     return m_base;
00479 }
00480 
00481 inline glob_sequence::const_iterator glob_sequence::end() const
00482 {
00483     return m_base + m_cItems;
00484 }
00485 
00486 #ifdef __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT
00487 inline glob_sequence::const_reverse_iterator glob_sequence::rbegin() const
00488 {
00489     return const_reverse_iterator(end());
00490 }
00491 
00492 inline glob_sequence::const_reverse_iterator glob_sequence::rend() const
00493 {
00494     return const_reverse_iterator(begin());
00495 }
00496 #endif /* __STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */
00497 
00498 inline /* static */ us_uint_t glob_sequence::validate_flags_(us_uint_t flags)
00499 {
00500     if(0 == (flags & (directories | files)))
00501     {
00502         flags |= (directories | files);
00503     }
00504 
00505     if(0 == (flags & directories))
00506     {
00507 #ifndef UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS
00508         // It's more efficient to not bother doing a separate dots check if all
00509         // directories are being elided.
00510         flags |= includeDots;
00511 
00512         // Since we're not going to be returning directories to the caller, and
00513         // it's more efficient to believe the glob() directory marking rather
00514         // than calling stat, we add the markDirs flag here.
00515         flags |= markDirs;
00516 #endif /* UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS */
00517     }
00518 
00519     return flags;
00520 }
00521 
00522 inline /* static */ us_bool_t glob_sequence::is_end_of_path_elements_(glob_sequence::char_type const *pch, glob_sequence::difference_type index)
00523 {
00524     return  pch[index] == '\0' ||
00525             (   pch[index + 1] == '\0' &&
00526                 (
00527 #if defined(_UNIXSTL_COMPILER_IS_UNKNOWN) && \
00528     !defined(_UNIXSTL_GLOB_SEQUENCE_NO_BACK_SLASH_TERMINATOR)
00529                     pch[index] == '\\' || /* Allow for testing on Win32 systems */
00530 #endif /* _UNIXSTL_COMPILER_IS_UNKNOWN && !_UNIXSTL_GLOB_SEQUENCE_NO_BACK_SLASH_TERMINATOR */
00531                     pch[index] == '/'));
00532 }
00533 
00534 inline /* static */ us_bool_t glob_sequence::is_dots_maybe_slashed_(glob_sequence::char_type const *s, us_bool_t &bTwoDots)
00535 {
00536     unixstl_assert(NULL != s);
00537 
00538     return  s[0] == '.' &&
00539             (   (bTwoDots = false, is_end_of_path_elements_(s, 1)) ||
00540                 (bTwoDots = true, ( s[1] == '.' &&
00541                                     is_end_of_path_elements_(s, 2))));
00542 }
00543 
00544 inline us_size_t glob_sequence::init_glob_(glob_sequence::char_type const *directory, glob_sequence::char_type const *pattern)
00545 {
00546     unixstl_message_assert("Null pattern given to glob_sequence", NULL != pattern);
00547 
00548     us_uint_t                           glob_flags  =   0;
00549     basic_file_path_buffer<char_type>   scratch_;   // Scratch buffer for directory / pattern
00550 
00551 #ifndef __STLSOFT_CF_EXCEPTION_SUPPORT
00552     if(0 == scratch_.size())
00553     {
00554         m_base = NULL;
00555 
00556         return 0;
00557     }
00558 #endif /* !__STLSOFT_CF_EXCEPTION_SUPPORT */
00559 
00560     // If a directory is given, then ...
00561     if( NULL != directory &&
00562         '\0' != *directory)
00563     {
00564         // ... optionally turn it into an absolute directory, ...
00565         if(absolutePath == (m_flags & absolutePath))
00566         {
00567             traits_type::get_full_path_name(directory, scratch_.size(), &scratch_[0]);
00568         }
00569         else
00570         {
00571             traits_type::str_copy(&scratch_[0], directory);
00572         }
00573 
00574         // ... ensure that it has a trailing path name-separator, and ...
00575         traits_type::ensure_dir_end(&scratch_[0]);
00576 
00577         // ... prefix directory onto pattern.
00578         traits_type::str_cat(&scratch_[0], pattern);
00579 
00580         pattern = c_str_ptr(scratch_);
00581     }
00582 
00583     if(m_flags & noSort)
00584     {
00585         // Don't bother sorting
00586         glob_flags |= GLOB_NOSORT;
00587     }
00588 
00589     if(m_flags & markDirs)
00590     {
00591         // Ask for trailing slashes on directories
00592         glob_flags |= GLOB_MARK;
00593     }
00594 
00595     if(directories == (m_flags & (directories | files)))
00596     {
00597         // Ask for only directories
00598         glob_flags |= GLOB_ONLYDIR;
00599     }
00600 
00601     int gr = glob(pattern, glob_flags, NULL, &m_glob);
00602 
00603     if(0 != gr)
00604     {
00605 #ifdef __STLSOFT_CF_EXCEPTION_SUPPORT
00606         if(GLOB_NOMATCH != gr)
00607         {
00608             throw glob_sequence_exception(gr, 0);
00609         }
00610 #endif /* __STLSOFT_CF_EXCEPTION_SUPPORT */
00611 
00612         m_base = NULL;
00613 
00614         return 0;
00615     }
00616     else
00617     {
00618         char_type   **base  =   m_glob.gl_pathv;
00619         us_size_t   cItems  =   static_cast<us_size_t>(m_glob.gl_pathc);
00620 
00621         // If we are eliding dots, or trimming out directories, then
00622         // we'll copy the pointers into the buffer, and process them
00623         // there
00624         if( 0 == (m_flags & includeDots) ||
00625 #ifdef UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS
00626             (m_flags & (directories | files)) != (directories | files))
00627 #else /* ? UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS */
00628             (m_flags & (directories | files)) == files)
00629 #endif /* UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS */
00630         {
00631 #ifdef __STLSOFT_CF_EXCEPTION_SUPPORT
00632             try
00633             {
00634                 m_buffer.resize(cItems);
00635             }
00636             catch(...)
00637             {
00638                 globfree(&m_glob);
00639 
00640                 throw;
00641             }
00642 #else /* __STLSOFT_CF_EXCEPTION_SUPPORT */
00643             if(!m_buffer.resize(cItems))
00644             {
00645                 globfree(&m_glob);
00646 
00647                 m_base = NULL;
00648 
00649                 return 0;
00650             }
00651 #endif /* __STLSOFT_CF_EXCEPTION_SUPPORT */
00652 
00653             unixstl_assert(m_buffer.size() == cItems);
00654 
00655             base = static_cast<char_type**>(memcpy(&m_buffer[0], base, m_buffer.size() * sizeof(char_type*)));
00656         }
00657 
00658         if(0 == (m_flags & includeDots))
00659         {
00660             // Now remove the dots. If located at the start of
00661             // the gl buffer, then simply increment m_base to
00662             // be above that. If not then rearrange the base
00663             // two pointers such that they are there.
00664 
00665             us_bool_t   foundDot1   =   false;
00666             us_bool_t   foundDot2   =   false;
00667             char_type   **begin     =   base;
00668             char_type   **end       =   begin + cItems;
00669 
00670             for(; begin != end; ++begin)
00671             {
00672                 us_bool_t   bTwoDots = false;
00673 
00674                 if(is_dots_maybe_slashed_(*begin, bTwoDots))
00675                 {
00676                     // Swap with whatever is at base[0]
00677                     if(begin != base)
00678                     {
00679                         unixstl_ns_qual_std(swap)(*begin, *base);
00680                     }
00681                     ++base;
00682                     --cItems;
00683 
00684 #ifndef UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS
00685                      // We're only going to get one "." and one ".."
00686                     (bTwoDots ? foundDot2 : foundDot1) = true;
00687 
00688                     if( foundDot1 &&
00689                         foundDot2)
00690                     {
00691                         break;
00692                     }
00693 #endif /* !UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS */
00694                 }
00695             }
00696         }
00697 
00698         // We should be able to trust glob() to return only directories when
00699         // asked, so we assume the following only needs to be done when
00700         // have asked for files alone
00701 #ifdef UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS
00702         if((m_flags & (directories | files)) != (directories | files))
00703 #else /* ? UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS */
00704         if((m_flags & (directories | files)) == files)
00705 #endif /* UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS */
00706         {
00707             basic_file_path_buffer<char_type>   buffer;
00708             char_type                           **begin =   base;
00709             char_type                           **end   =   begin + cItems;
00710 
00711 #ifndef __STLSOFT_CF_EXCEPTION_SUPPORT
00712             if(0 == buffer.size())
00713             {
00714                 globfree(&m_glob);
00715 
00716                 m_base = NULL;
00717 
00718                 return 0;
00719             }
00720 #endif /* !__STLSOFT_CF_EXCEPTION_SUPPORT */
00721 
00722             for(; begin != end; ++begin)
00723             {
00724                 // Now need to process the file, by using stat
00725                 struct stat     st;
00726                 int             res;
00727                 char_type const *entry  =   *begin;
00728 
00729 // TODO: If not ultra-cautious, and asked for markDirs, then trust
00730 #ifndef UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS
00731                 unixstl_assert(files == (m_flags & (directories | files)));
00732 
00733                 if( 0 == (m_flags & markDirs) ||
00734                     !traits_type::has_dir_end(entry))
00735 #endif /* !UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS */
00736                 {
00737                     if(markDirs == (m_flags & markDirs))
00738                     {
00739                         traits_type::str_copy(&buffer[0], entry);
00740                         traits_type::remove_dir_end(&buffer[0]);
00741 #if defined(__STLSOFT_COMPILER_IS_GCC) && \
00742     __GNUC__ < 3
00743                         entry = buffer.c_str();
00744 #else /* ? __GNUC__ < 3 */
00745                         entry = stlsoft_ns_qual(c_str_ptr)(buffer);
00746 #endif /* ? __GNUC__ < 3 */
00747                     }
00748                     res = stat(entry, &st);
00749 
00750                     if(0 != res)
00751                     {
00752                         // We could throw an exception here, but it might just be
00753                         // the case that a file has been deleted subsequent to its
00754                         // having been included in the glob list. As such, it makes
00755                         // more sense to just kick it from the list
00756 
00757 #if 0   // Can't decide on unequivocal list of error codes to exempt (exacerbated
00758         // by the fact that there are different ones of different systems) so
00759         // just kick all erroneous entries
00760 #ifdef __STLSOFT_CF_EXCEPTION_SUPPORT
00761                         switch(errno)
00762                         {
00763                             case    ENOENT:
00764                             case    ENOTDIR:
00765 # if defined(EACCESS)
00766                             case    EACCESS:
00767 # endif /* EACCESS */
00768                                 break;
00769                             default:
00770                                 globfree(&m_glob);
00771                                 throw glob_sequence_exception(0, errno);
00772                                 break;
00773                         }
00774 #endif /* __STLSOFT_CF_EXCEPTION_SUPPORT */
00775 #endif /* 0 */
00776                     }
00777                     else
00778                     {
00779 #ifdef UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS
00780                         if(m_flags & directories) // Want directories
00781                         {
00782                             if(S_IFDIR == (st.st_mode & S_IFDIR))
00783                             {
00784                                 continue; // A directory, so accept it
00785                             }
00786                         }
00787 #endif /* UNIXSTL_GLOB_SEQUENCE_ULTRA_CAUTIOUS */
00788                         if(m_flags & files) // Want files
00789                         {
00790                             if(S_IFREG == (st.st_mode & S_IFREG))
00791                             {
00792                                 continue; // A file, so accept it
00793                             }
00794                         }
00795                     }
00796                 }
00797 
00798                 // Note that there is no test here to determine whether or not
00799                 // begin == base. It is assumed that most cases of file elision
00800                 // will involve several files - how many directories have just
00801                 // one file in them? - so the test would actually be a
00802                 // pessimisation
00803 
00804                 // Swap with whatever is at base[0]
00805                 unixstl_ns_qual_std(swap)(*begin, *base);
00806                 ++base;
00807                 --cItems;
00808             }
00809         }
00810 
00811         // Ensure we've not corrupted the sort order
00812         if( 0 == (m_flags & noSort) &&
00813             cItems != static_cast<us_size_t>(m_glob.gl_pathc))
00814         {
00815             unixstl_ns_qual_std(sort)(base, base + cItems);
00816         }
00817 
00818         // Set m_base and m_cItems to the correct values, with
00819         // or without dots. m_base is cast here to remove the
00820         // need for const-casting throughout the rest of the
00821         // class
00822         m_base = const_cast<char_type const **>(base);
00823 
00824         return cItems;
00825     }
00826 }
00827 
00828 /* 
00829 
00831 
00832 /* 
00833 
00834 #ifndef _UNIXSTL_NO_NAMESPACE
00835 # if defined(_STLSOFT_NO_NAMESPACE) || \
00836      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00837 } // namespace unixstl
00838 # else
00839 } // namespace unixstl_project
00840 } // namespace stlsoft
00841 # endif /* _STLSOFT_NO_NAMESPACE */
00842 #endif /* !_UNIXSTL_NO_NAMESPACE */
00843 
00844 /* 
00845 
00846 #endif /* !UNIXSTL_INCL_H_UNIXSTL_GLOB_SEQUENCE */
00847 
00848 /* 

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