\ dbframework

needs core-ext
needs dbfwstruct

: db-open  ( mode db -- )
    >r
    0. r@ db.ref!  \ null ref if not open
    r@ db.zname@ >abs   r@ db.card@
    DmFindDatabase    ( mode dbID. )
    2dup  r@ db.id!         ( mode dbID. )
    2dup or 0=  -38 and  throw
    r@ db.card@ DmOpenDatabase
    2dup or 0= if
        DmGetLastErr throw
    then
    r> db.ref! ;

: db-open-rw  ( db -- )
    3 over db-open 
    false swap (db.readonly) ! ;

: db-open-ro  ( db -- )
    1 over db-open
    true swap (db.readonly) ! ; 

: db-create  ( db -- )
    dup >r db.isrsrc?
    r@ db.type@
    r@ db.creator@
    r@ db.zname@ >abs
    r@ db.card@
    DmCreateDatabase throw 
    r> db-open-rw ;

: db-close  ( db -- )
    >r
    r@ db.ref@ or if
        r@ db.ref@
        DmCloseDatabase throw
        0. r@ db.ref!
    then
    r> drop ;

: db-lock-rec  ( rechandle. db -- )
    >r
    2dup or 0= if
        DmGetLastErr throw
    then      ( rechandle. )
    2dup r@ db.rec.h!
    MemHandleLock  r> db.rec.ptr! ;

: db-create-rec
    ( size recindex db -- )
    dup >r db.rec.ndx!
    u>ud         ( size. )
    r@ (db.rec.ndx) >abs
    r@ db.ref@ 
    DmNewRecord
    r@ db-lock-rec 
    r> mark-dirty ;

: db-open-rec-rw  ( recindex db -- )
    dup >r db.ref@    ( recindex dbr. )
    DmGetRecord       ( rechandle. )
    r@ db-lock-rec
    r> mark-fresh ;

: db-open-rec-ro  ( recindex db -- )
    dup >r db.ref@   ( recindex dbr. )
    DmQueryRecord   ( rechandle. )
    r@ db-lock-rec
    r> mark-fresh ;

\ Note: must have an open record to
\ call this function, or we'll crash.
: db-rec-size  ( db -- recsize. )
    db.rec.h@ MemHandleSize ;

: db-rec-count  ( db -- #records )
    db.ref@  DmNumRecords ;

: db-open-rec  ( recindex db -- )
    dup db.readonly? if
        db-open-rec-ro
    else
        db-open-rec-rw
    then ;

: db-close-rec-rw  ( db -- )
    dup >r db.rec.h@  
    ( memhandle. )
    MemHandleUnlock throw
    r@ db.rec.dirty?
    r@ db.rec.ndx@
    r> db.ref@
    DmReleaseRecord throw ;

: db-close-rec-ro  ( db -- )
    db.rec.h@  
    ( memhandle. )
    MemHandleUnlock throw ;

: db-close-rec  ( db -- )
    dup db.readonly? if
        db-close-rec-ro
    else
        db-close-rec-rw
    then ;

: db-rec-remove  ( rec# db -- )
    db.ref@ DmRemoveRecord throw ;

: db-write-rec-rw
    ( src-addr len offset db -- )
    >r >r  swap >r    ( len )
    u>ud    r>  >abs   ( len. src-addr. )
    r> u>ud      ( len. src-addr. offset. )
    r@ db.rec.ptr@
    DmWrite throw 
    r> mark-dirty ;

: db-write-rec
    ( src-addr len offset db -- )
    dup db.readonly? if
        2drop 2drop
    else
        db-write-rec-rw
    then ;
variable tempbyte
: c!db  ( byte offset db -- )
    >r >r  tempbyte c! 
    tempbyte  1  r>   ( adr len offset )
    r> db-write-rec ;   

: db-init
( resDB? type. creator. zname db -- )
    dup >r  
    [ sizeof Database: ] literal  erase
    r@ (db.zname) !
    r@ (db.creator) 2!
    r@ (db.type) 2!
    r> (db.isrsrc) ! ;


\ needs zstrings
\ needs ids
\ Database: foo
\ : n z" davestest" drop ;
\ 0 (id) JunK (id) dAvE n foo db-init


