Any non-Boost solution will include system code (which is hidden in Boost if you use Boost). And you will need to determine exactly what you mean by "match": should "./MyFile.xxx" and "MyFile.xxx" compare equal? What about "aaa/.../MyFile.xxx" and "MyFile.xxx" ?
The way I will handle this is to define a class with two data members, a std::string with a "prefix" (which would always be empty on Unix) and std::vector<std::string> with the whole path elements. This class will be used with the necessary function mapping and will use system code to implement the constructor; the constructor itself will be in the source file, and the source file will include a machine-specific header (usually using a separate directory for each option and selecting a header using -I or /I to indicate which directory to use). Things that may be included in the title:
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; }
for Unix, with:
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 ); }
for windows.
Then the constructor will use getHeader to initialize the header and input.begin() + header.size() over input.begin() + header.size() and input.end() , breaking the string into elements. If you encounter the element "." , ignore it, and for one of ".." use pop_back() to remove the top element of the path if the path is not empty. Subsequently, it is just a matter of defining comparators for using charCompare and charMatch for char and std::lexicographical_compare or std::equal (after checking that the sizes are equal) with a comparator for std::string (and probably more so for your new class ) Sort of:
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 ); } };
gotta do the trick. (Just remember that operator()( char, char ) const must be in the source file, you cannot embed them in a header that will not include the system- charCompare header that defines charCompare and charMatch .)