Simple abstract stream
BlitzMax Forums/BlitzMax Programming/Simple abstract stream
| ||
| Here is a very simple abstract stream type. You can simply go ReadFile("abstract::readme.txt") and the stream will return any file in any subfolder called "readme.txt". This allows you to load media and other files without knowing exactly where they are in your directories. The initialization uses a TMap, so it should be very fast to startup and retrieve files. Implementing a package file system in the RegisterAbstractPath() routine would make this much more powerful. Strict
Private
Global AbstractFileMap:TMap=New TMap
Public
Type TAbstractStreamFactory Extends TStreamFactory
Method CreateStream:TStream( url:Object,proto$,path$,readable,writeable )
If proto<>"abstract" Return Null
Local filename$
Local p
filename=Lower(StripDir(String(url)))
p=Instr(filename,"::")
If p filename=Right(filename,Len(filename)-p-1)
If filename="" Return Null
filename=String(MapValueForKey(AbstractFileMap,filename))
If filename<>"" Return ReadStream(filename)
EndMethod
EndType
New TAbstractStreamFactory
Function RegisterAbstractPath(filepath$)
Local name$,filename$
Local d
d=ReadDir(filepath)
If Not d Return
If Right(filepath,1)="/" filepath=Left(filepath,Len(filepath)-1)
If Right(filepath,1)="\" filepath=Left(filepath,Len(filepath)-1)
Repeat
filename$=NextFile(d)
Select FileType(filepath+"/"+filename)
Case 0 Exit
Case 1
name=Lower(StripDir(filename))
If MapValueForKey(AbstractFileMap,name) Continue
MapInsert AbstractFileMap,name,RealPath(filepath+"/"+filename)
Case 2
If filename<>"." And filename<>".."
RegisterAbstractPath(filepath+"/"+filename)
EndIf
EndSelect
Forever
CloseDir d
EndFunction
'-----------------------------------------------
' Test Program
'-----------------------------------------------
Local stream:TStream
RegisterAbstractPath(AppDir)
stream=ReadFile("abstract::readme.txt")
If Not stream
Notify "Failed to open abstract stream ~qreadme.txt~q.",1
End
EndIf
While Not stream.eof()
Notify stream.readline()
Wend
End |
| ||
This version adds support for zip packages. So you can retrieve a zipped file anywhere in the subdirectory by just specifying the file name and extension. Perfect for loading media:Import koriolis.zipstream
Import gman.zipengine
Private
Global AbstractFileMap:TMap=New TMap
Public
Type TAbstractStreamFactory Extends TStreamFactory
Method CreateStream:TStream( url:Object,proto$,path$,readable,writeable )
If proto<>"abstract" Return Null
Local filename$
Local p
filename=Lower(StripDir(String(url)))
p=Instr(filename,"::")
If p filename=Right(filename,Len(filename)-p-1)
If filename="" Return Null
filename=String(MapValueForKey(AbstractFileMap,filename))
If filename="" Return Null
Return ReadStream(filename)
EndMethod
EndType
New TAbstractStreamFactory
Function RegisterAbstractPath(filepath$)
Local name$,filename$
Local d
Local zrObject:ZipReader
Local packagefile$
d=ReadDir(filepath)
If Not d Return
If Right(filepath,1)="/" filepath=Left(filepath,Len(filepath)-1)
If Right(filepath,1)="\" filepath=Left(filepath,Len(filepath)-1)
Repeat
filename$=NextFile(d)
If filename="" Exit
Select FileType(filepath+"/"+filename)
Case 0 Exit
Case 1
name=Lower(StripDir(filename))
If MapValueForKey(AbstractFileMap,name) Continue
MapInsert AbstractFileMap,name,RealPath(filepath+"/"+filename)
'Zip stream support
Select Lower(ExtractExt(filename))
Case "zip","pk3"
packagefile=filename
zrObject=New ZipReader
If zrObject.OpenZip(filename)
For Local i:Int=0 To zrObject.getFileCount()-1
filename$=zrObject.getFileInfo(i).zipFileName
If ExtractExt(filename)<>""
name=Lower(StripDir(filename))
filename="zip::"+packagefile+"//"+filename
If MapValueForKey(AbstractFileMap,name) Continue
MapInsert AbstractFileMap,name,filename
EndIf
Next
zrObject.CloseZip()
EndIf
EndSelect
Case 2
If filename<>"." And filename<>".."
RegisterAbstractPath(filepath+"/"+filename)
EndIf
EndSelect
Forever
CloseDir d
EndFunction
'-----------------------------------------------
' Test Program
'-----------------------------------------------
Local stream:TStream
RegisterAbstractPath(AppDir)
stream=ReadFile("abstract::readme.txt")
If Not stream
Notify "Failed to open abstract stream ~qreadme~q.",1
End
EndIf
While Not stream.eof()
Notify stream.readline()
Wend
End |