как я могу сделать boost:: filesystem:: path без учета регистра


Может ли кто-нибудь просветить меня относительно того, как я могу сделать boost::filesystem::path нечувствительным к регистру? Обычно чувствительность к регистру-это решение платформы native , однако это не так просто для моего приложения, поскольку сведения о пути извлекаются из двоичного файла, и требование приложения состоит в том, что независимо от того, на какой платформе я работаю, я должен обрабатывать все пути без учета регистра.

Способ, которым я занимаюсь до сих пор, заключается в использовании boost::filesystem::path::generic_string () метод, чтобы поместить пути, которые я сравниваю в общий формат строки для лексикографического сравнения. Затем я преобразую строки в нижний регистр и использую функции std::string для выполнения сравнений и других методов операторов. Очевидно, что это неоптимально, поскольку я хотел бы иметь возможность выполнять лексикографические сравнения на путях , а не на строках . Внутри реализации boost's path operator использует умное лексикографическое сравнение путей с использованием итераторов пути-это отличается от строковых лексикографических сравнений.

Я думал, что есть какой-то способ предоставить специальный пользовательский строковый тип в качестве внутреннего представления для повышения пути в конструкторе, но я не уверен, как это сделать. Обычно нечувствительность к регистру такого рода выполнялась бы через связанные классы признаков - как вы можете видеть ниже в классе символов нечувствительных к регистру строковых признаков, используемом для UtlCIString (служебная строка без учета регистра). Если бы было возможно связать другой тип строки как внутренний класс строки, Я бы использовал следующее, Но я не уверен, как:

// case insensitive character traits
// inherited copy (preserves case),
// case insensitive comparison, search
struct traits_nocase : std::char_traits<char>
{
    static bool eq(const char& c1, const char& c2) {
        return toupper(c1) == toupper(c2);
    }
    static bool lt(const char& c1, const char& c2) {
        return toupper(c1) < toupper(c2);
    }
    static int compare(const char* s1, const char* s2, size_t N) {
#if defined (_WIN32)
        return _strnicmp(s1, s2, N);
#else // POSIX
        return strncasecmp( s1, s2, N );
#endif
    }
    static const char* find(const char* s, size_t N, const char& a) {
        for (size_t i = 0; i < N; ++i) {
            if (toupper(s[i]) == toupper(a)) {
                return s + i;
            }
        }
        return 0;
    }
    static bool eq_int_type(const int_type& c1, const int_type& c2) {
        return toupper(c1) == toupper(c2);
    }
};

// string preserves case; comparisons are case insensitive
typedef std::basic_string<char, traits_nocase> UtlCIString;
1 2

1 ответ:

Краткий ответ: использовать boost::filesystem::directory_iterator и сами находите пути.

Длинный ответ: не надо.

Как вы предлагаете обрабатывать ситуации, когда пользователь законно имеет несколько файлов в заданном пути с одинаковыми именами, отличными от case?

Как вы думаете, что произойдет, когда пользователь специально скажет вам использовать один из этих файлов, но через ваше превосходно непогрешимое предположительное знание того, что пользователь "хочет", решил использовать другой путь вместо этого?

Почему вы используете / ориентируетесь на файловую систему с учетом регистра, если вы думаете, что не должны этого делать?