Browse Source

std.filesystem tweaks.

Mark Sibly 7 years ago
parent
commit
358d149e28

+ 119 - 47
modules/std/filesystem/filesystem.monkey2

@@ -7,9 +7,23 @@ Using libc
 #Import "native/filesystem.cpp"
 
 #If __TARGET__="android"
+
 #Import "native/Monkey2FileSystem.java"
+
+Using android
+
 #Elseif __TARGET__="ios"
+
 #Import "native/filesystem.mm"
+
+#endif
+
+#If __TARGET__="android"
+
+Extern Private
+
+Function fopenAsset:FILE Ptr( asset:AAsset )="bbFileSystem::fopenAsset"
+	
 #endif
 
 Extern
@@ -63,8 +77,6 @@ Function FixPath:String( path:String )
 	
 	Select root
 	Case "asset::" return AssetsDir()+path
-	Case "desktop::" Return DesktopDir()+path
-	Case "home::" Return HomeDir()+path
 #If __MOBILE_TARGET__
 	Case "internal::" Return InternalDir()+path
 	Case "external::" Return ExternalDir()+path
@@ -226,13 +238,13 @@ Note that only the desktop and web targets have an assets directory. Other targe
 Function AssetsDir:String()
 	If Not _assetsDir
 #If __TARGET__="macos"
-		_assetsDir=ExtractDir( AppDir() )+"Resources/"	'enable me!
+		_assetsDir=ExtractDir( AppDir() )+"Resources/"
 #Else If __DESKTOP_TARGET__ Or __WEB_TARGET__
 		_assetsDir=AppDir()+"assets/"
 #Else If __TARGET__="ios"
 		_assetsDir=GetSpecialDir( "assets" )
 #Else
-		_assetsDir="asset::"
+		_assetsDir="${ASSETS}/"	'"asset::"
 #Endif
 	Endif
 	Return _assetsDir
@@ -261,7 +273,7 @@ Function DesktopDir:String()
 #Else If __DESKTOP_TARGET__
  	Return GetEnv( "HOME" )+"/Desktop/"
  #Else
- 	Return "desktop::"
+ 	Return "${DESKTOP}/"
 #Endif
 End
 
@@ -278,7 +290,7 @@ Function HomeDir:String()
 #Else if __DESKTOP_TARGET__
 	Return GetEnv( "HOME" )+"/"
 #Else
-	Return "home::"
+	Return "${HOME}/"
 #Endif
 End
 
@@ -333,19 +345,20 @@ Function ExtractRootDir:String( path:String )
 	
 	If path.StartsWith( "//" ) Return "//"
 	
+	If path.StartsWith( "/" ) Return "/"
+
 	Local i:=path.Find( "/" )
-	If i=0 Return "/"
 	
-	If i=-1 i=path.Length
+	If path.StartsWith( "$" ) And i<>-1 Return path.Slice( 0,i+1 )
 	
-	Local j:=path.Find( "://" )
-	If j>0 And j<i Return path.Slice( 0,j+3 )
+	Local j:=path.Find( ":" )
+	If j=-1 Or (i<>-1 And j>i) Return ""
 	
-	j=path.Find( ":/" )
-	If j>0 And j<i Return path.Slice( 0,j+2 )
+	If path.Slice( j,j+3 )="://" Return path.Slice( 0,j+3)
 	
-	j=path.Find( "::" )
-	If j>0 And j<i Return path.Slice( 0,j+2 )
+	If path.Slice( j,j+2 )=":/" Return path.Slice( 0,j+2 )
+	
+	If path.Slice( j,j+2 )="::" Return path.Slice( 0,j+2 )
 	
 	Return ""
 End
@@ -359,26 +372,7 @@ End
 #end
 Function IsRootDir:Bool( path:String )
 	
