{-# LANGUAGE RecordWildCards #-}

module System.Log.FastLogger.Write (
    writeLogStr,
    writeBigLogStr,
    Loggers (..),
) where

import Foreign.Marshal.Alloc (allocaBytes)
import Foreign.Ptr (plusPtr)

import System.Log.FastLogger.FileIO
import System.Log.FastLogger.IO
import System.Log.FastLogger.Imports
import System.Log.FastLogger.LogStr

----------------------------------------------------------------

-- | Writting 'LogStr' using a buffer in blocking mode.
--   The size of 'LogStr' must be smaller or equal to
--   the size of buffer.
writeLogStr :: Buffer -> IORef FD -> LogStr -> IO ()
writeLogStr :: Buffer -> IORef FD -> LogStr -> IO ()
writeLogStr Buffer
buf IORef FD
fdref (LogStr Int
len Builder
builder) =
    Buffer -> Int -> (Buffer -> Int -> IO ()) -> Builder -> IO ()
toBufIOWith Buffer
buf Int
len (IORef FD -> Buffer -> Int -> IO ()
write IORef FD
fdref) Builder
builder

-- | Writting 'LogStr' using a temporary buffer.
writeBigLogStr :: IORef FD -> LogStr -> IO ()
writeBigLogStr :: IORef FD -> LogStr -> IO ()
writeBigLogStr IORef FD
fdref (LogStr Int
len Builder
builder) = Int -> (Buffer -> IO ()) -> IO ()
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
len ((Buffer -> IO ()) -> IO ()) -> (Buffer -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Buffer
buf ->
    Buffer -> Int -> (Buffer -> Int -> IO ()) -> Builder -> IO ()
toBufIOWith Buffer
buf Int
len (IORef FD -> Buffer -> Int -> IO ()
write IORef FD
fdref) Builder
builder

write :: IORef FD -> Buffer -> Int -> IO ()
write :: IORef FD -> Buffer -> Int -> IO ()
write IORef FD
fdref Buffer
buf Int
len' = Buffer -> Int -> IO ()
loop Buffer
buf (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len')
  where
    loop :: Buffer -> Int -> IO ()
loop Buffer
bf Int
len = do
        Int
written <- IORef FD -> Buffer -> Int -> IO Int
writeRawBufferPtr2FD IORef FD
fdref Buffer
bf Int
len
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
written Bool -> Bool -> Bool
&& Int
written Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
            Buffer -> Int -> IO ()
loop (Buffer
bf Buffer -> Int -> Buffer
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
written) (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
written)

----------------------------------------------------------------

-- | A class for internal loggers.
class Loggers a where
    stopLoggers :: a -> IO ()
    pushLog :: a -> LogStr -> IO ()
    flushAllLog :: a -> IO ()