AbstractStream update

BlitzMax Forums/BlitzMax Programming/AbstractStream update

JoshK(Posted 2007) [#1]
This modification will allow you to either specify just the file name to load:

ReadFile("abstract::test.md3")

Or you can also just specify the name with no extension:

ReadFile("abstract::test")

Obviously you can only have one file named "test.xxx" if you only use the name with no extension.

This is useful for loading media when you don't know or care exactly where it may be located. It will automatically detect and read files within zip packages (requires gman.zipengine and koriolis.zipstream).


Private
Global AbstractFileMap:TMap[2]
AbstractFileMap[0]=New TMap
AbstractFileMap[1]=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
		If ExtractExt(filename)=""
			filename=String(MapValueForKey(AbstractFileMap[1],filename))
		Else
			filename=String(MapValueForKey(AbstractFileMap[0],filename))
		EndIf
		If filename="" Return Null
		Return ReadStream(filename)
	EndMethod
	
EndType

New TAbstractStreamFactory

Function AbstractFileExists:Int(name$)
	If ExtractExt(name)=""
		If String(MapValueForKey(AbstractFileMap[1],Lower(name)))<>"" Return 1
	Else
		If String(MapValueForKey(AbstractFileMap[0],Lower(name)))<>"" Return 1
	EndIf
EndFunction

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[0],name) Continue
				MapInsert AbstractFileMap[0],name,RealPath(filepath+"/"+filename)
				
				If Not MapValueForKey(AbstractFileMap[1],StripExt(name))
					MapInsert AbstractFileMap[1],StripExt(name),RealPath(filepath+"/"+filename)				
				EndIf
				
				'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[0],name) Continue
								MapInsert AbstractFileMap[0],name,filename

								If Not MapValueForKey(AbstractFileMap[1],StripExt(name))
									MapInsert AbstractFileMap[1],StripExt(name),filename			
								EndIf
								
							EndIf
						Next
						zrObject.CloseZip()
					EndIf
				EndSelect
				
			Case 2
				If filename<>"." And filename<>".."
					RegisterAbstractPath(filepath+"/"+filename)
				EndIf
		EndSelect
	Forever
	CloseDir d
EndFunction

Rem
'-----------------------------------------------
' 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

endrem