2015-03-17 21:59:39 +01:00
# include "manager.hpp"
# include <stdexcept>
2022-07-16 18:19:56 +02:00
# include <istream>
2022-08-03 00:00:54 +02:00
# include <algorithm>
2015-03-17 21:59:39 +01:00
2022-08-03 00:00:54 +02:00
# include <components/misc/strings/lower.hpp>
2015-12-07 21:58:30 +01:00
2015-03-17 21:59:39 +01:00
# include "archive.hpp"
namespace
{
char strict_normalize_char ( char ch )
{
return ch = = ' \\ ' ? ' / ' : ch ;
}
char nonstrict_normalize_char ( char ch )
{
2015-12-07 21:58:30 +01:00
return ch = = ' \\ ' ? ' / ' : Misc : : StringUtils : : toLower ( ch ) ;
2015-03-17 21:59:39 +01:00
}
void normalize_path ( std : : string & path , bool strict )
{
char ( * normalize_char ) ( char ) = strict ? & strict_normalize_char : & nonstrict_normalize_char ;
std : : transform ( path . begin ( ) , path . end ( ) , path . begin ( ) , normalize_char ) ;
}
}
namespace VFS
{
Manager : : Manager ( bool strict )
: mStrict ( strict )
{
}
2022-07-16 12:14:20 +02:00
Manager : : ~ Manager ( ) { }
2017-08-21 22:31:19 -04:00
void Manager : : reset ( )
{
mIndex . clear ( ) ;
2015-03-17 21:59:39 +01:00
mArchives . clear ( ) ;
}
2022-07-16 12:14:20 +02:00
void Manager : : addArchive ( std : : unique_ptr < Archive > & & archive )
2015-03-17 21:59:39 +01:00
{
2022-07-16 12:14:20 +02:00
mArchives . push_back ( std : : move ( archive ) ) ;
2015-03-17 21:59:39 +01:00
}
void Manager : : buildIndex ( )
{
mIndex . clear ( ) ;
2022-07-16 12:14:20 +02:00
for ( const auto & archive : mArchives )
2022-06-19 13:28:33 +02:00
archive - > listResources ( mIndex , mStrict ? & strict_normalize_char : & nonstrict_normalize_char ) ; //TODO(Project579): This will probably break in windows with unicode paths
2015-03-17 21:59:39 +01:00
}
2022-07-17 12:19:19 +02:00
Files : : IStreamPtr Manager : : get ( std : : string_view name ) const
2015-03-17 21:59:39 +01:00
{
2022-07-17 12:19:19 +02:00
std : : string normalized ( name ) ;
2015-03-17 21:59:39 +01:00
normalize_path ( normalized , mStrict ) ;
2015-03-26 18:02:51 +01:00
return getNormalized ( normalized ) ;
}
Files : : IStreamPtr Manager : : getNormalized ( const std : : string & normalizedName ) const
{
std : : map < std : : string , File * > : : const_iterator found = mIndex . find ( normalizedName ) ;
2015-03-17 21:59:39 +01:00
if ( found = = mIndex . end ( ) )
2015-03-26 18:02:51 +01:00
throw std : : runtime_error ( " Resource ' " + normalizedName + " ' not found " ) ;
2015-03-17 21:59:39 +01:00
return found - > second - > open ( ) ;
}
2022-07-17 12:19:19 +02:00
bool Manager : : exists ( std : : string_view name ) const
2015-03-17 21:59:39 +01:00
{
2022-07-17 12:19:19 +02:00
std : : string normalized ( name ) ;
2015-03-17 21:59:39 +01:00
normalize_path ( normalized , mStrict ) ;
return mIndex . find ( normalized ) ! = mIndex . end ( ) ;
}
2022-07-17 12:19:19 +02:00
std : : string Manager : : normalizeFilename ( std : : string_view name ) const
2015-03-26 18:02:51 +01:00
{
2022-07-17 12:19:19 +02:00
std : : string result ( name ) ;
2021-09-06 22:01:41 +02:00
normalize_path ( result , mStrict ) ;
return result ;
2015-03-26 18:02:51 +01:00
}
2022-07-17 12:19:19 +02:00
std : : string Manager : : getArchive ( std : : string_view name ) const
2020-12-29 21:45:59 +01:00
{
2022-07-17 12:19:19 +02:00
std : : string normalized ( name ) ;
2020-12-29 21:45:59 +01:00
normalize_path ( normalized , mStrict ) ;
2020-12-30 10:35:51 +01:00
for ( auto it = mArchives . rbegin ( ) ; it ! = mArchives . rend ( ) ; + + it )
2020-12-29 21:45:59 +01:00
{
2020-12-30 10:35:51 +01:00
if ( ( * it ) - > contains ( normalized , mStrict ? & strict_normalize_char : & nonstrict_normalize_char ) )
return ( * it ) - > getDescription ( ) ;
2020-12-29 21:45:59 +01:00
}
return { } ;
}
2021-09-06 21:56:32 +02:00
2022-06-19 13:28:33 +02:00
std : : filesystem : : path Manager : : getAbsoluteFileName ( const std : : filesystem : : path & name ) const
2022-05-13 18:58:00 -07:00
{
2022-06-19 13:28:33 +02:00
std : : string normalized ( name ) ; //TODO(Project579): This will probably break in windows with unicode paths
normalize_path ( normalized , mStrict ) ; //TODO(Project579): This will probably break in windows with unicode paths
2022-05-13 18:58:00 -07:00
2022-06-19 13:28:33 +02:00
const auto found = mIndex . find ( normalized ) ;
2022-05-13 18:58:00 -07:00
if ( found = = mIndex . end ( ) )
throw std : : runtime_error ( " Resource ' " + normalized + " ' not found " ) ;
2022-06-19 13:28:33 +02:00
return found - > second - > getPath ( ) ; //TODO(Project579): This will probably break in windows with unicode paths
2022-05-13 18:58:00 -07:00
}
2021-09-23 18:47:59 +02:00
namespace
2021-09-06 21:56:32 +02:00
{
2021-09-23 18:47:59 +02:00
bool startsWith ( std : : string_view text , std : : string_view start )
{
return text . rfind ( start , 0 ) = = 0 ;
}
}
2022-07-17 12:19:19 +02:00
Manager : : RecursiveDirectoryRange Manager : : getRecursiveDirectoryIterator ( std : : string_view path ) const
2021-09-23 18:47:59 +02:00
{
if ( path . empty ( ) )
return { mIndex . begin ( ) , mIndex . end ( ) } ;
auto normalized = normalizeFilename ( path ) ;
const auto it = mIndex . lower_bound ( normalized ) ;
if ( it = = mIndex . end ( ) | | ! startsWith ( it - > first , normalized ) )
return { it , it } ;
+ + normalized . back ( ) ;
return { it , mIndex . lower_bound ( normalized ) } ;
2021-09-06 21:56:32 +02:00
}
2015-03-17 21:59:39 +01:00
}