unix-bytestring-0.3.2: Unix/Posix-specific functions for ByteStrings.

Portabilitynon-portable (POSIX.1, XPG4.2; hsc2hs, FFI)
Stabilityexperimental
Maintainerwren@community.haskell.org

System.Posix.IO.ByteString

Contents

Description

Provides a strict-ByteString file-descriptor based I/O API, designed loosely after the String file-descriptor based I/O API in System.Posix.IO. The functions here wrap standard C implementations of the functions specified by the ISO/IEC 9945-1:1990 (``POSIX.1'') and X/Open Portability Guide Issue 4, Version 2 (``XPG4.2'') specifications.

Synopsis

I/O with file descriptors

Reading

The POSIX.1 read(2) syscall

fdReadSource

Arguments

:: Fd 
-> ByteCount

How many bytes to try to read.

-> IO ByteString

The bytes read.

Read data from an Fd and convert it to a ByteString. Throws an exception if this is an invalid descriptor, or EOF has been reached.

This is essentially equivalent to the POSIX.1 read(2) system call; the differences are that we allocate a byte buffer for the ByteString (and then pass its underlying Ptr Word8 and ByteCount components to fdReadBuf), and that we detect EOF and throw an IOError.

fdReadBufSource

Arguments

:: Fd 
-> Ptr Word8

Memory in which to put the data.

-> ByteCount

How many bytes to try to read.

-> IO ByteCount

How many bytes were actually read (zero for EOF).

Read data from an Fd into memory. This is exactly equivalent to the POSIX.1 read(2) system call.

TODO: better documentation.

fdReadsSource

Arguments

:: (ByteCount -> a -> Maybe a)

A stateful predicate for retrying.

-> a

An initial state for the predicate.

-> Fd 
-> ByteCount

How many bytes to try to read.

-> IO ByteString

The bytes read.

Read data from an Fd and convert it to a ByteString. Throws an exception if this is an invalid descriptor, or EOF has been reached.

This version takes a kind of stateful predicate for whether and how long to keep retrying. Assume the function is called as fdReads f z0 fd n0. We will attempt to read n0 bytes from fd. If we fall short, then we will call f len z where len is the total number of bytes read so far and z is the current state (initially z0). If it returns Nothing then we will give up and return the current buffer; otherwise we will retry with the new state, continuing from where we left off.

For example, to define a function that tries up to n times, we can use:

 fdReadUptoNTimes :: Int -> Fd -> ByteCount -> IO ByteString
 fdReadUptoNTimes n0
     | n0 <= 0   = \_ _ -> return empty
     | otherwise = fdReads retry n0
     where
     retry _ 0 = Nothing
     retry _ n = Just $! n-1

The benefit of doing this instead of the naive approach of calling fdRead repeatedly is that we only need to allocate one byte buffer, and trim it once at the end--- whereas the naive approach would allocate a buffer, trim it to the number of bytes read, and then concatenate with the previous one (another allocation, plus copying everything over) for each time around the loop.

The XPG4.2 readv(2) syscall

fdReadvBufSource

Arguments

:: Fd 
-> Ptr CIovec

A C-style array of buffers to fill.

-> Int

How many buffers there are.

-> IO ByteCount

How many bytes were actually read (zero for EOF).

Read data from an Fd and scatter it into memory. This is exactly equivalent to the XPG4.2 readv(2) system call.

TODO: better documentation.

The XPG4.2 pread(2) syscall

fdPreadSource

Arguments

:: Fd 
-> ByteCount

How many bytes to try to read.

-> FileOffset

Where to read the data from.

-> IO ByteString

The bytes read.

Read data from a specified position in the Fd and convert it to a ByteString, without altering the position stored in the Fd. Throws an exception if this is an invalid descriptor, or EOF has been reached.

This is essentially equivalent to the XPG4.2 pread(2) system call; the differences are that we allocate a byte buffer for the ByteString (and then pass its underlying Ptr Word8 and ByteCount components to fdPreadBuf), and that we detect EOF and throw an IOError.

fdPreadBufSource

Arguments

:: Fd 
-> Ptr Word8

Memory in which to put the data.

-> ByteCount

How many bytes to try to read.

-> FileOffset

Where to read the data from.

