Idris2/libs/base/Data/Buffer.idr

277 lines
8.3 KiB
Idris
Raw Normal View History

2020-05-18 15:59:07 +03:00
module Data.Buffer
import System.Directory
2020-05-18 15:59:07 +03:00
import System.File
-- Reading and writing binary buffers. Note that this primitives are unsafe,
-- in that they don't check that buffer locations are within bounds.
-- We really need a safe wrapper!
-- They are used in the Idris compiler itself for reading/writing checked
-- files.
-- This is known to the compiler, so maybe ought to be moved to Builtin
2020-05-18 15:59:07 +03:00
export
data Buffer : Type where [external]
%foreign "scheme:blodwen-buffer-size"
prim__bufferSize : Buffer -> Int
export
2020-07-01 23:55:14 +03:00
rawSize : HasIO io => Buffer -> io Int
2020-05-18 15:59:07 +03:00
rawSize buf = pure (prim__bufferSize buf)
%foreign "scheme:blodwen-new-buffer"
prim__newBuffer : Int -> PrimIO Buffer
export
2020-07-01 23:55:14 +03:00
newBuffer : HasIO io => Int -> io (Maybe Buffer)
2020-05-18 15:59:07 +03:00
newBuffer size
= do buf <- primIO (prim__newBuffer size)
pure $ Just buf
-- if prim__nullAnyPtr buf /= 0
-- then pure Nothing
-- else pure $ Just $ MkBuffer buf size 0
-- might be needed if we do this in C...
export
2020-07-01 23:55:14 +03:00
freeBuffer : HasIO io => Buffer -> io ()
2020-05-18 15:59:07 +03:00
freeBuffer buf = pure ()
%foreign "scheme:blodwen-buffer-setbyte"
prim__setByte : Buffer -> Int -> Int -> PrimIO ()
%foreign "scheme:blodwen-buffer-setbyte"
prim__setBits8 : Buffer -> Int -> Bits8 -> PrimIO ()
2020-05-18 15:59:07 +03:00
-- Assumes val is in the range 0-255
export
2020-07-01 23:55:14 +03:00
setByte : HasIO io => Buffer -> (loc : Int) -> (val : Int) -> io ()
2020-05-18 15:59:07 +03:00
setByte buf loc val
= primIO (prim__setByte buf loc val)
export
2020-07-01 23:55:14 +03:00
setBits8 : HasIO io => Buffer -> (loc : Int) -> (val : Bits8) -> io ()
setBits8 buf loc val
= primIO (prim__setBits8 buf loc val)
2020-05-18 15:59:07 +03:00
%foreign "scheme:blodwen-buffer-getbyte"
prim__getByte : Buffer -> Int -> PrimIO Int
%foreign "scheme:blodwen-buffer-getbyte"
prim__getBits8 : Buffer -> Int -> PrimIO Bits8
2020-05-18 15:59:07 +03:00
export
2020-07-01 23:55:14 +03:00
getByte : HasIO io => Buffer -> (loc : Int) -> io Int
2020-05-18 15:59:07 +03:00
getByte buf loc
= primIO (prim__getByte buf loc)
export
2020-07-01 23:55:14 +03:00
getBits8 : HasIO io => Buffer -> (loc : Int) -> io Bits8
getBits8 buf loc
= primIO (prim__getBits8 buf loc)
%foreign "scheme:blodwen-buffer-setbits16"
prim__setBits16 : Buffer -> Int -> Bits16 -> PrimIO ()
export
2020-07-01 23:55:14 +03:00
setBits16 : HasIO io => Buffer -> (loc : Int) -> (val : Bits16) -> io ()
setBits16 buf loc val
= primIO (prim__setBits16 buf loc val)
%foreign "scheme:blodwen-buffer-getbits16"
prim__getBits16 : Buffer -> Int -> PrimIO Bits16
export
2020-07-01 23:55:14 +03:00
getBits16 : HasIO io => Buffer -> (loc : Int) -> io Bits16
getBits16 buf loc
= primIO (prim__getBits16 buf loc)
%foreign "scheme:blodwen-buffer-setbits32"
prim__setBits32 : Buffer -> Int -> Bits32 -> PrimIO ()
export
2020-07-01 23:55:14 +03:00
setBits32 : HasIO io => Buffer -> (loc : Int) -> (val : Bits32) -> io ()
setBits32 buf loc val
= primIO (prim__setBits32 buf loc val)
%foreign "scheme:blodwen-buffer-getbits32"
prim__getBits32 : Buffer -> Int -> PrimIO Bits32
export
2020-07-01 23:55:14 +03:00
getBits32 : HasIO io => Buffer -> (loc : Int) -> io Bits32
getBits32 buf loc
= primIO (prim__getBits32 buf loc)
%foreign "scheme:blodwen-buffer-setbits64"
prim__setBits64 : Buffer -> Int -> Bits64 -> PrimIO ()
export
2020-07-01 23:55:14 +03:00
setBits64 : HasIO io => Buffer -> (loc : Int) -> (val : Bits64) -> io ()
setBits64 buf loc val
= primIO (prim__setBits64 buf loc val)
%foreign "scheme:blodwen-buffer-getbits64"
prim__getBits64 : Buffer -> Int -> PrimIO Bits64
export
2020-07-01 23:55:14 +03:00
getBits64 : HasIO io => Buffer -> (loc : Int) -> io Bits64
getBits64 buf loc
= primIO (prim__getBits64 buf loc)
2020-05-19 19:03:18 +03:00
%foreign "scheme:blodwen-buffer-setint32"
prim__setInt32 : Buffer -> Int -> Int -> PrimIO ()
export
2020-07-01 23:55:14 +03:00
setInt32 : HasIO io => Buffer -> (loc : Int) -> (val : Int) -> io ()
2020-05-19 19:03:18 +03:00
setInt32 buf loc val
= primIO (prim__setInt32 buf loc val)
%foreign "scheme:blodwen-buffer-getint32"
prim__getInt32 : Buffer -> Int -> PrimIO Int
export
2020-07-01 23:55:14 +03:00
getInt32 : HasIO io => Buffer -> (loc : Int) -> io Int
2020-05-19 19:03:18 +03:00
getInt32 buf loc
= primIO (prim__getInt32 buf loc)
2020-05-18 15:59:07 +03:00
%foreign "scheme:blodwen-buffer-setint"
prim__setInt : Buffer -> Int -> Int -> PrimIO ()
export
2020-07-01 23:55:14 +03:00
setInt : HasIO io => Buffer -> (loc : Int) -> (val : Int) -> io ()
2020-05-18 15:59:07 +03:00
setInt buf loc val
= primIO (prim__setInt buf loc val)
%foreign "scheme:blodwen-buffer-getint"
prim__getInt : Buffer -> Int -> PrimIO Int
export
2020-07-01 23:55:14 +03:00
getInt : HasIO io => Buffer -> (loc : Int) -> io Int
2020-05-18 15:59:07 +03:00
getInt buf loc
= primIO (prim__getInt buf loc)
%foreign "scheme:blodwen-buffer-setdouble"
prim__setDouble : Buffer -> Int -> Double -> PrimIO ()
export
2020-07-01 23:55:14 +03:00
setDouble : HasIO io => Buffer -> (loc : Int) -> (val : Double) -> io ()
2020-05-18 15:59:07 +03:00
setDouble buf loc val
= primIO (prim__setDouble buf loc val)
%foreign "scheme:blodwen-buffer-getdouble"
prim__getDouble : Buffer -> Int -> PrimIO Double
export
2020-07-01 23:55:14 +03:00
getDouble : HasIO io => Buffer -> (loc : Int) -> io Double
2020-05-18 15:59:07 +03:00
getDouble buf loc
= primIO (prim__getDouble buf loc)
-- Get the length of a string in bytes, rather than characters
export
%foreign "C:strlen,libc 6"
stringByteLength : String -> Int
%foreign "scheme:blodwen-buffer-setstring"
prim__setString : Buffer -> Int -> String -> PrimIO ()
export
2020-07-01 23:55:14 +03:00
setString : HasIO io => Buffer -> (loc : Int) -> (val : String) -> io ()
2020-05-18 15:59:07 +03:00
setString buf loc val
= primIO (prim__setString buf loc val)
%foreign "scheme:blodwen-buffer-getstring"
prim__getString : Buffer -> Int -> Int -> PrimIO String
export
2020-07-01 23:55:14 +03:00
getString : HasIO io => Buffer -> (loc : Int) -> (len : Int) -> io String
2020-05-18 15:59:07 +03:00
getString buf loc len
= primIO (prim__getString buf loc len)
2020-07-01 23:55:14 +03:00
2020-05-18 15:59:07 +03:00
export
2020-07-01 23:55:14 +03:00
bufferData : HasIO io => Buffer -> io (List Int)
2020-05-18 15:59:07 +03:00
bufferData buf
= do len <- rawSize buf
unpackTo [] len
where
2020-07-01 23:55:14 +03:00
unpackTo : List Int -> Int -> io (List Int)
2020-05-18 15:59:07 +03:00
unpackTo acc 0 = pure acc
unpackTo acc loc
= do val <- getByte buf (loc - 1)
unpackTo (val :: acc) (loc - 1)
2020-07-01 23:55:14 +03:00
2020-05-18 15:59:07 +03:00
%foreign "scheme:blodwen-buffer-copydata"
prim__copyData : Buffer -> Int -> Int -> Buffer -> Int -> PrimIO ()
export
2020-07-01 23:55:14 +03:00
copyData : HasIO io => (src : Buffer) -> (start, len : Int) ->
(dest : Buffer) -> (loc : Int) -> io ()
2020-05-18 15:59:07 +03:00
copyData src start len dest loc
= primIO (prim__copyData src start len dest loc)
%foreign "C:idris2_readBufferData,libidris2_support"
prim__readBufferData : FilePtr -> Buffer -> Int -> Int -> PrimIO Int
%foreign "C:idris2_writeBufferData,libidris2_support"
prim__writeBufferData : FilePtr -> Buffer -> Int -> Int -> PrimIO Int
2020-05-18 15:59:07 +03:00
export
2020-07-01 23:55:14 +03:00
readBufferData : HasIO io => File -> Buffer ->
(loc : Int) -> -- position in buffer to start adding
(maxbytes : Int) -> -- maximums size to read, which must not
-- exceed buffer length
2020-07-01 23:55:14 +03:00
io (Either FileError ())
readBufferData (FHandle h) buf loc max
= do read <- primIO (prim__readBufferData h buf loc max)
if read >= 0
then pure (Right ())
else pure (Left FileReadError)
2020-05-18 15:59:07 +03:00
export
2020-07-01 23:55:14 +03:00
writeBufferData : HasIO io => File -> Buffer ->
(loc : Int) -> -- position in buffer to write from
(maxbytes : Int) -> -- maximums size to write, which must not
-- exceed buffer length
2020-07-01 23:55:14 +03:00
io (Either FileError ())
writeBufferData (FHandle h) buf loc max
= do written <- primIO (prim__writeBufferData h buf loc max)
if written >= 0
then pure (Right ())
else pure (Left FileWriteError)
2020-05-18 15:59:07 +03:00
export
2020-07-01 23:55:14 +03:00
writeBufferToFile : HasIO io => String -> Buffer -> Int -> io (Either FileError ())
2020-05-18 15:59:07 +03:00
writeBufferToFile fn buf max
= do Right f <- openFile fn WriteTruncate
| Left err => pure (Left err)
Right ok <- writeBufferData f buf 0 max
| Left err => pure (Left err)
closeFile f
pure (Right ok)
export
2020-07-01 23:55:14 +03:00
createBufferFromFile : HasIO io => String -> io (Either FileError Buffer)
createBufferFromFile fn
= do Right f <- openFile fn Read
| Left err => pure (Left err)
Right size <- fileSize f
| Left err => pure (Left err)
Just buf <- newBuffer size
| Nothing => pure (Left FileReadError)
Right ok <- readBufferData f buf 0 size
| Left err => pure (Left err)
closeFile f
pure (Right buf)
2020-05-18 15:59:07 +03:00
export
2020-07-01 23:55:14 +03:00
resizeBuffer : HasIO io => Buffer -> Int -> io (Maybe Buffer)
2020-05-18 15:59:07 +03:00
resizeBuffer old newsize
= do Just buf <- newBuffer newsize
| Nothing => pure Nothing
-- If the new buffer is smaller than the old one, just copy what
-- fits
oldsize <- rawSize old
let len = if newsize < oldsize then newsize else oldsize
copyData old 0 len buf 0
freeBuffer old
pure (Just buf)