PreviousUpNext

15.4.1253  src/lib/std/src/win32/winix-text-file-io-driver-for-win32–premicrothread.pkg

## winix-text-file-io-driver-for-win32--premicrothread.pkg
#
# Here we implement win32-specific text file I/O support.  
#
# This file gets used in:
#
#     src/lib/std/src/win32/winix-text-file-for-win32--premicrothread.pkg
#
# Compare to:
#
#     src/lib/std/src/win32/winix-data-file-io-driver-for-win32--premicrothread.pkg
#     src/lib/std/src/posix/winix-text-file-io-driver-for-posix--premicrothread.pkg
#     src/lib/src/lib/thread-kit/src/win32/winix-data-file-io-driver-for-win32.pkg
#

local
    package one_word_unt = Word32Imp
    package os = winix_guts
    package string = StringImp
    package int = int_guts
in
package winix_text_file_io_driver_for_win32__premicrothread
:
api
    include api Winix_Base_File_Io_Driver_For_Os__Premicrothread

    my stdin:   Void -> filereaders_and_filewriters::Reader
    my stdout:  Void -> filereaders_and_filewriters::Writer
    my stderr:  Void -> filereaders_and_filewriters::Writer

    my string_reader:  String -> filereaders_and_filewriters::Reader
end
{
        package drv = winix_base_text_file_io_driver_for_posix__premicrothread

        package W32FS = Win32::file_system
        package W32IO = Win32::IO
        package W32G = Win32::general

        package v = vector_of_chars

        type File_Descriptor = W32G::hndl

        say = W32G::logMsg

        fun announce s x y = (
# *         say "announce winix_text_file_io_driver_for_win32__premicrothread: "; say (s: String); say "\n"; *
             x y)

        bufferSzB = 4096

        fun mkReader { initablekMode=FALSE, ... } = 
            raise exception DIE "Nonblocking IO not supported";         # We never support blocking I/O these days, so this code will need rewriting.
          | mkReader { fd, name, initablekMode } = 
            let closed = REF FALSE
                fun ensureOpen f x = 
                    if *closed then raise exception io::CLOSED_IO_STREAM else f x
                blocking = REF initablekMode
                iod = W32FS::hndlToIOD fd
                fun readVec n = announce "readVecTxt" 
                                  W32IO::readVecTxt (W32FS::IODToHndl iod, n)
                fun readArr arg = announce "readArrTxt" 
                                    W32IO::readArrTxt (W32FS::IODToHndl iod, arg)
                fun close () = 
                    if *closed then ()
                    else (closed:=TRUE; announce "close" 
                                          W32IO::close (W32FS::IODToHndl iod))
            in
                drv::FILEREADER {
                    name = name,
                    chunkSize = bufferSzB,
                    readVec = THE (ensureOpen readVec),
                    readArr = THE (ensureOpen readArr),
                    readVecNB = NULL,
                    readArrNB = NULL,
                    block = NULL,
                    max_readable_without_blocking = NULL,
                    avail = \\ () => NULL,
                    getPos = NULL,
                    setPos = NULL,
                    endPos = NULL,
                    verifyPos = NULL,
                    close = close,
                    ioDesc = THE iod
                }
            end

        shareAll = one_word_unt::bitwise_or (W32IO::FILE_SHARE_READ,
                                  W32IO::FILE_SHARE_WRITE)

        fun checkHndl name h = 
            if W32G::isValidHandle h then h
            else raise exception winix__premicrothread::RUNTIME_EXCEPTION ("winix_text_file_io_driver_for_win32__premicrothread:"$name$": failed", NULL)

        fun openRd name = 
            mkReader {
                fd = checkHndl "openRd" 
                               (announce "createFile" 
                                         W32IO::createFile {
                                             name=name,
                                             access=W32IO::GENERIC_READ,
                                             share=shareAll,
                                             mode=W32IO::OPEN_EXISTING,
                                             attributes=0wx0
                                         } ),
                name = name,
                initablekMode = TRUE
            }

        fun mkWriter { initablekMode=FALSE, ... } =
            raise exception DIE "Nonblocking IO not supported";         # We never support blocking I/O these days, so this code will need rewriting.
          | mkWriter { fd, name, initablekMode, appendMode, chunkSize } = 
            let closed = REF FALSE
                blocking = REF initablekMode
                fun ensureOpen () = 
                    if *closed then raise exception io::CLOSED_IO_STREAM else ()
                iod = W32FS::hndlToIOD fd
                fun writeVec v = announce "writeVec" 
                                   W32IO::writeVecTxt (W32FS::IODToHndl iod, v)
                fun writeArr v = announce "writeArr" 
                                   W32IO::writeArrTxt (W32FS::IODToHndl iod, v)
                fun close () = 
                    if *closed then ()
                    else (closed:=TRUE; 
                          announce "close" 
                            W32IO::close (W32FS::IODToHndl iod))
            in
                drv::FILEWRITER {
                          name          = name,
                          chunkSize     = chunkSize,
                          writeVec      = THE writeVec,
                          writeArr      = THE writeArr,
                          writeVecNB    = NULL,
                          writeArrNB    = NULL,
                          block         = NULL,
                          canOutput     = NULL,
                          getPos        = NULL,
                          setPos        = NULL,
                          endPos        = NULL,
                          verifyPos     = NULL,
                          close         = close,
                          ioDesc        = THE iod
                         }
            end

        fun openWr name = 
            mkWriter {
                fd = checkHndl "openWr" 
                               (announce "createFile" 
                                         W32IO::createFile {
                                             name=name,
                                             access=W32IO::GENERIC_WRITE,
                                             share=shareAll,
                                             mode=W32IO::CREATE_ALWAYS,
                                             attributes=W32FS::FILE_ATTRIBUTE_NORMAL
                                         } ),
                name = name,
                initablekMode = TRUE,
                appendMode = FALSE,
                chunkSize = bufferSzB
            }

        fun openApp name = 
            let h = checkHndl "openApp" 
                                  (announce "createFile" 
                                            W32IO::createFile {
                                                name=name,
                                                access=W32IO::GENERIC_WRITE,
                                                share=shareAll,
                                                mode=W32IO::OPEN_EXISTING,
                                                attributes=W32FS::FILE_ATTRIBUTE_NORMAL
                                            } )
                announce "setFilePointer'"
                                 W32IO::setFilePointer' (h, 0wx0, W32IO::FILE_END)
            in
                mkWriter {
                    fd = h,
                    name = name,
                    initablekMode = TRUE,
                    appendMode = TRUE,
                    chunkSize = bufferSzB
                }
            end

        fun stdin () = 
            let h = W32IO::getStdHandle (W32IO::STD_INPUT_HANDLE)
            in
                if W32G::isValidHandle h then
                    mkReader { fd = h,
                             name = "<stdin>",
                             initablekMode = TRUE }
        
                else
                    raise exception winix__premicrothread::RUNTIME_EXCEPTION("winix_text_file_io_driver_for_win32__premicrothread: can't get stdin", NULL)
            end

        fun stdout () = 
            let h = W32IO::getStdHandle (W32IO::STD_OUTPUT_HANDLE)
            in
                if W32G::isValidHandle h then
                    mkWriter { fd = h,
                             name = "<stdout>",
                             initablekMode = TRUE,
                             appendMode = TRUE,
                             chunkSize = bufferSzB }
                else
                    raise exception winix__premicrothread::RUNTIME_EXCEPTION("winix_text_file_io_driver_for_win32__premicrothread: can't get stdout", NULL)
            end

        fun stderr () = 
            let h = W32IO::getStdHandle (W32IO::STD_ERROR_HANDLE)
            in
                if W32G::isValidHandle h then
                    mkWriter { fd = h,
                             name = "<stderr>",
                             initablekMode = TRUE,
                             appendMode = TRUE,
                             chunkSize = bufferSzB }
                else
                    raise exception winix__premicrothread::RUNTIME_EXCEPTION("winix_text_file_io_driver_for_win32__premicrothread: can't get stderr", NULL)
            end

        
        fun string_reader src = #  stolen wholesale from winix-text-file-io-driver-for-posix--premicrothread.pkg 
            let pos = REF 0
                closed = REF FALSE
                fun checkClosed () = if *closed then raise exception io::CLOSED_IO_STREAM else ()
                len = string::size src
                fun avail () = (len - *pos)
                fun readV n = 
                    let p = *pos
                        m = int::min (n, len-p)
                    in
                        checkClosed ();
                        pos := p+m;
                        # * NOTE: could use unchecked operations here *
                        string::substring (src, p, m)
                    end
                fun readA asl = 
                    let p = *pos
                        my (buf, i, n) = rw_vector_slice_of_chars::base asl
                        m = int::min (n, len - p)
                    in
                        checkClosed ();
                        pos := p+m;
                        rw_vector_slice_of_chars::copyVec { src = vector_slice_of_chars::slice
                                                           (src, p, THE m),
                                                 dst = buf, di = i };
                        m
                    end
                fun getPos () = (checkClosed(); *pos)
            in
                drv::FILEREADER {
                    name      = "<string>", 
                    chunkSize = len,
                    readVec   = THE readV,
                    readArr   = THE readA,
                    readVecNB = THE (THE o readV),
                    readArrNB = THE (THE o readA),
                    block     = THE checkClosed,
                    max_readable_without_blocking  = THE (\\ () => (checkClosed(); TRUE)),
                    avail     = THE o avail,
                    getPos    = THE getPos,
                    setPos    = THE (\\ i => (checkClosed();
                                              if (i < 0) or (len < i)
                                                  then raise exception INDEX_OUT_OF_BOUNDS
                                              
                                              pos := i)),
                    endPos    = THE (\\ () => (checkClosed(); len)),
                    verifyPos = THE getPos,
                    close     = \\ () => closed := TRUE,
                    ioDesc    = NULL
                }
            end

    }
end



Comments and suggestions to: bugs@mythryl.org

PreviousUpNext