module NumParse ( readDigits, readFloat ) where

import qualified Data.ByteString       as BS
import qualified Data.ByteString.Char8 as ASCII
import           Foreign.C.String      (CString)
import           System.IO.Unsafe      (unsafeDupablePerformIO)

readFloat :: BS.ByteString -> Double
readFloat :: ByteString -> Double
readFloat = IO Double -> Double
forall a. IO a -> a
unsafeDupablePerformIO (IO Double -> Double)
-> (ByteString -> IO Double) -> ByteString -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> (CString -> IO Double) -> IO Double
forall a. ByteString -> (CString -> IO a) -> IO a
`BS.useAsCString` CString -> IO Double
atof)

foreign import ccall unsafe atof :: CString -> IO Double

readDigits :: BS.ByteString -> Integer
readDigits :: ByteString -> Integer
readDigits ByteString
b | Just (Word8
45, ByteString
bs) <- ByteString -> Maybe (Word8, ByteString)
BS.uncons ByteString
b = Integer -> Integer
forall a. Num a => a -> a
negate (Integer -> Integer) -> Integer -> Integer
forall a b. (a -> b) -> a -> b
$ ByteString -> Integer
readDigits ByteString
bs
readDigits ByteString
b = (Integer -> Char -> Integer) -> Integer -> ByteString -> Integer
forall a. (a -> Char -> a) -> a -> ByteString -> a
ASCII.foldl' (\Integer
seed Char
x -> Integer
10 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
seed Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Char -> Integer
forall {a}. Num a => Char -> a
f Char
x) Integer
0 ByteString
b
    where f :: Char -> a
f Char
'0' = a
0; f Char
'1' = a
1; f Char
'2' = a
2; f Char
'3' = a
3;
          f Char
'4' = a
4; f Char
'5' = a
5; f Char
'6' = a
6; f Char
'7' = a
7;
          f Char
'8' = a
8; f Char
'9' = a
9
          f Char
c   = [Char] -> a
forall a. HasCallStack => [Char] -> a
error (Char
cChar -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:[Char]
" is not a valid digit!")