-	path=path.Replace( "\","/" )
-	
-
-	If path="//" Return True
-	
-	If path="/" Return True
-	
-	Local i:=path.Find( "/" )
-	If i=-1 i=path.Length
-	
-	Local j:=path.Find( "://" )
-	If j>0 And j<i Return j+3=path.Length
-	
-	j=path.Find( ":/" )
-	If j>0 And j<i Return j+2=path.Length
-	
-	j=path.Find( "::" )
-	If j>0 And j<i Return j+2=path.Length
-	
-	Return False
+	Return ExtractRootDir( path )<>""
 End
 
 #rem monkeydoc Gets the process current directory.
@@ -418,30 +412,30 @@ Function RealPath:String( path:String )
 	
 	path=FixPath( path )
 	
-	Local rpath:=ExtractRootDir( path )
-	If rpath 
-		path=path.Slice( rpath.Length )
+	Local root:=ExtractRootDir( path )
+	If root 
+		path=path.Slice( root.Length )
 	Else
-		rpath=CurrentDir()
+		root=CurrentDir()
 	Endif
 	
 	While path
 		Local i:=path.Find( "/" )
-		If i=-1 Return rpath+path
+		If i=-1 Return root+path
 		Local t:=path.Slice( 0,i )
 		path=path.Slice( i+1 )
 		Select t
 		Case ""
 		Case "."
 		Case ".."
-			If Not rpath rpath=CurrentDir()
-			rpath=ExtractDir( rpath )
+			If Not root root=CurrentDir()
+			root=ExtractDir( root )
 		Default
-			rpath+=t+"/"
+			root+=t+"/"
 		End
 	Wend
 	
-	Return rpath
+	Return root
 	
 	#rem Not working on macos!
 	
@@ -593,6 +587,21 @@ End
 Function GetFileType:FileType( path:String )
 	
 	path=FixFilePath( path )
+	
+#If __TARGET__="android"
+	If path.StartsWith( "${ASSETS}/" )
+		
+		path=path.Slice( 10 )
+		
+		Local asset:=AAssetManager_open( GetAssetManager(),path,0 )
+		If Not asset Return FileType.Unknown
+		
+		Local length:=AAsset_getLength( asset )
+		AAsset_close( asset )
+		
+		Return length<>0 ? FileType.File Else FileType.Unknown
+	End
+#Endif
 
 	Local st:stat_t
 	If stat( path,Varptr st )<0 Return FileType.None
@@ -630,9 +639,24 @@ End
 
 #end
 Function GetFileSize:Long( path:String )
-
+	
 	path=FixFilePath( path )
 
+#If __TARGET__="android"
+	If path.StartsWith( "${ASSETS}/" )
+		
+		path=path.Slice( 10 )
+		
+		Local asset:=AAssetManager_open( GetAssetManager(),path,0 )
+		If Not asset Return 0
+		
+		Local length:=AAsset_getLength( asset )
+		AAsset_close( asset )
+		
+		Return length
+	End
+#Endif
+
 	Local st:stat_t
 	If stat( path,Varptr st )<0 Return 0
 
@@ -664,13 +688,35 @@ Does not return any '.' or '..' entries in a directory.
 #end
 Function LoadDir:String[]( path:String )
 	
+	Local files:=New StringStack
+	
 	path=FixFilePath( path )
-
+	
+#If __TARGET__="android"
+	If path.StartsWith( "${ASSETS}/" )
+		
+		path=path.Slice( 10 )
+		
+		Print "Asset dir path 3="+path
+		
+		Local assetDir:=AAssetManager_openDir( GetAssetManager(),path )
+		
+		If assetDir
+			Repeat
+				Local file:=AAssetDir_getNextFileName( assetDir )
+				If Not file Exit
+				files.Add( file )
+			Forever
+			AAssetDir_close( assetDir )
+		Endif
+		
+		Return files.ToArray()
+	Endif
+#endif
+	
 	Local dir:=opendir( path )
 	If Not dir Return Null
 	
-	Local files:=New StringStack
-	
 	Repeat
 		Local ent:=readdir( dir )
 		If Not ent Exit
@@ -851,3 +897,29 @@ Function CopyDir:Bool( srcDir:String,dstDir:String,recursive:Bool=True )
 	Return True
 
 End
+
+#rem monkeydoc Opens a 'C' file.
+
+Opens a file that can be used with the 'C' calls fopen, fread, fwrite and fclose. Similar to plain libc.fopen, except that it can also handle assets on android.
+
+`mode` should be one of: "r", "w" or "rw". When opening a file using "r" or "rw", the file must already exist or the function will fail and null will be returned. When opening a file using "w", any existing file at the same path will be overwritten.
+
+#end
+Function OpenCFile:FILE Ptr( path:String,mode:String )
+	
+	path=FixFilePath( path )
+	
+#If __TARGET__="android"
+	If path.StartsWith( "${ASSETS}/" )
+		
+		path=path.Slice( 10 )
+		
+		Local asset:=AAssetManager_open( GetAssetManager(),path,0 )
+		If Not asset Return Null
+		
+		Return fopenAsset( asset )
+	Endif
+#Endif
+	
+	Return libc.fopen( path,mode )
+End

+ 53 - 0
modules/std/filesystem/native/filesystem.cpp

@@ -37,6 +37,12 @@
 
 #endif
 
+#if BB_ANDROID
+
+#include <sdl2/SDL/src/core/android/SDL_android.h>
+
+#endif
+
 namespace bbFileSystem{
 
 	bbString _appDir;
@@ -172,4 +178,51 @@ namespace bbFileSystem{
 #endif
 	}
 	
+#if BB_ANDROID
+	int android_read( void *cookie,char *buf,int size ){
+	
+	  return AAsset_read( (AAsset*)cookie,buf,size );
+	}
+	
+	int android_write( void *cookie,const char* buf,int size ){
+	
+	  return EACCES; // can't provide write access to the apk
+	}
+	
+	fpos_t android_seek( void *cookie,fpos_t offset,int whence ){
+	
+	  return AAsset_seek( (AAsset*)cookie,offset,whence );
+	}
+	
+	int android_close(void* cookie) {
+	
+	  AAsset_close( (AAsset*)cookie );
+	  return 0;
+	}
+
+	FILE *fopenAsset( void *asset ){
+
+		return funopen( asset,android_read,android_write,android_seek,android_close );
+	}
+
+#endif
+
+/*	
+	FILE *fopen( const char *path,const char *mode ){
+
+#if BB_ANDROID
+		if( !strncmp( path,"asset::",7 ) ){
+			
+			AAssetManager *assetManager=Android_JNI_GetAssetManager();
+			if( !assetManager ) return 0;
+			
+	  		AAsset* asset=AAssetManager_open( assetManager,path+7,0 );
+			if( !asset ) return 0;
+			
+			return fopenAsset( asset );
+		}
+#endif
+		return ::fopen( path,mode );
+	}
+*/	
 }

+ 4 - 2
modules/std/filesystem/native/filesystem.h

@@ -16,9 +16,11 @@ namespace bbFileSystem{
 	bbBool copyFile( bbString srcPath,bbString dstPath );
 	
 #if BB_IOS
-	
 	bbString getSpecialDir( bbString name );
-	
+#endif
+
+#if BB_ANDROID
+	FILE *fopenAsset( void *asset );
 #endif
 
 }

+ 1 - 2
modules/std/graphics/pixmaploader.monkey2

@@ -72,9 +72,8 @@ Public
 Function LoadPixmap:Pixmap( path:String,format:PixelFormat )
 	
 	If ExtractExt( path )=".hdr"
-		path=RealPath( path )
 		
-		Local file:=libc.fopen( path,"rb" )
+		Local file:=filesystem.OpenCFile( path,"rb" )
 		If Not file Return Null
 		
 		Local width:=0,height:=0

+ 1 - 1
modules/std/module.json

@@ -4,5 +4,5 @@
 	"author":"Mark Sibly",
 	"version":"1.0.0",
 	"support":"http://monkeycoder.co.nz",
-	"depends":["libc","emscripten","jni","sdl2","miniz","stb-image","stb-image-write","stb-vorbis","zlib"]
+	"depends":["libc","sdl2","jni","android","emscripten","zlib","miniz","stb-image","stb-image-write","stb-vorbis"]
 }

