TPath
BlitzMax Forums/BlitzMax Module Tweaks/TPath
| ||
I've put together an example of how paths could be abstracted into a type. The type would eliminate the need to manually tweak strings and handle any cross platform issues automatically in one place. This would also clean up a lot of the modules where path$ = path$.Replace( "\", "/" ) is constantly repeated. Here's the code: Strict Import BRL.Stream Import BRL.FileSystem Type TInvalidPathException Method ToString:String() Return "The specified path does not exist." End Method End Type Type TPath Function FromString:TPath( path:String ) Local aPath:TPath = New TPath aPath.SetPath( path ) Return aPath End Function Method GetFileName:String() Local index:Int = m_path.FindLast( "/" ) Local result:String = Null If index > -1 result = m_path[index + 1..m_path.length] End If Return result End Method Method GetFileNameWithoutExtension:String() Local temp:String = GetFileName() If temp <> Null Local index:Int = temp.FindLast( "." ) If index > -1 temp = temp[..index] End If End If Return temp End Method Method GetExtension:String() Local index:Int = m_path.FindLast( "." ) Local result:String = Null If index > -1 result = m_path[index + 1..m_path.length] End If Return result End Method Method Exists:Int() Return FileType( m_path ) <> FILETYPE_NONE End Method Method ChangeExtension( extension:String ) Local index:Int = m_path.FindLast( "." ) If index > -1 m_path = m_path[..index] + extension End If End Method Method GetDirectoryName:String() Local index:Int = m_path.FindLast( "/" ) Local result:String = Null If index > -1 result = m_path[..index] Else If FileType( m_path ) = FILETYPE_DIR result = m_path End If End If Return result End Method Method SetPath( path:String ) m_path = path.Replace( "\", "/" ) If FileType( m_path ) = FILETYPE_NONE Throw New TInvalidPathException ElseIf FileType( m_path ) = FILETYPE_DIR m_path:+"/" End If ?Linux ?MacOS Local cased:String = CasedFileName( m_path ) If cased m_path = cased End If Local index:Int = m_path.Find( ":" ) If index > -1 m_path = m_path[index + 1..m_path.length] End If ? End Method Method Append( path:String ) Local temp:String = m_path If temp[temp.length - 1] <> "/" temp:+"/" End If temp:+path SetPath( temp ) End Method Method ToString:String() Return m_path End Method Field m_path:String End Type TestTPath() Function TestTPath() Local testPath:TPath = TPath.FromString( "c:\temp" ) testPath.Append( "form.dat" ) Print testPath.ToString() Print testPath.GetDirectoryName() Print testPath.GetFileName() Print testPath.GetFileNameWithoutExtension() Print testPath.GetExtension() Print testPath.Exists() End Function Everything that accepts a String now for a path would instead accept a TPath. To make the impact on client code almost seamless BRL could add a ToPath() method on String, which would simply create a new instance of TPath via TPath.FromString. An example might look like this: Global anImage:TImage = LoadImage( "C:\gfx\balloon.png".ToPath() ) NOTES: Since this is really the first class I've implemented in BlitzMax I'd like to pass on some comments/suggestions to BRL: 1. Private/Public should work within a Type. Without being able to set members to Private we lose true encapsulation. In the TPath example above, m_path is still publically accessible so a beginner might accidentially access it directly which would render the abstraction worthless. An alternative here would be to support encapsulated fields a.k.a properties a la .NET, Ruby. 2. The ability to add extensions to the base types would be wonderful. In the TPath example I would have loved to add a ToPath method on String. This is different from inheritence as it changes an existing type. This is similar but not quite the same as partial types. 3. Wishful thinking, I'm sure, but some form of simple reflection would be wonderful. |