{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE NoImplicitPrelude
           , BangPatterns
           , NondecreasingIndentation
  #-}
{-# OPTIONS_GHC  -funbox-strict-fields #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  GHC.IO.Encoding.Latin1
-- Copyright   :  (c) The University of Glasgow, 2009
-- License     :  see libraries/base/LICENSE
-- 
-- Maintainer  :  libraries@haskell.org
-- Stability   :  internal
-- Portability :  non-portable
--
-- Single-byte encodings that map directly to Unicode code points.
--
-- Portions Copyright   : (c) Tom Harper 2008-2009,
--                        (c) Bryan O'Sullivan 2009,
--                        (c) Duncan Coutts 2009
--
-----------------------------------------------------------------------------

module GHC.IO.Encoding.Latin1 (
  latin1, mkLatin1,
  latin1_checked, mkLatin1_checked,
  ascii, mkAscii,
  latin1_decode,
  ascii_decode,
  latin1_encode,
  latin1_checked_encode,
  ascii_encode,
  ) where

import GHC.Base
import GHC.Real
import GHC.Num
-- import GHC.IO
import GHC.IO.Buffer
import GHC.IO.Encoding.Failure
import GHC.IO.Encoding.Types

-- -----------------------------------------------------------------------------
-- Latin1

latin1 :: TextEncoding
latin1 :: TextEncoding
latin1 = CodingFailureMode -> TextEncoding
mkLatin1 CodingFailureMode
ErrorOnCodingFailure

-- | @since 4.4.0.0
mkLatin1 :: CodingFailureMode -> TextEncoding
mkLatin1 :: CodingFailureMode -> TextEncoding
mkLatin1 CodingFailureMode
cfm = TextEncoding { textEncodingName :: String
textEncodingName = String
"ISO-8859-1",
                              mkTextDecoder :: IO (TextDecoder ())
mkTextDecoder = CodingFailureMode -> IO (TextDecoder ())
latin1_DF CodingFailureMode
cfm,
                              mkTextEncoder :: IO (TextEncoder ())
mkTextEncoder = CodingFailureMode -> IO (TextEncoder ())
latin1_EF CodingFailureMode
cfm }

latin1_DF :: CodingFailureMode -> IO (TextDecoder ())
latin1_DF :: CodingFailureMode -> IO (TextDecoder ())
latin1_DF CodingFailureMode
cfm =
  forall (m :: * -> *) a. Monad m => a -> m a
return (BufferCodec {
             encode :: CodeBuffer Word8 Char
encode   = CodeBuffer Word8 Char
latin1_decode,
             recover :: Buffer Word8 -> Buffer Char -> IO (Buffer Word8, Buffer Char)
recover  = CodingFailureMode
-> Buffer Word8 -> Buffer Char -> IO (Buffer Word8, Buffer Char)
recoverDecode CodingFailureMode
cfm,
             close :: IO ()
close    = forall (m :: * -> *) a. Monad m => a -> m a
return (),
             getState :: IO ()
getState = forall (m :: * -> *) a. Monad m => a -> m a
return (),
             setState :: () -> IO ()
setState = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return ()
          })

latin1_EF :: CodingFailureMode -> IO (TextEncoder ())
latin1_EF :: CodingFailureMode -> IO (TextEncoder ())
latin1_EF CodingFailureMode
cfm =
  forall (m :: * -> *) a. Monad m => a -> m a
return (BufferCodec {
             encode :: CodeBuffer Char Word8
encode   = CodeBuffer Char Word8
latin1_encode,
             recover :: Buffer Char -> Buffer Word8 -> IO (Buffer Char, Buffer Word8)
recover  = CodingFailureMode
-> Buffer Char -> Buffer Word8 -> IO (Buffer Char, Buffer Word8)
recoverEncode CodingFailureMode
cfm,
             close :: IO ()
close    = forall (m :: * -> *) a. Monad m => a -> m a
return (),
             getState :: IO ()
getState = forall (m :: * -> *) a. Monad m => a -> m a
return (),
             setState :: () -> IO ()
setState = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return ()
          })

latin1_checked :: TextEncoding
latin1_checked :: TextEncoding
latin1_checked = CodingFailureMode -> TextEncoding
mkLatin1_checked CodingFailureMode
ErrorOnCodingFailure

-- | @since 4.4.0.0
mkLatin1_checked :: CodingFailureMode -> TextEncoding
mkLatin1_checked :: CodingFailureMode -> TextEncoding
mkLatin1_checked CodingFailureMode
cfm = TextEncoding { textEncodingName :: String
textEncodingName = String
"ISO-8859-1",
                                      mkTextDecoder :: IO (TextDecoder ())
mkTextDecoder = CodingFailureMode -> IO (TextDecoder ())
latin1_DF CodingFailureMode
cfm,
                                      mkTextEncoder :: IO (TextEncoder ())
mkTextEncoder = CodingFailureMode -> IO (TextEncoder ())
latin1_checked_EF CodingFailureMode
cfm }

latin1_checked_EF :: CodingFailureMode -> IO (TextEncoder ())
latin1_checked_EF :: CodingFailureMode -> IO (TextEncoder ())
latin1_checked_EF CodingFailureMode
cfm =
  forall (m :: * -> *) a. Monad m => a -> m a
return (BufferCodec {
             encode :: CodeBuffer Char Word8
encode   = CodeBuffer Char Word8
latin1_checked_encode,
             recover :: Buffer Char -> Buffer Word8 -> IO (Buffer Char, Buffer Word8)
recover  = CodingFailureMode
-> Buffer Char -> Buffer Word8 -> IO (Buffer Char, Buffer Word8)
recoverEncode CodingFailureMode
cfm,
             close :: IO ()
close    = forall (m :: * -> *) a. Monad m => a -> m a
return (),
             getState :: IO ()
getState = forall (m :: * -> *) a. Monad m => a -> m a
return (),
             setState :: () -> IO ()
setState = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return ()
          })

-- -----------------------------------------------------------------------------
-- ASCII

-- | @since 4.9.0.0
ascii :: TextEncoding
ascii :: TextEncoding
ascii = CodingFailureMode -> TextEncoding
mkAscii CodingFailureMode
ErrorOnCodingFailure

-- | @since 4.9.0.0
mkAscii :: CodingFailureMode -> TextEncoding
mkAscii :: CodingFailureMode -> TextEncoding
mkAscii CodingFailureMode
cfm = TextEncoding { textEncodingName :: String
textEncodingName = String
"ASCII",
                             mkTextDecoder :: IO (TextDecoder ())
mkTextDecoder = CodingFailureMode -> IO (TextDecoder ())
ascii_DF CodingFailureMode
cfm,
                             mkTextEncoder :: IO (TextEncoder ())
mkTextEncoder = CodingFailureMode -> IO (TextEncoder ())
ascii_EF CodingFailureMode
cfm }

ascii_DF :: CodingFailureMode -> IO (TextDecoder ())
ascii_DF :: CodingFailureMode -> IO (TextDecoder ())
ascii_DF CodingFailureMode
cfm =
  forall (m :: * -> *) a. Monad m => a -> m a
return (BufferCodec {
             encode :: CodeBuffer Word8 Char
encode   = CodeBuffer Word8 Char
ascii_decode,
             recover :: Buffer Word8 -> Buffer Char -> IO (Buffer Word8, Buffer Char)
recover  = CodingFailureMode
-> Buffer Word8 -> Buffer Char -> IO (Buffer Word8, Buffer Char)
recoverDecode CodingFailureMode
cfm,
             close :: IO ()
close    = forall (m :: * -> *) a. Monad m => a -> m a
return (),
             getState :: IO ()
getState = forall (m :: * -> *) a. Monad m => a -> m a
return (),
             setState :: () -> IO ()
setState = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return ()
          })

ascii_EF :: CodingFailureMode -> IO (TextEncoder ())
ascii_EF :: CodingFailureMode -> IO (TextEncoder ())
ascii_EF CodingFailureMode
cfm =
  forall (m :: * -> *) a. Monad m => a -> m a
return (BufferCodec {
             encode :: CodeBuffer Char Word8
encode   = CodeBuffer Char Word8
ascii_encode,
             recover :: Buffer Char -> Buffer Word8 -> IO (Buffer Char, Buffer Word8)
recover  = CodingFailureMode
-> Buffer Char -> Buffer Word8 -> IO (Buffer Char, Buffer Word8)
recoverEncode CodingFailureMode
cfm,
             close :: IO ()
close    = forall (m :: * -> *) a. Monad m => a -> m a
return (),
             getState :: IO ()
getState = forall (m :: * -> *) a. Monad m => a -> m a
return (),
             setState :: () -> IO ()
setState = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return ()
          })



-- -----------------------------------------------------------------------------
-- The actual decoders and encoders

-- TODO: Eliminate code duplication between the checked and unchecked
-- versions of the decoder or encoder (but don't change the Core!)

latin1_decode :: DecodeBuffer
latin1_decode :: CodeBuffer Word8 Char
latin1_decode 
  input :: Buffer Word8
input@Buffer{  bufRaw :: forall e. Buffer e -> RawBuffer e
bufRaw=RawBuffer Word8
iraw, bufL :: forall e. Buffer e -> Int
bufL=Int
ir0, bufR :: forall e. Buffer e -> Int
bufR=Int
iw,  bufSize :: forall e. Buffer e -> Int
bufSize=Int
_  }
  output :: Buffer Char
output@Buffer{ bufRaw :: forall e. Buffer e -> RawBuffer e
bufRaw=RawBuffer Char
oraw, bufL :: forall e. Buffer e -> Int
bufL=Int
_,   bufR :: forall e. Buffer e -> Int
bufR=Int
ow0, bufSize :: forall e. Buffer e -> Int
bufSize=Int
os }
 = let 
       loop :: Int -> Int -> IO (CodingProgress, Buffer Word8, Buffer Char)
loop !Int
ir !Int
ow
         | Int
ow forall a. Ord a => a -> a -> Bool
>= Int
os = forall {m :: * -> *} {a}.
Monad m =>
a -> Int -> Int -> m (a, Buffer Word8, Buffer Char)
done CodingProgress
OutputUnderflow Int
ir Int
ow
         | Int
ir forall a. Ord a => a -> a -> Bool
>= Int
iw = forall {m :: * -> *} {a}.
Monad m =>
a -> Int -> Int -> m (a, Buffer Word8, Buffer Char)
done CodingProgress
InputUnderflow Int
ir Int
ow
         | Bool
otherwise = do
              Word8
c0 <- RawBuffer Word8 -> Int -> IO Word8
readWord8Buf RawBuffer Word8
iraw Int
ir
              Int
ow' <- RawBuffer Char -> Int -> Char -> IO Int
writeCharBuf RawBuffer Char
oraw Int
ow (Int -> Char
unsafeChr (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
c0))
              Int -> Int -> IO (CodingProgress, Buffer Word8, Buffer Char)
loop (Int
irforall a. Num a => a -> a -> a
+Int
1) Int
ow'

       -- lambda-lifted, to avoid thunks being built in the inner-loop:
       done :: a -> Int -> Int -> m (a, Buffer Word8, Buffer Char)
done a
why !Int
ir !Int
ow = forall (m :: * -> *) a. Monad m => a -> m a
return (a
why,
                                  if Int
ir forall a. Eq a => a -> a -> Bool
== Int
iw then Buffer Word8
input{ bufL :: Int
bufL=Int
0, bufR :: Int
bufR=Int
0 }
                                              else Buffer Word8
input{ bufL :: Int
bufL=Int
ir },
                                  Buffer Char
output{ bufR :: Int
bufR=Int
ow })
    in
    Int -> Int -> IO (CodingProgress, Buffer Word8, Buffer Char)
loop Int
ir0 Int
ow0

ascii_decode :: DecodeBuffer
ascii_decode :: CodeBuffer Word8 Char
ascii_decode
  input :: Buffer Word8
input@Buffer{  bufRaw :: forall e. Buffer e -> RawBuffer e
bufRaw=RawBuffer Word8
iraw, bufL :: forall e. Buffer e -> Int
bufL=Int
ir0, bufR :: forall e. Buffer e -> Int
bufR=Int
iw,  bufSize :: forall e. Buffer e -> Int
bufSize=Int
_  }
  output :: Buffer Char
output@Buffer{ bufRaw :: forall e. Buffer e -> RawBuffer e
bufRaw=RawBuffer Char
oraw, bufL :: forall e. Buffer e -> Int
bufL=Int
_,   bufR :: forall e. Buffer e -> Int
bufR=Int
ow0, bufSize :: forall e. Buffer e -> Int
bufSize=Int
os }
 = let
       loop :: Int -> Int -> IO (CodingProgress, Buffer Word8, Buffer Char)
loop !Int
ir !Int
ow
         | Int
ow forall a. Ord a => a -> a -> Bool
>= Int
os = forall {m :: * -> *} {a}.
Monad m =>
a -> Int -> Int -> m (a, Buffer Word8, Buffer Char)
done CodingProgress
OutputUnderflow Int
ir Int
ow
         | Int
ir forall a. Ord a => a -> a -> Bool
>= Int
iw = forall {m :: * -> *} {a}.
Monad m =>
a -> Int -> Int -> m (a, Buffer Word8, Buffer Char)
done CodingProgress
InputUnderflow Int
ir Int
ow
         | Bool
otherwise = do
              Word8
c0 <- RawBuffer Word8 -> Int -> IO Word8
readWord8Buf RawBuffer Word8
iraw Int
ir
              if Word8
c0 forall a. Ord a => a -> a -> Bool
> Word8
0x7f then IO (CodingProgress, Buffer Word8, Buffer Char)
invalid else do
              Int
ow' <- RawBuffer Char -> Int -> Char -> IO Int
writeCharBuf RawBuffer Char
oraw Int
ow (Int -> Char
unsafeChr (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
c0))
              Int -> Int -> IO (CodingProgress, Buffer Word8, Buffer Char)
loop (Int
irforall a. Num a => a -> a -> a
+Int
1) Int
ow'
         where
           invalid :: IO (CodingProgress, Buffer Word8, Buffer Char)
invalid = forall {m :: * -> *} {a}.
Monad m =>
a -> Int -> Int -> m (a, Buffer Word8, Buffer Char)
done CodingProgress
InvalidSequence Int
ir Int
ow

       -- lambda-lifted, to avoid thunks being built in the inner-loop:
       done :: a -> Int -> Int -> m (a, Buffer Word8, Buffer Char)
done a
why !Int
ir !Int
ow = forall (m :: * -> *) a. Monad m => a -> m a
return (a
why,
                                  if Int
ir forall a. Eq a => a -> a -> Bool
== Int
iw then Buffer Word8
input{ bufL :: Int
bufL=Int
0, bufR :: Int
bufR=Int
0 }
                                              else Buffer Word8
input{ bufL :: Int
bufL=Int
ir },
                                  Buffer Char
output{ bufR :: Int
bufR=Int
ow })
    in
    Int -> Int -> IO (CodingProgress, Buffer Word8, Buffer Char)
loop Int
ir0 Int
ow0

latin1_encode :: EncodeBuffer
latin1_encode :: CodeBuffer Char Word8
latin1_encode
  input :: Buffer Char
input@Buffer{  bufRaw :: forall e. Buffer e -> RawBuffer e
bufRaw=RawBuffer Char
iraw, bufL :: forall e. Buffer e -> Int
bufL=Int
ir0, bufR :: forall e. Buffer e -> Int
bufR=Int
iw,  bufSize :: forall e. Buffer e -> Int
bufSize=Int
_  }
  output :: Buffer Word8
output@Buffer{ bufRaw :: forall e. Buffer e -> RawBuffer e
bufRaw=RawBuffer Word8
oraw, bufL :: forall e. Buffer e -> Int
bufL=Int
_,   bufR :: forall e. Buffer e -> Int
bufR=Int
ow0, bufSize :: forall e. Buffer e -> Int
bufSize=Int
os }
 = let
      done :: a -> Int -> Int -> m (a, Buffer Char, Buffer Word8)
done a
why !Int
ir !Int
ow = forall (m :: * -> *) a. Monad m => a -> m a
return (a
why,
                                 if Int
ir forall a. Eq a => a -> a -> Bool
== Int
iw then Buffer Char
input{ bufL :: Int
bufL=Int
0, bufR :: Int
bufR=Int
0 }
                                             else Buffer Char
input{ bufL :: Int
bufL=Int
ir },
                                 Buffer Word8
output{ bufR :: Int
bufR=Int
ow })
      loop :: Int -> Int -> IO (CodingProgress, Buffer Char, Buffer Word8)
loop !Int
ir !Int
ow
        | Int
ow forall a. Ord a => a -> a -> Bool
>= Int
os = forall {m :: * -> *} {a}.
Monad m =>
a -> Int -> Int -> m (a, Buffer Char, Buffer Word8)
done CodingProgress
OutputUnderflow Int
ir Int
ow
        | Int
ir forall a. Ord a => a -> a -> Bool
>= Int
iw = forall {m :: * -> *} {a}.
Monad m =>
a -> Int -> Int -> m (a, Buffer Char, Buffer Word8)
done CodingProgress
InputUnderflow Int
ir Int
ow
        | Bool
otherwise = do
           (Char
c,Int
ir') <- RawBuffer Char -> Int -> IO (Char, Int)
readCharBuf RawBuffer Char
iraw Int
ir
           RawBuffer Word8 -> Int -> Word8 -> IO ()
writeWord8Buf RawBuffer Word8
oraw Int
ow (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c))
           Int -> Int -> IO (CodingProgress, Buffer Char, Buffer Word8)
loop Int
ir' (Int
owforall a. Num a => a -> a -> a
+Int
1)
    in
    Int -> Int -> IO (CodingProgress, Buffer Char, Buffer Word8)
loop Int
ir0 Int
ow0

latin1_checked_encode :: EncodeBuffer
latin1_checked_encode :: CodeBuffer Char Word8
latin1_checked_encode Buffer Char
input Buffer Word8
output
 = Int -> CodeBuffer Char Word8
single_byte_checked_encode Int
0xff Buffer Char
input Buffer Word8
output

ascii_encode :: EncodeBuffer
ascii_encode :: CodeBuffer Char Word8
ascii_encode Buffer Char
input Buffer Word8
output
 = Int -> CodeBuffer Char Word8
single_byte_checked_encode Int
0x7f Buffer Char
input Buffer Word8
output

single_byte_checked_encode :: Int -> EncodeBuffer
single_byte_checked_encode :: Int -> CodeBuffer Char Word8
single_byte_checked_encode Int
max_legal_char
  input :: Buffer Char
input@Buffer{  bufRaw :: forall e. Buffer e -> RawBuffer e
bufRaw=RawBuffer Char
iraw, bufL :: forall e. Buffer e -> Int
bufL=Int
ir0, bufR :: forall e. Buffer e -> Int
bufR=Int
iw,  bufSize :: forall e. Buffer e -> Int
bufSize=Int
_  }
  output :: Buffer Word8
output@Buffer{ bufRaw :: forall e. Buffer e -> RawBuffer e
bufRaw=RawBuffer Word8
oraw, bufL :: forall e. Buffer e -> Int
bufL=Int
_,   bufR :: forall e. Buffer e -> Int
bufR=Int
ow0, bufSize :: forall e. Buffer e -> Int
bufSize=Int
os }
 = let
      done :: a -> Int -> Int -> m (a, Buffer Char, Buffer Word8)
done a
why !Int
ir !Int
ow = forall (m :: * -> *) a. Monad m => a -> m a
return (a
why,
                                 if Int
ir forall a. Eq a => a -> a -> Bool
== Int
iw then Buffer Char
input{ bufL :: Int
bufL=Int
0, bufR :: Int
bufR=Int
0 }
                                             else Buffer Char
input{ bufL :: Int
bufL=Int
ir },
                                 Buffer Word8
output{ bufR :: Int
bufR=Int
ow })
      loop :: Int -> Int -> IO (CodingProgress, Buffer Char, Buffer Word8)
loop !Int
ir !Int
ow
        | Int
ow forall a. Ord a => a -> a -> Bool
>= Int
os = forall {m :: * -> *} {a}.
Monad m =>
a -> Int -> Int -> m (a, Buffer Char, Buffer Word8)
done CodingProgress
OutputUnderflow Int
ir Int
ow
        | Int
ir forall a. Ord a => a -> a -> Bool
>= Int
iw = forall {m :: * -> *} {a}.
Monad m =>
a -> Int -> Int -> m (a, Buffer Char, Buffer Word8)
done CodingProgress
InputUnderflow Int
ir Int
ow
        | Bool
otherwise = do
           (Char
c,Int
ir') <- RawBuffer Char -> Int -> IO (Char, Int)
readCharBuf RawBuffer Char
iraw Int
ir
           if Char -> Int
ord Char
c forall a. Ord a => a -> a -> Bool
> Int
max_legal_char then IO (CodingProgress, Buffer Char, Buffer Word8)
invalid else do
           RawBuffer Word8 -> Int -> Word8 -> IO ()
writeWord8Buf RawBuffer Word8
oraw Int
ow (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
c))
           Int -> Int -> IO (CodingProgress, Buffer Char, Buffer Word8)
loop Int
ir' (Int
owforall a. Num a => a -> a -> a
+Int
1)
        where
           invalid :: IO (CodingProgress, Buffer Char, Buffer Word8)
invalid = forall {m :: * -> *} {a}.
Monad m =>
a -> Int -> Int -> m (a, Buffer Char, Buffer Word8)
done CodingProgress
InvalidSequence Int
ir Int
ow
    in
    Int -> Int -> IO (CodingProgress, Buffer Char, Buffer Word8)
loop Int
ir0 Int
ow0
{-# INLINE single_byte_checked_encode #-}