[Haskell-cafe] [Word8] -> FilePath using ghc's file system encoding

Joey Hess joey at kitenet.net
Wed Jun 20 21:26:35 CEST 2012


I found myself writing the code below today, and thought I'd write to see if
there's a better way, perhaps one that doesn't use unsafePerformIO.

A sample use case for this is a program that reads a FilePath from a Handle,
and then operates on that file on disk. GHC uses a special encoding for
FilePaths that cleanly roundtrips invalid utf8, but for that to work,
the FilePath must be read using that encoding too. Neglecting to do that
would result in a program that worked for most filenames, but failed on edge
case non-utf8 encoded filenames.

Another way to deal with this problem is to first hSetEncoding using
GHC.IO.Encoding.getFileSystemEncoding, and then read from the Handle using
hGetLine, which applies the encoding to the data it reads. However, in this
case I needed to use ByteString to read from the Handle, and so needed a way to
convert from a ByteString to a FilePath. (Using RawFilePath would be another
approach, but reworking my program to use it isn't practical.)

Anyway, it seems there should be a pure way to encode a string with
GHC's filesystem encoding.

-----

import qualified GHC.Foreign as GHC
import qualified GHC.IO.Encoding as Encoding
import System.IO.Unsafe
import Data.Bits.Utils -- from MissingH

{- Converts a [Word8] to a FilePath, encoding using the filesystem encoding.
 -
 - w82c produces a String, which may contain Chars that are invalid
 - unicode. From there, this is really a simple matter of applying the
 - file system encoding, only complicated by GHC's interface to doing so.
 -}
{-# NOINLINE encodeW8 #-}
encodeW8 :: [Word8] -> FilePath
encodeW8 w8 = unsafePerformIO $ do
        enc <- Encoding.getFileSystemEncoding
        GHC.withCString Encoding.char8 (w82s w8) (GHC.peekCString enc)

-- 
see shy jo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 828 bytes
Desc: Digital signature
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20120620/65160ebb/attachment.pgp>


More information about the Haskell-Cafe mailing list