Portability | portable |
---|---|
Stability | experimental |
Maintainer | Matti Niemenmaa <matti.niemenmaa+web@iki.fi> |
Operations for piping data through multiple processes.
pipe
is the most general function, with filePipe
and 'pipe\'' provided
for convenience purposes. For the common case of piping between String
s,
the pipeString
wrapper and the word8ToString
and stringToWord8
helpers
are included.
Whenever specifying a path to a process, explicitly specifying the current directory is recommended for portability. That is: use "./foo" instead of "foo", for instance.
On Windows, appending ".exe" to process paths is attempted if the invocation fails.
- filePipe :: [(FilePath, [String])] -> FilePath -> FilePath -> IO ()
- class Tap a where
- class Sink a where
- bufferSize :: Int
- pipe :: (Tap t, Sink s) => FilePath -> [(FilePath, [String])] -> t -> s -> IO (t, s)
- pipe' :: (Tap t, Sink s) => [(FilePath, [String])] -> t -> s -> IO (t, s)
- pipeString :: [(FilePath, [String])] -> String -> IO String
- word8ToString :: [Word8] -> String
- stringToWord8 :: String -> [Word8]
Documentation
filePipe :: [(FilePath, [String])] -> FilePath -> FilePath -> IO ()Source
Pipes the contents of the first file to the second file through all the programs named.
The working directory used is the directory component of the path to the first file.
From a Tap
, data up to the requested amount flows into a Ptr
. The
exact amount of 'Word8'\'s that flowed is returned. The requested amount is
guaranteed to be no greater than bufferSize
.
To a Sink
, the requested amount of 'Word8'\'s flows from a Ptr
. The
requested amount is guaranteed to be no greater than bufferSize
.
pipe :: (Tap t, Sink s) => FilePath -> [(FilePath, [String])] -> t -> s -> IO (t, s)Source
Pipes data from the Tap
to the Sink
through all the commands named, in
the given working directory.
Be careful! All IO is at the byte level: this means that piping even a
String such as "foo" will result in the raw UTF-32 moving: the bytes (in
my case; I believe this is implementation-dependent) in question are not the
ASCII [102, 111, 111]
but rather [102, 0, 0, 0, 111, 0, 0, 0, 111, 0, 0,
0]
.
Note to Windows users: since hGetBufNonBlocking
doesn't work on Windows
(it blocks despite its name, see
http://hackage.haskell.org/trac/ghc/ticket/806), this pipeline uses a
non-constant amount of space. The amount used is linear in the amount of
data used at any point in the pipeline. So if you want to pipe 20 gibioctets
of data to a program, you better make sure you have at least said amount of
memory available. (In fact, ByteStrings are used, and their documentation
suggests that you might want twice that, just in case.)
In addition, the Tap
and Sink
classes are meant for the POSIX code:
having to move data through the Ptr
Word8
types, bufferSize
bytes at a
time, results in extra complexity.
If you want to do something about the above, ideally fix the GHC ticket (probably nontrivial) and let me know so that I can activate the better code for Windows as well. Alternatively, feel free to code an implementation of this which works on Windows.
pipe' :: (Tap t, Sink s) => [(FilePath, [String])] -> t -> s -> IO (t, s)Source
A convenience function for when you don't care about the working directory.
pipe' = pipe "."
pipeString :: [(FilePath, [String])] -> String -> IO StringSource
A convenience function for the common case of piping from a String
to a
String
. This uses the word8ToString
and stringToWord8
functions and
thus loses information if your Char
s are non-ASCII.
word8ToString :: [Word8] -> StringSource
A helper function which converts a [
to a Word8
]String
by mapping
chr
over the octets.
In most cases, when you wish to pipe data to a String, you do not want to
interpret the results as the raw byte pattern of Char
s, so you use
[
as the Word8
]Sink
type. This function handles the common case of
ASCII data simply—if you're dealing with non-ASCII data you probably need
to handle the results in a different way.
stringToWord8 :: String -> [Word8]Source
The inverse of word8ToString
. Any Char
s greater than 255 are
truncated: once again, be careful with non-ASCII.