Simple abstract stream

BlitzMax Forums/BlitzMax Programming/Simple abstract stream

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