{-# LANGUAGE MultiParamTypeClasses
  #-}


module Data.ByteString.Nums.Careless.Float where


import Prelude hiding (length, splitAt)
import Data.ByteString.Char8 hiding (inits, elem, last)
import qualified Data.ByteString.Lazy.Char8 as Lazy


import Data.ByteString.Nums.Careless.Int





{-| Types that can be read from floating point strings. The fractional part is
    taken to be the last group of digits behind a decimal point or comma.
    Characters are not decimal digits are simply skipped.
 -}
class (Intable b f, Fractional f) => Floatable b f where
  float                     ::  b -> f

instance Floatable ByteString Float where
  float                      =  strict_float
instance Floatable ByteString Double where
  float                      =  strict_float
instance Floatable ByteString Rational where
  float                      =  strict_float

instance Floatable Lazy.ByteString Float where
  float                      =  lazy_float
instance Floatable Lazy.ByteString Double where
  float                      =  lazy_float
instance Floatable Lazy.ByteString Rational where
  float                      =  lazy_float


strict_float bytes           =  case findIndices (`elem` ".,") bytes of
  [ ]                       ->  int bytes
  idx                       ->  hi' + (int lo * (0.1 ^ length lo) * s)
   where
    (hi, lo)                 =  splitAt (last idx) bytes
    hi'                      =  int hi
    s                        =  signum hi'

lazy_float bytes             =  case Lazy.findIndices (`elem` ".,") bytes of
  [ ]                       ->  int bytes
  idx                       ->  hi' + (int lo * (0.1 ^ Lazy.length lo) * s)
   where
    (hi, lo)                 =  Lazy.splitAt (last idx) bytes
    hi'                      =  int hi
    s                        =  signum hi'