filesystem.monkey2 11 KB

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