manage path routines

This commit is contained in:
Garux 2021-01-22 02:21:54 +03:00
parent b0e62198ba
commit d734199601
18 changed files with 50 additions and 98 deletions

View File

@ -207,34 +207,36 @@ inline MatchFileExtension<Functor> matchFileExtension( const char* extension, co
return MatchFileExtension<Functor>( extension, functor ); return MatchFileExtension<Functor>( extension, functor );
} }
class PathExtensionless /// \brief Returns portion of \p path without .ext part.
{ inline StringRange PathExtensionless( const char *path ){
public: return StringRange( path, path_get_filename_base_end( path ) );
const char* m_path;
PathExtensionless( const char* path ) : m_path( path ){
} }
};
/// \brief Writes \p path to \p ostream without .ext part. /// \brief Returns portion of \p path without directory and .ext parts.
template<typename TextOutputStreamType> inline StringRange PathFilename( const char *path ){
TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const PathExtensionless& path ){ return StringRange( path_get_filename_start( path ), path_get_filename_base_end( path ) );
ostream << StringRange( path.m_path, path_get_filename_base_end( path.m_path ) ); }
return ostream;
/// \brief Returns portion of \p path without filename part.
inline StringRange PathFilenameless( const char *path ){
return StringRange( path, path_get_filename_start( path ) );
} }
class PathCleaned class PathCleaned
{ {
public: public:
const char* m_path; const char* m_path;
PathCleaned( const char* path ) : m_path( path ){ const char* m_end;
PathCleaned( const char* path ) : m_path( path ), m_end( path + std::strlen( path ) ){
}
PathCleaned( const StringRange& range ) : m_path( range.first ), m_end( range.last ){
} }
}; };
/// \brief Writes \p path to \p ostream with dos-style separators replaced by unix-style separators. /// \brief Writes \p path to \p ostream with dos-style separators replaced by unix-style separators.
template<typename TextOutputStreamType> template<typename TextOutputStreamType>
TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const PathCleaned& path ){ TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const PathCleaned& path ){
const char* i = path.m_path; for ( const char* i = path.m_path; i != path.m_end; ++i )
for (; *i != '\0'; ++i )
{ {
if ( *i == '\\' ) { if ( *i == '\\' ) {
ostream << '/'; ostream << '/';

View File

@ -67,9 +67,7 @@ class RemapKeysObserver : public Entity::Observer, public ModelSkin
const char* split = strchr( value, ';' ); const char* split = strchr( value, ';' );
if( split != nullptr ){ if( split != nullptr ){
m_from = { value, split }; m_from = { value, split };
StringOutputStream stream( 64 ); m_to = StringOutputStream( 64 )( PathCleaned( split + 1 ) ).c_str();
stream << PathCleaned( split + 1 );
m_to = stream.c_str();
} }
else{ else{
m_from = ""; m_from = "";

View File

@ -31,9 +31,7 @@
#include "traverselib.h" #include "traverselib.h"
inline void parseTextureName( CopiedString& name, const char* token ){ inline void parseTextureName( CopiedString& name, const char* token ){
StringOutputStream cleaned( 256 ); name = StringOutputStream( 256 )( PathCleaned( PathExtensionless( token ) ) ).c_str(); // remove extension
cleaned << PathCleaned( token );
name = StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ); // remove extension
} }
class ModelSkinKey : public ModuleObserver class ModelSkinKey : public ModuleObserver

View File

@ -38,9 +38,7 @@
#include "stringio.h" #include "stringio.h"
void parseShaderName( CopiedString& name, const char* token ){ void parseShaderName( CopiedString& name, const char* token ){
StringOutputStream cleaned( 256 ); name = StringOutputStream( 256 )( PathCleaned( token ) ).c_str();
cleaned << PathCleaned( token );
name = cleaned.c_str();
} }
class Doom3ModelSkin class Doom3ModelSkin

View File

@ -66,9 +66,7 @@ inline VertexPointer vertexpointer_arbitrarymeshvertex( const ArbitraryMeshVerte
} }
inline void parseTextureName( CopiedString& name, const char* token ){ inline void parseTextureName( CopiedString& name, const char* token ){
StringOutputStream cleaned( 256 ); name = StringOutputStream( 256 )( PathCleaned( PathExtensionless( token ) ) ).c_str(); // remove extension
cleaned << PathCleaned( token );
name = StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ); // remove extension
} }
// generic renderable triangle surface // generic renderable triangle surface

View File

@ -232,9 +232,7 @@ typedef CopiedString TextureExpression;
//++timo FIXME: we need to put code somewhere to detect when two shaders that are case insensitive equal are present //++timo FIXME: we need to put code somewhere to detect when two shaders that are case insensitive equal are present
template<typename StringType> template<typename StringType>
void parseTextureName( StringType& name, const char* token ){ void parseTextureName( StringType& name, const char* token ){
StringOutputStream cleaned( 256 ); name = StringOutputStream( 256 )( PathCleaned( PathExtensionless( token ) ) ).c_str(); // remove extension
cleaned << PathCleaned( token );
name = CopiedString( StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ) ).c_str(); // remove extension
} }
bool Tokeniser_parseTextureName( Tokeniser& tokeniser, TextureExpression& name ){ bool Tokeniser_parseTextureName( Tokeniser& tokeniser, TextureExpression& name ){
@ -1610,12 +1608,9 @@ void ShaderList_addFromArchive( const char *archivename ){
return; return;
} }
StringOutputStream shaderlist( 256 );
shaderlist << DirectoryCleaned( shaderpath ) << "shaderlist.txt";
Archive *archive = GlobalFileSystem().getArchive( archivename, false ); Archive *archive = GlobalFileSystem().getArchive( archivename, false );
if ( archive ) { if ( archive ) {
ArchiveTextFile *file = archive->openTextFile( shaderlist.c_str() ); ArchiveTextFile *file = archive->openTextFile( StringOutputStream( 64 )( DirectoryCleaned( shaderpath ), "shaderlist.txt" ).c_str() );
if ( file ) { if ( file ) {
globalOutputStream() << "Found shaderlist.txt in " << archivename << "\n"; globalOutputStream() << "Found shaderlist.txt in " << archivename << "\n";
BuildShaderList( file->getInputStream() ); BuildShaderList( file->getInputStream() );
@ -1658,8 +1653,7 @@ void Shaders_Load(){
const char* shaderPath = GlobalRadiant().getGameDescriptionKeyValue( "shaderpath" ); const char* shaderPath = GlobalRadiant().getGameDescriptionKeyValue( "shaderpath" );
if ( !string_empty( shaderPath ) ) { if ( !string_empty( shaderPath ) ) {
StringOutputStream path( 256 ); const auto path = StringOutputStream( 64 )( DirectoryCleaned( shaderPath ) );
path << DirectoryCleaned( shaderPath );
if ( g_useShaderList ) { if ( g_useShaderList ) {
// preload shader files that have been listed in shaderlist.txt // preload shader files that have been listed in shaderlist.txt

View File

@ -53,31 +53,24 @@ void Map_Snapshot(){
// 1. make sure the snapshot directory exists (create it if it doesn't) // 1. make sure the snapshot directory exists (create it if it doesn't)
// 2. find out what the lastest save is based on number // 2. find out what the lastest save is based on number
// 3. inc that and save the map // 3. inc that and save the map
const char* path = Map_Name( g_map ); const char* mapname = Map_Name( g_map );
const char* name = path_get_filename_start( path ); const auto snapshotsDir = StringOutputStream( 256 )( PathFilenameless( mapname ), "snapshots" );
StringOutputStream snapshotsDir( 256 );
snapshotsDir << StringRange( path, name ) << "snapshots";
if ( file_exists( snapshotsDir.c_str() ) || Q_mkdir( snapshotsDir.c_str() ) ) { if ( file_exists( snapshotsDir.c_str() ) || Q_mkdir( snapshotsDir.c_str() ) ) {
std::size_t lSize = 0; std::size_t lSize = 0;
StringOutputStream strNewPath( 256 ); const auto strNewPath = StringOutputStream( 256 )( snapshotsDir.c_str(), '/', mapname );
strNewPath << snapshotsDir.c_str() << '/' << name; const char* ext = path_get_filename_base_end( strNewPath.c_str() );
StringOutputStream snapshotFilename( 256 ); StringOutputStream snapshotFilename( 256 );
for ( int nCount = 0; ; ++nCount ) for ( int nCount = 0; ; ++nCount )
{ {
// The original map's filename is "<path>/<name>.<ext>" // The original map's filename is "<path>/<name>.<ext>"
// The snapshot's filename will be "<path>/snapshots/<name>.<count>.<ext>" // The snapshot's filename will be "<path>/snapshots/<name>.<count>.<ext>"
const char* end = path_get_filename_base_end( strNewPath.c_str() ); snapshotFilename( StringRange( strNewPath.c_str(), ext ), '.', nCount, ext );
snapshotFilename << StringRange( strNewPath.c_str(), end ) << '.' << nCount << end;
if ( !DoesFileExist( snapshotFilename.c_str(), lSize ) ) { if ( !DoesFileExist( snapshotFilename.c_str(), lSize ) ) {
break; break;
} }
snapshotFilename.clear();
} }
// save in the next available slot // save in the next available slot
@ -159,8 +152,7 @@ void QE_CheckAutoSave( void ){
{ {
const char* name = Map_Name( g_map ); const char* name = Map_Name( g_map );
const char* extension = path_get_filename_base_end( name ); const char* extension = path_get_filename_base_end( name );
StringOutputStream autosave( 256 ); const auto autosave = StringOutputStream( 256 )( StringRange( name, extension ), ".autosave", extension );
autosave << StringRange( name, extension ) << ".autosave" << extension;
Map_SaveFile( autosave.c_str() ); Map_SaveFile( autosave.c_str() );
} }
} }

View File

@ -275,9 +275,7 @@ EntityClass *Eclass_InitFromText( const char *text ){
e->m_comments = text; e->m_comments = text;
setSpecialLoad( e, "model=", e->m_modelpath ); setSpecialLoad( e, "model=", e->m_modelpath );
StringOutputStream buffer( string_length( e->m_modelpath.c_str() ) ); e->m_modelpath = StringOutputStream( 256 )( PathCleaned( e->m_modelpath.c_str() ) ).c_str();
buffer << PathCleaned( e->m_modelpath.c_str() );
e->m_modelpath = buffer.c_str();
if ( !e->fixedsize ) { if ( !e->fixedsize ) {
EntityClass_insertAttribute( *e, "angle", EntityClassAttribute( "direction", "Direction" ) ); EntityClass_insertAttribute( *e, "angle", EntityClassAttribute( "direction", "Direction" ) );

View File

@ -359,9 +359,7 @@ static bool EntityClass_parse( EntityClass& entityClass, Tokeniser& tokeniser ){
const char* token; const char* token;
PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) ); PARSE_RETURN_FALSE_IF_FAIL( EntityClassDoom3_parseString( tokeniser, token ) );
entityClass.fixedsize = true; entityClass.fixedsize = true;
StringOutputStream buffer( 256 ); entityClass.m_modelpath = StringOutputStream( 256 )( PathCleaned( token ) ).c_str();
buffer << PathCleaned( token );
entityClass.m_modelpath = buffer.c_str();
} }
else if ( string_equal( key, "editor_color" ) ) { else if ( string_equal( key, "editor_color" ) ) {
const char* value; const char* value;

View File

@ -166,9 +166,7 @@ void EntityClassFGD_parseClass( Tokeniser& tokeniser, bool fixedsize, bool isBas
} }
else if ( string_equal( property, "iconsprite" ) ) { else if ( string_equal( property, "iconsprite" ) ) {
ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR );
StringOutputStream buffer( 256 ); entityClass->m_modelpath = StringOutputStream( 256 )( PathCleaned( tokeniser.getToken() ) ).c_str();
buffer << PathCleaned( tokeniser.getToken() );
entityClass->m_modelpath = buffer.c_str();
ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR ); ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, ")" ), PARSE_ERROR );
} }
else if ( string_equal( property, "sprite" ) else if ( string_equal( property, "sprite" )
@ -504,10 +502,7 @@ void EntityClassFGD_parse( TextInputStream& inputStream, const char* path ){
} }
// hl2 below // hl2 below
else if ( string_equal( blockType, "@include" ) ) { else if ( string_equal( blockType, "@include" ) ) {
StringOutputStream includePath( 256 ); EntityClassFGD_loadFile( StringOutputStream( 256 )( PathFilenameless( path ), tokeniser.getToken() ).c_str() );
includePath << StringRange( path, path_get_filename_start( path ) );
includePath << tokeniser.getToken();
EntityClassFGD_loadFile( includePath.c_str() );
} }
else if ( string_equal( blockType, "@mapsize" ) ) { else if ( string_equal( blockType, "@mapsize" ) ) {
ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR ); ASSERT_MESSAGE( EntityClassFGD_parseToken( tokeniser, "(" ), PARSE_ERROR );

View File

@ -293,9 +293,7 @@ ClassImporter( EntityClassCollector& collector, ListAttributeTypes& listTypes, c
const char* model = element.attribute( "model" ); const char* model = element.attribute( "model" );
if ( !string_empty( model ) ) { if ( !string_empty( model ) ) {
StringOutputStream buffer( 256 ); m_eclass->m_modelpath = StringOutputStream( 256 )( PathCleaned( model ) ).c_str();
buffer << PathCleaned( model );
m_eclass->m_modelpath = buffer.c_str();
} }
const char* type = element.name(); const char* type = element.name();

View File

@ -198,9 +198,7 @@ CopiedString g_openMapByCmd;
void cmdMap(){ void cmdMap(){
for ( int i = 1; i < g_argc; ++i ) for ( int i = 1; i < g_argc; ++i )
if( extension_equal( path_get_extension( g_argv[i] ), "map" ) ){ if( extension_equal( path_get_extension( g_argv[i] ), "map" ) ){
StringOutputStream stream( 256 ); g_openMapByCmd = StringOutputStream( 256 )( PathCleaned( g_argv[i] ) ).c_str();
stream << PathCleaned( g_argv[i] );
g_openMapByCmd = stream.c_str();
return; return;
} }
} }
@ -257,14 +255,12 @@ void environment_init( int argc, char* argv[] ){
ASSERT_MESSAGE( !string_empty( app_filepath.c_str() ), "failed to deduce app path" ); ASSERT_MESSAGE( !string_empty( app_filepath.c_str() ), "failed to deduce app path" );
// NOTE: we build app path with a trailing '/' // NOTE: we build app path with a trailing '/'
// it's a general convention in Radiant to have the slash at the end of directories // it's a general convention in Radiant to have the slash at the end of directories
app_path = StringRange( real, path_get_filename_start( real ) ); app_path = PathFilenameless( real );
} }
if ( !portable_app_setup() ) { if ( !portable_app_setup() ) {
StringOutputStream home( 256 ); home_path = StringOutputStream( 256 )( DirectoryCleaned( g_get_home_dir() ), ".netradiant/" ).c_str();
home << DirectoryCleaned( g_get_home_dir() ) << ".netradiant/"; Q_mkdir( home_path.c_str() );
Q_mkdir( home.c_str() );
home_path = home.c_str();
} }
gamedetect(); gamedetect();
cmdMap(); cmdMap();
@ -282,10 +278,8 @@ void environment_init( int argc, char* argv[] ){
char filename[MAX_PATH + 1]; char filename[MAX_PATH + 1];
GetModuleFileName( 0, filename, MAX_PATH ); GetModuleFileName( 0, filename, MAX_PATH );
StringOutputStream stream( 256 ); app_filepath = StringOutputStream( 256 )( PathCleaned( filename ) ).c_str();
stream << PathCleaned( filename ); app_path = PathFilenameless( app_filepath.c_str() );
app_filepath = stream.c_str();
app_path = StringRange( stream.c_str(), path_get_filename_start( stream.c_str() ) );
} }
if ( !portable_app_setup() ) { if ( !portable_app_setup() ) {

View File

@ -79,11 +79,8 @@ static bool g_bFindActive = true;
namespace namespace
{ {
void FindTextureDialog_apply(){ void FindTextureDialog_apply(){
StringOutputStream find( 256 ); const auto find = StringOutputStream( 256 )( "textures/", g_FindTextureDialog.m_strFind.c_str() );
StringOutputStream replace( 256 ); const auto replace = StringOutputStream( 256 )( "textures/", PathCleaned( g_FindTextureDialog.m_strReplace.c_str() ) );
find << "textures/" << g_FindTextureDialog.m_strFind.c_str();
replace << "textures/" << PathCleaned( g_FindTextureDialog.m_strReplace.c_str() );
FindReplaceTextures( find.c_str(), replace.c_str(), g_FindTextureDialog.m_bSelectedOnly ); FindReplaceTextures( find.c_str(), replace.c_str(), g_FindTextureDialog.m_bSelectedOnly );
} }

View File

@ -332,8 +332,7 @@ void EnginePath_Unrealise(){
} }
void setEnginePath( CopiedString& self, const char* value ){ void setEnginePath( CopiedString& self, const char* value ){
StringOutputStream buffer( 256 ); const auto buffer = StringOutputStream( 256 )( DirectoryCleaned( value ) );
buffer << DirectoryCleaned( value );
if ( !path_equal( buffer.c_str(), self.c_str() ) ) { if ( !path_equal( buffer.c_str(), self.c_str() ) ) {
#if 0 #if 0
while ( !ConfirmModified( "Paths Changed" ) ) while ( !ConfirmModified( "Paths Changed" ) )
@ -3736,9 +3735,7 @@ void MainFrame_Construct(){
#error "unknown platform" #error "unknown platform"
#endif #endif
; ;
StringOutputStream path( 256 ); g_strEnginePath = StringOutputStream( 256 )( DirectoryCleaned( g_pGameDescription->getRequiredKeyValue( ENGINEPATH_ATTRIBUTE ) ) ).c_str();
path << DirectoryCleaned( g_pGameDescription->getRequiredKeyValue( ENGINEPATH_ATTRIBUTE ) );
g_strEnginePath = path.c_str();
} }

View File

@ -1156,8 +1156,7 @@ public:
// parse string of format *pathToLoad/depth*path2ToLoad/depth* // parse string of format *pathToLoad/depth*path2ToLoad/depth*
// */depth* for root path // */depth* for root path
ModelFolders( const char* pathsString ){ ModelFolders( const char* pathsString ){
StringOutputStream str( 128 ); const auto str = StringOutputStream( 128 )( PathCleaned( pathsString ) );
str << PathCleaned( pathsString );
const char* start = str.c_str(); const char* start = str.c_str();
while( 1 ){ while( 1 ){

View File

@ -184,9 +184,7 @@ void bsp_init(){
} }
{ {
StringOutputStream name( 256 ); build_set_variable( "MapName", StringOutputStream( 64 )( PathFilename( mapname ) ).c_str() );
name << StringRange( path_get_filename_start( mapname ), path_get_filename_base_end( mapname ) );
build_set_variable( "MapName", name.c_str() );
} }
} }
@ -285,8 +283,7 @@ void RunBSP( const char* name ){
if ( g_WatchBSP_Enabled && monitor ) { if ( g_WatchBSP_Enabled && monitor ) {
// grab the file name for engine running // grab the file name for engine running
const char* fullname = Map_Name( g_map ); const char* fullname = Map_Name( g_map );
StringOutputStream bspname( 64 ); const auto bspname = StringOutputStream( 64 )( PathFilename( fullname ) );
bspname << StringRange( path_get_filename_start( fullname ), path_get_filename_base_end( fullname ) );
BuildMonitor_Run( listener.array(), bspname.c_str() ); BuildMonitor_Run( listener.array(), bspname.c_str() );
} }
else else

View File

@ -1373,8 +1373,7 @@ void SurfaceInspector::Update(){
=============== ===============
*/ */
void SurfaceInspector::ApplyShader(){ void SurfaceInspector::ApplyShader(){
StringOutputStream name( 256 ); const auto name = StringOutputStream( 256 )( GlobalTexturePrefix_get(), PathCleaned( gtk_entry_get_text( m_texture ) ) );
name << GlobalTexturePrefix_get() << PathCleaned( gtk_entry_get_text( m_texture ) );
// TTimo: detect and refuse invalid texture names (at least the ones with spaces) // TTimo: detect and refuse invalid texture names (at least the ones with spaces)
if ( !texdef_name_valid( name.c_str() ) ) { if ( !texdef_name_valid( name.c_str() ) ) {

View File

@ -95,7 +95,7 @@ void TextureGroups_addWad( TextureGroups& groups, const char* archive ){
#if 1 #if 1
groups.insert( archive ); groups.insert( archive );
#else #else
CopiedString archiveBaseName( path_get_filename_start( archive ), path_get_filename_base_end( archive ) ); CopiedString archiveBaseName( PathFilename( archive ) );
groups.insert( archiveBaseName ); groups.insert( archiveBaseName );
#endif #endif
} }
@ -696,7 +696,7 @@ class LoadShaderVisitor : public Archive::Visitor
{ {
public: public:
void visit( const char* name ){ void visit( const char* name ){
IShader* shader = QERApp_Shader_ForName( CopiedString( StringRange( name, path_get_filename_base_end( name ) ) ).c_str() ); IShader* shader = QERApp_Shader_ForName( CopiedString( PathExtensionless( name ) ).c_str() );
shader->DecRef(); shader->DecRef();
} }
}; };