-- |
-- Module      : Basement.String.Encoding.ISO_8859_1
-- License     : BSD-style
-- Maintainer  : Foundation
-- Stability   : experimental
-- Portability : portable
--

{-# LANGUAGE MagicHash #-}

module Basement.String.Encoding.ISO_8859_1
    ( ISO_8859_1(..)
    , ISO_8859_1_Invalid(..)
    ) where

import Basement.Compat.Base
import Basement.Compat.Primitive
import Basement.Types.OffsetSize
import Basement.Numerical.Additive
import Basement.Monad

import GHC.Prim (int2Word#, ord#)
import GHC.Word
import GHC.Types
import Basement.UArray
import Basement.UArray.Mutable (MUArray)
import Basement.MutableBuilder

import Basement.String.Encoding.Encoding

-- offset of size one
aone :: Offset Word8
aone :: Offset Word8
aone = Int -> Offset Word8
forall ty. Int -> Offset ty
Offset Int
1

data ISO_8859_1_Invalid
    = NotISO_8859_1 Char
  deriving (Typeable, Int -> ISO_8859_1_Invalid -> ShowS
[ISO_8859_1_Invalid] -> ShowS
ISO_8859_1_Invalid -> String
(Int -> ISO_8859_1_Invalid -> ShowS)
-> (ISO_8859_1_Invalid -> String)
-> ([ISO_8859_1_Invalid] -> ShowS)
-> Show ISO_8859_1_Invalid
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ISO_8859_1_Invalid] -> ShowS
$cshowList :: [ISO_8859_1_Invalid] -> ShowS
show :: ISO_8859_1_Invalid -> String
$cshow :: ISO_8859_1_Invalid -> String
showsPrec :: Int -> ISO_8859_1_Invalid -> ShowS
$cshowsPrec :: Int -> ISO_8859_1_Invalid -> ShowS
Show, ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool
(ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool)
-> (ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool)
-> Eq ISO_8859_1_Invalid
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool
$c/= :: ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool
== :: ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool
$c== :: ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool
Eq)
instance Exception ISO_8859_1_Invalid

data ISO_8859_1 = ISO_8859_1

instance Encoding ISO_8859_1 where
    type Unit ISO_8859_1 = Word8
    type Error ISO_8859_1 = ISO_8859_1_Invalid
    encodingNext :: ISO_8859_1
-> (Offset (Unit ISO_8859_1) -> Unit ISO_8859_1)
-> Offset (Unit ISO_8859_1)
-> Either (Error ISO_8859_1) (Char, Offset (Unit ISO_8859_1))
encodingNext  ISO_8859_1
_ = (Offset Word8 -> Word8)
-> Offset Word8 -> Either ISO_8859_1_Invalid (Char, Offset Word8)
(Offset (Unit ISO_8859_1) -> Unit ISO_8859_1)
-> Offset (Unit ISO_8859_1)
-> Either (Error ISO_8859_1) (Char, Offset (Unit ISO_8859_1))
next
    encodingWrite :: ISO_8859_1
-> Char
-> Builder
     (UArray (Unit ISO_8859_1))
     (MUArray (Unit ISO_8859_1))
     (Unit ISO_8859_1)
     st
     err
     ()
encodingWrite ISO_8859_1
_ = Char
-> Builder
     (UArray (Unit ISO_8859_1))
     (MUArray (Unit ISO_8859_1))
     (Unit ISO_8859_1)
     st
     err
     ()
forall (st :: * -> *) err.
(PrimMonad st, Monad st) =>
Char -> Builder (UArray Word8) (MUArray Word8) Word8 st err ()
write

next :: (Offset Word8 -> Word8)
     -> Offset Word8
     -> Either ISO_8859_1_Invalid (Char, Offset Word8)
next :: (Offset Word8 -> Word8)
-> Offset Word8 -> Either ISO_8859_1_Invalid (Char, Offset Word8)
next Offset Word8 -> Word8
getter Offset Word8
off = (Char, Offset Word8)
-> Either ISO_8859_1_Invalid (Char, Offset Word8)
forall a b. b -> Either a b
Right (Word8# -> Char
toChar Word8#
w, Offset Word8
off Offset Word8 -> Offset Word8 -> Offset Word8
forall a. Additive a => a -> a -> a
+ Offset Word8
aone)
  where
    !(W8# Word8#
w) = Offset Word8 -> Word8
getter Offset Word8
off
    toChar :: Word8# -> Char
    toChar :: Word8# -> Char
toChar Word8#
a = Char# -> Char
C# (Word8# -> Char#
word8ToChar# Word8#
w)

write :: (PrimMonad st, Monad st)
      => Char
      -> Builder (UArray Word8) (MUArray Word8) Word8 st err ()
write :: Char -> Builder (UArray Word8) (MUArray Word8) Word8 st err ()
write c :: Char
c@(C# Char#
ch)
    | Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> Char
forall a. Enum a => Int -> a
toEnum Int
0xFF = Word8 -> Builder (UArray Word8) (MUArray Word8) Word8 st err ()
forall ty (state :: * -> *) err.
(PrimType ty, PrimMonad state) =>
ty -> Builder (UArray ty) (MUArray ty) ty state err ()
builderAppend (Word8# -> Word8
W8# Word8#
x)
    | Bool
otherwise        = ISO_8859_1_Invalid
-> Builder (UArray Word8) (MUArray Word8) Word8 st err ()
forall a e. Exception e => e -> a
throw (ISO_8859_1_Invalid
 -> Builder (UArray Word8) (MUArray Word8) Word8 st err ())
-> ISO_8859_1_Invalid
-> Builder (UArray Word8) (MUArray Word8) Word8 st err ()
forall a b. (a -> b) -> a -> b
$ Char -> ISO_8859_1_Invalid
NotISO_8859_1 Char
c
  where
    x :: Word8#
    !x :: Word8#
x = Word8# -> Word8#
wordToWord8# (Int# -> Word8#
int2Word# (Char# -> Int#
ord# Char#
ch))