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

import PtrPoker.Prelude
import qualified Data.Text.Internal as Text
import qualified Data.Text.Array as TextArray
import qualified PtrPoker.Ffi as Ffi


{-|
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
textUtf8 :: Text -> Int
textUtf8 (Text.Text Array
arr Int
off Int
len) =
  ByteArray# -> CSize -> CSize -> IO CInt
Ffi.countTextAllocationSize
    (Array -> ByteArray#
TextArray.aBA Array
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