{-# LANGUAGE CPP #-}
#ifdef BYTESTRING_STRICT
module Data.ByteString.ReadInt
#else
module Data.ByteString.Lazy.ReadInt
#endif
    ( readInt
    , readInt8
    , readInt16
    , readInt32
    , readWord
    , readWord8
    , readWord16
    , readWord32
    , readInt64
    , readWord64
    ) where
import qualified Data.ByteString.Internal as BI
#ifdef BYTESTRING_STRICT
import Data.ByteString
#else
import Data.ByteString.Lazy
import Data.ByteString.Lazy.Internal
#endif
import Data.Bits (FiniteBits, isSigned)
import Data.ByteString.Internal (pattern BS, plusForeignPtr)
import Data.Int
import Data.Word
import Foreign.ForeignPtr (ForeignPtr)
import Foreign.Ptr (minusPtr, plusPtr)
import Foreign.Storable (Storable(..))
readInt :: ByteString -> Maybe (Int, ByteString)
readInt :: ByteString -> Maybe (Int, ByteString)
readInt = ByteString -> Maybe (Int, ByteString)
forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
readInt32 :: ByteString -> Maybe (Int32, ByteString)
readInt32 :: ByteString -> Maybe (Int32, ByteString)
readInt32 = ByteString -> Maybe (Int32, ByteString)
forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
readInt16 :: ByteString -> Maybe (Int16, ByteString)
readInt16 :: ByteString -> Maybe (Int16, ByteString)
readInt16 = ByteString -> Maybe (Int16, ByteString)
forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
readInt8 :: ByteString -> Maybe (Int8, ByteString)
readInt8 :: ByteString -> Maybe (Int8, ByteString)
readInt8 = ByteString -> Maybe (Int8, ByteString)
forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
readWord :: ByteString -> Maybe (Word, ByteString)
readWord :: ByteString -> Maybe (Word, ByteString)
readWord = ByteString -> Maybe (Word, ByteString)
forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
readWord32 :: ByteString -> Maybe (Word32, ByteString)
readWord32 :: ByteString -> Maybe (Word32, ByteString)
readWord32 = ByteString -> Maybe (Word32, ByteString)
forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
readWord16 :: ByteString -> Maybe (Word16, ByteString)
readWord16 :: ByteString -> Maybe (Word16, ByteString)
readWord16 = ByteString -> Maybe (Word16, ByteString)
forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
readWord8 :: ByteString -> Maybe (Word8, ByteString)
readWord8 :: ByteString -> Maybe (Word8, ByteString)
readWord8 = ByteString -> Maybe (Word8, ByteString)
forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
readInt64 :: ByteString -> Maybe (Int64, ByteString)
readInt64 :: ByteString -> Maybe (Int64, ByteString)
readInt64 = ByteString -> Maybe (Int64, ByteString)
forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
readWord64 :: ByteString -> Maybe (Word64, ByteString)
readWord64 :: ByteString -> Maybe (Word64, ByteString)
readWord64 = ByteString -> Maybe (Word64, ByteString)
forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
_read :: forall a. (Integral a, FiniteBits a, Bounded a)
      => ByteString  -> Maybe (a, ByteString)
{-# INLINE _read #-}
_read :: forall a.
(Integral a, FiniteBits a, Bounded a) =>
ByteString -> Maybe (a, ByteString)
_read
    | forall a. Bits a => a -> Bool
isSigned @a a
0
      = \ ByteString
bs -> ByteString -> Maybe (Word64, ByteString, Word64)
signed ByteString
bs Maybe (Word64, ByteString, Word64)
-> ((Word64, ByteString, Word64) -> Maybe (a, ByteString))
-> Maybe (a, ByteString)
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ (Word64
r, ByteString
s, Word64
d1) -> Word64 -> ByteString -> Word64 -> Maybe (a, ByteString)
forall a.
(Integral a, Bounded a) =>
Word64 -> ByteString -> Word64 -> Maybe (a, ByteString)
_readDecimal Word64
r ByteString
s Word64
d1
    | Bool
otherwise
      
      
      = \ ByteString
bs -> Word64 -> ByteString -> Maybe (Word64, ByteString, Word64)
unsigned Word64
5 ByteString
bs Maybe (Word64, ByteString, Word64)
-> ((Word64, ByteString, Word64) -> Maybe (a, ByteString))
-> Maybe (a, ByteString)
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ (Word64
r, ByteString
s, Word64
d1) -> Word64 -> ByteString -> Word64 -> Maybe (a, ByteString)
forall a.
(Integral a, Bounded a) =>
Word64 -> ByteString -> Word64 -> Maybe (a, ByteString)
_readDecimal Word64
r ByteString
s Word64
d1
  where
    
    
    
    
    
    
    
    
    signed :: ByteString -> Maybe (Word64, ByteString, Word64)
    signed :: ByteString -> Maybe (Word64, ByteString, Word64)
signed ByteString
bs = do
        (w, s) <- ByteString -> Maybe (Word8, ByteString)
uncons ByteString
bs
        let d1 = Word8 -> Word64
fromDigit Word8
w
        if | d1 <= 9   -> Just (7, s, d1) 
           | w == 0x2d -> unsigned 8 s    
           | w == 0x2b -> unsigned 7 s    
           | otherwise -> Nothing         
    unsigned :: Word64 -> ByteString -> Maybe (Word64, ByteString, Word64)
    unsigned :: Word64 -> ByteString -> Maybe (Word64, ByteString, Word64)
unsigned Word64
r ByteString
bs = do
        (w, s) <- ByteString -> Maybe (Word8, ByteString)
uncons ByteString
bs
        let d1 = Word8 -> Word64
fromDigit Word8
w
        if | d1 <= 9   -> Just (r, s, d1) 
           | otherwise -> Nothing         
data Result = Overflow
            | Result !Int    
                     !Word64 
_readDecimal :: forall a. (Integral a, Bounded a)
             => Word64     
             -> ByteString 
             -> Word64     
             -> Maybe (a, ByteString)
{-# INLINE _readDecimal #-}
_readDecimal :: forall a.
(Integral a, Bounded a) =>
Word64 -> ByteString -> Word64 -> Maybe (a, ByteString)
_readDecimal !Word64
r = ByteString -> Word64 -> Maybe (a, ByteString)
consume
  where
    consume :: ByteString -> Word64 -> Maybe (a, ByteString)
#ifdef BYTESTRING_STRICT
    consume (BS fp len) a = case _digits q r fp len a of
        Result used acc
            | used == len
              -> convert acc empty
            | otherwise
              -> convert acc $ BS (fp `plusForeignPtr` used) (len - used)
        _   -> Nothing
#else
    
    consume :: ByteString -> Word64 -> Maybe (a, ByteString)
consume ByteString
Empty Word64
acc = Word64 -> ByteString -> Maybe (a, ByteString)
convert Word64
acc ByteString
Empty
    
    consume (Chunk (BS ForeignPtr Word8
fp Int
len) ByteString
cs) Word64
acc
        = case Word64 -> Word64 -> ForeignPtr Word8 -> Int -> Word64 -> Result
_digits Word64
q Word64
r ForeignPtr Word8
fp Int
len Word64
acc of
            Result Int
used Word64
acc'
                | Int
used Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
len
                  
                  -> ByteString -> Word64 -> Maybe (a, ByteString)
consume ByteString
cs Word64
acc'
                | Bool
otherwise
                  
                  -> Word64 -> ByteString -> Maybe (a, ByteString)
convert Word64
acc' (ByteString -> Maybe (a, ByteString))
-> ByteString -> Maybe (a, ByteString)
forall a b. (a -> b) -> a -> b
$
                     ByteString -> ByteString -> ByteString
Chunk (ForeignPtr Word8 -> Int -> ByteString
BS (ForeignPtr Word8
fp ForeignPtr Word8 -> Int -> ForeignPtr Word8
forall a b. ForeignPtr a -> Int -> ForeignPtr b
`plusForeignPtr` Int
used) (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
used)) ByteString
cs
            Result
_     -> Maybe (a, ByteString)
forall a. Maybe a
Nothing
#endif
    convert :: Word64 -> ByteString -> Maybe (a, ByteString)
    convert :: Word64 -> ByteString -> Maybe (a, ByteString)
convert !Word64
acc ByteString
rest =
        let !i :: a
i = case Word64
r of
                
                Word64
8 -> a -> a
forall a. Num a => a -> a
negate (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral @Word64 @a Word64
acc
                Word64
_ -> forall a b. (Integral a, Num b) => a -> b
fromIntegral @Word64 @a Word64
acc
         in (a, ByteString) -> Maybe (a, ByteString)
forall a. a -> Maybe a
Just (a
i, ByteString
rest)
    
    
    
    
    
    q :: Word64
q = forall a b. (Integral a, Num b) => a -> b
fromIntegral @a @Word64 a
forall a. Bounded a => a
maxBound Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
`div` Word64
10
_digits :: Word64           
        -> Word64           
        -> ForeignPtr Word8 
        -> Int              
        -> Word64           
        -> Result           
                            
{-# INLINE _digits #-}
_digits :: Word64 -> Word64 -> ForeignPtr Word8 -> Int -> Word64 -> Result
_digits !Word64
q !Word64
r ForeignPtr Word8
fp Int
len Word64
a = IO Result -> Result
forall a. IO a -> a
BI.accursedUnutterablePerformIO (IO Result -> Result) -> IO Result -> Result
forall a b. (a -> b) -> a -> b
$
    ForeignPtr Word8 -> (Ptr Word8 -> IO Result) -> IO Result
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
BI.unsafeWithForeignPtr ForeignPtr Word8
fp ((Ptr Word8 -> IO Result) -> IO Result)
-> (Ptr Word8 -> IO Result) -> IO Result
forall a b. (a -> b) -> a -> b
$ \ Ptr Word8
ptr -> do
        let end :: Ptr b
end = Ptr Word8
ptr Ptr Word8 -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
len
        Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Word64 -> IO Result
forall {b}. Ptr b -> Ptr Word8 -> Ptr Word8 -> Word64 -> IO Result
go Ptr Word8
ptr Ptr Word8
forall {b}. Ptr b
end Ptr Word8
ptr Word64
a
  where
    go :: Ptr b -> Ptr Word8 -> Ptr Word8 -> Word64 -> IO Result
go !Ptr b
start !Ptr Word8
end = Ptr Word8 -> Word64 -> IO Result
loop
      where
        loop :: Ptr Word8 -> Word64 -> IO Result
loop !Ptr Word8
ptr !Word64
acc = IO Word64
getDigit IO Word64 -> (Word64 -> IO Result) -> IO Result
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ !Word64
d ->
            if | Word64
d Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
9
                 -> Result -> IO Result
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Result -> IO Result) -> Result -> IO Result
forall a b. (a -> b) -> a -> b
$ Int -> Word64 -> Result
Result (Ptr Word8
ptr Ptr Word8 -> Ptr b -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` Ptr b
start) Word64
acc
               | Word64
acc Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
q Bool -> Bool -> Bool
|| Word64
acc Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
q Bool -> Bool -> Bool
&& Word64
d Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word64
r
                 -> Ptr Word8 -> Word64 -> IO Result
loop (Ptr Word8
ptr Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) (Word64
acc Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
10 Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
d)
               | Bool
otherwise
                 -> Result -> IO Result
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Result
Overflow
          where
            getDigit :: IO Word64
            getDigit :: IO Word64
getDigit
                | Ptr Word8
ptr Ptr Word8 -> Ptr Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Ptr Word8
end = Word8 -> Word64
fromDigit (Word8 -> Word64) -> IO Word8 -> IO Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr Word8 -> IO Word8
forall a. Storable a => Ptr a -> IO a
peek Ptr Word8
ptr
                | Bool
otherwise  = Word64 -> IO Word64
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Word64
10  
            {-# NOINLINE getDigit #-}
            
            
            
            
            
            
            
            
            
fromDigit :: Word8 -> Word64
{-# INLINE fromDigit #-}
fromDigit :: Word8 -> Word64
fromDigit = \ !Word8
w -> Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
0x30