+ 19 - 52
modules/std/std.monkey2

@@ -1,23 +1,20 @@
 
 Namespace std
 
-#Import "<libc.monkey2>"
+#Import "<libc>"
+#Import "<zlib>"
+#Import "<miniz>"
 #Import "<stb-image>"
 #Import "<stb-image-write>"
 #import "<stb-vorbis>"
-#Import "<miniz>"
-#Import "<zlib>"
 
-#If __MOBILE_TARGET__
-#Import "<sdl2>"
-#If __TARGET__="android"
-#Import "<jni>"
-#Endif
-#Endif
-
-#If __WEB_TARGET__
+#If __TARGET__="emscripten"
 #Import "<emscripten>"
-#endif
+#ElseIf __TARGET__="android"
+#Import "<android>"
+#ElseIf __TARGET__="ios"
+'#Import "<ios>"
+#Endif
 
 #Import "collections/container"
 #Import "collections/stack"
@@ -30,9 +27,9 @@ Namespace std
 #Import "stream/stream"
 #Import "stream/filestream"
 
-#If __MOBILE_TARGET__
-#Import "stream/sdl_rwstream.monkey2"
-#Endif
+'#If __MOBILE_TARGET__
+'#Import "stream/sdl_rwstream.monkey2"
+'#Endif
 
 #Import "memory/byteorder"
 #Import "memory/databuffer"
