bytestring-read 0.1.0 → 0.2.0
raw patch · 8 files changed
+453/−325 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.ByteString.Read: class KnownNat n => Base n
- Data.ByteString.Read: class (Fractional a, Num (Fraction a), Ord (Fraction a)) => EffectiveDigit a where data family Fraction a
- Data.ByteString.Read: floating :: EffectiveDigit r => ByteString -> Maybe (r, ByteString)
- Data.ByteString.Read: floating' :: (Base b, EffectiveDigit r) => proxy b -> ByteString -> Maybe (r, ByteString)
- Data.ByteString.Read: floating10 :: EffectiveDigit r => ByteString -> Maybe (r, ByteString)
- Data.ByteString.Read: fromFraction :: (EffectiveDigit a, Num b) => Fraction a -> b
- Data.ByteString.Read: instance Base 10
- Data.ByteString.Read: instance Base 11
- Data.ByteString.Read: instance Base 12
- Data.ByteString.Read: instance Base 13
- Data.ByteString.Read: instance Base 14
- Data.ByteString.Read: instance Base 15
- Data.ByteString.Read: instance Base 16
- Data.ByteString.Read: instance Base 17
- Data.ByteString.Read: instance Base 18
- Data.ByteString.Read: instance Base 19
- Data.ByteString.Read: instance Base 2
- Data.ByteString.Read: instance Base 20
- Data.ByteString.Read: instance Base 21
- Data.ByteString.Read: instance Base 22
- Data.ByteString.Read: instance Base 23
- Data.ByteString.Read: instance Base 24
- Data.ByteString.Read: instance Base 25
- Data.ByteString.Read: instance Base 26
- Data.ByteString.Read: instance Base 27
- Data.ByteString.Read: instance Base 28
- Data.ByteString.Read: instance Base 29
- Data.ByteString.Read: instance Base 3
- Data.ByteString.Read: instance Base 30
- Data.ByteString.Read: instance Base 31
- Data.ByteString.Read: instance Base 32
- Data.ByteString.Read: instance Base 33
- Data.ByteString.Read: instance Base 34
- Data.ByteString.Read: instance Base 35
- Data.ByteString.Read: instance Base 36
- Data.ByteString.Read: instance Base 4
- Data.ByteString.Read: instance Base 5
- Data.ByteString.Read: instance Base 6
- Data.ByteString.Read: instance Base 7
- Data.ByteString.Read: instance Base 8
- Data.ByteString.Read: instance Base 9
- Data.ByteString.Read: instance EffectiveDigit Double
- Data.ByteString.Read: instance EffectiveDigit Float
- Data.ByteString.Read: instance EffectiveDigit Rational
- Data.ByteString.Read: instance Eq (Fraction Double)
- Data.ByteString.Read: instance Eq (Fraction Float)
- Data.ByteString.Read: instance Eq (Fraction Rational)
- Data.ByteString.Read: instance Num (Fraction Double)
- Data.ByteString.Read: instance Num (Fraction Float)
- Data.ByteString.Read: instance Num (Fraction Rational)
- Data.ByteString.Read: instance Ord (Fraction Double)
- Data.ByteString.Read: instance Ord (Fraction Float)
- Data.ByteString.Read: instance Ord (Fraction Rational)
- Data.ByteString.Read: isDigit :: Base n => proxy n -> Word8 -> Bool
- Data.ByteString.Read: maxValue :: EffectiveDigit a => proxy a -> Maybe (Fraction a)
- Data.ByteString.Read: unsafeToDigit :: Base n => proxy n -> Word8 -> Word8
+ Data.ByteString.Read: class (Fractional a, Num (Fraction a), Ord (Fraction a)) => ReadFractional a
+ Data.ByteString.Read: fractional :: ReadFractional r => ByteString -> Maybe (r, ByteString)
+ Data.ByteString.Read: int :: ByteString -> Maybe (Int, ByteString)
+ Data.ByteString.Read: integral :: Num n => ByteString -> Maybe (n, ByteString)
+ Data.ByteString.Read.Class: class KnownNat n => Radix n
+ Data.ByteString.Read.Class: class (Fractional a, Num (Fraction a), Ord (Fraction a)) => ReadFractional a where data family Fraction a
+ Data.ByteString.Read.Class: fromFraction :: (ReadFractional a, Num b) => Fraction a -> b
+ Data.ByteString.Read.Class: instance Eq (Fraction Double)
+ Data.ByteString.Read.Class: instance Eq (Fraction Float)
+ Data.ByteString.Read.Class: instance Eq (Fraction Rational)
+ Data.ByteString.Read.Class: instance Num (Fraction Double)
+ Data.ByteString.Read.Class: instance Num (Fraction Float)
+ Data.ByteString.Read.Class: instance Num (Fraction Rational)
+ Data.ByteString.Read.Class: instance Ord (Fraction Double)
+ Data.ByteString.Read.Class: instance Ord (Fraction Float)
+ Data.ByteString.Read.Class: instance Ord (Fraction Rational)
+ Data.ByteString.Read.Class: instance Radix 10
+ Data.ByteString.Read.Class: instance Radix 11
+ Data.ByteString.Read.Class: instance Radix 12
+ Data.ByteString.Read.Class: instance Radix 13
+ Data.ByteString.Read.Class: instance Radix 14
+ Data.ByteString.Read.Class: instance Radix 15
+ Data.ByteString.Read.Class: instance Radix 16
+ Data.ByteString.Read.Class: instance Radix 17
+ Data.ByteString.Read.Class: instance Radix 18
+ Data.ByteString.Read.Class: instance Radix 19
+ Data.ByteString.Read.Class: instance Radix 2
+ Data.ByteString.Read.Class: instance Radix 20
+ Data.ByteString.Read.Class: instance Radix 21
+ Data.ByteString.Read.Class: instance Radix 22
+ Data.ByteString.Read.Class: instance Radix 23
+ Data.ByteString.Read.Class: instance Radix 24
+ Data.ByteString.Read.Class: instance Radix 25
+ Data.ByteString.Read.Class: instance Radix 26
+ Data.ByteString.Read.Class: instance Radix 27
+ Data.ByteString.Read.Class: instance Radix 28
+ Data.ByteString.Read.Class: instance Radix 29
+ Data.ByteString.Read.Class: instance Radix 3
+ Data.ByteString.Read.Class: instance Radix 30
+ Data.ByteString.Read.Class: instance Radix 31
+ Data.ByteString.Read.Class: instance Radix 32
+ Data.ByteString.Read.Class: instance Radix 33
+ Data.ByteString.Read.Class: instance Radix 34
+ Data.ByteString.Read.Class: instance Radix 35
+ Data.ByteString.Read.Class: instance Radix 36
+ Data.ByteString.Read.Class: instance Radix 4
+ Data.ByteString.Read.Class: instance Radix 5
+ Data.ByteString.Read.Class: instance Radix 6
+ Data.ByteString.Read.Class: instance Radix 7
+ Data.ByteString.Read.Class: instance Radix 8
+ Data.ByteString.Read.Class: instance Radix 9
+ Data.ByteString.Read.Class: instance ReadFractional Double
+ Data.ByteString.Read.Class: instance ReadFractional Float
+ Data.ByteString.Read.Class: instance ReadFractional Rational
+ Data.ByteString.Read.Class: isDigit :: Radix n => proxy n -> Word8 -> Bool
+ Data.ByteString.Read.Class: maxValue :: ReadFractional a => proxy a -> Maybe (Fraction a)
+ Data.ByteString.Read.Class: unsafeToDigit :: Radix n => proxy n -> Word8 -> Word8
+ Data.ByteString.Read.DEPRECATED: floating :: EffectiveDigit r => ByteString -> Maybe (r, ByteString)
+ Data.ByteString.Read.DEPRECATED: floating' :: (Base b, EffectiveDigit r) => proxy b -> ByteString -> Maybe (r, ByteString)
+ Data.ByteString.Read.DEPRECATED: floating10 :: EffectiveDigit r => ByteString -> Maybe (r, ByteString)
+ Data.ByteString.Read.DEPRECATED: type Base = Radix
+ Data.ByteString.Read.DEPRECATED: type EffectiveDigit = ReadFractional
+ Data.ByteString.Read.Fractional: double :: ByteString -> Maybe (Double, ByteString)
+ Data.ByteString.Read.Fractional: fractional :: ReadFractional r => ByteString -> Maybe (r, ByteString)
+ Data.ByteString.Read.Fractional: fractional' :: (Radix b, ReadFractional r) => proxy b -> ByteString -> Maybe (r, ByteString)
+ Data.ByteString.Read.Fractional: fractional10 :: ReadFractional r => ByteString -> Maybe (r, ByteString)
+ Data.ByteString.Read.Integral: int :: ByteString -> Maybe (Int, ByteString)
+ Data.ByteString.Read.Integral: integral :: Num n => ByteString -> Maybe (n, ByteString)
+ Data.ByteString.Read.Integral: integral' :: (Radix b, Num n) => proxy b -> ByteString -> Maybe (n, ByteString)
Files
- bench/main.hs +1/−1
- bytestring-read.cabal +6/−2
- src/Data/ByteString/Read.hs +21/−280
- src/Data/ByteString/Read/Class.hs +123/−0
- src/Data/ByteString/Read/DEPRECATED.hs +26/−0
- src/Data/ByteString/Read/Fractional.hs +169/−0
- src/Data/ByteString/Read/Integral.hs +58/−0
- tests/tasty.hs +49/−42
bench/main.hs view
@@ -28,7 +28,7 @@ checkConsumed _ = error "not consumed" bytestringRead :: ByteString -> Double-bytestringRead = maybe (error "parse error") checkConsumed . R.signed R.floating+bytestringRead = maybe (error "parse error") checkConsumed . R.signed R.fractional text :: ByteString -> Double text = either (const $ error "parse error") checkConsumed . T.signed T.double . T.decodeUtf8
bytestring-read.cabal view
@@ -1,6 +1,6 @@ name: bytestring-read-version: 0.1.0-synopsis: fast ByteString to Double converting library+version: 0.2.0+synopsis: fast ByteString to number converting library description: benchmark: <http://philopon.github.io/bytestring-read/bench.html> license: MIT license-file: LICENSE@@ -15,6 +15,10 @@ library exposed-modules: Data.ByteString.Read+ Data.ByteString.Read.Class+ Data.ByteString.Read.Fractional+ Data.ByteString.Read.Integral+ Data.ByteString.Read.DEPRECATED build-depends: base >=4.6 && <4.8 , bytestring >=0.10 && <0.11 , types-compat >=0.1 && <0.2
src/Data/ByteString/Read.hs view
@@ -1,297 +1,35 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE CPP #-}- module Data.ByteString.Read- ( -- * functions- floating+ ( -- * fractional+ ReadFractional+ , fractional , double- , signed - -- * classes- , EffectiveDigit(..)- , Base(..)+ -- * integral+ , integral+ , int - -- * raw functions- , floating10- , floating'+ -- * common+ , signed++ -- * DEPRECATED+ , module Data.ByteString.Read.DEPRECATED ) where -import Control.Arrow(first)-import Control.Applicative((<$>))+import Control.Applicative+import Control.Arrow -import Data.ByteString.Unsafe import Data.ByteString(ByteString)+import Data.ByteString.Unsafe import qualified Data.ByteString as S-import Data.Word -import GHC.TypeLits.Compat-import Data.Proxy.Compat+import Data.ByteString.Read.Class+import Data.ByteString.Read.Integral+import Data.ByteString.Read.Fractional+import Data.ByteString.Read.DEPRECATED -- $setup -- >>> :set -XDataKinds -XOverloadedStrings -minus :: Word8-minus = 45-{-# INLINE minus #-}--plus :: Word8-plus = 43-{-# INLINE plus #-}---class (Fractional a, Num (Fraction a), Ord (Fraction a)) => EffectiveDigit a where- -- | data type to store fractional part of floating- data Fraction a-- -- | maximum value of fractional part.- --- -- Nothing if arbitrary-precision.- -- - -- @- -- Just $ fromIntegral (floatRadix t) ^ floatDigits t- -- @- maxValue :: proxy a -> Maybe (Fraction a)-- -- | lifted fromIntegral- fromFraction :: Num b => Fraction a -> b--instance EffectiveDigit Float where- newtype Fraction Float = FractionFloat Word32- deriving(Eq, Ord, Num)-- maxValue _ = let t = 0 :: Float in Just $ fromIntegral (floatRadix t) ^ floatDigits t- fromFraction (FractionFloat a) = fromIntegral a-- {-# INLINE maxValue #-}- {-# INLINE fromFraction #-}--instance EffectiveDigit Double where- newtype Fraction Double = FractionDouble Word64- deriving(Eq, Ord, Num)-- maxValue _ = let t = 0 :: Double in Just $ fromIntegral (floatRadix t) ^ floatDigits t- fromFraction (FractionDouble a) = fromIntegral a-- {-# INLINE maxValue #-}- {-# INLINE fromFraction #-}--instance EffectiveDigit Rational where- newtype Fraction Rational = WordRational Integer- deriving(Eq, Ord, Num)-- maxValue _ = Nothing- fromFraction (WordRational a) = fromIntegral a-- {-# INLINE maxValue #-}- {-# INLINE fromFraction #-}--class KnownNat n => Base n where- -- | check input Word8 is digit charactor or not.- isDigit :: proxy n -> Word8 -> Bool-- -- | convert digit charactor to number.- -- undefined behaviour when give non-digit charactor.- unsafeToDigit :: proxy n -> Word8 -> Word8--#define defineBaseUnder10(BASE, MAX)\-instance Base BASE where;\- {-# INLINE isDigit #-};\- {-# INLINE unsafeToDigit #-};\- isDigit _ = \w -> 48 <= w && w <= MAX;\- unsafeToDigit _ w = w - 48--defineBaseUnder10( 2, 49)-defineBaseUnder10( 3, 50)-defineBaseUnder10( 4, 51)-defineBaseUnder10( 5, 52)-defineBaseUnder10( 6, 53)-defineBaseUnder10( 7, 54)-defineBaseUnder10( 8, 55)-defineBaseUnder10( 9, 56)-defineBaseUnder10(10, 57)--#define defineBaseOver10(BASE, MAXu, MAXl)\-instance Base BASE where;\- {-# INLINE isDigit #-};\- {-# INLINE unsafeToDigit #-};\- isDigit _ = \w -> 48 <= w && w <= 57 || 65 <= w && w <= MAXu || 97 <= w && w <= MAXl;\- unsafeToDigit _ w = if 48 <= w && w <= 57;\- then fromIntegral w - 48;\- else if 65 <= w && w <= 90;\- then fromIntegral w - 55;\- else fromIntegral w - 87--defineBaseOver10(11, 65, 97)-defineBaseOver10(12, 66, 98)-defineBaseOver10(13, 67, 99)-defineBaseOver10(14, 68, 100)-defineBaseOver10(15, 69, 101)-defineBaseOver10(16, 70, 102)-defineBaseOver10(17, 71, 103)-defineBaseOver10(18, 72, 104)-defineBaseOver10(19, 73, 105)-defineBaseOver10(20, 74, 106)-defineBaseOver10(21, 75, 107)-defineBaseOver10(22, 76, 108)-defineBaseOver10(23, 77, 109)-defineBaseOver10(24, 78, 110)-defineBaseOver10(25, 79, 111)-defineBaseOver10(26, 80, 112)-defineBaseOver10(27, 81, 113)-defineBaseOver10(28, 82, 114)-defineBaseOver10(29, 83, 115)-defineBaseOver10(30, 84, 116)-defineBaseOver10(31, 85, 117)-defineBaseOver10(32, 86, 118)-defineBaseOver10(33, 87, 119)-defineBaseOver10(34, 88, 120)-defineBaseOver10(35, 89, 121)-defineBaseOver10(36, 90, 122)---integral :: forall proxy n r. (Base n, EffectiveDigit r, Ord (Fraction r), Num (Fraction r))- => proxy n -> ByteString -> (Fraction r, Int, Int, ByteString)-integral pn = loop 0 0 0- where- pr :: Proxy r- pr = Proxy-- loop !i !d !ad !s- | S.null s = (i, d, ad, s)- | not (isDigit pn (unsafeHead s)) = (i, d, ad, s)- | maybe False (i >=) (maxValue pr) = loop i d (ad + 1) (unsafeTail s)- | otherwise = loop- (i * fromIntegral (natVal pn) + (fromIntegral $ unsafeToDigit pn (unsafeHead s) :: Fraction r))- (d+1) ad (unsafeTail s)-{-# INLINABLE integral #-}--toFractional :: (Base b, EffectiveDigit r, Fractional r)- => proxy b -> Fraction r -> Fraction r -> Int -> Int -> r-toFractional p q r du d = fromFraction q * base ^ du + fromFraction r / base ^ d- where- base = fromIntegral (natVal p)-{-# INLINABLE toFractional #-}---- | convert bytestring into unsigned floating using radix.------ this function can parse------ * floating(0.1, 12224.3543)------ >>> floating' (Proxy :: Proxy 36) "12z" :: Maybe (Double, ByteString)--- Just (1403.0,"")--- >>> floating' (Proxy :: Proxy 2) "1012" :: Maybe (Double, ByteString)--- Just (5.0,"2")--- >>> floating' (Proxy :: Proxy 10) "a12" :: Maybe (Double, ByteString)--- Nothing-floating' :: (Base b, EffectiveDigit r) => proxy b -> ByteString -> Maybe (r, ByteString)-floating' pn s = case integral pn s of- (_, 0, _, _) -> Nothing- (q, _, d, "") -> Just (fromFraction q * fromIntegral (natVal pn) ^ d, "")- (q, _, d, s1)- | unsafeHead s1 /= dot -> Just (fromFraction q, s1)- | otherwise -> case integral pn (unsafeTail s1) of- (_, 0, _, _) -> Just (fromFraction q, s1)- (r, d', _, s2) -> Just (toFractional pn q r d d', s2)- where- dot = 46-{-# INLINABLE floating' #-}--exponential :: forall proxy r. (EffectiveDigit r, Ord (Fraction r), Num (Fraction r))- => proxy r -> ByteString -> (Int, ByteString)-exponential _ s0- | S.null s0 = (0, s0)- | isE (unsafeHead s0) = sign (unsafeTail s0)- | otherwise = (0, s0)- where- isE w = w == 101 || w == 69-- sign s1- | S.null s1 = (0, s0)- | unsafeHead s1 == plus = expPart $ unsafeTail s1- | unsafeHead s1 == minus = let (e, s) = expPart $ unsafeTail s1 in (-e, s)- | otherwise = expPart s1-- expPart s2 = case integral (Proxy :: Proxy 10) s2 :: (Fraction r, Int, Int, ByteString) of- (_, 0, _, _) -> (0, s0)- (e, _, _, s) -> (fromFraction e, s)-{-# INLINABLE exponential #-}--setExpPart :: Fractional f => Int -> f -> f-setExpPart e f- | e >= 0 = f * 10 ^ e- | otherwise = f / 10 ^ abs e-{-# SPECIALIZE setExpPart :: Int -> Double -> Double #-}-{-# SPECIALIZE setExpPart :: Int -> Float -> Float #-}-{-# INLINABLE setExpPart #-}---- | convert bytestring into unsigned floating using radix.------ this function can parse------ * floating(0.1, 12224.3543)--- * exponential (e1, E+2, e-123) (optional)------ >>> floating10 "12.5" :: Maybe (Double, ByteString)--- Just (12.5,"")--- >>> floating10 "124.1e12" :: Maybe (Double, ByteString)--- Just (1.241e14,"")--- >>> floating10 "12.5e-3" :: Maybe (Double, ByteString)--- Just (1.25e-2,"")--- >>> floating10 "3.11e+3" :: Maybe (Double, ByteString)--- Just (3110.0,"")-floating10 :: forall r. EffectiveDigit r => ByteString -> Maybe (r, ByteString)-floating10 s = floating' (Proxy :: Proxy 10) s >>= \(f, s') ->- let (e, s'') = exponential (Proxy :: Proxy r) s'- in Just (setExpPart e f, s'')-{-# INLINABLE floating10 #-}---- | convert bytestring into unsigned floating using radix.------ this function can parse------ * oct/hexa-decimal (0o,0O,0x,0X) (optional)--- * floating(0.1, 12224.3543)--- * exponential (e1, E+2, e-123) (10-radixed only, optional)------ >>> floating "12.4" :: Maybe (Double, ByteString)--- Just (12.4,"")--- >>> floating "1.23e12" :: Maybe (Double, ByteString)--- Just (1.23e12,"")--- >>> floating "0o0.4" :: Maybe (Double, ByteString)--- Just (0.5,"")--- >>> floating "0x3f.12" :: Maybe (Double, ByteString)--- Just (63.0703125,"")-floating :: EffectiveDigit r => ByteString -> Maybe (r, ByteString)-floating s0- | S.null s0 = Nothing- | unsafeHead s0 == zero = base $ unsafeTail s0- | otherwise = floating10 s0- where- zero = 48- isX w = w == 120 || w == 88- isO w = w == 111 || w == 79-- base s1- | S.null s1 = Just (0, "")- | isX (unsafeHead s1) = floating' (Proxy :: Proxy 16) (unsafeTail s1)- | isO (unsafeHead s1) = floating' (Proxy :: Proxy 8) (unsafeTail s1)- | otherwise = floating10 s0-{-# INLINABLE floating #-}---- | @--- double = floating--- @-double :: ByteString -> Maybe (Double, ByteString)-double = floating- -- | convert unsigned parser to signed parser. -- -- this function can parse@@ -310,3 +48,6 @@ | unsafeHead s == minus = first negate <$> f (unsafeTail s) | unsafeHead s == plus = f (unsafeTail s) | otherwise = f s+ where+ minus = 45+ plus = 43
+ src/Data/ByteString/Read/Class.hs view
@@ -0,0 +1,123 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE CPP #-}++module Data.ByteString.Read.Class+ ( ReadFractional(..)+ , Radix(..)+ ) where++import Data.Word+import GHC.TypeLits.Compat++class (Fractional a, Num (Fraction a), Ord (Fraction a)) => ReadFractional a where+ -- | data type to store fractional part of floating+ data Fraction a++ -- | maximum value of fractional part.+ --+ -- Nothing if arbitrary-precision.+ -- + -- @+ -- Just $ fromIntegral (floatRadix t) ^ floatDigits t+ -- @+ maxValue :: proxy a -> Maybe (Fraction a)++ -- | lifted fromIntegral+ fromFraction :: Num b => Fraction a -> b++instance ReadFractional Float where+ newtype Fraction Float = FractionFloat Word32+ deriving(Eq, Ord, Num)++ maxValue _ = let t = 0 :: Float in Just $ fromIntegral (floatRadix t) ^ floatDigits t+ fromFraction (FractionFloat a) = fromIntegral a++ {-# INLINE maxValue #-}+ {-# INLINE fromFraction #-}++instance ReadFractional Double where+ newtype Fraction Double = FractionDouble Word64+ deriving(Eq, Ord, Num)++ maxValue _ = let t = 0 :: Double in Just $ fromIntegral (floatRadix t) ^ floatDigits t+ fromFraction (FractionDouble a) = fromIntegral a++ {-# INLINE maxValue #-}+ {-# INLINE fromFraction #-}++instance ReadFractional Rational where+ newtype Fraction Rational = WordRational Integer+ deriving(Eq, Ord, Num)++ maxValue _ = Nothing+ fromFraction (WordRational a) = fromIntegral a++ {-# INLINE maxValue #-}+ {-# INLINE fromFraction #-}++class KnownNat n => Radix n where+ -- | check input Word8 is digit charactor or not.+ isDigit :: proxy n -> Word8 -> Bool++ -- | convert digit charactor to number.+ -- undefined behaviour when give non-digit charactor.+ unsafeToDigit :: proxy n -> Word8 -> Word8++#define defineRadixUnder10(RADIX, MAX)\+instance Radix RADIX where;\+ {-# INLINE isDigit #-};\+ {-# INLINE unsafeToDigit #-};\+ isDigit _ = \w -> 48 <= w && w <= MAX;\+ unsafeToDigit _ w = w - 48++defineRadixUnder10( 2, 49)+defineRadixUnder10( 3, 50)+defineRadixUnder10( 4, 51)+defineRadixUnder10( 5, 52)+defineRadixUnder10( 6, 53)+defineRadixUnder10( 7, 54)+defineRadixUnder10( 8, 55)+defineRadixUnder10( 9, 56)+defineRadixUnder10(10, 57)++#define defineRadixOver10(RADIX, MAXu, MAXl)\+instance Radix RADIX where;\+ {-# INLINE isDigit #-};\+ {-# INLINE unsafeToDigit #-};\+ isDigit _ = \w -> 48 <= w && w <= 57 || 65 <= w && w <= MAXu || 97 <= w && w <= MAXl;\+ unsafeToDigit _ w = if 48 <= w && w <= 57;\+ then fromIntegral w - 48;\+ else if 65 <= w && w <= 90;\+ then fromIntegral w - 55;\+ else fromIntegral w - 87++defineRadixOver10(11, 65, 97)+defineRadixOver10(12, 66, 98)+defineRadixOver10(13, 67, 99)+defineRadixOver10(14, 68, 100)+defineRadixOver10(15, 69, 101)+defineRadixOver10(16, 70, 102)+defineRadixOver10(17, 71, 103)+defineRadixOver10(18, 72, 104)+defineRadixOver10(19, 73, 105)+defineRadixOver10(20, 74, 106)+defineRadixOver10(21, 75, 107)+defineRadixOver10(22, 76, 108)+defineRadixOver10(23, 77, 109)+defineRadixOver10(24, 78, 110)+defineRadixOver10(25, 79, 111)+defineRadixOver10(26, 80, 112)+defineRadixOver10(27, 81, 113)+defineRadixOver10(28, 82, 114)+defineRadixOver10(29, 83, 115)+defineRadixOver10(30, 84, 116)+defineRadixOver10(31, 85, 117)+defineRadixOver10(32, 86, 118)+defineRadixOver10(33, 87, 119)+defineRadixOver10(34, 88, 120)+defineRadixOver10(35, 89, 121)+defineRadixOver10(36, 90, 122)
+ src/Data/ByteString/Read/DEPRECATED.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ConstraintKinds #-}++module Data.ByteString.Read.DEPRECATED where++import Data.ByteString(ByteString)+import Data.ByteString.Read.Class+import Data.ByteString.Read.Fractional++{-# DEPRECATED EffectiveDigit "use ReadFractional" #-}+type EffectiveDigit = ReadFractional++{-# DEPRECATED floating "use fractional" #-}+floating :: EffectiveDigit r => ByteString -> Maybe (r, ByteString)+floating = fractional++{-# DEPRECATED Base "use Radix" #-}+type Base = Radix++{-# DEPRECATED floating10 "use fractional10" #-}+floating10 :: forall r. EffectiveDigit r => ByteString -> Maybe (r, ByteString) +floating10 = fractional10++{-# DEPRECATED floating' "use floating'" #-}+floating' :: (Base b, EffectiveDigit r) => proxy b -> ByteString -> Maybe (r, ByteString) +floating' = fractional'
+ src/Data/ByteString/Read/Fractional.hs view
@@ -0,0 +1,169 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE CPP #-}++module Data.ByteString.Read.Fractional+ ( -- * functions+ fractional+ , double++ -- * raw functions+ , fractional10+ , fractional'+ ) where++import Data.ByteString.Unsafe+import Data.ByteString(ByteString)+import qualified Data.ByteString as S++import GHC.TypeLits.Compat+import Data.Proxy.Compat++import Data.ByteString.Read.Class++-- $setup+-- >>> :set -XDataKinds -XOverloadedStrings++integral :: forall proxy n r. (Radix n, ReadFractional r, Ord (Fraction r), Num (Fraction r))+ => proxy n -> ByteString -> (Fraction r, Int, Int, ByteString)+integral pn = loop 0 0 0+ where+ pr :: Proxy r+ pr = Proxy++ loop !i !d !ad !s+ | S.null s = (i, d, ad, s)+ | not (isDigit pn (unsafeHead s)) = (i, d, ad, s)+ | maybe False (i >=) (maxValue pr) = loop i d (ad + 1) (unsafeTail s)+ | otherwise = loop+ (i * fromIntegral (natVal pn) + (fromIntegral $ unsafeToDigit pn (unsafeHead s) :: Fraction r))+ (d+1) ad (unsafeTail s)+{-# INLINABLE integral #-}++toFractional :: (Radix b, ReadFractional r, Fractional r)+ => proxy b -> Fraction r -> Fraction r -> Int -> Int -> r+toFractional p q r du d = fromFraction q * radix ^ du + fromFraction r / radix ^ d+ where+ radix = fromIntegral (natVal p)+{-# INLINABLE toFractional #-}++-- | convert bytestring into unsigned fractional using radix.+--+-- this function can parse+--+-- * fractional(0.1, 12224.3543)+--+-- >>> fractional' (Proxy :: Proxy 36) "12z" :: Maybe (Double, ByteString)+-- Just (1403.0,"")+-- >>> fractional' (Proxy :: Proxy 2) "1012" :: Maybe (Double, ByteString)+-- Just (5.0,"2")+-- >>> fractional' (Proxy :: Proxy 10) "a12" :: Maybe (Double, ByteString)+-- Nothing+fractional' :: (Radix b, ReadFractional r) => proxy b -> ByteString -> Maybe (r, ByteString)+fractional' pn s = case integral pn s of+ (_, 0, _, _) -> Nothing+ (q, _, d, "") -> Just (fromFraction q * fromIntegral (natVal pn) ^ d, "")+ (q, _, d, s1)+ | unsafeHead s1 /= dot -> Just (fromFraction q, s1)+ | otherwise -> case integral pn (unsafeTail s1) of+ (_, 0, _, _) -> Just (fromFraction q, s1)+ (r, d', _, s2) -> Just (toFractional pn q r d d', s2)+ where+ dot = 46+{-# INLINABLE fractional' #-}++exponential :: ByteString -> (Int, ByteString)+exponential s0+ | S.null s0 = (0, s0)+ | isE (unsafeHead s0) = sign (unsafeTail s0)+ | otherwise = (0, s0)+ where+ isE w = w == 101 || w == 69++ minus = 45+ plus = 43++ sign s1+ | S.null s1 = (0, s0)+ | unsafeHead s1 == plus = expPart $ unsafeTail s1+ | unsafeHead s1 == minus = let (e, s) = expPart $ unsafeTail s1 in (-e, s)+ | otherwise = expPart s1++ expPart s2 = case integral (Proxy :: Proxy 10) s2 :: (Fraction Double, Int, Int, ByteString) of+ (_, 0, _, _) -> (0, s0)+ (e, _, _, s) -> (fromFraction e, s)+{-# INLINABLE exponential #-}++setExpPart :: Fractional f => Int -> f -> f+setExpPart e f+ | e >= 0 = f * 10 ^ e+ | otherwise = f / 10 ^ abs e+{-# SPECIALIZE setExpPart :: Int -> Double -> Double #-}+{-# SPECIALIZE setExpPart :: Int -> Float -> Float #-}+{-# INLINABLE setExpPart #-}++-- | convert bytestring into unsigned fractional using radix.+--+-- this function can parse+--+-- * fractional(0.1, 12224.3543)+-- * exponential (e1, E+2, e-123) (optional)+--+-- >>> fractional10 "12.5" :: Maybe (Double, ByteString)+-- Just (12.5,"")+-- >>> fractional10 "124.1e12" :: Maybe (Double, ByteString)+-- Just (1.241e14,"")+-- >>> fractional10 "12.5e-3" :: Maybe (Double, ByteString)+-- Just (1.25e-2,"")+-- >>> fractional10 "3.11e+3" :: Maybe (Double, ByteString)+-- Just (3110.0,"")+fractional10 :: ReadFractional r => ByteString -> Maybe (r, ByteString)+fractional10 s = fractional' (Proxy :: Proxy 10) s >>= \(f, s') ->+ let (e, s'') = exponential s'+ in Just (setExpPart e f, s'')+{-# INLINABLE fractional10 #-}++-- | convert bytestring into unsigned fractional using radix.+--+-- this function can parse+--+-- * oct/hexa-decimal (0o,0O,0x,0X) (optional)+-- * fractional(0.1, 12224.3543)+-- * exponential (e1, E+2, e-123) (10-radixed only, optional)+--+-- >>> fractional "12.4" :: Maybe (Double, ByteString)+-- Just (12.4,"")+-- >>> fractional "1.23e12" :: Maybe (Double, ByteString)+-- Just (1.23e12,"")+-- >>> fractional "0o0.4" :: Maybe (Double, ByteString)+-- Just (0.5,"")+-- >>> fractional "0x3f.12" :: Maybe (Double, ByteString)+-- Just (63.0703125,"")+fractional :: ReadFractional r => ByteString -> Maybe (r, ByteString)+fractional s0+ | S.null s0 = Nothing+ | unsafeHead s0 == zero = radix $ unsafeTail s0+ | otherwise = fractional10 s0+ where+ zero = 48+ isX w = w == 120 || w == 88+ isO w = w == 111 || w == 79++ radix s1+ | S.null s1 = Just (0, "")+ | isX (unsafeHead s1) = fractional' (Proxy :: Proxy 16) (unsafeTail s1)+ | isO (unsafeHead s1) = fractional' (Proxy :: Proxy 8) (unsafeTail s1)+ | otherwise = fractional10 s0+{-# INLINABLE fractional #-}++-- | @+-- double = fractional+-- @+double :: ByteString -> Maybe (Double, ByteString)+double = fractional
+ src/Data/ByteString/Read/Integral.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-}++module Data.ByteString.Read.Integral+ ( integral'+ , integral+ , int+ ) where++import Data.ByteString(ByteString)+import qualified Data.ByteString as S+import Data.ByteString.Unsafe++import Data.Proxy.Compat+import GHC.TypeLits.Compat++import Data.ByteString.Read.Class++-- $setup+-- >>> :set -XDataKinds -XOverloadedStrings++integral_ :: (Radix b, Num n) => proxy b -> ByteString -> (n, Int, ByteString)+integral_ pn = loop 0 0+ where+ loop !i !d !s+ | S.null s = (i, d, s)+ | not (isDigit pn (unsafeHead s)) = (i, d, s)+ | otherwise = loop+ (i * fromIntegral (natVal pn) + (fromIntegral $ unsafeToDigit pn (unsafeHead s)))+ (d+1) (unsafeTail s)+{-# INLINABLE integral_ #-}++-- | convert bytestring into unsigned integral using radix+--+-- >>> integral' (Proxy :: Proxy 10) "12345" :: Maybe (Int, ByteString)+-- Just (12345,"")+-- >>> integral' (Proxy :: Proxy 2) "10112" :: Maybe (Int, ByteString)+-- Just (11,"2")+-- >>> integral' (Proxy :: Proxy 36) "Z" :: Maybe (Double, ByteString)+-- Just (35.0,"")+integral' :: (Radix b, Num n) => proxy b -> ByteString -> Maybe (n, ByteString)+integral' pn s0 = case integral_ pn s0 of+ (_, 0, _) -> Nothing+ (n, _, s) -> Just (n, s)+{-# INLINABLE integral' #-}+-- | @+-- integral = 'integral'' (Proxy :: Proxy 10)+-- @+integral :: Num n => ByteString -> Maybe (n, ByteString)+integral = integral' (Proxy :: Proxy 10)+{-# INLINABLE integral #-}++-- | @+-- int = integral+-- @+int :: ByteString -> Maybe (Int, ByteString)+int = integral+{-# INLINABLE int #-}
tests/tasty.hs view
@@ -99,59 +99,66 @@ main :: IO () main = defaultMain $ testGroup "read . show == id"- [ testProperty "showEFloat" $ \d ->- let Just (d', "") = signed floating . S.pack $ showEFloat Nothing d ""- in (d :: Double) =~~ d'+ [ testGroup "Integral"+ [ testProperty "Int" $ \i ->+ let Just (i', "") = signed integral . S.pack $ show i+ in (i :: Int) == i'+ ]+ , testGroup "Fractional"+ [ testProperty "showEFloat" $ \d ->+ let Just (d', "") = signed fractional . S.pack $ showEFloat Nothing d ""+ in (d :: Double) =~~ d' - , testProperty "showFFloat" $ \d ->- let Just (d', "") = signed floating . S.pack $ showFFloat Nothing d ""- in (d :: Double) =~~ d'+ , testProperty "showFFloat" $ \d ->+ let Just (d', "") = signed fractional . S.pack $ showFFloat Nothing d ""+ in (d :: Double) =~~ d' - , testProperty "showGFloat" $ \d ->- let Just (d', "") = signed floating . S.pack $ showGFloat Nothing d ""- in (d :: Double) =~~ d'+ , testProperty "showGFloat" $ \d ->+ let Just (d', "") = signed fractional . S.pack $ showGFloat Nothing d ""+ in (d :: Double) =~~ d' - , testProperty "showHex" $ \i ->- let Just (i', "") = signed floating . (S.append "0x") . S.pack $ showHex (abs i) ""- in fromIntegral (abs i :: Int) =~~ i'+ , testProperty "showHex" $ \i ->+ let Just (i', "") = signed fractional . (S.append "0x") . S.pack $ showHex (abs i) ""+ in fromIntegral (abs i :: Int) =~~ i' - , testProperty "showOct" $ \i ->- let Just (i', "") = signed floating . (S.append "0o") . S.pack $ showOct (abs i) ""- in fromIntegral (abs i :: Int) =~~ i'+ , testProperty "showOct" $ \i ->+ let Just (i', "") = signed fractional . (S.append "0o") . S.pack $ showOct (abs i) ""+ in fromIntegral (abs i :: Int) =~~ i' - , testProperty "Word8" $ \(Word8 d) ->- let Just (d', "") = signed floating (S.pack d)- in d' =~~ (read d :: Double)+ , testProperty "Word8" $ \(Word8 d) ->+ let Just (d', "") = signed fractional (S.pack d)+ in d' =~~ (read d :: Double) - , testProperty "Word10" $ \(Word10 d) ->- let Just (d', "") = signed floating (S.pack d)- in d' =~~ (read d :: Double)+ , testProperty "Word10" $ \(Word10 d) ->+ let Just (d', "") = signed fractional (S.pack d)+ in d' =~~ (read d :: Double) - , testProperty "Word16" $ \(Word16 d) ->- let Just (d', "") = signed floating (S.pack d)- in d' =~~ (read d :: Double)+ , testProperty "Word16" $ \(Word16 d) ->+ let Just (d', "") = signed fractional (S.pack d)+ in d' =~~ (read d :: Double) - , testProperty "Int8" $ \(Int8 d) ->- let Just (d', "") = signed floating (S.pack d)- in d' =~~ (read d :: Double)+ , testProperty "Int8" $ \(Int8 d) ->+ let Just (d', "") = signed fractional (S.pack d)+ in d' =~~ (read d :: Double) - , testProperty "Int10" $ \(Int10 d) ->- let Just (d', "") = signed floating (S.pack d)- in d' =~~ (read d :: Double)+ , testProperty "Int10" $ \(Int10 d) ->+ let Just (d', "") = signed fractional (S.pack d)+ in d' =~~ (read d :: Double) - , testProperty "Int16" $ \(Int16 d) ->- let Just (d', "") = signed floating (S.pack d)- in d' =~~ (read d :: Double)+ , testProperty "Int16" $ \(Int16 d) ->+ let Just (d', "") = signed fractional (S.pack d)+ in d' =~~ (read d :: Double) - , testProperty "Float10" $ \(Float10 d) ->- let Just (d', "") = signed floating (S.pack d)- in d' =~~ (read d :: Double)+ , testProperty "Float10" $ \(Float10 d) ->+ let Just (d', "") = signed fractional (S.pack d)+ in d' =~~ (read d :: Double) - , testProperty "SmallFloat10" $ \(SmallFloat10 d) ->- let Just (d', "") = signed floating (S.pack d)- in d' =~~ (read d :: Double)+ , testProperty "SmallFloat10" $ \(SmallFloat10 d) ->+ let Just (d', "") = signed fractional (S.pack d)+ in d' =~~ (read d :: Double) - , testProperty "Float10Exp" $ \(Float10Exp d) ->- let Just (d', "") = signed floating (S.pack d)- in d' =~~ (read d :: Double)+ , testProperty "Float10Exp" $ \(Float10Exp d) ->+ let Just (d', "") = signed fractional (S.pack d)+ in d' =~~ (read d :: Double)+ ] ]