{-# LINE 1 "System/Locale/SetLocale.hsc" #-}
{-# LANGUAGE DeriveDataTypeable
{-# LINE 2 "System/Locale/SetLocale.hsc" #-}
           , ForeignFunctionInterface #-}

-- Copyright (c) 2014, Sven Bartscher
-- Look the file LICENSE.txt in the toplevel directory of the source tree for
-- more information.

module System.Locale.SetLocale ( Category(..)
                               , categoryToCInt
                               , setLocale
                               )
    where


{-# LINE 15 "System/Locale/SetLocale.hsc" #-}

import Data.Typeable (Typeable)
import Foreign.C ( peekCString
                 , CString
                 , withCString
                 , CInt(CInt) -- Newtypes are only allowed in foreign
                 )            -- declarations if their constructor is
                              -- in scope.
import Foreign.Ptr (nullPtr)

data Category = LC_ALL
              | LC_COLLATE
              | LC_CTYPE
              | LC_MESSAGES
              | LC_MONETARY
              | LC_NUMERIC
              | LC_TIME
                deriving (Bounded, Enum, Eq, Ord, Read, Show, Typeable)

categoryToCInt :: Category -> CInt
categoryToCInt LC_ALL = 6
{-# LINE 36 "System/Locale/SetLocale.hsc" #-}
categoryToCInt LC_COLLATE = 3
{-# LINE 37 "System/Locale/SetLocale.hsc" #-}
categoryToCInt LC_CTYPE = 0
{-# LINE 38 "System/Locale/SetLocale.hsc" #-}

{-# LINE 39 "System/Locale/SetLocale.hsc" #-}
categoryToCInt LC_MESSAGES = 5
{-# LINE 40 "System/Locale/SetLocale.hsc" #-}

{-# LINE 43 "System/Locale/SetLocale.hsc" #-}
categoryToCInt LC_MONETARY = 4
{-# LINE 44 "System/Locale/SetLocale.hsc" #-}
categoryToCInt LC_NUMERIC = 1
{-# LINE 45 "System/Locale/SetLocale.hsc" #-}
categoryToCInt LC_TIME = 2
{-# LINE 46 "System/Locale/SetLocale.hsc" #-}

foreign import ccall "locale.h setlocale" c_setlocale :: CInt -> CString -> IO CString

setLocale :: Category -> Maybe String -> IO (Maybe String)

{-# LINE 53 "System/Locale/SetLocale.hsc" #-}
setLocale c Nothing = c_setlocale (categoryToCInt c) nullPtr >>= checkReturn
setLocale c (Just locale) = (withCString locale $ c_setlocale $ categoryToCInt c)
                            >>= checkReturn

checkReturn :: CString -> IO (Maybe String)
checkReturn r
    | r == nullPtr = return Nothing
    | otherwise = fmap Just $ peekCString r