@@ -107,9 +104,9 @@ Function Main()
 		Return FileStream.Open( path,mode )
 	End
 	
-	Stream.OpenFuncs["memblock"]=Lambda:Stream( proto:String,path:String,mode:String )
+	Stream.OpenFuncs["asset"]=Lambda:Stream( proto:String,path:String,mode:String )
 	
-		Return DataStream.Open( path,mode )
+		Return FileStream.Open( filesystem.AssetsDir()+path,mode )
 	End
 	
 #If __MOBILE_TARGET__
@@ -126,46 +123,16 @@ Function Main()
 
 #endif
 	
-#If __DESKTOP_TARGET__
-
-	Stream.OpenFuncs["process"]=Lambda:Stream( proto:String,path:String,mode:String )
-
-		Return std.process.ProcessStream.Open( path,mode )
-	End
-	
-	Stream.OpenFuncs["desktop"]=Lambda:Stream( proto:String,path:String,mode:String )
+	Stream.OpenFuncs["memory"]=Lambda:Stream( proto:String,path:String,mode:String )
 	
-		Return FileStream.Open( filesystem.DesktopDir()+path,mode )
-	End
-
-	Stream.OpenFuncs["home"]=Lambda:Stream( proto:String,path:String,mode:String )
-	
-		Return FileStream.Open( filesystem.HomeDir()+path,mode )
-	End
-	
-#Endif
-
-#If __DESKTOP_TARGET__ Or __WEB_TARGET__
-
-	'note: ios and android asset proto is implemented using SDL and implemented in mojo...
-	'
-	Stream.OpenFuncs["asset"]=Lambda:Stream( proto:String,path:String,mode:String )
-	
-		Return FileStream.Open( filesystem.AssetsDir()+path,mode )
+		Return DataStream.Open( path,mode )
 	End
-
-#Else If __TARGET__="android"
-
-	Stream.OpenFuncs["asset"]=Lambda:Stream( proto:String,path:String,mode:String )
 	
-		Return SDL_RWStream.Open( path,mode )
-	End
+#If __DESKTOP_TARGET__
 
-#Else If __TARGET__="ios"
+	Stream.OpenFuncs["process"]=Lambda:Stream( proto:String,path:String,mode:String )
 
-	Stream.OpenFuncs["asset"]=Lambda:Stream( proto:String,path:String,mode:String )
-	
-		Return SDL_RWStream.Open( "assets/"+path,mode )
+		Return std.process.ProcessStream.Open( path,mode )
 	End
 	
 #Endif

+ 4 - 12
modules/std/stream/filestream.monkey2

@@ -92,9 +92,6 @@ Class FileStream Extends Stream
 	
 	When opening a file using "w", any existing file at the same path will be overwritten.
 	
-	Note: This method should not be used to open an 'asset stream' because assets are not always files. You should instead use 
-	[[Stream.Open]] for streams that have a stream path prefix such as `asset::`, `internal::`, `external::` etc.
-	
 	@param path The path of the file to open.
 	
 	@param mode The mode to open the file in: "r", "w" or "rw".
@@ -105,19 +102,14 @@ Class FileStream Extends Stream
 	Function Open:FileStream( path:String,mode:String )
 	
 		Select mode
-		Case "r"
-			mode="rb"
-		Case "w"
-			mode="wb"
-		Case "rw"
-			mode="r+b"
+		Case "r" mode="rb"
+		Case "w" mode="wb"
+		Case "rw" mode="r+b"
 		Default
 			Return Null
 		End
 		
-		path=RealPath( path )
-		
-		Local file:=fopen( path,mode )
+		Local file:=OpenCFile( path,mode )
 		If Not file Return Null
 		
 		Return New FileStream( file )