-> IO ByteCount

How many bytes were actually read (zero for EOF).

Read data from a specified position in the Fd into memory, without altering the position stored in the Fd. This is exactly equivalent to the XPG4.2 pread(2) system call.

TODO: better documentation.

fdPreadsSource

Arguments

:: (ByteCount -> a -> Maybe a)

A stateful predicate for retrying.

-> a

An initial state for the predicate.

-> Fd 
-> ByteCount

How many bytes to try to read.

-> FileOffset

Where to read the data from.

-> IO ByteString

The bytes read.

Read data from a specified position in the Fd and convert it to a ByteString, without altering the position stored in the Fd. Throws an exception if this is an invalid descriptor, or EOF has been reached. This is a pread(2) based version of fdReads; see that function for more details.

Writing

The POSIX.1 write(2) syscall

fdWriteSource

Arguments

:: Fd 
-> ByteString

The string to write.

-> IO ByteCount

How many bytes were actually written.

Write a ByteString to an Fd. The return value is the total number of bytes actually written. This is exactly equivalent to the POSIX.1 write(2) system call; we just convert the ByteString into its underlying Ptr Word8 and ByteCount components for passing to fdWriteBuf.

fdWriteBufSource

Arguments

:: Fd 
-> Ptr Word8

Memory containing the data to write.

-> ByteCount

How many bytes to try to write.

-> IO ByteCount

How many bytes were actually written.

Write data from memory to an Fd. This is exactly equivalent to the POSIX.1 write(2) system call.

TODO: better documentation.

fdWritesSource

Arguments

:: Fd 
-> [ByteString]

The strings to write.

-> IO (ByteCount, ByteCount, [ByteString])

The total number of bytes written, the number of bytes written from the first of the remaining strings, the remaining (unwritten) strings.

Write a sequence of ByteStrings to an Fd. The return value is a triple of: the total number of bytes written, the number of bytes written from the first of the remaining strings, and the remaining (unwritten) strings. We return this triple instead of a pair adjusting the head of the remaining strings (i.e., removing the bytes already written) in case there is some semantic significance to the way the input is split into chunks.

This version consumes the list lazily and will call the write(2) system call once for each ByteString. This laziness allows the early parts of the list to be garbage collected and prevents needing to hold the whole list of ByteStrings in memory at once. Compare against fdWritev.

The XPG4.2 writev(2) syscall

fdWritevSource

Arguments

:: Fd 
-> [ByteString]

The strings to write.

-> IO ByteCount

How many bytes were actually written.

Write a sequence of ByteStrings to an Fd. The return value is the total number of bytes written. Unfortunately the writev(2) system call does not provide enough information to return the triple that fdWrites does.

This version will force the spine of the list, convert each ByteString into an iovec, and then call the writev(2) system call. This means we only make one system call, which reduces the overhead of performing context switches. But it also means that we must store the whole list of ByteStrings in memory at once, and that we must perform some allocation and conversion. Compare against fdWrites.

fdWritevBufSource

Arguments

:: Fd 
-> Ptr CIovec

A C-style array of buffers to write.

-> Int

How many buffers there are.

-> IO ByteCount

How many bytes were actually written.

Write data from memory to an Fd. This is exactly equivalent to the XPG4.2 writev(2) system call.

TODO: better documentation.

The XPG4.2 pwrite(2) syscall

fdPwriteSource

Arguments

:: Fd 
-> ByteString

The string to write.

-> FileOffset

Where to write the data to.

-> IO ByteCount

How many bytes were actually written.

Write data from memory to a specified position in the Fd, but without altering the position stored in the Fd. This is exactly equivalent to the XPG4.2 pwrite(2) system call; we just convert the ByteString into its underlying Ptr Word8 and ByteCount components for passing to fdPwriteBuf.

fdPwriteBufSource

Arguments

:: Fd 
-> Ptr Word8

Memory containing the data to write.

-> ByteCount

How many bytes to try to write.

-> FileOffset

Where to write the data to.

-> IO ByteCount

How many bytes were actually written.

Write data from memory to a specified position in the Fd, but without altering the position stored in the Fd. This is exactly equivalent to the XPG4.2 pwrite(2) system call.

TODO: better documentation.