module Data.Double.Conversion.ByteString
(
toExponential
, toFixed
, toPrecision
, toShortest
) where
import Control.Monad (when)
import Foreign.ForeignPtr (withForeignPtr)
import Data.Double.Conversion.FFI
import Data.Word (Word8)
import Data.ByteString.Internal (ByteString(..), mallocByteString)
import Foreign.C.Types (CDouble, CInt)
import Foreign.Ptr (Ptr)
import System.IO.Unsafe (unsafePerformIO)
toExponential :: Int -> Double -> ByteString
toExponential ndigits = convert "toExponential" len $ \val mba ->
c_ToExponential val mba (fromIntegral ndigits)
where len = c_ToExponentialLength
toFixed :: Int -> Double -> ByteString
toFixed ndigits = convert "toFixed" len $ \val mba ->
c_ToFixed val mba (fromIntegral ndigits)
where len = c_ToFixedLength
toShortest :: Double -> ByteString
toShortest = convert "toShortest" len c_ToShortest
where len = c_ToShortestLength
toPrecision :: Int -> Double -> ByteString
toPrecision ndigits = convert "toPrecision" len $ \val mba ->
c_ToPrecision val mba (fromIntegral ndigits)
where len = c_ToPrecisionLength
convert :: String -> CInt -> (CDouble -> Ptr Word8 -> IO CInt)
-> Double -> ByteString
convert func len act val = unsafePerformIO $ do
fp <- mallocByteString (fromIntegral len)
size <- withForeignPtr fp $ act (realToFrac val)
when (size == 1) .
fail $ "Data.Double.Conversion.ByteString." ++ func ++
": conversion failed (invalid precision requested)"
return $ PS fp 0 (fromIntegral size)