{-# LANGUAGE CPP                        #-}
#if MIN_VERSION_base(4,5,0)
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving         #-}
#endif
{-# OPTIONS_GHC -fno-warn-orphans #-}
{-|
Module:      TextShow.Foreign.C.Types
Copyright:   (C) 2014-2015 Ryan Scott
License:     BSD-style (see the file LICENSE)
Maintainer:  Ryan Scott
Stability:   Provisional
Portability: GHC

Monomorphic 'TextShow' functions for Haskell newtypes corresponding to C
types in the Foreign Function Interface (FFI).

/Since: 2/
-}
module TextShow.Foreign.C.Types (
      showbCCharPrec
    , showbCSCharPrec
    , showbCUChar
    , showbCShortPrec
    , showbCUShort
    , showbCIntPrec
    , showbCUInt
    , showbCLongPrec
    , showbCULong
    , showbCPtrdiffPrec
    , showbCSize
    , showbCWcharPrec
    , showbCSigAtomicPrec
    , showbCLLongPrec
    , showbCULLong
    , showbCIntPtrPrec
    , showbCUIntPtr
    , showbCIntMaxPrec
    , showbCUIntMax
    , showbCClockPrec
    , showbCTimePrec
#if MIN_VERSION_base(4,4,0)
    , showbCUSeconds
    , showbCSUSecondsPrec
#endif
    , showbCFloatPrec
    , showbCDoublePrec
    ) where

import Data.Text.Lazy.Builder (Builder)

import Foreign.C.Types

import TextShow.Classes (TextShow(showb, showbPrec))
import TextShow.Data.Floating ()
import TextShow.Data.Integral ()

#if !(MIN_VERSION_base(4,5,0))
import Data.Int
import Data.Word

import Unsafe.Coerce (unsafeCoerce)

# include "HsBaseConfig.h"
# include "inline.h"
#endif

-- | Convert a 'CChar' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCCharPrec :: Int -> CChar -> Builder
#if MIN_VERSION_base(4,5,0)
showbCCharPrec = showbPrec
{-# INLINE showbCCharPrec #-}
#else
showbCCharPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_CHAR -> Builder)
#endif

-- | Convert a 'CSChar' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCSCharPrec :: Int -> CSChar -> Builder
#if MIN_VERSION_base(4,5,0)
showbCSCharPrec = showbPrec
{-# INLINE showbCSCharPrec #-}
#else
showbCSCharPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_SIGNED_CHAR -> Builder)
#endif

-- | Convert a 'CUChar' to a 'Builder'.
--
-- /Since: 2/
showbCUChar :: CUChar -> Builder
#if MIN_VERSION_base(4,5,0)
showbCUChar = showb
{-# INLINE showbCUChar #-}
#else
showbCUChar = unsafeCoerce (showb :: HTYPE_UNSIGNED_CHAR -> Builder)
#endif

-- | Convert a 'CShort' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCShortPrec :: Int -> CShort -> Builder
#if MIN_VERSION_base(4,5,0)
showbCShortPrec = showbPrec
{-# INLINE showbCShortPrec #-}
#else
showbCShortPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_SHORT -> Builder)
#endif

-- | Convert a 'CUShort' to a 'Builder'.
--
-- /Since: 2/
showbCUShort :: CUShort -> Builder
#if MIN_VERSION_base(4,5,0)
showbCUShort = showb
{-# INLINE showbCUShort #-}
#else
showbCUShort = unsafeCoerce (showb :: HTYPE_UNSIGNED_SHORT -> Builder)
#endif

-- | Convert a 'CInt' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCIntPrec :: Int -> CInt -> Builder
#if MIN_VERSION_base(4,5,0)
showbCIntPrec = showbPrec
{-# INLINE showbCIntPrec #-}
#else
showbCIntPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_INT -> Builder)
#endif

-- | Convert a 'CUInt' to a 'Builder'.
--
-- /Since: 2/
showbCUInt :: CUInt -> Builder
#if MIN_VERSION_base(4,5,0)
showbCUInt = showb
{-# INLINE showbCUInt #-}
#else
showbCUInt = unsafeCoerce (showb :: HTYPE_UNSIGNED_INT -> Builder)
#endif

-- | Convert a 'CLong' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCLongPrec :: Int -> CLong -> Builder
#if MIN_VERSION_base(4,5,0)
showbCLongPrec = showbPrec
{-# INLINE showbCLongPrec #-}
#else
showbCLongPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_LONG -> Builder)
#endif

-- | Convert a 'CULong' to a 'Builder'.
--
-- /Since: 2/
showbCULong :: CULong -> Builder
#if MIN_VERSION_base(4,5,0)
showbCULong = showb
{-# INLINE showbCULong #-}
#else
showbCULong = unsafeCoerce (showb :: HTYPE_UNSIGNED_LONG -> Builder)
#endif

-- | Convert a 'CPtrdiff' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCPtrdiffPrec :: Int -> CPtrdiff -> Builder
#if MIN_VERSION_base(4,5,0)
showbCPtrdiffPrec = showbPrec
{-# INLINE showbCPtrdiffPrec #-}
#else
showbCPtrdiffPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_PTRDIFF_T -> Builder)
#endif

-- | Convert a 'CSize' to a 'Builder'.
--
-- /Since: 2/
showbCSize :: CSize -> Builder
#if MIN_VERSION_base(4,5,0)
showbCSize = showb
{-# INLINE showbCSize #-}
#else
showbCSize = unsafeCoerce (showb :: HTYPE_SIZE_T -> Builder)
#endif

-- | Convert a 'CWchar' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCWcharPrec :: Int -> CWchar -> Builder
#if MIN_VERSION_base(4,5,0)
showbCWcharPrec = showbPrec
{-# INLINE showbCWcharPrec #-}
#else
showbCWcharPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_WCHAR_T -> Builder)
#endif

-- | Convert a 'CSigAtomic' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCSigAtomicPrec :: Int -> CSigAtomic -> Builder
#if MIN_VERSION_base(4,5,0)
showbCSigAtomicPrec = showbPrec
{-# INLINE showbCSigAtomicPrec #-}
#else
showbCSigAtomicPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_SIG_ATOMIC_T -> Builder)
#endif

-- | Convert a 'CLLong' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCLLongPrec :: Int -> CLLong -> Builder
#if MIN_VERSION_base(4,5,0)
showbCLLongPrec = showbPrec
{-# INLINE showbCLLongPrec #-}
#else
showbCLLongPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_LONG_LONG -> Builder)
#endif

-- | Convert a 'CULLong' to a 'Builder'.
--
-- /Since: 2/
showbCULLong :: CULLong -> Builder
#if MIN_VERSION_base(4,5,0)
showbCULLong = showb
{-# INLINE showbCULLong #-}
#else
showbCULLong = unsafeCoerce (showb :: HTYPE_UNSIGNED_LONG_LONG -> Builder)
#endif

-- | Convert a 'CIntPtr' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCIntPtrPrec :: Int -> CIntPtr -> Builder
#if MIN_VERSION_base(4,5,0)
showbCIntPtrPrec = showbPrec
{-# INLINE showbCIntPtrPrec #-}
#else
showbCIntPtrPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_INTPTR_T -> Builder)
#endif

-- | Convert a 'CUIntPtr' to a 'Builder'.
--
-- /Since: 2/
showbCUIntPtr :: CUIntPtr -> Builder
#if MIN_VERSION_base(4,5,0)
showbCUIntPtr = showb
{-# INLINE showbCUIntPtr #-}
#else
showbCUIntPtr = unsafeCoerce (showb :: HTYPE_UINTPTR_T -> Builder)
#endif

-- | Convert a 'CIntMax' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCIntMaxPrec :: Int -> CIntMax -> Builder
#if MIN_VERSION_base(4,5,0)
showbCIntMaxPrec = showbPrec
{-# INLINE showbCIntMaxPrec #-}
#else
showbCIntMaxPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_INTMAX_T -> Builder)
#endif

-- | Convert a 'CUIntMax' to a 'Builder'.
--
-- /Since: 2/
showbCUIntMax :: CUIntMax -> Builder
#if MIN_VERSION_base(4,5,0)
showbCUIntMax = showb
{-# INLINE showbCUIntMax #-}
#else
showbCUIntMax = unsafeCoerce (showb :: HTYPE_UINTMAX_T -> Builder)
#endif

-- | Convert a 'CClock' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCClockPrec :: Int -> CClock -> Builder
#if MIN_VERSION_base(4,5,0)
showbCClockPrec = showbPrec
{-# INLINE showbCClockPrec #-}
#else
showbCClockPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_CLOCK_T -> Builder)
#endif

-- | Convert a 'CTime' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCTimePrec :: Int -> CTime -> Builder
#if MIN_VERSION_base(4,5,0)
showbCTimePrec = showbPrec
{-# INLINE showbCTimePrec #-}
#else
showbCTimePrec = unsafeCoerce (showbPrec :: Int -> HTYPE_TIME_T -> Builder)
#endif

#if MIN_VERSION_base(4,4,0)
-- | Convert a 'CUSeconds' value to a 'Builder'.
-- This function is only available with @base-4.4.0.0@ or later.
--
-- /Since: 2/
showbCUSeconds :: CUSeconds -> Builder
# if MIN_VERSION_base(4,5,0)
showbCUSeconds = showb
{-# INLINE showbCUSeconds #-}
# else
showbCUSeconds = unsafeCoerce (showb :: HTYPE_USECONDS_T -> Builder)
# endif

-- | Convert a 'CSUSeconds' value to a 'Builder' with the given precedence.
-- This function is only available with @base-4.4.0.0@ or later.
--
-- /Since: 2/
showbCSUSecondsPrec :: Int -> CSUSeconds -> Builder
# if MIN_VERSION_base(4,5,0)
showbCSUSecondsPrec = showbPrec
{-# INLINE showbCSUSecondsPrec #-}
# else
showbCSUSecondsPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_SUSECONDS_T -> Builder)
# endif
#endif

-- | Convert a 'CFloat' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCFloatPrec :: Int -> CFloat -> Builder
#if MIN_VERSION_base(4,5,0)
showbCFloatPrec = showbPrec
{-# INLINE showbCFloatPrec #-}
#else
showbCFloatPrec = unsafeCoerce (showbPrec :: Int -> HTYPE_FLOAT -> Builder)
#endif

-- | Convert a 'CDouble' to a 'Builder' with the given precedence.
--
-- /Since: 2/
showbCDoublePrec :: Int -> CDouble -> Builder
#if MIN_VERSION_base(4,5,0)
showbCDoublePrec = showbPrec
{-# INLINE showbCDoublePrec #-}
#else
showbCDoublePrec = unsafeCoerce (showbPrec :: Int -> HTYPE_DOUBLE -> Builder)
#endif

#if MIN_VERSION_base(4,5,0)
deriving instance TextShow CChar
deriving instance TextShow CSChar
deriving instance TextShow CUChar
deriving instance TextShow CShort
deriving instance TextShow CUShort
deriving instance TextShow CInt
deriving instance TextShow CUInt
deriving instance TextShow CLong
deriving instance TextShow CULong
deriving instance TextShow CPtrdiff
deriving instance TextShow CSize
deriving instance TextShow CWchar
deriving instance TextShow CSigAtomic
deriving instance TextShow CLLong
deriving instance TextShow CULLong
deriving instance TextShow CIntPtr
deriving instance TextShow CUIntPtr
deriving instance TextShow CIntMax
deriving instance TextShow CUIntMax
deriving instance TextShow CClock
deriving instance TextShow CTime
# if MIN_VERSION_base(4,4,0)
deriving instance TextShow CUSeconds
deriving instance TextShow CSUSeconds
# endif
deriving instance TextShow CFloat
deriving instance TextShow CDouble
#else
instance TextShow CChar where
    showbPrec = showbCCharPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CSChar where
    showbPrec = showbCSCharPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CUChar where
    showb = showbCUChar
    INLINE_INST_FUN(showb)

instance TextShow CShort where
    showbPrec = showbCShortPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CUShort where
    showb = showbCUShort
    INLINE_INST_FUN(showb)

instance TextShow CInt where
    showbPrec = showbCIntPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CUInt where
    showb = showbCUInt
    INLINE_INST_FUN(showb)

instance TextShow CLong where
    showbPrec = showbCLongPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CULong where
    showb = showbCULong
    INLINE_INST_FUN(showb)

instance TextShow CPtrdiff where
    showbPrec = showbCPtrdiffPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CSize where
    showb = showbCSize
    INLINE_INST_FUN(showb)

instance TextShow CWchar where
    showbPrec = showbCWcharPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CSigAtomic where
    showbPrec = showbCSigAtomicPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CLLong where
    showbPrec = showbCLLongPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CULLong where
    showb = showbCULLong
    INLINE_INST_FUN(showb)

instance TextShow CIntPtr where
    showbPrec = showbCIntPtrPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CUIntPtr where
    showb = showbCUIntPtr
    INLINE_INST_FUN(showb)

instance TextShow CIntMax where
    showbPrec = showbCIntMaxPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CUIntMax where
    showb = showbCUIntMax
    INLINE_INST_FUN(showb)

instance TextShow CClock where
    showbPrec = showbCClockPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CTime where
    showbPrec = showbCTimePrec
    INLINE_INST_FUN(showbPrec)

# if MIN_VERSION_base(4,4,0)
instance TextShow CUSeconds where
    showb = showbCUSeconds
    INLINE_INST_FUN(showb)

instance TextShow CSUSeconds where
    showbPrec = showbCSUSecondsPrec
    INLINE_INST_FUN(showbPrec)
# endif

instance TextShow CFloat where
    showbPrec = showbCFloatPrec
    INLINE_INST_FUN(showbPrec)

instance TextShow CDouble where
    showbPrec = showbCDoublePrec
    INLINE_INST_FUN(showbPrec)
#endif
