filesystem.monkey2 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. Namespace std.filesystem
  2. Using libc
  3. #Import "native/filesystem.h"
  4. #Import "native/filesystem.cpp"
  5. Extern
  6. #rem monkeydoc Gets application directory.
  7. @return The directory containing the application executable.
  8. #end
  9. Function AppDir:String()="bbFileSystem::appDir"
  10. #rem monkeydoc Gets the application file path.
  11. @return The path of the application executable.
  12. #end
  13. Function AppPath:String()="bbFileSystem::appPath"
  14. #rem monkeydoc Gets application command line arguments.
  15. @return The application command line arguments.
  16. #end
  17. Function AppArgs:String[]()="bbFileSystem::appArgs"
  18. #rem monkeydoc Copies a file.
  19. @return True if the file was successfully copied.
  20. #end
  21. Function CopyFile:Bool( srcPath:String,dstPath:String )="bbFileSystem::copyFile"
  22. Public
  23. #rem monkeydoc FileType enumeration.
  24. | FileType | Description
  25. |:--------------|:-----------
  26. | `None` | File does not exist.
  27. | `File` | File is a normal file.
  28. | `Directory` | File is a directory.
  29. | `Unknown` | File is of unknown type.
  30. #end
  31. Enum FileType
  32. None=0
  33. File=1
  34. Directory=2
  35. Unknown=3
  36. End
  37. 'For backward compatibility - don't use!
  38. '
  39. #rem monkeydoc @hidden
  40. #end
  41. Const FILETYPE_NONE:=FileType.None
  42. #rem monkeydoc @hidden
  43. #end
  44. Const FILETYPE_FILE:=FileType.File
  45. #rem monkeydoc @hidden
  46. #end
  47. Const FILETYPE_DIR:=FileType.Directory
  48. #rem monkeydoc @hidden
  49. #end
  50. Const FILETYPE_UNKNOWN:=FileType.Unknown
  51. #rem monkeydoc Gets the filesystem directory of the assets folder.
  52. @return The directory app assets are stored in.
  53. #end
  54. Function AssetsDir:String()
  55. #If __TARGET__="macos"
  56. Return AppDir()+"../Resources/"
  57. #Else If __DESKTOP_TARGET__ Or __TARGET__="emscripten"
  58. Return AppDir()+"assets/"
  59. #Else
  60. Return ""
  61. #Endif
  62. End
  63. Function DesktopDir:String()
  64. #If __TARGET__="windows"
  65. Return (String.FromCString( getenv( "HOMEDRIVE" ) )+String.FromCString( getenv( "HOMEPATH" ) )).Replace( "\","/" )+"/Desktop/"
  66. #Else If __DESKTOP_TARGET__
  67. Return String.FromCString( getenv( "HOME" ) )+"/Desktop/"
  68. #Endif
  69. Return ""
  70. End
  71. #rem monkeydoc Extracts the root directory from a file system path.
  72. @param path The filesystem path.
  73. @return The root directory of `path`, or an empty string if `path` is not an absolute path.
  74. #end
  75. Function ExtractRootDir:String( path:String )
  76. If path.StartsWith( "//" ) Return "//"
  77. Local i:=path.Find( "/" )
  78. If i=0 Return "/"
  79. If i=-1 i=path.Length
  80. Local j:=path.Find( "://" )
  81. If j>0 And j<i Return path.Slice( 0,j+3 )
  82. j=path.Find( ":/" )
  83. If j>0 And j<i Return path.Slice( 0,j+2 )
  84. j=path.Find( "::" )
  85. If j>0 And j<i Return path.Slice( 0,j+2 )
  86. Return ""
  87. End
  88. #rem monkeydoc Checks if a path is a root directory.
  89. @param path The filesystem path to check.
  90. @return True if `path` is a root directory path.
  91. #end
  92. Function IsRootDir:Bool( path:String )
  93. If path="//" Return True
  94. If path="/" Return True
  95. Local i:=path.Find( "/" )
  96. If i=-1 i=path.Length
  97. Local j:=path.Find( "://" )
  98. If j>0 And j<i Return j+3=path.Length
  99. j=path.Find( ":/" )
  100. If j>0 And j<i Return j+2=path.Length
  101. j=path.Find( "::" )
  102. If j>0 And j<i Return j+2=path.Length
  103. Return False
  104. End
  105. #rem monkeydoc Strips any trailing slashes from a filesystem path.
  106. This function will not strip slashes from a root directory path.
  107. @param path The filesystem path.
  108. @return The path stripped of trailing slashes.
  109. #end
  110. Function StripSlashes:String( path:String )
  111. If Not path.EndsWith( "/" ) Return path
  112. Local root:=ExtractRootDir( path )
  113. Repeat
  114. If path=root Return path
  115. path=path.Slice( 0,-1 )
  116. Until Not path.EndsWith( "/" )
  117. Return path
  118. End
  119. #rem monkeydoc Extracts the directory component from a filesystem path.
  120. If `path` is a root directory it is returned without modification.
  121. If `path` does not contain a directory component, an empty string is returned.
  122. @param path The filesystem path.
  123. @return The directory component of `path`.
  124. #end
  125. Function ExtractDir:String( path:String )
  126. path=StripSlashes( path )
  127. If IsRootDir( path ) Return path
  128. Local i:=path.FindLast( "/" )
  129. If i>=0 Return path.Slice( 0,i+1 )
  130. i=path.Find( "::" )
  131. If i>=0 Return path.Slice( 0,i+2 )
  132. Return ""
  133. End
  134. #rem monkeydoc Strips the directory component from a filesystem path.
  135. If `path` is a root directory an empty string is returned.
  136. If `path` does not contain a directory component, `path` is returned without modification.
  137. @param path The filesystem path.
  138. @return The path with the directory component stripped.
  139. #end
  140. Function StripDir:String( path:String )
  141. path=StripSlashes( path )
  142. If IsRootDir( path ) Return ""
  143. Local i:=path.FindLast( "/" )
  144. If i>=0 Return path.Slice( i+1 )
  145. i=path.Find( "::" )
  146. If i>=0 Return path.Slice( i+2 )
  147. Return path
  148. End
  149. #rem monkeydoc Extracts the extension component from a filesystem path.
  150. @param path The filesystem path.
  151. @return The extension component of `path` including the '.' if any.
  152. #end
  153. Function ExtractExt:String( path:String )
  154. Local i:=path.FindLast( "." )
  155. If i=-1 Return ""
  156. Local j:=path.Find( "/",i+1 )
  157. If j=-1 Return path.Slice( i )
  158. Return ""
  159. End
  160. #rem monkeydoc Strips the extension component from a filesystem path
  161. @param path The filesystem path.
  162. @return The path with the extension stripped.
  163. #end
  164. Function StripExt:String( path:String )
  165. Local i:=path.FindLast( "." )
  166. If i=-1 Return path
  167. Local j:=path.Find( "/",i+1 )
  168. If j=-1 Return path.Slice( 0,i )
  169. Return path
  170. End
  171. #rem monkeydoc Converts a path to a real path.
  172. If `path` is a relative path, it is first converted into an absolute path by prefixing the current directory.
  173. Then, any internal './' or '../' references in the path are collapsed.
  174. @param path The filesystem path.
  175. @return An absolute path with any './', '../' references collapsed.
  176. #end
  177. Function RealPath:String( path:String )
  178. Local rpath:=ExtractRootDir( path )
  179. If rpath
  180. path=path.Slice( rpath.Length )
  181. Else
  182. rpath=CurrentDir()
  183. Endif
  184. While path
  185. Local i:=path.Find( "/" )
  186. If i=-1 Return rpath+path
  187. Local t:=path.Slice( 0,i )
  188. path=path.Slice( i+1 )
  189. Select t
  190. Case ""
  191. Case "."
  192. Case ".."
  193. If Not rpath rpath=CurrentDir()
  194. rpath=ExtractDir( rpath )
  195. Default
  196. rpath+=t+"/"
  197. End
  198. Wend
  199. Return rpath
  200. End
  201. #rem monkeydoc Gets the type of the file at a filesystem path.
  202. @param path The filesystem path.
  203. @return The file type of the file at `path`, one of: FileType.None, FileType.File or FileType.Directory.
  204. #end
  205. Function GetFileType:FileType( path:String )
  206. Local st:stat_t
  207. If stat( StripSlashes( path ),Varptr st )<0 Return FileType.None
  208. Select st.st_mode & S_IFMT
  209. Case S_IFREG Return FileType.File
  210. Case S_IFDIR Return FileType.Directory
  211. End
  212. Return FileType.Unknown
  213. End
  214. #rem monkeydoc Gets the time a file was most recently modified.
  215. @param path The filesystem path.
  216. @return The time the file at `path` was most recently modified.
  217. #end
  218. Function GetFileTime:Long( path:String )
  219. Local st:stat_t
  220. If stat( StripSlashes( path ),Varptr st )<0 Return 0
  221. Return libc.tolong( st.st_mtime )
  222. End
  223. #rem monkeydoc Gets the size of the file at a filesystem path.
  224. @param path The filesystem path.
  225. @return The size file at `path` in bytes.
  226. #end
  227. Function GetFileSize:Long( path:String )
  228. path=StripSlashes( path )
  229. Local st:stat_t
  230. If stat( path,Varptr st )<0 Return 0
  231. return st.st_size
  232. End
  233. #rem monkeydoc Gets the process current directory.
  234. @return The current directory for the running process.
  235. #end
  236. Function CurrentDir:String()
  237. Local sz:=4096
  238. Local buf:=Cast<char_t Ptr>( malloc( sz ) )
  239. getcwd( buf,sz )
  240. Local path:=String.FromCString( buf )
  241. free( buf )
  242. path=path.Replace( "\","/" )
  243. If path.EndsWith( "/" ) Return path
  244. Return path+"/"
  245. End
  246. #rem monkeydoc Changes the process current directory.
  247. @param path The filesystem path of the directory to make current.
  248. #end
  249. Function ChangeDir( path:String )
  250. chdir( StripSlashes( path ) )
  251. End
  252. #rem monkeydoc Loads a directory.
  253. @param path The filesystem path of the directory to load.
  254. @return An array containing all filenames in the `path`, excluding '.' and '..' entries.
  255. #end
  256. Function LoadDir:String[]( path:String )
  257. path=StripSlashes( path )
  258. Local dir:=opendir( path )
  259. If Not dir Return Null
  260. Local files:=New StringStack
  261. Repeat
  262. Local ent:=readdir( dir )
  263. If Not ent Exit
  264. Local file:=String.FromCString( ent[0].d_name )
  265. If file="." Or file=".." Continue
  266. files.Push( file )
  267. Forever
  268. closedir( dir )
  269. Return files.ToArray()
  270. End
  271. #rem monkeydoc Creates a file at a filesystem path.
  272. Any existing file at the path will be overwritten.
  273. @param path The filesystem path of the file file to create.
  274. @param createDir If true, also creates the file directory if necessary.
  275. @return True if a file at the given path was created.
  276. #end
  277. Function CreateFile:Bool( path:String,createDir:Bool=True )
  278. If createDir And Not CreateDir( ExtractDir( path ),True ) Return False
  279. Local f:=fopen( path,"wb" )
  280. If Not f Return False
  281. fclose( f )
  282. Return True
  283. End
  284. #rem monkeydoc Creates a directory at a filesystem path.
  285. @param path The filesystem path of the directory to create.
  286. @param recursive If true, any required parent directories are also created.
  287. @return True if a directory at `path` was successfully created or already existed.
  288. #end
  289. Function CreateDir:Bool( dir:String,recursive:Bool=True )
  290. If recursive
  291. Local parent:=ExtractDir( dir )
  292. If parent And Not IsRootDir( parent )
  293. Select GetFileType( parent )
  294. Case FileType.None
  295. If Not CreateDir( parent,True ) Return False
  296. Case FileType.File
  297. Return False
  298. End
  299. Endif
  300. Endif
  301. mkdir( StripSlashes( dir ),$1ff )
  302. Return GetFileType( dir )=FileType.Directory
  303. End
  304. #rem monkeydoc Deletes a file at a filesystem path.
  305. @param path The filesystem path.
  306. @return True if the file was successfully deleted.
  307. #end
  308. Function DeleteFile:Bool( path:String )
  309. remove( path )
  310. Return GetFileType( path )=FileType.None
  311. End
  312. #rem monkeydoc Deletes a directory at a filesystem path.
  313. @param path The filesystem path.
  314. @param recursive True to delete subdirectories too.
  315. @return True if the directory was successfully deleted or never existed.
  316. #end
  317. Function DeleteDir:Bool( dir:String,recursive:Bool=False )
  318. Select GetFileType( dir )
  319. Case FileType.None
  320. Return True
  321. Case FileType.Directory
  322. If recursive
  323. For Local f:=Eachin LoadDir( dir )
  324. Local p:=dir+"/"+f
  325. Select GetFileType( p )
  326. Case FileType.File
  327. If Not DeleteFile( p ) Return False
  328. Case FileType.Directory
  329. If Not DeleteDir( p,True ) Return false
  330. End
  331. Next
  332. Endif
  333. rmdir( StripSlashes( dir ) )
  334. Return GetFileType( dir )=FileType.None
  335. End
  336. Return False
  337. End
  338. Function CopyDir:Bool( srcDir:String,dstDir:String,recursive:Bool=True )
  339. If GetFileType( srcDir )<>FileType.Directory Return False
  340. If GetFileType( dstDir )<>FileType.Directory And Not CreateDir( dstDir,True ) Return False
  341. For Local f:=Eachin LoadDir( srcDir )
  342. Local src:=srcDir+"/"+f
  343. Local dst:=dstDir+"/"+f
  344. Select GetFileType( src )
  345. Case FileType.File
  346. If Not CopyFile( src,dst ) Return False
  347. Case FileType.Directory
  348. If recursive And Not CopyDir( src,dst ) Return False
  349. End
  350. Next
  351. Return True
  352. End