~vdupras/duskos

ae2001a9e052545edb974070ea2bfbc651f30aa7 — Virgil Dupras 1 year, 6 months ago 50af071
fs/fat: consolidate

Come over here and tell me that these iterator thingies aren't freaking
awesome?!
2 files changed, 23 insertions(+), 28 deletions(-)

M fs/fs/fat.fs
M fs/fs/fatlo.fs
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