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 );
}
class PathExtensionless
{
public:
const char* m_path;
PathExtensionless( const char* path ) : m_path( path ){
/// \brief Returns portion of \p path without .ext part.
inline StringRange PathExtensionless( const char *path ){
return StringRange( path, path_get_filename_base_end( path ) );
}
};
/// \brief Writes \p path to \p ostream without .ext part.
template<typename TextOutputStreamType>
TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const PathExtensionless& path ){
ostream << StringRange( path.m_path, path_get_filename_base_end( path.m_path ) );
return ostream;
/// \brief Returns portion of \p path without directory and .ext parts.
inline StringRange PathFilename( const char *path ){
return StringRange( path_get_filename_start( path ), path_get_filename_base_end( path ) );
}
/// \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
{
public:
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.
template<typename TextOutputStreamType>
TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const PathCleaned& path ){
const char* i = path.m_path;
for (; *i != '\0'; ++i )
for ( const char* i = path.m_path; i != path.m_end; ++i )
{
if ( *i == '\\' ) {
ostream << '/';

View File

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

View File

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

View File

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

View File

@ -66,9 +66,7 @@ inline VertexPointer vertexpointer_arbitrarymeshvertex( const ArbitraryMeshVerte
}
inline void parseTextureName( CopiedString& name, const char* token ){
StringOutputStream cleaned( 256 );
cleaned << PathCleaned( token );
name = StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ); // remove extension
name = StringOutputStream( 256 )( PathCleaned( PathExtensionless( token ) ) ).c_str(); // remove extension
}
// 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
template<typename StringType>
void parseTextureName( StringType& name, const char* token ){
StringOutputStream cleaned( 256 );
cleaned << PathCleaned( token );
name = CopiedString( StringRange( cleaned.c_str(), path_get_filename_base_end( cleaned.c_str() ) ) ).c_str(); // remove extension
name = StringOutputStream( 256 )( PathCleaned( PathExtensionless( token ) ) ).c_str(); // remove extension
}
bool Tokeniser_parseTextureName( Tokeniser& tokeniser, TextureExpression& name ){
@ -1610,12 +1608,9 @@ void ShaderList_addFromArchive( const char *archivename ){
return;
}
StringOutputStream shaderlist( 256 );
shaderlist << DirectoryCleaned( shaderpath ) << "shaderlist.txt";
Archive *archive = GlobalFileSystem().getArchive( archivename, false );
if ( archive ) {
ArchiveTextFile *file = archive->openTextFile( shaderlist.c_str() );
ArchiveTextFile *file = archive->openTextFile( StringOutputStream( 64 )( DirectoryCleaned( shaderpath ), "shaderlist.txt" ).c_str() );
if ( file ) {
globalOutputStream() << "Found shaderlist.txt in " << archivename << "\n";
BuildShaderList( file->getInputStream() );
@ -1658,8 +1653,7 @@ void Shaders_Load(){
const char* shaderPath = GlobalRadiant().getGameDescriptionKeyValue( "shaderpath" );
if ( !string_empty( shaderPath ) ) {
StringOutputStream path( 256 );
path << DirectoryCleaned( shaderPath );
const auto path = StringOutputStream( 64 )( DirectoryCleaned( shaderPath ) );
if ( g_useShaderList ) {
// 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)
// 2. find out what the lastest save is based on number
// 3. inc that and save the map
const char* path = Map_Name( g_map );
const char* name = path_get_filename_start( path );
StringOutputStream snapshotsDir( 256 );
snapshotsDir << StringRange( path, name ) << "snapshots";
const char* mapname = Map_Name( g_map );
const auto snapshotsDir = StringOutputStream( 256 )( PathFilenameless( mapname ), "snapshots" );
if ( file_exists( snapshotsDir.c_str() ) || Q_mkdir( snapshotsDir.c_str() ) ) {
std::size_t lSize = 0;
StringOutputStream strNewPath( 256 );
strNewPath << snapshotsDir.c_str() << '/' << name;
const auto strNewPath = StringOutputStream( 256 )( snapshotsDir.c_str(), '/', mapname );
const char* ext = path_get_filename_base_end( strNewPath.c_str() );
StringOutputStream snapshotFilename( 256 );
for ( int nCount = 0; ; ++nCount )
{
// The original map's filename is "<path>/<name>.<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(), end ) << '.' << nCount << end;
snapshotFilename( StringRange( strNewPath.c_str(), ext ), '.', nCount, ext );
if ( !DoesFileExist( snapshotFilename.c_str(), lSize ) ) {
break;
}
snapshotFilename.clear();
}
// save in the next available slot
@ -159,8 +152,7 @@ void QE_CheckAutoSave( void ){
{
const char* name = Map_Name( g_map );
const char* extension = path_get_filename_base_end( name );
StringOutputStream autosave( 256 );
autosave << StringRange( name, extension ) << ".autosave" << extension;
const auto autosave = StringOutputStream( 256 )( StringRange( name, extension ), ".autosave", extension );
Map_SaveFile( autosave.c_str() );
}
}

View File

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

View File

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

View File

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

View File

@ -198,9 +198,7 @@ CopiedString g_openMapByCmd;
void cmdMap(){
for ( int i = 1; i < g_argc; ++i )
if( extension_equal( path_get_extension( g_argv[i] ), "map" ) ){
StringOutputStream stream( 256 );
stream << PathCleaned( g_argv[i] );
g_openMapByCmd = stream.c_str();
g_openMapByCmd = StringOutputStream( 256 )( PathCleaned( g_argv[i] ) ).c_str();
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" );
// NOTE: we build app path with a trailing '/'
// 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() ) {
StringOutputStream home( 256 );
home << DirectoryCleaned( g_get_home_dir() ) << ".netradiant/";
Q_mkdir( home.c_str() );
home_path = home.c_str();
home_path = StringOutputStream( 256 )( DirectoryCleaned( g_get_home_dir() ), ".netradiant/" ).c_str();
Q_mkdir( home_path.c_str() );
}
gamedetect();
cmdMap();
@ -282,10 +278,8 @@ void environment_init( int argc, char* argv[] ){
char filename[MAX_PATH + 1];
GetModuleFileName( 0, filename, MAX_PATH );
StringOutputStream stream( 256 );
stream << PathCleaned( filename );
app_filepath = stream.c_str();
app_path = StringRange( stream.c_str(), path_get_filename_start( stream.c_str() ) );
app_filepath = StringOutputStream( 256 )( PathCleaned( filename ) ).c_str();
app_path = PathFilenameless( app_filepath.c_str() );
}
if ( !portable_app_setup() ) {

View File

@ -79,11 +79,8 @@ static bool g_bFindActive = true;
namespace
{
void FindTextureDialog_apply(){
StringOutputStream find( 256 );
StringOutputStream replace( 256 );
find << "textures/" << g_FindTextureDialog.m_strFind.c_str();
replace << "textures/" << PathCleaned( g_FindTextureDialog.m_strReplace.c_str() );
const auto find = StringOutputStream( 256 )( "textures/", g_FindTextureDialog.m_strFind.c_str() );
const auto replace = StringOutputStream( 256 )( "textures/", PathCleaned( g_FindTextureDialog.m_strReplace.c_str() ) );
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 ){
StringOutputStream buffer( 256 );
buffer << DirectoryCleaned( value );
const auto buffer = StringOutputStream( 256 )( DirectoryCleaned( value ) );
if ( !path_equal( buffer.c_str(), self.c_str() ) ) {
#if 0
while ( !ConfirmModified( "Paths Changed" ) )
@ -3736,9 +3735,7 @@ void MainFrame_Construct(){
#error "unknown platform"
#endif
;
StringOutputStream path( 256 );
path << DirectoryCleaned( g_pGameDescription->getRequiredKeyValue( ENGINEPATH_ATTRIBUTE ) );
g_strEnginePath = path.c_str();
g_strEnginePath = StringOutputStream( 256 )( DirectoryCleaned( g_pGameDescription->getRequiredKeyValue( ENGINEPATH_ATTRIBUTE ) ) ).c_str();
}

View File

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

View File

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

View File

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

View File

@ -95,7 +95,7 @@ void TextureGroups_addWad( TextureGroups& groups, const char* archive ){
#if 1
groups.insert( archive );
#else
CopiedString archiveBaseName( path_get_filename_start( archive ), path_get_filename_base_end( archive ) );
CopiedString archiveBaseName( PathFilename( archive ) );
groups.insert( archiveBaseName );
#endif
}
@ -696,7 +696,7 @@ class LoadShaderVisitor : public Archive::Visitor
{
public:
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();
}
};