{-# LANGUAGE CPP #-}

-- |
-- Functions that compute the required allocation size by value.
module PtrPoker.Size where

import qualified PtrPoker.Ffi as Ffi
import PtrPoker.Prelude
import qualified PtrPoker.Text as Text

-- |
-- Efficiently count the amount of bytes required to encode Word64
-- as a decimal number in ASCII.
--
-- Implemented as a balanced tree of \"ifs\"
-- centered around the middle of the range.
-- This is much faster than anything based on logarithms.
{-# INLINE word64AsciiDec #-}
word64AsciiDec :: Word64 -> Int
word64AsciiDec :: Word64 -> Int
word64AsciiDec Word64
x =
  if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
9999999999
    then
      if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
99999999999999
        then
          if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
9999999999999999
            then
              if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
99999999999999999
                then
                  if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
999999999999999999
                    then
                      if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
9999999999999999999
                        then Int
20
                        else Int
19
                    else Int
18
                else Int
17
            else
              if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
999999999999999
                then Int
16
                else Int
15
        else
          if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
999999999999
            then
              if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
9999999999999
                then Int
14
                else Int
13
            else
              if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
99999999999
                then Int
12
                else Int
11
    else
      if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
99999
        then
          if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
9999999
            then
              if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
99999999
                then
                  if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
999999999
                    then Int
10
                    else Int
9
                else Int
8
            else
              if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
999999
                then Int
7
                else Int
6
        else
          if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
99
            then
              if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
999
                then
                  if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
9999
                    then Int
5
                    else Int
4
                else Int
3
            else
              if Word64
x Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
> Word64
9
                then Int
2
                else Int
1

-- |
-- Efficiently count the amount of bytes required to encode Int64
-- as a signed decimal number in ASCII.
--
-- Implemented as a balanced tree of \"ifs\"
-- centered around the middle of the range.
-- This is much faster than anything based on logarithms.
{-# INLINE int64AsciiDec #-}
int64AsciiDec :: Int64 -> Int
int64AsciiDec :: Int64 -> Int
int64AsciiDec Int64
x =
  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0
    then
      if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
9999999999
        then
          if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
99999999999999
            then
              if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
9999999999999999
                then
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
99999999999999999
                    then
                      if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
999999999999999999
                        then Int
20
                        else Int
19
                    else Int
18
                else
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
999999999999999
                    then Int
17
                    else Int
16
            else
              if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
999999999999
                then
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
9999999999999
                    then Int
15
                    else Int
14
                else
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
99999999999
                    then Int
13
                    else Int
12
        else
          if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
99999
            then
              if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
9999999
                then
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
99999999
                    then
                      if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
999999999
                        then Int
11
                        else Int
10
                    else Int
9
                else
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
999999
                    then Int
8
                    else Int
7
            else
              if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
99
                then
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
999
                    then
                      if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
9999
                        then Int
6
                        else Int
5
                    else Int
4
                else
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< -Int64
9
                    then Int
3
                    else Int
2
    else
      if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
9999999999
        then
          if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
99999999999999
            then
              if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
9999999999999999
                then
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
99999999999999999
                    then
                      if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
999999999999999999
                        then Int
19
                        else Int
18
                    else Int
17
                else
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
999999999999999
                    then Int
16
                    else Int
15
            else
              if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
999999999999
                then
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
9999999999999
                    then Int
14
                    else Int
13
                else
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
99999999999
                    then Int
12
                    else Int
11
        else
          if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
99999
            then
              if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
9999999
                then
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
99999999
                    then
                      if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
999999999
                        then Int
10
                        else Int
9
                    else Int
8
                else
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
999999
                    then Int
7
                    else Int
6
            else
              if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
99
                then
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
999
                    then
                      if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
9999
                        then Int
5
                        else Int
4
                    else Int
3
                else
                  if Int64
x Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
9
                    then Int
2
                    else Int
1

-- |
-- Efficiently count the amount of bytes required to encode Text
-- in UTF8.
{-# INLINE textUtf8 #-}
textUtf8 :: Text -> Int
#if MIN_VERSION_text(2,0,0)
textUtf8 = Text.destruct $ \_arr _off len -> len
#else
textUtf8 :: Text -> Int
textUtf8 = (ByteArray# -> Int -> Int -> Int) -> Text -> Int
forall x. (ByteArray# -> Int -> Int -> x) -> Text -> x
Text.destruct ((ByteArray# -> Int -> Int -> Int) -> Text -> Int)
-> (ByteArray# -> Int -> Int -> Int) -> Text -> Int
forall a b. (a -> b) -> a -> b
$ \ByteArray#
arr Int
off Int
len ->
  ByteArray# -> CSize -> CSize -> IO CInt
Ffi.countTextAllocationSize
    ByteArray#
arr
    (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
off)
    (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len)
    IO CInt -> (IO CInt -> CInt) -> CInt
forall a b. a -> (a -> b) -> b
& IO CInt -> CInt
forall a. IO a -> a
unsafeDupablePerformIO
    CInt -> (CInt -> Int) -> Int
forall a b. a -> (a -> b) -> b
& CInt -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
#endif