packages feed

dataframe-parsing-1.0.2.0: src/DataFrame/Internal/Parsing/Fast/Int.hs

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}

{- | Non-backtracking @Int@ slice parser, bit-compatible with
@readByteStringInt@ (i.e. @Data.ByteString.Char8.readInt . strip@):
grammar @WS* sign? digit+ WS*@, whole slice consumed, 'Nothing' on
64-bit overflow.
-}
module DataFrame.Internal.Parsing.Fast.Int (parseIntField#) where

import qualified Data.ByteString as BS
import qualified Data.ByteString.Unsafe as BSU

import GHC.Exts (Int (..), Int#)

import DataFrame.Internal.Parsing.Fast.Common

{- | Result is @(# ok, value #)@ with @ok@ 0 or 1. Caller guarantees
@0 <= start <= end <= length buf@.
-}
parseIntField# :: BS.ByteString -> Int -> Int -> (# Int#, Int# #)
parseIntField# bs start end0
    | i0 >= end = none
    | otherwise =
        let !c0 = BSU.unsafeIndex bs i0
            !neg = c0 == 0x2D
            !i1 = if neg || c0 == 0x2B then i0 + 1 else i0
         in if i1 >= end || not (isDigitByte (BSU.unsafeIndex bs i1))
                then none
                else
                    let !iz = skipZeroes bs i1 end
                     in takeDigits64 bs iz end $ \dEnd w ->
                            if dEnd /= end || dEnd - iz > 19
                                then none
                                else
                                    if neg
                                        then
                                            if w <= 9223372036854775808
                                                then done (negate (fromIntegral w))
                                                else none
                                        else
                                            if w <= 9223372036854775807
                                                then done (fromIntegral w)
                                                else none
  where
    !i0 = skipStrip bs start end0
    !end = skipStripEnd bs i0 end0
    none = (# 0#, 0# #)
    done :: Int -> (# Int#, Int# #)
    done (I# n) = (# 1#, n #)
    {-# INLINE done #-}
{-# INLINE parseIntField# #-}