|
Boost : |
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk