-- Copyright 2007-2009, Judah Jacobson.
-- All Rights Reserved.

-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:

-- - Redistribution of source code must retain the above copyright notice,
-- this list of conditions and the following disclaimer.

-- - Redistribution in binary form must reproduce the above copyright notice,
-- this list of conditions and the following disclaimer in the documentation
-- and/or other materials provided with the distribution.

-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTORS BE LIABLE
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-- SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
-- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{-# LANGUAGE CPP #-}
module Darcs.Util.Encoding
    ( encode, decode
    , encodeUtf8, decodeUtf8
    ) where

import Prelude ()
import Darcs.Prelude

import qualified Data.ByteString  as B

#ifdef WIN32
import qualified Darcs.Util.Encoding.Win32 ( encode, decode )
#else
import System.IO
import GHC.IO.Encoding ( getFileSystemEncoding )
import qualified Data.Knob as K

-- | Encode a 'String' into a 'B.ByteString' according to the user's locale
-- with the ghc specific //ROUNDTRIP feature added. This means the argument
-- is allowed to contain non-Unicode 'Char's as produced by 'decode'.
encode :: String -> IO B.ByteString
encode s = do
  knob <- K.newKnob B.empty
  h <- K.newFileHandle  knob "darcs-encode" WriteMode
  hSetEncoding h =<< getFileSystemEncoding
  hPutStr h s
  hClose h
  K.getContents knob

-- | Decode a 'B.ByteString' into a 'String' according to the user's locale
-- with the ghc specific //ROUNDTRIP feature added. This means the result
-- may contain 'Char's that are not valid Unicode in case decoding with the
-- user's locale fails.
decode :: B.ByteString -> IO String
decode bs = do
  knob <- K.newKnob bs
  h <- K.newFileHandle  knob "darcs-decode" ReadMode
  hSetEncoding h =<< getFileSystemEncoding
  s <- hGetContents h
  -- NOTE must NOT close the handle, since we use the lazy hGetContents.
  -- It will be auto-closed when the output is fully consumed.
  --hClose h
  return s

encodeUtf8 :: String -> IO B.ByteString
encodeUtf8 s = do
  knob <- K.newKnob B.empty
  h <- K.newFileHandle  knob "darcs-encode" WriteMode
  hSetEncoding h =<< mkTextEncoding "UTF-8//TRANSLIT"
  hPutStr h s
  hClose h
  K.getContents knob

decodeUtf8 :: B.ByteString -> IO String
decodeUtf8 bs = do
  knob <- K.newKnob bs
  h <- K.newFileHandle  knob "darcs-decode" ReadMode
  hSetEncoding h =<< mkTextEncoding "UTF-8//TRANSLIT"
  s <- hGetContents h
  -- NOTE must NOT close the handle, since we use the lazy hGetContents.
  -- It will be auto-closed when the output is fully consumed.
  --hClose h
  return s

#endif