module Data.String.Interpolate.Internal.Util where

import           Data.Char
import           Data.Maybe
import qualified Numeric as N

import           Data.String.Interpolate.Compat

toString :: Show a => a -> String
toString :: a -> String
toString a :: a
a = let s :: String
s = a -> String
forall a. Show a => a -> String
show a
a in String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
s (String -> Maybe String
forall a. Read a => String -> Maybe a
readMaybe String
s)
{-# NOINLINE toString #-}
{-# RULES "toString/String" toString = id #-}
{-# RULES "toString/Int" toString = show :: Int -> String #-}
{-# RULES "toString/Integer" toString = show :: Integer -> String #-}
{-# RULES "toString/Float" toString = show :: Float -> String #-}
{-# RULES "toString/Double" toString = show :: Double -> String #-}

-- Haskell 2010 character unescaping, see:
-- http://www.haskell.org/onlinereport/haskell2010/haskellch2.html#x7-200002.6
unescape :: String -> String
unescape :: String -> String
unescape = String -> String
go
  where
    go :: String -> String
go input :: String
input = case String
input of
      "" -> ""
      '\\' : 'x' : x :: Char
x : xs :: String
xs | Char -> Bool
isHexDigit Char
x -> case (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
span Char -> Bool
isHexDigit String
xs of
        (ys :: String
ys, zs :: String
zs) -> (Int -> Char
chr (Int -> Char) -> (String -> Int) -> String -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
readHex (String -> Char) -> String -> Char
forall a b. (a -> b) -> a -> b
$ Char
xChar -> String -> String
forall a. a -> [a] -> [a]
:String
ys) Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
zs
      '\\' : 'o' : x :: Char
x : xs :: String
xs | Char -> Bool
isOctDigit Char
x -> case (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
span Char -> Bool
isOctDigit String
xs of
        (ys :: String
ys, zs :: String
zs) -> (Int -> Char
chr (Int -> Char) -> (String -> Int) -> String -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
readOct (String -> Char) -> String -> Char
forall a b. (a -> b) -> a -> b
$ Char
xChar -> String -> String
forall a. a -> [a] -> [a]
:String
ys) Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
zs
      '\\' : x :: Char
x : xs :: String
xs | Char -> Bool
isDigit Char
x -> case (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
span Char -> Bool
isDigit String
xs of
        (ys :: String
ys, zs :: String
zs) -> (Int -> Char
chr (Int -> Char) -> (String -> Int) -> String -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
forall a. Read a => String -> a
read (String -> Char) -> String -> Char
forall a b. (a -> b) -> a -> b
$ Char
xChar -> String -> String
forall a. a -> [a] -> [a]
:String
ys) Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
zs
      '\\' : input_ :: String
input_ -> case String
input_ of
        '\\' : xs :: String
xs -> '\\' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'a' : xs :: String
xs -> '\a' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'b' : xs :: String
xs -> '\b' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'f' : xs :: String
xs -> '\f' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'n' : xs :: String
xs -> '\n' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'r' : xs :: String
xs -> '\r' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        't' : xs :: String
xs -> '\t' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'v' : xs :: String
xs -> '\v' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '&' : xs :: String
xs -> String -> String
go String
xs
        'N':'U':'L' : xs :: String
xs -> '\NUL' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'S':'O':'H' : xs :: String
xs -> '\SOH' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'S':'T':'X' : xs :: String
xs -> '\STX' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'E':'T':'X' : xs :: String
xs -> '\ETX' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'E':'O':'T' : xs :: String
xs -> '\EOT' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'E':'N':'Q' : xs :: String
xs -> '\ENQ' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'A':'C':'K' : xs :: String
xs -> '\ACK' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'B':'E':'L' : xs :: String
xs -> '\BEL' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'B':'S' : xs :: String
xs -> '\BS' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'H':'T' : xs :: String
xs -> '\HT' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'L':'F' : xs :: String
xs -> '\LF' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'V':'T' : xs :: String
xs -> '\VT' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'F':'F' : xs :: String
xs -> '\FF' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'C':'R' : xs :: String
xs -> '\CR' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'S':'O' : xs :: String
xs -> '\SO' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'S':'I' : xs :: String
xs -> '\SI' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'D':'L':'E' : xs :: String
xs -> '\DLE' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'D':'C':'1' : xs :: String
xs -> '\DC1' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'D':'C':'2' : xs :: String
xs -> '\DC2' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'D':'C':'3' : xs :: String
xs -> '\DC3' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'D':'C':'4' : xs :: String
xs -> '\DC4' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'N':'A':'K' : xs :: String
xs -> '\NAK' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'S':'Y':'N' : xs :: String
xs -> '\SYN' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'E':'T':'B' : xs :: String
xs -> '\ETB' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'C':'A':'N' : xs :: String
xs -> '\CAN' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'E':'M' : xs :: String
xs -> '\EM' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'S':'U':'B' : xs :: String
xs -> '\SUB' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'E':'S':'C' : xs :: String
xs -> '\ESC' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'F':'S' : xs :: String
xs -> '\FS' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'G':'S' : xs :: String
xs -> '\GS' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'R':'S' : xs :: String
xs -> '\RS' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'U':'S' : xs :: String
xs -> '\US' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'S':'P' : xs :: String
xs -> '\SP' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        'D':'E':'L' : xs :: String
xs -> '\DEL' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'@' : xs :: String
xs -> '\^@' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'A' : xs :: String
xs -> '\^A' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'B' : xs :: String
xs -> '\^B' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'C' : xs :: String
xs -> '\^C' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'D' : xs :: String
xs -> '\^D' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'E' : xs :: String
xs -> '\^E' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'F' : xs :: String
xs -> '\^F' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'G' : xs :: String
xs -> '\^G' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'H' : xs :: String
xs -> '\^H' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'I' : xs :: String
xs -> '\^I' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'J' : xs :: String
xs -> '\^J' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'K' : xs :: String
xs -> '\^K' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'L' : xs :: String
xs -> '\^L' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'M' : xs :: String
xs -> '\^M' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'N' : xs :: String
xs -> '\^N' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'O' : xs :: String
xs -> '\^O' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'P' : xs :: String
xs -> '\^P' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'Q' : xs :: String
xs -> '\^Q' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'R' : xs :: String
xs -> '\^R' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'S' : xs :: String
xs -> '\^S' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'T' : xs :: String
xs -> '\^T' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'U' : xs :: String
xs -> '\^U' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'V' : xs :: String
xs -> '\^V' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'W' : xs :: String
xs -> '\^W' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'X' : xs :: String
xs -> '\^X' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'Y' : xs :: String
xs -> '\^Y' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'Z' : xs :: String
xs -> '\^Z' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'[' : xs :: String
xs -> '\^[' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'\\' : xs :: String
xs -> '\^\' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':']' : xs :: String
xs -> '\^]' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'^' : xs :: String
xs -> '\^^' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        '^':'_' : xs :: String
xs -> '\^_' Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs
        xs :: String
xs -> String -> String
go String
xs
      x :: Char
x:xs :: String
xs -> Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
go String
xs

    readHex :: String -> Int
    readHex :: String -> Int
readHex xs :: String
xs = case ReadS Int
forall a. (Eq a, Num a) => ReadS a
N.readHex String
xs of
      [(n :: Int
n, "")] -> Int
n
      _ -> String -> Int
forall a. HasCallStack => String -> a
error "Data.String.Interpolate.Util.readHex: no parse"

    readOct :: String -> Int
    readOct :: String -> Int
readOct xs :: String
xs = case ReadS Int
forall a. (Eq a, Num a) => ReadS a
N.readOct String
xs of
      [(n :: Int
n, "")] -> Int
n
      _ -> String -> Int
forall a. HasCallStack => String -> a
error "Data.String.Interpolate.Util.readHex: no parse"