⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 glob_sequence.hpp

📁 新版本TR1的stl
💻 HPP
📖 第 1 页 / 共 3 页
字号:
            else
            {
                return false;
            }
        }
    }

    return false;
}

inline us_size_t glob_sequence::init_glob_(glob_sequence::char_type const* directory, glob_sequence::char_type const* pattern)
{
    UNIXSTL_MESSAGE_ASSERT("Null pattern given to glob_sequence", NULL != pattern);

    us_int_t                            glob_flags  =   0;
    basic_file_path_buffer<char_type>   scratch_;   // Scratch buffer for directory / pattern

#ifndef STLSOFT_CF_EXCEPTION_SUPPORT
    if(0 == scratch_.size())
    {
        m_base = NULL;

        return 0;
    }
#endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */

    if( NULL == directory &&
        absolutePath == (m_flags & absolutePath))
    {
        static const char_type  s_thisDir[] = { '.', '\0' };

        directory = s_thisDir;
    }

    // If a directory is given, then ...
    if( NULL != directory &&
        '\0' != *directory)
    {
        us_size_t dirLen;

        // ... optionally turn it into an absolute directory, ...
        if(absolutePath == (m_flags & absolutePath))
        {
            dirLen = traits_type::get_full_path_name(directory, scratch_.size(), &scratch_[0]);
        }
        else
        {
            traits_type::str_copy(&scratch_[0], directory);
            dirLen = traits_type::str_len(scratch_.c_str());
        }

        // ... ensure that it has a trailing path name-separator, and ...
        traits_type::ensure_dir_end(&scratch_[0] + (dirLen ? dirLen - 1 : 0));

        // ... prefix directory onto pattern.
        traits_type::str_cat(&scratch_[0] + dirLen, pattern);
        pattern = scratch_.c_str();
    }

    if(m_flags & noSort)
    {
        // Don't bother sorting
        glob_flags |= GLOB_NOSORT;
    }

    if(m_flags & markDirs)
    {
        // Ask for trailing slashes on directories
        glob_flags |= GLOB_MARK;
    }

#ifdef GLOB_ONLYDIR // If this is not defined, we rely on stat
    if(directories == (m_flags & (directories | files)))
    {
        // Ask for only directories
        glob_flags |= GLOB_ONLYDIR;
    }
#endif /* GLOB_ONLYDIR */

#ifdef GLOB_ONLYFILE // If this is not defined, we rely on stat
    if(files == (m_flags & (directories | files)))
    {
        // Ask for only files
        glob_flags |= GLOB_ONLYFILE;
    }
#endif /* GLOB_ONLYFILE */

#ifdef GLOB_ERR
    if(m_flags & breakOnError)
    {
        glob_flags |= GLOB_ERR;
    }
#endif /* GLOB_ERR */

#ifdef GLOB_NOESCAPE
    if(m_flags & noEscape)
    {
        glob_flags |= GLOB_NOESCAPE;
    }
#endif /* GLOB_NOESCAPE */

#ifdef GLOB_PERIOD
    if(m_flags & matchPeriod)
    {
        glob_flags |= GLOB_PERIOD;
    }
#endif /* GLOB_PERIOD */

#ifdef GLOB_BRACE
    if(m_flags & bracePatterns)
    {
        glob_flags |= GLOB_BRACE;
    }
#endif /* GLOB_BRACE */

#ifdef GLOB_TILDE
    if(m_flags & expandTilde)
    {
        glob_flags |= GLOB_TILDE;
    }
#endif /* GLOB_TILDE */

    int gr = ::glob(pattern, glob_flags, NULL, &m_glob);

    if(0 != gr)
    {
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
# ifdef GLOB_NOMATCH
        // When GLOB_NOMATCH is not defined, we can reasonably infer that
        // there is no replacement value, so throwing on a non-zero
        // return from glob() is appropriate
        if(GLOB_NOMATCH != gr)
# endif /* GLOB_NOMATCH */
        {
            STLSOFT_THROW_X(glob_sequence_exception(gr, 0));
        }
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */

        m_base = NULL;

        return 0;
    }
    else
    {
        // Sink the glob_t instance into a local scoped_handle, to invoke
        // ::globfree() automatically if we encounter any problems during
        // the processing. At the end we'll call detach(), to "give it"
        // to the glob_sequence instance.

        stlsoft_ns_qual(scoped_handle)<glob_t*>     cleanup(&m_glob, ::globfree);

        char_type   **base  =   m_glob.gl_pathv;
        us_size_t   cItems  =   static_cast<us_size_t>(m_glob.gl_pathc);

        // This section performs a COW on the entry pointers, into
        // the m_buffer member, if any of the following hold:
        //
        // 1. we're eliding dots
        // 2. we want directories only, and so will need to
        //     remove files, AND we do not trust GLOB_ONLYDIR
        // 3. we want files only, and so will need
        //     to remove directories
        //
        if( 0 == (m_flags & includeDots) ||                     // 1
#ifndef UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR
            directories == (m_flags & (directories | files)) || // 2
#endif /* !UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR */
            files == (m_flags & (directories | files)))         // 3
        {
            if(!m_buffer.resize(cItems))
            {
#ifndef STLSOFT_CF_EXCEPTION_SUPPORT
                m_base = NULL;

                return 0;
#endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
            }

            UNIXSTL_ASSERT(m_buffer.size() == cItems);

            base = static_cast<char_type**>(memcpy(&m_buffer[0], base, m_buffer.size() * sizeof(char_type*)));
        }

        // This section elides dots directories.
        if(0 == (m_flags & includeDots))
        {
            // Now remove the dots. If located at the start of
            // the gl buffer, then simply increment m_base to
            // be above that. If not then rearrange the base
            // two pointers such that they are there.

            us_bool_t   bFoundDot1   =   false;
            us_bool_t   bFoundDot2   =   false;
            char_type   **begin     =   base;
            char_type   **end       =   begin + cItems;

            for(; begin != end; ++begin)
            {
                us_bool_t   bTwoDots = false;

                if(is_dots_maybe_slashed_(*begin, bTwoDots))
                {
                    // Swap with whatever is at base[0]
                    if(begin != base)
                    {
                        unixstl_ns_qual_std(swap)(*begin, *base);
                    }
                    ++base;
                    --cItems;

                     // We're only going to get one "." and one ".."
                    (bTwoDots ? bFoundDot2 : bFoundDot1) = true;

                    if( bFoundDot1 &&
                        bFoundDot2)
                    {
                        break;
                    }
                }
            }
        }

        // This section performs the filtering, if any of the following
        // hold:
        //
        // 1. we want directories only, and so will need to
        //     remove files, AND we do not trust GLOB_ONLYDIR
        // 2. we want files only, and so will need
        //     to remove directories
        //
#ifndef UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR
        if((m_flags & (directories | files)) != (directories | files))  // 1 & 2
#else /* ? UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR */
        if((m_flags & (directories | files)) == files)                  // 2
#endif /* !UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR */
        {
            // Declare a path buffer which will be used as a scratch area
            // in case we need to remove trailing path name separators to
            // perform stat() on a (suspected) directory entry
            basic_file_path_buffer<char_type>   buffer;

            char_type                           **begin =   base;
            char_type                           **end   =   begin + cItems;

#ifndef STLSOFT_CF_EXCEPTION_SUPPORT
            if(0 == buffer.size())
            {
                m_base = NULL;

                return 0;
            }
#endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */

            // This loop enumerates through the list of entries, and attempts
            // to match each with the requested file type.
            //
            // 1. If we're wanting to return only files, then markDirs (GLOB_MARK)
            //     will have been applied by validate_flags_(), so we test that
            //     first
            // 2. If we're wanting to return only directories, then we must not
            //     be trusting GLOB_ONLYDIR. Either:
            // 2.1. The user specified markDirs (GLOB_MARK), so use that, or
            // 2.2. The user did not specify, and we must stat()
            //
            for(; begin != end; ++begin)
            {
                // Now need to process the file, by using stat
                struct stat         st;
                int                 res;
                char_type const*    entry  =   *begin;

                // 1.
                if(files == (m_flags & (directories | files)))
                {
                    UNIXSTL_ASSERT(markDirs == (m_flags & markDirs));

                    if(!traits_type::has_dir_end(entry))
                    {
                        continue;   // A non-marked entry, hence a file, so accept
                    }
#ifndef UNIXSTL_GLOB_SEQUENCE_DONT_TRUST_MARK
                    else
                    {
                        res = ::stat(entry, &st);

                        if(0 != res)
                        {
                            // We could throw an exception here, but it might just be
                            // the case that a file has been deleted subsequent to its
                            // having been included in the glob list. As such, it makes
                            // more sense to just kick it from the list
                        }
                        else
                        { // stat() succeeded
                            if(S_IFREG == (st.st_mode & S_IFREG))
                            {
                                continue; // A file, so accept it
                            }
                        }
                    }
#endif /* !UNIXSTL_GLOB_SEQUENCE_DONT_TRUST_MARK */
                }
                else // 2.
                {
                    UNIXSTL_ASSERT(directories == (m_flags & (directories | files)));

#ifdef UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR
                    UNIXSTL_MESSAGE_ASSERT("Cannot get here, since trusting GLOB_ONLYDIR", 0);
#endif /* UNIXSTL_GLOB_SEQUENCE_TRUST_ONLYDIR */

                    if(markDirs == (m_flags & markDirs))
                    {
                        if(traits_type::has_dir_end(entry))
                        {
                            continue;   // A marked entry, hence a directory, so accept
                        }
                    }
#ifndef UNIXSTL_GLOB_SEQUENCE_DONT_TRUST_MARK
                    else
#endif /* !UNIXSTL_GLOB_SEQUENCE_DONT_TRUST_MARK */
                    {
                        // Now we must stat()
                        res = stat(entry, &st);

                        if(0 != res)
                        {
                            // We could throw an exception here, but it might just be
                            // the case that a file has been deleted subsequent to its
                            // having been included in the glob list. As such, it makes
                            // more sense to just kick it from the list
                        }
                        else
                        { // stat() succeeded
                            if(S_IFDIR == (st.st_mode & S_IFDIR))
                            {
                                continue; // A directory, so accept it
                            }
                        }
                    }

                }

                // This section elides the entry from the list
                //
                // Note that there is no test here to determine whether or not
                // begin == base. It is assumed that most cases of file elision
                // will involve several files - how many directories have just
                // one file in them? - so the test would actually be a
                // pessimisation

                // Swap with whatever is at base[0]
                unixstl_ns_qual_std(swap)(*begin, *base);
                ++base;
                --cItems;
            }
        }

        // Ensure we've not corrupted the sort order
        if( 0 == (m_flags & noSort) &&
            cItems != static_cast<us_size_t>(m_glob.gl_pathc))
        {
            unixstl_ns_qual_std(sort)(base, base + cItems);
        }

        // Set m_base and m_cItems to the correct values, with
        // or without dots. m_base is cast here to remove the
        // need for const-casting throughout the rest of the
        // class
        m_base = const_cast<char_type const**>(base);

        // Everything has succeeded, so give ownership over to the
        // glob_sequence instance
        cleanup.detach();

        return cItems;
    }
}

#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */

/* ////////////////////////////////////////////////////////////////////// */

#ifndef _UNIXSTL_NO_NAMESPACE
# if defined(_STLSOFT_NO_NAMESPACE) || \
     defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
} // namespace unixstl
# else
} // namespace unixstl_project
} // namespace stlsoft
# endif /* _STLSOFT_NO_NAMESPACE */
#endif /* !_UNIXSTL_NO_NAMESPACE */

/* ////////////////////////////////////////////////////////////////////// */

#endif /* !UNIXSTL_INCL_UNIXSTL_FILESYSTEM_HPP_GLOB_SEQUENCE */

/* ////////////////////////////////////////////////////////////////////// */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -