$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Angus Leeming (angus.leeming_at_[hidden])
Date: 2004-09-29 06:10:21
Martin wrote:
> How do I use it in windows where case-sensitivity is a file
> attribute (FILE_FLAG_POSIX_SEMANTICS).
> 
> boost::glob("*.[tT][xX][tT]", ...)
> 
> might return more files than
> 
> FindFirstFile("*.txt")/FindNextFile()
> 
> e.g. on a mounted case-sensitive filesystem
Good morning, Martin.
Having slept on it, I think that my original answer of "ask Beman" is 
wrong. I think that handling this requirement is easy.
In boost/details/glob.hpp you'll find
template <typename TraitsT = glob_traits>
class glob_predicate
{
    ...
public:
    /** @returns true if @c p.leaf() matches the glob expression. */
    bool operator()(filesystem::path const & p) const
    {
        if (contains_wildcards_) {
            boost::cmatch match_;
            return regex_match(p.leaf().c_str(), match_, regex_);
        }
        return p.leaf() == pattern_;
    }
};
I have two suggestions:
1. Add the ability to ignore case for all users:
#include <boost/algorithm/case_conv.hpp>
enum glob_flags {
    ...
    glob_case_insensitive = (1 << 5)
};
template <typename TraitsT = glob_traits>
class glob_predicate
{
    bool case_insensitive_;
public:
    glob_predicate(std::string const & pattern, glob_flags flags)
        : regex_(reg_expression())
        , case_insensitive(flags & glob_case_insensitive)
    { ... }
    bool operator()(filesystem::path const & p) const
    {
        std::string const leaf = case_insensitive_ ?
            to_lower_copy(p.leaf()) : p.leaf();
        if (contains_wildcards_) {
            boost::cmatch match_;
            return regex_match(leaf.c_str(), match_, regex_);
        }
        return leaf == pattern_;
    }
};
2. Interrogate the value of FILE_FLAG_POSIX_SEMANTICS on Windows 
boxes. I'm no Windows programmer, but a quick google suggests that 
this might do the trick. Feel free to improve:
bool operator()(filesystem::path const & p) const
{
    bool case_insensitive = case_insensitive_;
#ifdef BOOST_WINDOWS
    if (!case_insensitive) {
        WIN32_FILE_ATTRIBUTE_DATA data;
        if (GetFileAttributesEx(p.native_file_string(), 0, data)) {
            case_insensitive = 
                !(data.fileAttributes & FILE_FLAG_POSIX_SEMANTICS);
        }
    }
#endif
    ...
}
I have one further question for you, however. If the 'top level' 
pattern doesn not contain any wild cards (foo.cpp in ../*/foo.cpp), 
then I use
        fs::path const candidate = working_dir /= predicate.file();
        if (exists(candidate)
                matches.push_back(candidate);
So, will 'exists' do the right thing here?
Any other comments?
Regards,
Angus