M fs/fs/fat.fs => fs/fs/fat.fs +10 -14
@@ 99,22 99,14 @@ $e5 const DIRFREE
drop r@ allocatecluster ( cl ncl ) tuck swap r@ FAT! ( cl ncl )
else nip then rdrop ;
-\ try to find in current buffer
-: _findinsec ( self -- a-or-0 )
- r! :dirwin :buf( begin ( a ) \ V1=self
- dup c@ dup DIRFREE = swap not or if ( free! ) rdrop exit then
- DirEntry SZ + dup r@ :dirwin :)buf >= until rdrop drop 0 ;
-
\ find free dir entry in current buffer
: findfreedirentry ( self -- direntry )
- begin
- dup _findinsec ?dup not while ( self )
- dup :nextsector? while
- repeat \ nothing found, we have to extend the chain
- ( self ) dup >r allocatecluster0 ( newcl )
- r@ bufcluster r@ FAT! ( newcl )
- r@ :nextsector? drop ( has to work ) r> :dirwin :buf(
- else ( self a ) nip then ;
+ dup :iterdirentry i c@ bi DIRFREE = | not or if i break then next
+ ( self ) dup :nextcluster? if findfreedirentry else ( self )
+ \ nothing found, we have to extend the chain
+ r! allocatecluster0 ( newcl ) r@ bufcluster r@ FAT! ( newcl )
+ r@ :nextcluster? cl# r> :dirwin :buf( then
+ else ( self a ) nip then ;
: _newentry ( dirid name self -- direntry ) >r
fnbuf! ( dirid ) r@ :getdirentry r@ :readdir ( )
@@ 197,6 189,10 @@ $e5 const DIRFREE
: fatremove ( id self -- )
tuck :getdirentry ( dirent ) DIRFREE swap c! writecursector ;
+\ Read next sector if a sequential read is available, else return false.
+: :nextsector? ( self -- f )
+ dup :dirwin :next if 2drop 1 else :nextcluster? then ;
+
\ This approach to iteration is inefficient, but simple. I keep it as-is for now
: _next ( entry self -- entry-or-0 ) >r \ V1=self
DirEntry SZ + dup V1 :dirwin :)buf = if
M fs/fs/fatlo.fs => fs/fs/fatlo.fs +13 -14
@@ 96,22 96,21 @@ $18 const HDRSZ
: :EOC? ( cluster self -- f ) :FAT12? if $ff8 else $fff8 then tuck and = ;
-\ Read next sector if a sequential read is available, else return false.
-: :nextsector? ( self -- f )
- dup :dirwin :next if 2drop 1 else ( self ) \ try next cluster
- bi+ bufcluster | :FAT@ swap 2dup :EOC? if 2drop 0 else ( cl self )
- 2dup to bufcluster tuck :FirstSectorOfCluster ( self sec )
- over secpercluster rot :readsector 1 then then ;
+: :nextcluster? ( self -- f )
+ bi+ bufcluster | :FAT@ swap 2dup :EOC? if 2drop 0 else ( cl self )
+ 2dup to bufcluster tuck :FirstSectorOfCluster ( self sec )
+ over secpercluster rot :readsector 1 then ;
+
+:iterator :iterdirentry ( self -- )
+ to j 0 to k begin
+ k j :dirwin :seek while to i yield DirEntry SZ to+ k repeat unyield ;
\ Find current fnbuf( in current dir buffer and return a dir entry.
-: :findindir ( self -- direntry-or-0 ) >r
- begin
- r@ :dirwin :buf( begin ( a )
- dup r@ :dirwin :)buf < while ( a )
- fnbuf( over DirEntry :name[] []= not while ( a ) DirEntry SZ + repeat
- ( success ) else ( not found ) drop 0 then ( a )
- ?dup not while r@ :nextsector? while
- repeat ( not found ) 0 then rdrop ;
+: :findindir ( self -- direntry-or-0 )
+ dup :iterdirentry
+ fnbuf( i DirEntry :name[] []= if i break then next
+ ( self ) dup :nextcluster? if :findindir else drop 0 then
+ else ( self i ) nip then ;
\ Read specified "direntry" in :buf(
: :readdir ( direntry self -- ) >r