commit e34038044db5085567c0fcc44eb8459f4e8ed2f7
parent ce95a0ef822e52e0cb01dae88d7f0d4c0b654e00
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Sat, 4 Feb 2023 15:12:18 -0500
sys/file: make Path :iter into an :iterator
Diffstat:
3 files changed, 38 insertions(+), 50 deletions(-)
diff --git a/fs/doc/sys/file.txt b/fs/doc/sys/file.txt
@@ -132,20 +132,22 @@ on to a Path reference a little longer, you should copy it elsewhere.
doesn't start with "/", the search will start from this directory.
Aborts if path is not found.
+:iter ( self -- )
+ Writes an iterator that iterates over all "self"'s children. During yields,
+ "i" is the FSID of the children and "j" is the fsid of the parent (self). A
+ Path structure conveniently wraps "i" and live at ":i".
+
+ Recursion notes: :iter can recurse and it will behave as expected. However,
+ all recursive :iter calls must take place within the same filesystem.
+
+:i ( self -- path )
+ Wraps "i" from :iter in a Path structure.
+
:open ( self -- file )
:info ( self -- file )
:child ( name self -- path-or-0 )
-:iter ( w self -- )
Convenience proxies to the corresponding methods in the Filesystem API.
-:iterdirs ( w self -- )
- Calls :iter but filters the call to 'w' to directories only. On top of this,
- an additional "info" argument is passed to 'w', making its signature
- "id fs info -- "
-
-:iterfiles ( w self -- )
- Same as :iterdirs, but for files.
-
## Global variables
The File subsystem has 2 important global variables:
diff --git a/fs/sys/file.fs b/fs/sys/file.fs
@@ -24,7 +24,7 @@ struct[ Path
create _curpath bootfs , 0 ,
- $100 const BUFSZ
+ $200 const BUFSZ
create _paths BUFSZ SZ * allot
0 value _pathidx
@@ -41,19 +41,15 @@ struct[ Path
r@ id swap r@ fs Filesystem :newfile ( id ) r> fs swap :new ;
: :newdir ( name self -- path ) >r
r@ id swap r@ fs Filesystem :newdir ( id ) r> fs swap :new ;
- : :iter ( w self -- ) dup fs >r swap >r ( self ) \ V1=fs V2=w
- id dup >r 0 V1 Filesystem :iter ( childid ) \ V3=dirid
- begin ?dup while
- dup V1 V2 execute ( childid )
- V3 swap V1 Filesystem :iter repeat
- 2rdrop rdrop ;
-
- : _dir? ( id fs -- info f ) 2dup Filesystem :info dup FSInfo dir? ;
- alias noop _w ( id fs info -- )
- : _ ( id fs -- ) _dir? if _w else 2drop drop then ;
- : :iterdirs ( w self -- ) swap ['] _w realias ['] _ swap :iter ;
- : _ ( id fs -- ) _dir? not if _w else 2drop drop then ;
- : :iterfiles ( w self -- ) swap ['] _w realias ['] _ swap :iter ;
+
+ \ recursive iteration works fine, but *only* within the same FS at once.
+ 0 value _fs
+ 0 value :i
+ :iterator :iter ( self -- )
+ dup fs to _fs id to j 0 to i begin
+ j i _fs Filesystem :iter ?dup while
+ to i _fs i :new to :i yield repeat unyield ;
+
: :remove ( self -- ) dup id swap fs Filesystem :remove ;
: :root ( self -- path ) fs 0 :new ;
@@ -91,28 +87,20 @@ struct[ Path
: :appendfile ( src self -- )
:open dup File size over File :seek swap :open _copyfile ;
-
- \ dst is the *parent* of where the source element will be
- create _dst SZ allot
- create _src SZ allot
- : _ ( id fs -- )
- _src to fs _src to id
- _src :info dup FSInfo name stype nl>
- dup FSInfo dir? if ( info )
- _dst id swap FSInfo name _dst fs Filesystem :?newdir ( id )
- to@! _dst id ( oldid )
- ['] _ _src :iter ( oldid ) to _dst id
- else ( info )
- _dst id swap FSInfo name _dst fs Filesystem :?newfile ( id )
- _dst fs Filesystem :open ( dstfile ) _src :open ( srcfile )
- _copyfile then ;
-
\ For now, this method has to be called on a freshly created directory as
\ "dst". We assume that no destination file or directory exist in dst.
- : :copydir ( dst self -- ) swap _dst SZ move ['] _ swap :iter ;
-
- : _ ( id fs -- ) Filesystem :info FSInfo name stype nl> ;
- : :listdir ( self -- ) ['] _ swap :iter ;
+ : :copydir ( dst self -- ) >r >r \ V1=self V2=dst
+ V1 :iter
+ :i :info dup FSInfo name stype nl>
+ dup FSInfo dir? if ( info )
+ V2 id swap FSInfo name V2 fs Filesystem :?newdir ( id )
+ V2 fs swap :new :i :copydir
+ else ( info )
+ V2 id swap FSInfo name V2 fs Filesystem :?newfile ( id )
+ V2 fs swap :new :i :copyfile then
+ next 2rdrop ;
+
+ : :listdir ( self -- ) :iter :i :info FSInfo name stype nl> next ;
]struct
Path _curpath structbind Path curpath
diff --git a/fs/xcomp/i386/pc/build.fs b/fs/xcomp/i386/pc/build.fs
@@ -30,14 +30,12 @@ org value kernel
\ $00 to fatopts drvnum
( drv ) dup FAT newFAT12 FAT :mountvolume ;
-0 value _dstfs
-: _iterdir ( id fs info -- )
- FSInfo name dup S" doc" s= if 2drop else ( id fs name )
- 0 swap _dstfs Filesystem :newdir ( id fs dstid )
- _dstfs swap Path :new ( id fs dstpath )
- rot> swap Path :new ( dstpath srcpath ) Path :copydir ;
: copyfs ( srcfs dstfs -- )
- to _dstfs 0 Path :new ['] _iterdir swap Path :iterdirs ;
+ 0 Path :new swap 0 Path :new Path :iter ( dst )
+ Path :i Path :info dup FSInfo dir?
+ over FSInfo name S" doc" s= not and if ( dst info )
+ FSInfo name over Path :newdir ( dst newdir )
+ Path :i Path :copydir else drop then next ( dst ) drop ;
$200 const SECSZ \ TODO: get from drive
create _buf SECSZ allot0