---------------------------------------------------------------- -- Daan Leijen (c) 2001 -- -- $Revision: 285 $ -- $Author: uust $ -- $Date: 2004-02-14 15:46:23 +0100 (Sat, 14 Feb 2004) $ ---------------------------------------------------------------- module LvmIO( Input, Output, Channel, Descriptor , stdin, stdout, stderr , flush, close , outputChar, outputPacked, outputString , inputChar , CreateMode(..), openInputFile, openOutputFile ) where import LvmLang( primIO, packedLength, packedFromString, bindIO, unsafePerformStrictIO, False, True ) {---------------------------------------------------------- Primitive I/O operations ----------------------------------------------------------} extern prim_open :: "IzII" extern prim_close :: "vI" extern prim_flag_mask :: "II" extern prim_input_flags :: "II" extern prim_output_flags :: "III" extern prim_open_descriptor :: "aIb" extern prim_close_channel :: "va" extern prim_set_binary_mode :: "vab" extern prim_flush_partial :: "ba" extern prim_flush :: "va" extern prim_output_char :: "vac" extern prim_output :: "vazll" extern prim_input_char :: "Ia" {---------------------------------------------------------- Channels ----------------------------------------------------------} data Input data Output data Channel a type Descriptor = Int {---------------------------------------------------------- Private helpers ----------------------------------------------------------} primOpenInputDescriptor :: Descriptor -> Channel Input primOpenInputDescriptor fd = let! fd = fd in prim_open_descriptor fd False primOpenOutputDescriptor :: Descriptor -> Channel Output primOpenOutputDescriptor fd = let! fd = fd in prim_open_descriptor fd True {---------------------------------------------------------- Files ----------------------------------------------------------} data CreateMode = CreateNever -- don't create a new file, and append writes | CreateIfNotExists -- create one if none exists yet, append otherwise | CreateExclusive -- create if none exists, but fail if a file exists | CreateOverwrite -- destroy previous file, and create a new one {---------------------------------------------------------- Private file operations ----------------------------------------------------------} data OpenFlag = OpenReadOnly | OpenWriteOnly | OpenCreate | OpenTruncate | OpenExclusive | OpenBinary | OpenText | OpenNonBlocking primOpenInputFile :: FilePath -> Bool -> Channel Input primOpenInputFile fpath asText = let! b = asText m = prim_input_flags b fname = packedFromString fpath fd = prim_open fname m 0o744 in primOpenInputDescriptor fd primOpenOutputFile :: FilePath -> Bool -> CreateMode -> Channel Output primOpenOutputFile fpath asText cmode = let! b = asText c = cmode m = prim_output_flags b c fname = packedFromString fpath fd = prim_open fname m 0o744 in primOpenOutputDescriptor fd {---------------------------------------------------------- Channel I/O, based on the OCaml interface ----------------------------------------------------------} stdin :: Channel Input stdin = primOpenInputDescriptor 0 stdout :: Channel Output stdout = primOpenOutputDescriptor 1 stderr :: Channel Output stderr = primOpenOutputDescriptor 2 openInputFile :: FilePath -> Bool -> IO (Channel Input) openInputFile fpath asText = let action _ = primOpenInputFile fpath asText in primIO action openOutputFile :: FilePath -> Bool -> CreateMode -> IO (Channel Output) openOutputFile fpath asText createMode = let action _ = primOpenOutputFile fpath asText createMode in primIO action {-------------------------------------------------------------------------- Channel operations --------------------------------------------------------------------------} flush :: Channel Output -> IO () flush out = let action _ = (let! out = out in prim_flush out) in primIO action close :: Channel a -> IO () close chan = let action _ = (let! chan = chan in prim_close_channel chan) in primIO action outputChar :: Channel Output -> Char -> IO () outputChar out c = let action _ = let! out = out c = c in prim_output_char out c in primIO action inputChar :: Channel Input -> IO Char inputChar inp = let action _ = let! inp = inp in prim_input_char inp in primIO action outputPacked :: Channel Output -> PackedString -> IO () outputPacked chan s = let action _ = let! chan = chan s = s len = packedLength s in prim_output chan s 0 len in primIO action -- TODO: use direct I/O primitive for strings outputString :: Channel Output -> String -> IO () outputString chan s = outputPacked chan (packedFromString s)