Skip to content

Instantly share code, notes, and snippets.

@snoyberg
Created October 11, 2015 09:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save snoyberg/2a5ca79d97f483bdcfe9 to your computer and use it in GitHub Desktop.
Save snoyberg/2a5ca79d97f483bdcfe9 to your computer and use it in GitHub Desktop.
Consume null-terminated strings on stdin using Haskell/conduit. Conduit tutorial: https://github.com/snoyberg/conduit#readme
{-# LANGUAGE OverloadedStrings #-}
import Conduit
import Data.ByteString (ByteString)
conduitNullTerm :: Monad m => Conduit ByteString m ByteString
conduitNullTerm =
loop
where
loop = do
-- Check if there's any more data on the stream
-- This function peeks at the next byte
mhasMore <- peekCE
case mhasMore of
-- Nothing means no data left, so just exit
Nothing -> return ()
-- Some data left
Just _ -> do
-- Take all of the bytes up until the null byte
-- Use foldC to combine them into a single ByteString
bs <- takeWhileCE (/= 0) =$ foldC
-- Drop the next byte if present, which must be a null byte
dropCE 1
-- Yield the new ByteString downstream
yield bs
-- Loop for the next ByteString
loop
main :: IO ()
main = do
-- Grab the data from stdin, turn into a stream of null-terminated strings,
-- and consume as a list
files <- stdinC $$ conduitNullTerm =$ sinkList
-- Print them out, could obviously due something else as well
print files
$ echo -en "foo\0bar\0baz\0bin\0with\nnewline" | stack --resolver lts-3.7 runghc --package conduit-combinators nullterm.hs
Run from outside a project, using implicit global project config
Using resolver: lts-3.7 specified on command line
["foo","bar","baz","bin","with\nnewline"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment