-- | Loading and storing integers directly from/to memory buffers.
--
--   * The implementation uses native Haskell unboxed primitives. 
--     There there should not be any significant performance penalty
--     relative to the standard implementations in other languages (like C).
--
module Data.Repa.Scalar.Int
        ( -- * Reading from strings
          readInt
        , readIntFromByteString

          -- * Loading from buffers
        , loadInt
        , loadInt#
        , loadIntWith#

          -- * Showing to strings
          -- ** Unpadded
        , showInt
        , showIntToByteString

          -- ** Padded
        , showIntPad
        , showIntPadToByteString

          -- * Storing to buffers
          -- ** Unpadded
        , storeInt
        , storeInt#
        , storeIntWith#

          -- ** Padded
        , storeIntPad
        , storeIntPad#
        , storeIntPadWith#)
where
import Data.Word
import Data.Char
import GHC.Exts
import qualified Data.ByteString.Char8                  as BS
import qualified Data.ByteString.Internal               as BS
import qualified Foreign.Ptr                            as F
import qualified Foreign.ForeignPtr                     as F
import qualified Foreign.Storable                       as F
import qualified Foreign.Marshal.Alloc                  as F
import System.IO.Unsafe                       


-- Read/Load --------------------------------------------------------------------------------------
-- | Read an `Int` from a `String`, or `Nothing` if this isn't one.
readInt :: String -> Maybe Int
readInt :: String -> Maybe Int
readInt String
str
        = ByteString -> Maybe Int
readIntFromByteString (ByteString -> Maybe Int) -> ByteString -> Maybe Int
forall a b. (a -> b) -> a -> b
$ String -> ByteString
BS.pack String
str
{-# INLINE readInt #-}


-- | Read an `Int` from a `ByteString`, or `Nothing` if this isn't one.
readIntFromByteString 
        :: BS.ByteString -> Maybe Int

readIntFromByteString :: ByteString -> Maybe Int
readIntFromByteString (BS.PS ForeignPtr Word8
fptr Int
offset Int
len)
 --   accursed ... may increase sharing of result,
 --   but this is ok here as we're not allocating mutable object.
 = IO (Maybe Int) -> Maybe Int
forall a. IO a -> a
unsafePerformIO      
 (IO (Maybe Int) -> Maybe Int) -> IO (Maybe Int) -> Maybe Int
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> (Ptr Word8 -> IO (Maybe Int)) -> IO (Maybe Int)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
F.withForeignPtr ForeignPtr Word8
fptr
 ((Ptr Word8 -> IO (Maybe Int)) -> IO (Maybe Int))
-> (Ptr Word8 -> IO (Maybe Int)) -> IO (Maybe Int)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr -> Maybe Int -> IO (Maybe Int)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return 
        (Maybe Int -> IO (Maybe Int)) -> Maybe Int -> IO (Maybe Int)
forall a b. (a -> b) -> a -> b
$  Ptr Word8
-> Int -> Maybe Int -> (Int -> Int -> Maybe Int) -> Maybe Int
forall b. Ptr Word8 -> Int -> b -> (Int -> Int -> b) -> b
loadInt (Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
F.plusPtr Ptr Word8
ptr Int
offset) Int
len
                Maybe Int
forall a. Maybe a
Nothing
                (\Int
val Int
n -> if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
len
                                then Int -> Maybe Int
forall a. a -> Maybe a
Just Int
val
                                else Maybe Int
forall a. Maybe a
Nothing)

{-# INLINE readIntFromByteString #-}


-- | Load an ASCII `Int` from a foreign buffer,
--   returning the value and number of characters read.
--
--   * This function is set to `INLINE`. It unboxes the pointer and
--     integer then calls `loadInt#', which is `NOINLINE`.
--
loadInt :: Ptr Word8                    -- ^ Buffer holding digits.
        -> Int                          -- ^ Length of buffer.
        -> b                            -- ^ On convert failure, return this value.
        -> (Int -> Int -> b)            -- ^ On convert success, given int read and number of chars.
        -> b
 
loadInt :: forall b. Ptr Word8 -> Int -> b -> (Int -> Int -> b) -> b
loadInt (Ptr Addr#
addr) (I# Int#
len) b
fails Int -> Int -> b
eat
 = case Addr# -> Int# -> (# Int#, Int#, Int# #)
loadInt# Addr#
addr Int#
len of
        (# Int#
0#, Int#
_, Int#
_  #) -> b
fails
        (# Int#
_,  Int#
n, Int#
ix #) -> Int -> Int -> b
eat (Int# -> Int
I# Int#
n) (Int# -> Int
I# Int#
ix)
{-# INLINE loadInt #-}


-- | Load an ASCII `Int` from a buffer,
--   producing an unboxed tuple describing the result.
--
--   * This function is set to `NOINLINE`, so it can be safely called from 
--     multiple places in the program.
--
loadInt#
        :: Addr#                        -- ^ Address of buffer holding digits
        -> Int#                         -- ^ Length of buffer.
        -> (# Int#, Int#, Int# #)       -- ^ Convert success?, value, length read.

loadInt# :: Addr# -> Int# -> (# Int#, Int#, Int# #)
loadInt# Addr#
addr Int#
len
 = let  
        Ptr Word8
buf :: Ptr Word8 
         = Addr# -> Ptr Word8
forall a. Addr# -> Ptr a
Ptr Addr#
addr

        peek8 :: Int# -> Int#
peek8 Int#
ix
           -- accursed .. may increase sharing of the result value, 
           -- but this isn't a problem here because the result is not
           -- mutable, and will be unboxed by the simplifier anyway.
         = case IO Word8 -> Word8
forall a. IO a -> a
BS.accursedUnutterablePerformIO (Ptr Word8 -> Int -> IO Word8
forall b. Ptr b -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
F.peekByteOff Ptr Word8
buf (Int# -> Int
I# Int#
ix)) of
                (Word8
w8 :: Word8) -> case Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w8 of
                                        I# Int#
i    -> Int#
i
        {-# INLINE peek8 #-}

   in  Int# -> (Int# -> Int#) -> (# Int#, Int#, Int# #)
loadIntWith# Int#
len Int# -> Int#
peek8
{-# NOINLINE loadInt# #-}


-- | Primitive `Int` loading function.
--
--   * This function is set to `INLINE`, so you will get a new copy of it in the
--     compiled program each time it is invoked. Consider providing an appropriate
--     wrapper for your use case.
--
loadIntWith# 
        :: Int#                         -- ^ Length of input buffer.
        -> (Int# -> Int#)               -- ^ Function to get a byte from the source.
        -> (# Int#, Int#, Int# #)       -- ^ Convert success?, value, length read

loadIntWith# :: Int# -> (Int# -> Int#) -> (# Int#, Int#, Int# #)
loadIntWith# !Int#
len Int# -> Int#
get
 = Int# -> (# Int#, Int#, Int# #)
start Int#
0#
 where
        start :: Int# -> (# Int#, Int#, Int# #)
start !Int#
ix
         | Int#
1# <- Int#
ix Int# -> Int# -> Int#
>=# Int#
len = (# Int#
0#, Int#
0#, Int#
0# #)
         | Bool
otherwise        = Int# -> (# Int#, Int#, Int# #)
sign Int#
ix
        {-# INLINE start #-}

        -- Check for explicit sign character,
        -- and encode what it was as an integer.
        sign :: Int# -> (# Int#, Int#, Int# #)
sign !Int#
ix
         | !Int#
s   <- Int# -> Int#
get Int#
0#
         = case Int -> Char
chr (Int -> Char) -> Int -> Char
forall a b. (a -> b) -> a -> b
$ Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# Int#
s) of
                Char
'-'     -> Int# -> Int# -> Int# -> (# Int#, Int#, Int# #)
loop Int#
1# (Int#
ix Int# -> Int# -> Int#
+# Int#
1#) Int#
0#
                Char
'+'     -> Int# -> Int# -> Int# -> (# Int#, Int#, Int# #)
loop Int#
2# (Int#
ix Int# -> Int# -> Int#
+# Int#
1#) Int#
0#
                Char
_       -> Int# -> Int# -> Int# -> (# Int#, Int#, Int# #)
loop Int#
0#  Int#
ix        Int#
0#
        {-# INLINE sign #-}

        loop :: Int# -> Int# -> Int# -> (# Int#, Int#, Int# #)
loop !Int#
neg !Int#
ix !Int#
n 
         -- We've hit the end of the array.
         | Int#
1# <- Int#
ix Int# -> Int# -> Int#
>=# Int#
len   
         = Int# -> Int# -> Int# -> (# Int#, Int#, Int# #)
end Int#
neg Int#
ix Int#
n

         | Bool
otherwise
         = case Int# -> Int#
get Int#
ix of
               -- Current character is a digit, so add it to the accmulator.
             Int#
w | Int#
1# <- Int#
w Int# -> Int# -> Int#
>=# Int#
0x30# 
               , Int#
1# <- Int#
w Int# -> Int# -> Int#
<=# Int#
0x039#
               -> Int# -> Int# -> Int# -> (# Int#, Int#, Int# #)
loop Int#
neg ( Int#
ix Int# -> Int# -> Int#
+# Int#
1#) 
                           ((Int#
n  Int# -> Int# -> Int#
*# Int#
10#) Int# -> Int# -> Int#
+# (Int#
w Int# -> Int# -> Int#
-# Int#
0x30#))

               -- Current character is not a digit.
               | Bool
otherwise
               -> Int# -> Int# -> Int# -> (# Int#, Int#, Int# #)
end Int#
neg Int#
ix Int#
n

        end :: Int# -> Int# -> Int# -> (# Int#, Int#, Int# #)
end !Int#
neg !Int#
ix !Int#
n
         -- We didn't find any digits, and there was no explicit sign.
         | Int#
1# <- Int#
ix  Int# -> Int# -> Int#
==# Int#
0#
         , Int#
1# <- Int#
neg Int# -> Int# -> Int#
==# Int#
0#
         = (# Int#
0#, Int#
0#, Int#
0# #)

         -- We didn't find any digits, but there was an explicit sign.
         | Int#
1# <- Int#
ix  Int# -> Int# -> Int#
==# Int#
1#
         , Int#
1# <- Int#
neg Int# -> Int# -> Int#
/=# Int#
0#
         = (# Int#
0#, Int#
0#, Int#
0# #)

         -- Number was explicitly negated.
         | Int#
1# <- Int#
neg Int# -> Int# -> Int#
==# Int#
1#                    
         , I# Int#
n' <- Int -> Int
forall a. Num a => a -> a
negate (Int# -> Int
I# Int#
n)
         = (# Int#
1#, Int#
n', Int#
ix #)

         -- Number was not negated.
         | Bool
otherwise
         = (# Int#
1#, Int#
n, Int#
ix #)
        {-# NOINLINE end #-}
{-# INLINE loadIntWith# #-}


---------------------------------------------------------------------------------------------------
-- | Show an `Int`, allocating a new `String`.
showInt :: Int -> String
showInt :: Int -> String
showInt Int
i
 = ByteString -> String
BS.unpack (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ Int -> ByteString
showIntToByteString Int
i
{-# INLINE showInt #-}


-- | Show an `Int`, allocating a new `ByteString`.
showIntToByteString :: Int -> BS.ByteString
showIntToByteString :: Int -> ByteString
showIntToByteString (I# Int#
i)
 = IO ByteString -> ByteString
forall a. IO a -> a
unsafePerformIO
 (IO ByteString -> ByteString) -> IO ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ let  
        alloc :: Int# -> IO (Ptr a)
alloc Int#
len
         = Int -> IO (Ptr a)
forall a. Int -> IO (Ptr a)
F.mallocBytes (Int# -> Int
I# Int#
len)
        {-# INLINE alloc #-}

        write :: Ptr b -> Int# -> Int# -> IO ()
write  Ptr b
ptr Int#
ix Int#
val
         = Ptr b -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
F.pokeByteOff Ptr b
ptr (Int# -> Int
I# Int#
ix) (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# Int#
val) :: Word8)
        {-# INLINE write #-}

        make :: Ptr Word8 -> Int# -> IO ByteString
make   Ptr Word8
ptr Int#
len
         = do   ForeignPtr Word8
fptr    <- FinalizerPtr Word8 -> Ptr Word8 -> IO (ForeignPtr Word8)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
F.newForeignPtr FinalizerPtr Word8
forall a. FinalizerPtr a
F.finalizerFree Ptr Word8
ptr
                ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return  (ByteString -> IO ByteString) -> ByteString -> IO ByteString
forall a b. (a -> b) -> a -> b
$  ForeignPtr Word8 -> Int -> Int -> ByteString
BS.PS ForeignPtr Word8
fptr Int
0 (Int# -> Int
I# Int#
len)
        {-# INLINE make #-}

   in   (Int# -> IO (Ptr Word8))
-> (Ptr Word8 -> Int# -> Int# -> IO ())
-> Int#
-> (Ptr Word8 -> Int# -> IO ByteString)
-> IO ByteString
forall buf b.
(Int# -> IO buf)
-> (buf -> Int# -> Int# -> IO ())
-> Int#
-> (buf -> Int# -> IO b)
-> IO b
storeIntWith# Int# -> IO (Ptr Word8)
forall {a}. Int# -> IO (Ptr a)
alloc Ptr Word8 -> Int# -> Int# -> IO ()
forall {b}. Ptr b -> Int# -> Int# -> IO ()
write Int#
i Ptr Word8 -> Int# -> IO ByteString
make
{-# NOINLINE showIntToByteString #-}


-- | Store an ASCII `Int` into a buffer, producing the number of bytes written.
-- 
--   * This functon is set to `INLINE`. It unboxes the pointer and integer then
--     calls `storeInt#` which is `NOINLINE`.
--
storeInt :: Ptr Word8                   -- ^ Pointer to output buffer.
         -> Int                         -- ^ Int to store.
         -> IO Int                      -- ^ Number of bytes written.

storeInt :: Ptr Word8 -> Int -> IO Int
storeInt (Ptr Addr#
addr) (I# Int#
val)
 = Addr# -> Int# -> IO Int
storeInt# Addr#
addr Int#
val
{-# INLINE storeInt #-}


-- | Store an ASCII `Int` into a buffer, producing the number of bytes written.
--
--   * This function is set to NOINLINE, so it can be safely called from
--     multiple places in the program.
--
storeInt# 
        :: Addr#                        -- ^ Address of output buffer.
        -> Int#                         -- ^ Int to store.
        -> IO Int                       -- ^ Number of bytes written.

storeInt# :: Addr# -> Int# -> IO Int
storeInt# Addr#
addr Int#
val
 = let
        -- move along, nothing to see..
        alloc :: Int# -> IO (Ptr Any)
alloc Int#
_ 
         = Ptr Any -> IO (Ptr Any)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Ptr Any -> IO (Ptr Any)) -> Ptr Any -> IO (Ptr Any)
forall a b. (a -> b) -> a -> b
$ Addr# -> Ptr Any
forall a. Addr# -> Ptr a
Ptr Addr#
addr
        {-# INLINE alloc #-}

        write :: Ptr Any -> Int# -> Int# -> IO ()
write Ptr Any
_ Int#
ix Int#
byte
         = Ptr Any -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
F.pokeByteOff (Addr# -> Ptr Any
forall a. Addr# -> Ptr a
Ptr Addr#
addr) (Int# -> Int
I# Int#
ix) (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# Int#
byte) :: Word8)
        {-# INLINE write #-}

        make :: p -> Int# -> m Int
make p
_ Int#
len
         = Int -> m Int
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> m Int) -> Int -> m Int
forall a b. (a -> b) -> a -> b
$ Int# -> Int
I# Int#
len
        {-# INLINE make #-}

  in do
        (Int# -> IO (Ptr Any))
-> (Ptr Any -> Int# -> Int# -> IO ())
-> Int#
-> (Ptr Any -> Int# -> IO Int)
-> IO Int
forall buf b.
(Int# -> IO buf)
-> (buf -> Int# -> Int# -> IO ())
-> Int#
-> (buf -> Int# -> IO b)
-> IO b
storeIntWith# Int# -> IO (Ptr Any)
alloc Ptr Any -> Int# -> Int# -> IO ()
write Int#
val Ptr Any -> Int# -> IO Int
forall {m :: * -> *} {p}. Monad m => p -> Int# -> m Int
make
{-# NOINLINE storeInt# #-}


-- | Primitive `Int` storing function.
-- 
--   * This function is set to `INLINE`, so you will get a new copy of it in the compiled
--     program each time it is invoked. Consider providing an appropriate wrapper
--     for your use case.
--
storeIntWith#
        :: (Int# -> IO buf)             -- ^ Function to allocate a new output buffer,
                                        --   given the length in bytes.
        -> (buf -> Int# -> Int# -> IO ())      
                                        -- ^ Function to write a byte to the buffer,
                                        --   given the index and byte value.
        -> Int#                         -- ^ Int to store.
        -> (buf -> Int# -> IO b)        -- ^ Continuation for buffer and bytes written.
        -> IO b

storeIntWith# :: forall buf b.
(Int# -> IO buf)
-> (buf -> Int# -> Int# -> IO ())
-> Int#
-> (buf -> Int# -> IO b)
-> IO b
storeIntWith# Int# -> IO buf
alloc buf -> Int# -> Int# -> IO ()
write Int#
val buf -> Int# -> IO b
k
 =  Int -> (Ptr Word8 -> IO b) -> IO b
forall a b. Int -> (Ptr a -> IO b) -> IO b
F.allocaBytes Int
32 ((Ptr Word8 -> IO b) -> IO b) -> (Ptr Word8 -> IO b) -> IO b
forall a b. (a -> b) -> a -> b
$ \(Ptr Word8
buf :: Ptr Word8)
 -> let 
        -- Get starting magnitude.
        !start :: IO b
start
         | Int#
1#   <- Int#
val Int# -> Int# -> Int#
<# Int#
0#    = Int# -> Int# -> IO b
digits (Int#
0# Int# -> Int# -> Int#
-# Int#
val) Int#
0#
         | Bool
otherwise            = Int# -> Int# -> IO b
digits Int#
val         Int#
0#
        {-# INLINE start #-}

        -- Load digits into buffer.
        digits :: Int# -> Int# -> IO b
digits !Int#
mag !Int#
ix
         = do   Ptr Word8 -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
F.pokeByteOff Ptr Word8
buf (Int# -> Int
I# Int#
ix) 
                        (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# (Int#
0x030# Int# -> Int# -> Int#
+# Int#
mag Int# -> Int# -> Int#
`remInt#` Int#
10#)) :: Word8)
                let  !ix' :: Int#
ix'  = Int#
ix Int# -> Int# -> Int#
+# Int#
1#
                let  !mag' :: Int#
mag' = Int#
mag Int# -> Int# -> Int#
`quotInt#` Int#
10#
                (case Int#
mag' Int# -> Int# -> Int#
==# Int#
0# of
                  Int#
1#    -> Int# -> IO b
sign   Int#
ix'
                  Int#
_     -> Int# -> Int# -> IO b
digits Int#
mag' Int#
ix')
        {-# NOINLINE digits #-}

        -- Load sign into buffer.
        sign :: Int# -> IO b
sign !Int#
ix
         = case Int#
val Int# -> Int# -> Int#
<# Int#
0# of
            Int#
1# -> do Ptr Word8 -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
F.pokeByteOff Ptr Word8
buf (Int# -> Int
I# Int#
ix) 
                        (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# Int#
0x02d#) :: Word8)
                     Int# -> IO b
create (Int#
ix Int# -> Int# -> Int#
+# Int#
1#)
            Int#
_  ->    Int# -> IO b
create Int#
ix
        {-# INLINE sign #-}

        -- Create a new output buffer, now that we know the length.
        create :: Int# -> IO b
create Int#
len 
         = do   buf
out     <- Int# -> IO buf
alloc Int#
len
                Int# -> buf -> Int# -> IO b
output Int#
len buf
out Int#
0#
        {-# NOINLINE create #-}

        -- Read chars back from buffer to output them
        -- in the correct order.
        output :: Int# -> buf -> Int# -> IO b
output Int#
len buf
out Int#
ix0
         = Int# -> IO b
go Int#
ix0
         where  go :: Int# -> IO b
go Int#
ix
                 | Int#
1# <- Int#
ix Int# -> Int# -> Int#
<# Int#
len
                 = do   Word8
x :: Word8  <- Ptr Word8 -> Int -> IO Word8
forall b. Ptr b -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
F.peekByteOff Ptr Word8
buf (Int# -> Int
I# ((Int#
len Int# -> Int# -> Int#
-# Int#
1#) Int# -> Int# -> Int#
-# Int#
ix))
                        let !(I# Int#
i) = Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
x
                        buf -> Int# -> Int# -> IO ()
write buf
out Int#
ix Int#
i
                        Int# -> IO b
go (Int#
ix Int# -> Int# -> Int#
+# Int#
1#)

                 | Bool
otherwise
                 = buf -> Int# -> IO b
k buf
out Int#
len
        {-# INLINE output #-}
    in IO b
start
{-# INLINE storeIntWith# #-}


---------------------------------------------------------------------------------------------------
-- | Show an `Int`, allocating a new `String`.
showIntPad :: Int -> Int -> String
showIntPad :: Int -> Int -> String
showIntPad Int
i Int
pad
 = ByteString -> String
BS.unpack (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ Int -> Int -> ByteString
showIntPadToByteString Int
i Int
pad
{-# INLINE showIntPad #-}


-- | Show an `Int`, allocating a new `ByteString`.
showIntPadToByteString :: Int -> Int -> BS.ByteString
showIntPadToByteString :: Int -> Int -> ByteString
showIntPadToByteString (I# Int#
i) Int
pad'
 = IO ByteString -> ByteString
forall a. IO a -> a
unsafePerformIO
 (IO ByteString -> ByteString) -> IO ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ let  
        !(I# Int#
pad)
         = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 Int
pad'

        alloc :: Int# -> IO (Ptr a)
alloc Int#
len
         = Int -> IO (Ptr a)
forall a. Int -> IO (Ptr a)
F.mallocBytes (Int# -> Int
I# Int#
len)
        {-# INLINE alloc #-}

        write :: Ptr b -> Int# -> Int# -> IO ()
write  Ptr b
ptr Int#
ix Int#
val
         = Ptr b -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
F.pokeByteOff Ptr b
ptr (Int# -> Int
I# Int#
ix) (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# Int#
val) :: Word8)
        {-# INLINE write #-}

        make :: Ptr Word8 -> Int# -> IO ByteString
make   Ptr Word8
ptr Int#
len
         = do   ForeignPtr Word8
fptr    <- FinalizerPtr Word8 -> Ptr Word8 -> IO (ForeignPtr Word8)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
F.newForeignPtr FinalizerPtr Word8
forall a. FinalizerPtr a
F.finalizerFree Ptr Word8
ptr
                ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return  (ByteString -> IO ByteString) -> ByteString -> IO ByteString
forall a b. (a -> b) -> a -> b
$  ForeignPtr Word8 -> Int -> Int -> ByteString
BS.PS ForeignPtr Word8
fptr Int
0 (Int# -> Int
I# Int#
len)
        {-# INLINE make #-}

   in   (Int# -> IO (Ptr Word8))
-> (Ptr Word8 -> Int# -> Int# -> IO ())
-> Int#
-> Int#
-> (Ptr Word8 -> Int# -> IO ByteString)
-> IO ByteString
forall buf b.
(Int# -> IO buf)
-> (buf -> Int# -> Int# -> IO ())
-> Int#
-> Int#
-> (buf -> Int# -> IO b)
-> IO b
storeIntPadWith# Int# -> IO (Ptr Word8)
forall {a}. Int# -> IO (Ptr a)
alloc Ptr Word8 -> Int# -> Int# -> IO ()
forall {b}. Ptr b -> Int# -> Int# -> IO ()
write Int#
i Int#
pad Ptr Word8 -> Int# -> IO ByteString
make
{-# NOINLINE showIntPadToByteString #-}


-- | Store an ASCII `Int` into a buffer, producing the number of bytes written.
storeIntPad
        :: Ptr Word8                   -- ^ Pointer to output buffer.
        -> Int                         -- ^ Int to store.
        -> Int                         -- ^ Minimum number of digits.
        -> IO Int                      -- ^ Number of bytes written.

storeIntPad :: Ptr Word8 -> Int -> Int -> IO Int
storeIntPad (Ptr Addr#
addr) (I# Int#
val) (I# Int#
pad)
 = Addr# -> Int# -> Int# -> IO Int
storeIntPad# Addr#
addr Int#
val Int#
pad
{-# INLINE storeIntPad #-}


-- | Store an ASCII `Int` into a buffer, producing the number of bytes written.
--
--   * This function is set to NOINLINE, so it can be safely called from
--     multiple places in the program.
--
storeIntPad# 
        :: Addr#                        -- ^ Address of output buffer.
        -> Int#                         -- ^ Int to store.
        -> Int#                         -- ^ Minimum number of digits.
        -> IO Int                       -- ^ Number of bytes written.

storeIntPad# :: Addr# -> Int# -> Int# -> IO Int
storeIntPad# Addr#
addr Int#
val Int#
pad
 = let
        -- move along, nothing to see..
        alloc :: Int# -> IO (Ptr Any)
alloc Int#
_ 
         = Ptr Any -> IO (Ptr Any)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Ptr Any -> IO (Ptr Any)) -> Ptr Any -> IO (Ptr Any)
forall a b. (a -> b) -> a -> b
$ Addr# -> Ptr Any
forall a. Addr# -> Ptr a
Ptr Addr#
addr
        {-# INLINE alloc #-}

        write :: Ptr Any -> Int# -> Int# -> IO ()
write Ptr Any
_ Int#
ix Int#
byte
         = Ptr Any -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
F.pokeByteOff (Addr# -> Ptr Any
forall a. Addr# -> Ptr a
Ptr Addr#
addr) (Int# -> Int
I# Int#
ix) (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# Int#
byte) :: Word8)
        {-# INLINE write #-}

        make :: p -> Int# -> m Int
make p
_ Int#
len
         = Int -> m Int
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> m Int) -> Int -> m Int
forall a b. (a -> b) -> a -> b
$ Int# -> Int
I# Int#
len
        {-# INLINE make #-}

  in do
        (Int# -> IO (Ptr Any))
-> (Ptr Any -> Int# -> Int# -> IO ())
-> Int#
-> Int#
-> (Ptr Any -> Int# -> IO Int)
-> IO Int
forall buf b.
(Int# -> IO buf)
-> (buf -> Int# -> Int# -> IO ())
-> Int#
-> Int#
-> (buf -> Int# -> IO b)
-> IO b
storeIntPadWith# Int# -> IO (Ptr Any)
alloc Ptr Any -> Int# -> Int# -> IO ()
write Int#
val Int#
pad Ptr Any -> Int# -> IO Int
forall {m :: * -> *} {p}. Monad m => p -> Int# -> m Int
make
{-# NOINLINE storeIntPad# #-}


-- | Like `storeIntWith#`, but add leading zeros to the front of the integer
--   to pad it out to at least the given number of digits.

storeIntPadWith#
        :: (Int# -> IO buf)             -- ^ Function to allocate a new output buffer,
                                        --   given the length in bytes.
        -> (buf -> Int# -> Int# -> IO ())      
                                        -- ^ Function to write a byte to the buffer,
                                        --   given the index and byte value.
        -> Int#                         -- ^ Int to store.
        -> Int#                         -- ^ Pad out result to achieve at this many digits.
        -> (buf -> Int# -> IO b)        -- ^ Continuation for buffer and bytes written.
        -> IO b

storeIntPadWith# :: forall buf b.
(Int# -> IO buf)
-> (buf -> Int# -> Int# -> IO ())
-> Int#
-> Int#
-> (buf -> Int# -> IO b)
-> IO b
storeIntPadWith# Int# -> IO buf
alloc buf -> Int# -> Int# -> IO ()
write Int#
val Int#
pad buf -> Int# -> IO b
k
 =  Int -> (Ptr Word8 -> IO b) -> IO b
forall a b. Int -> (Ptr a -> IO b) -> IO b
F.allocaBytes (Int# -> Int
I# (Int#
32# Int# -> Int# -> Int#
+# Int#
pad)) ((Ptr Word8 -> IO b) -> IO b) -> (Ptr Word8 -> IO b) -> IO b
forall a b. (a -> b) -> a -> b
$ \(Ptr Word8
buf :: Ptr Word8)
 -> let 
        -- Get starting magnitude.
        !start :: IO b
start
         | Int#
1#   <- Int#
val Int# -> Int# -> Int#
<# Int#
0#    = Int# -> Int# -> IO b
digits (Int#
0# Int# -> Int# -> Int#
-# Int#
val) Int#
0#
         | Bool
otherwise            = Int# -> Int# -> IO b
digits Int#
val         Int#
0#
        {-# INLINE start #-}

        -- Load digits into buffer.
        digits :: Int# -> Int# -> IO b
digits !Int#
mag !Int#
ix
         = do   Ptr Word8 -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
F.pokeByteOff Ptr Word8
buf (Int# -> Int
I# Int#
ix) 
                        (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# (Int#
0x030# Int# -> Int# -> Int#
+# Int#
mag Int# -> Int# -> Int#
`remInt#` Int#
10#)) :: Word8)
                let  !ix' :: Int#
ix'  = Int#
ix Int# -> Int# -> Int#
+# Int#
1#
                let  !mag' :: Int#
mag' = Int#
mag Int# -> Int# -> Int#
`quotInt#` Int#
10#
                (case Int#
mag' Int# -> Int# -> Int#
==# Int#
0# of
                  Int#
1#    -> Int# -> IO b
padder Int#
ix'
                  Int#
_     -> Int# -> Int# -> IO b
digits Int#
mag' Int#
ix')
        {-# NOINLINE digits #-}

        -- Pad result out with zeros.
        padder :: Int# -> IO b
padder !Int#
ix
         | Int#
1#   <- Int#
ix Int# -> Int# -> Int#
>=# Int#
pad
         = Int# -> IO b
sign Int#
ix

         | Bool
otherwise
         = do   Ptr Word8 -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
F.pokeByteOff Ptr Word8
buf (Int# -> Int
I# Int#
ix)
                        (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# Int#
0x030#) :: Word8)
                Int# -> IO b
padder (Int#
ix Int# -> Int# -> Int#
+# Int#
1#)

        -- Load sign into buffer.
        sign :: Int# -> IO b
sign !Int#
ix
         = case Int#
val Int# -> Int# -> Int#
<# Int#
0# of
            Int#
1# -> do Ptr Word8 -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
F.pokeByteOff Ptr Word8
buf (Int# -> Int
I# Int#
ix) 
                        (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int# -> Int
I# Int#
0x02d#) :: Word8)
                     Int# -> IO b
create (Int#
ix Int# -> Int# -> Int#
+# Int#
1#)
            Int#
_  ->    Int# -> IO b
create Int#
ix
        {-# INLINE sign #-}

        -- Create a new output buffer, now that we know the length.
        create :: Int# -> IO b
create Int#
len 
         = do   buf
out     <- Int# -> IO buf
alloc Int#
len
                Int# -> buf -> Int# -> IO b
output Int#
len buf
out Int#
0#
        {-# NOINLINE create #-}

        -- Read chars back from buffer to output them
        -- in the correct order.
        output :: Int# -> buf -> Int# -> IO b
output Int#
len buf
out Int#
ix0
         = Int# -> IO b
go Int#
ix0
         where  go :: Int# -> IO b
go Int#
ix
                 | Int#
1# <- Int#
ix Int# -> Int# -> Int#
<# Int#
len
                 = do   Word8
x :: Word8  <- Ptr Word8 -> Int -> IO Word8
forall b. Ptr b -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
F.peekByteOff Ptr Word8
buf (Int# -> Int
I# ((Int#
len Int# -> Int# -> Int#
-# Int#
1#) Int# -> Int# -> Int#
-# Int#
ix))
                        let !(I# Int#
i) = Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
x
                        buf -> Int# -> Int# -> IO ()
write buf
out Int#
ix Int#
i
                        Int# -> IO b
go (Int#
ix Int# -> Int# -> Int#
+# Int#
1#)

                 | Bool
otherwise
                 = buf -> Int# -> IO b
k buf
out Int#
len
        {-# INLINE output #-}
    in IO b
start
{-# INLINE storeIntPadWith# #-}