Любое решение не Boost будет включать системно-зависимый код (который
скрыто в Boost, если вы используете Boost). И вам нужно будет точно определить
что вы подразумеваете под «соответствием»: должны "./MyFile.xxx"
и "MyFile.xxx"
сравнить равных? А как насчет "aaa/.../MyFile.xxx"
и "MyFile.xxx"
?
То, как я бы справился, это определить класс с двумя членами данных,
std::string
с префиксом & ldquo; rdquo; (который всегда будет
пуст в Unix) и std::vector<std::string>
со всеми путями
элементы. Этот класс будет увязан с необходимым сравнением
функции, и будет использовать системно-зависимый код для реализации
конструктор; сам конструктор будет в исходном файле, а
исходный файл будет включать машинно-зависимый заголовок (обычно с помощью
отдельный каталог для каждого варианта и выбор заголовка с помощью
-I
или /I
, чтобы указать, какой каталог использовать). Такие вещи
который может войти в заголовок:
inline bool
isPathSeparator( char ch )
{
return ch == '/';
}
std::string
getHeader( std::string const& fullPathName )
{
return "";
}
bool
charCompare( char lhs, char rhs )
{
return lhs < rhs;
}
bool
charMatch( char lhs, char rhs )
{
return lhs == rhs;
}
для Unix, с:
inline bool
isPathSeparator( char ch )
{
return ch == '/' || ch == '\\';
}
std::string
getHeader( std::string const& fullPathName )
{
return fullPathName.size() > 2 && fullPathName[1] == ':'
? fullPathName.substr( 0, 2 )
: std::string();
}
bool
charCompare( char lhs, char rhs )
{
return tolower( (unsigned char)lhs) < tolower( (unsigned char)rhs );
}
bool
charMatch( char lhs, char rhs )
{
return tolower( (unsigned char)lhs ) == tolower( (unsigned char)rhs );
}
для Windows.
Затем конструктор будет использовать getHeader
для инициализации заголовка, и
перебирать input.begin() + header.size()
и input.end()
, ломая
строка в элементы. Если вы столкнулись с элементом "."
,
игнорируйте его, и для одного из ".."
используйте pop_back()
, чтобы удалить верх
элемент пути, при условии, что путь не пуст. После этого
просто вопрос определения компараторов для использования charCompare
и
charMatch
для char
и std::lexicographical_compare
или
std::equal
(после проверки того, что размеры равны) с
компаратор для std::string
(и, вероятно, для вашего нового
учебный класс). Что-то вроде:
struct FileNameCompare
{
bool operator()( char lhs, char rhs ) const
{
return charCompare( lhs, rhs );
}
bool operator()( std::string const& lhs, std::string const& rhs ) const
{
return std::lexicographical_compare(
lhs.begin(), lhs.end(),
rhs.begin(), rhs.end(),
*this );
}
bool operator()( FileName const& lhs, FileName const& rhs ) const
{
return (*this)( lhs.prefix, rhs.prefix )
|| ( !(*this)( rhs.prefix, lhs.prefix )
&& std::lexicographical_compare(
lhs.elements.begin(), lhs.elements.end(),
rhs.elements.begin(), rhs.elements.end(),
*this ) );
}
};
struct FileNameMatch
{
bool operator()( char lhs, char rhs ) const
{
return charMatch( lhs, rhs );
}
bool operator()( std::string const& lhs, std::string const& rhs ) const
{
return lhs.size() == rhs.size()
&& std::equal( lhs.begin(), lhs.end(), rhs.begin(), *this );
}
bool operator()( FileName const& lhs, FileName const& rhs ) const
{
return (*this)( lhs.prefix, rhs.prefix )
&& lhs.elements.size() == rhs.elements.size()
&& std::equal( lhs.elements.begin(), lhs.elements.end(),
rhs.elements.begin(),
*this );
}
};
должен сделать трюк. (Просто помните, что operator()( char, char )
const
должно быть в исходном файле; вы не можете вставить их в заголовок,
который не будет включать системно-зависимый заголовок, который определяет
charCompare
и charMatch
.)