    {-# LANGUAGE BangPatterns, RecordWildCards #-}
    -- |
    -- Module      : Data.Text.Internal.IO
    -- Copyright   : (c) 2009, 2010 Bryan O'Sullivan,
    --               (c) 2009 Simon Marlow
    -- License     : BSD-style
    -- Maintainer  : bos@serpentine.com
    -- Stability   : experimental
    -- Portability : GHC
    --
    -- /Warning/: this is an internal module, and does not have a stable
    -- API or name. Functions in this module may not check or enforce
    -- preconditions expected by public modules. Use at your own risk!
    --
    -- Low-level support for text I\/O.

    module Data.Text.Internal.IO
        (
          hGetLineWith
        , readChunk
        ) where

    import qualified Control.Exception as E
    import Data.IORef (readIORef, writeIORef)
    import Data.Text (Text)
    import Data.Text.Internal.Fusion (unstream)
    import Data.Text.Internal.Fusion.Types (Step(..), Stream(..))
    import Data.Text.Internal.Fusion.Size (exactSize, maxSize)
    import Data.Text.Unsafe (inlinePerformIO)
    import Foreign.Storable (peekElemOff)
    import GHC.IO.Buffer (Buffer(..), CharBuffer, RawCharBuffer, bufferAdjustL,
                          bufferElems, charSize, isEmptyBuffer, readCharBuf,
                          withRawBuffer, writeCharBuf)
    import GHC.IO.Handle.Internals (ioe_EOF, readTextDevice, wantReadableHandle_)
    import GHC.IO.Handle.Types (Handle__(..), Newline(..))
    import System.IO (Handle)
    import System.IO.Error (isEOFError)
    import qualified Data.Text as T

    -- | Read a single line of input from a handle, constructing a list of
    -- decoded chunks as we go.  When we're done, transform them into the
    -- destination type.
    hGetLineWith :: ([Text] -> t) -> Handle -> IO t
    hGetLineWith :: forall t. ([Text] -> t) -> Handle -> IO t
    hGetLineWith [Text] -> t
    f Handle
    h = String -> Handle -> (Handle__ -> IO t) -> IO t
    forall a. String -> Handle -> (Handle__ -> IO a) -> IO a
    wantReadableHandle_ String
    "hGetLine" Handle
    h Handle__ -> IO t
    go
      where
        go :: Handle__ -> IO t
    go hh :: Handle__
    hh@Handle__{dev
    Maybe (MVar Handle__)
    Maybe TextEncoding
    Maybe (TextEncoder enc_state)
    Maybe (TextDecoder dec_state)
    IORef (dec_state, Buffer Word8)
    IORef (Buffer CharBufElem)
    IORef (Buffer Word8)
    IORef (BufferList CharBufElem)
    Newline
    BufferMode
    HandleType
    haDevice :: dev
    haType :: HandleType
    haByteBuffer :: IORef (Buffer Word8)
    haBufferMode :: BufferMode
    haLastDecode :: IORef (dec_state, Buffer Word8)
    haCharBuffer :: IORef (Buffer CharBufElem)
    haBuffers :: IORef (BufferList CharBufElem)
    haEncoder :: Maybe (TextEncoder enc_state)
    haDecoder :: Maybe (TextDecoder dec_state)
    haCodec :: Maybe TextEncoding
    haInputNL :: Newline
    haOutputNL :: Newline
    haOtherSide :: Maybe (MVar Handle__)
    haOtherSide :: Handle__ -> Maybe (MVar Handle__)
    haOutputNL :: Handle__ -> Newline
    haInputNL :: Handle__ -> Newline
    haCodec :: Handle__ -> Maybe TextEncoding
    haDecoder :: ()
    haEncoder :: ()
    haBuffers :: Handle__ -> IORef (BufferList CharBufElem)
    haCharBuffer :: Handle__ -> IORef (Buffer CharBufElem)
    haLastDecode :: ()
    haBufferMode :: Handle__ -> BufferMode
    haByteBuffer :: Handle__ -> IORef (Buffer Word8)
    haType :: Handle__ -> HandleType
    haDevice :: ()
    ..} = IORef (Buffer CharBufElem) -> IO (Buffer CharBufElem)
    forall a. IORef a -> IO a
    readIORef IORef (Buffer CharBufElem)
    haCharBuffer IO (Buffer CharBufElem) -> (Buffer CharBufElem -> IO t) -> IO t
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= ([Text] -> t) -> IO [Text] -> IO t
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap [Text] -> t
    f (IO [Text] -> IO t)
    -> (Buffer CharBufElem -> IO [Text]) -> Buffer CharBufElem -> IO t
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Handle__ -> [Text] -> Buffer CharBufElem -> IO [Text]
    hGetLineLoop Handle__
    hh []

    hGetLineLoop :: Handle__ -> [Text] -> CharBuffer -> IO [Text]
    hGetLineLoop :: Handle__ -> [Text] -> Buffer CharBufElem -> IO [Text]
    hGetLineLoop hh :: Handle__
    hh@Handle__{dev
    Maybe (MVar Handle__)
    Maybe TextEncoding
    Maybe (TextEncoder enc_state)
    Maybe (TextDecoder dec_state)
    IORef (dec_state, Buffer Word8)
    IORef (Buffer CharBufElem)
    IORef (Buffer Word8)
    IORef (BufferList CharBufElem)
    Newline
    BufferMode
    HandleType
    haOtherSide :: Handle__ -> Maybe (MVar Handle__)
    haOutputNL :: Handle__ -> Newline
    haInputNL :: Handle__ -> Newline
    haCodec :: Handle__ -> Maybe TextEncoding
    haDecoder :: ()
    haEncoder :: ()
    haBuffers :: Handle__ -> IORef (BufferList CharBufElem)
    haCharBuffer :: Handle__ -> IORef (Buffer CharBufElem)
    haLastDecode :: ()
    haBufferMode :: Handle__ -> BufferMode
    haByteBuffer :: Handle__ -> IORef (Buffer Word8)
    haType :: Handle__ -> HandleType
    haDevice :: ()
    haDevice :: dev
    haType :: HandleType
    haByteBuffer :: IORef (Buffer Word8)
    haBufferMode :: BufferMode
    haLastDecode :: IORef (dec_state, Buffer Word8)
    haCharBuffer :: IORef (Buffer CharBufElem)
    haBuffers :: IORef (BufferList CharBufElem)
    haEncoder :: Maybe (TextEncoder enc_state)
    haDecoder :: Maybe (TextDecoder dec_state)
    haCodec :: Maybe TextEncoding
    haInputNL :: Newline
    haOutputNL :: Newline
    haOtherSide :: Maybe (MVar Handle__)
    ..} = [Text] -> Buffer CharBufElem -> IO [Text]
    go where
     go :: [Text] -> Buffer CharBufElem -> IO [Text]
    go [Text]
    ts buf :: Buffer CharBufElem
    buf@Buffer{ bufL :: forall e. Buffer e -> Int
    bufL=Int
    r0, bufR :: forall e. Buffer e -> Int
    bufR=Int
    w, bufRaw :: forall e. Buffer e -> RawBuffer e
    bufRaw=RawBuffer CharBufElem
    raw0 } = do
      let findEOL :: RawBuffer CharBufElem -> Int -> IO (Bool, Int)
    findEOL RawBuffer CharBufElem
    raw Int
    r | Int
    r Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    w    = (Bool, Int) -> IO (Bool, Int)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Bool
    False, Int
    w)
                        | Bool
    otherwise = do
            (c,r') <- RawBuffer CharBufElem -> Int -> IO (CharBufElem, Int)
    readCharBuf RawBuffer CharBufElem
    raw Int
    r
            if c == '\n'
              then return (True, r)
              else findEOL raw r'
      (eol, off) <- RawBuffer CharBufElem -> Int -> IO (Bool, Int)
    findEOL RawBuffer CharBufElem
    raw0 Int
    r0
      (t,r') <- if haInputNL == CRLF
                then unpack_nl raw0 r0 off
                else do t <- unpack raw0 r0 off
                        return (t,off)
      if eol
        then do writeIORef haCharBuffer (bufferAdjustL (off+1) buf)
                return $ reverse (t:ts)
        else do
          let buf1 = Int -> Buffer CharBufElem -> Buffer CharBufElem
    forall e. Int -> Buffer e -> Buffer e
    bufferAdjustL Int
    r' Buffer CharBufElem
    buf
          maybe_buf <- maybeFillReadBuffer hh buf1
          case maybe_buf of
             -- Nothing indicates we caught an EOF, and we may have a
             -- partial line to return.
             Maybe (Buffer CharBufElem)
    Nothing -> do
                  -- we reached EOF.  There might be a lone \r left
                  -- in the buffer, so check for that and
                  -- append it to the line if necessary.
                  let pre :: Text
    pre | Buffer CharBufElem -> Bool
    forall e. Buffer e -> Bool
    isEmptyBuffer Buffer CharBufElem
    buf1 = Text
    T.empty
                          | Bool
    otherwise          = CharBufElem -> Text
    T.singleton CharBufElem
    '\r'
                  IORef (Buffer CharBufElem) -> Buffer CharBufElem -> IO ()
    forall a. IORef a -> a -> IO ()
    writeIORef IORef (Buffer CharBufElem)
    haCharBuffer Buffer CharBufElem
    buf1{ bufL=0, bufR=0 }
                  let str :: [Text]
    str = [Text] -> [Text]
    forall a. [a] -> [a]
    reverse ([Text] -> [Text]) -> ([Text] -> [Text]) -> [Text] -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Text -> Bool) -> [Text] -> [Text]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Bool
    T.null) ([Text] -> [Text]) -> [Text] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ Text
    preText -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    :Text
    tText -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    :[Text]
    ts
                  if [Text] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Text]
    str
                    then IO [Text]
    forall a. IO a
    ioe_EOF
                    else [Text] -> IO [Text]
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return [Text]
    str
             Just Buffer CharBufElem
    new_buf -> [Text] -> Buffer CharBufElem -> IO [Text]
    go (Text
    tText -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    :[Text]
    ts) Buffer CharBufElem
    new_buf

    -- This function is lifted almost verbatim from GHC.IO.Handle.Text.
    maybeFillReadBuffer :: Handle__ -> CharBuffer -> IO (Maybe CharBuffer)
    maybeFillReadBuffer :: Handle__ -> Buffer CharBufElem -> IO (Maybe (Buffer CharBufElem))
    maybeFillReadBuffer Handle__
    handle_ Buffer CharBufElem
    buf
      = IO (Maybe (Buffer CharBufElem))
    -> (IOError -> IO (Maybe (Buffer CharBufElem)))
    -> IO (Maybe (Buffer CharBufElem))
    forall e a. Exception e => IO a -> (e -> IO a) -> IO a
    E.catch (Buffer CharBufElem -> Maybe (Buffer CharBufElem)
    forall a. a -> Maybe a
    Just (Buffer CharBufElem -> Maybe (Buffer CharBufElem))
    -> IO (Buffer CharBufElem) -> IO (Maybe (Buffer CharBufElem))
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` Handle__ -> Buffer CharBufElem -> IO (Buffer CharBufElem)
    getSomeCharacters Handle__
    handle_ Buffer CharBufElem
    buf) ((IOError -> IO (Maybe (Buffer CharBufElem)))
     -> IO (Maybe (Buffer CharBufElem)))
    -> (IOError -> IO (Maybe (Buffer CharBufElem)))
    -> IO (Maybe (Buffer CharBufElem))
    forall a b. (a -> b) -> a -> b
    $ \IOError
    e ->
          if IOError -> Bool
    isEOFError IOError
    e
          then Maybe (Buffer CharBufElem) -> IO (Maybe (Buffer CharBufElem))
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (Buffer CharBufElem)
    forall a. Maybe a
    Nothing
          else IOError -> IO (Maybe (Buffer CharBufElem))
    forall a. IOError -> IO a
    ioError IOError
    e

    unpack :: RawCharBuffer -> Int -> Int -> IO Text
    unpack :: RawBuffer CharBufElem -> Int -> Int -> IO Text
    unpack !RawBuffer CharBufElem
    buf !Int
    r !Int
    w
     | Int
    charSize Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    4 = String -> IO Text
    forall a. String -> a
    sizeError String
    "unpack"
     | Int
    r Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    w        = Text -> IO Text
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Text
    T.empty
     | Bool
    otherwise     = RawBuffer CharBufElem -> (Ptr CharBufElem -> IO Text) -> IO Text
    forall e a. RawBuffer e -> (Ptr e -> IO a) -> IO a
    withRawBuffer RawBuffer CharBufElem
    buf Ptr CharBufElem -> IO Text
    forall {m :: * -> *}. Monad m => Ptr CharBufElem -> m Text
    go
     where
      go :: Ptr CharBufElem -> m Text
    go Ptr CharBufElem
    pbuf = Text -> m Text
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text -> m Text) -> Text -> m Text
    forall a b. (a -> b) -> a -> b
    $! Stream CharBufElem -> Text
    unstream ((Int -> Step Int CharBufElem) -> Int -> Size -> Stream CharBufElem
    forall a s. (s -> Step s a) -> s -> Size -> Stream a
    Stream Int -> Step Int CharBufElem
    next Int
    r (Int -> Size
    exactSize (Int
    wInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    r)))
       where
        next :: Int -> Step Int CharBufElem
    next !Int
    i | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    w    = Step Int CharBufElem
    forall s a. Step s a
    Done
                | Bool
    otherwise = CharBufElem -> Int -> Step Int CharBufElem
    forall s a. a -> s -> Step s a
    Yield (Int -> CharBufElem
    ix Int
    i) (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
        ix :: Int -> CharBufElem
    ix Int
    i = IO CharBufElem -> CharBufElem
    forall a. IO a -> a
    inlinePerformIO (IO CharBufElem -> CharBufElem) -> IO CharBufElem -> CharBufElem
    forall a b. (a -> b) -> a -> b
    $ Ptr CharBufElem -> Int -> IO CharBufElem
    forall a. Storable a => Ptr a -> Int -> IO a
    peekElemOff Ptr CharBufElem
    pbuf Int
    i

    unpack_nl :: RawCharBuffer -> Int -> Int -> IO (Text, Int)
    unpack_nl :: RawBuffer CharBufElem -> Int -> Int -> IO (Text, Int)
    unpack_nl !RawBuffer CharBufElem
    buf !Int
    r !Int
    w
     | Int
    charSize Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    4 = String -> IO (Text, Int)
    forall a. String -> a
    sizeError String
    "unpack_nl"
     | Int
    r Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    w        = (Text, Int) -> IO (Text, Int)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text
    T.empty, Int
    0)
     | Bool
    otherwise     = RawBuffer CharBufElem
    -> (Ptr CharBufElem -> IO (Text, Int)) -> IO (Text, Int)
    forall e a. RawBuffer e -> (Ptr e -> IO a) -> IO a
    withRawBuffer RawBuffer CharBufElem
    buf ((Ptr CharBufElem -> IO (Text, Int)) -> IO (Text, Int))
    -> (Ptr CharBufElem -> IO (Text, Int)) -> IO (Text, Int)
    forall a b. (a -> b) -> a -> b
    $ Ptr CharBufElem -> IO (Text, Int)
    forall {m :: * -> *}. Monad m => Ptr CharBufElem -> m (Text, Int)
    go
     where
      go :: Ptr CharBufElem -> m (Text, Int)
    go Ptr CharBufElem
    pbuf = do
        let !t :: Text
    t = Stream CharBufElem -> Text
    unstream ((Int -> Step Int CharBufElem) -> Int -> Size -> Stream CharBufElem
    forall a s. (s -> Step s a) -> s -> Size -> Stream a
    Stream Int -> Step Int CharBufElem
    next Int
    r (Int -> Size
    maxSize (Int
    wInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    r)))
            w' :: Int
    w' = Int
    w Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
        (Text, Int) -> m (Text, Int)
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((Text, Int) -> m (Text, Int)) -> (Text, Int) -> m (Text, Int)
    forall a b. (a -> b) -> a -> b
    $ if Int -> CharBufElem
    ix Int
    w' CharBufElem -> CharBufElem -> Bool
    forall a. Eq a => a -> a -> Bool
    == CharBufElem
    '\r'
                 then (Text
    t,Int
    w')
                 else (Text
    t,Int
    w)
       where
        next :: Int -> Step Int CharBufElem
    next !Int
    i | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    w = Step Int CharBufElem
    forall s a. Step s a
    Done
                | CharBufElem
    c CharBufElem -> CharBufElem -> Bool
    forall a. Eq a => a -> a -> Bool
    == CharBufElem
    '\r' = let i' :: Int
    i' = Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1
                              in if Int
    i' Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    w
                                 then if Int -> CharBufElem
    ix Int
    i' CharBufElem -> CharBufElem -> Bool
    forall a. Eq a => a -> a -> Bool
    == CharBufElem
    '\n'
                                      then CharBufElem -> Int -> Step Int CharBufElem
    forall s a. a -> s -> Step s a
    Yield CharBufElem
    '\n' (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    2)
                                      else CharBufElem -> Int -> Step Int CharBufElem
    forall s a. a -> s -> Step s a
    Yield CharBufElem
    '\n' Int
    i'
                                 else Step Int CharBufElem
    forall s a. Step s a
    Done
                | Bool
    otherwise = CharBufElem -> Int -> Step Int CharBufElem
    forall s a. a -> s -> Step s a
    Yield CharBufElem
    c (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
                where c :: CharBufElem
    c = Int -> CharBufElem
    ix Int
    i
        ix :: Int -> CharBufElem
    ix Int
    i = IO CharBufElem -> CharBufElem
    forall a. IO a -> a
    inlinePerformIO (IO CharBufElem -> CharBufElem) -> IO CharBufElem -> CharBufElem
    forall a b. (a -> b) -> a -> b
    $ Ptr CharBufElem -> Int -> IO CharBufElem
    forall a. Storable a => Ptr a -> Int -> IO a
    peekElemOff Ptr CharBufElem
    pbuf Int
    i

    -- This function is completely lifted from GHC.IO.Handle.Text.
    getSomeCharacters :: Handle__ -> CharBuffer -> IO CharBuffer
    getSomeCharacters :: Handle__ -> Buffer CharBufElem -> IO (Buffer CharBufElem)
    getSomeCharacters handle_ :: Handle__
    handle_@Handle__{dev
    Maybe (MVar Handle__)
    Maybe TextEncoding
    Maybe (TextEncoder enc_state)
    Maybe (TextDecoder dec_state)
    IORef (dec_state, Buffer Word8)
    IORef (Buffer CharBufElem)
    IORef (Buffer Word8)
    IORef (BufferList CharBufElem)
    Newline
    BufferMode
    HandleType
    haOtherSide :: Handle__ -> Maybe (MVar Handle__)
    haOutputNL :: Handle__ -> Newline
    haInputNL :: Handle__ -> Newline
    haCodec :: Handle__ -> Maybe TextEncoding
    haDecoder :: ()
    haEncoder :: ()
    haBuffers :: Handle__ -> IORef (BufferList CharBufElem)
    haCharBuffer :: Handle__ -> IORef (Buffer CharBufElem)
    haLastDecode :: ()
    haBufferMode :: Handle__ -> BufferMode
    haByteBuffer :: Handle__ -> IORef (Buffer Word8)
    haType :: Handle__ -> HandleType
    haDevice :: ()
    haDevice :: dev
    haType :: HandleType
    haByteBuffer :: IORef (Buffer Word8)
    haBufferMode :: BufferMode
    haLastDecode :: IORef (dec_state, Buffer Word8)
    haCharBuffer :: IORef (Buffer CharBufElem)
    haBuffers :: IORef (BufferList CharBufElem)
    haEncoder :: Maybe (TextEncoder enc_state)
    haDecoder :: Maybe (TextDecoder dec_state)
    haCodec :: Maybe TextEncoding
    haInputNL :: Newline
    haOutputNL :: Newline
    haOtherSide :: Maybe (MVar Handle__)
    ..} buf :: Buffer CharBufElem
    buf@Buffer{Int
    Word64
    RawBuffer CharBufElem
    BufferState
    bufL :: forall e. Buffer e -> Int
    bufR :: forall e. Buffer e -> Int
    bufRaw :: forall e. Buffer e -> RawBuffer e
    bufRaw :: RawBuffer CharBufElem
    bufState :: BufferState
    bufSize :: Int
    bufOffset :: Word64
    bufL :: Int
    bufR :: Int
    bufOffset :: forall e. Buffer e -> Word64
    bufSize :: forall e. Buffer e -> Int
    bufState :: forall e. Buffer e -> BufferState
    ..} =
      case Buffer CharBufElem -> Int
    forall e. Buffer e -> Int
    bufferElems Buffer CharBufElem
    buf of
        -- buffer empty: read some more
        Int
    0 -> {-# SCC "readTextDevice" #-} Handle__ -> Buffer CharBufElem -> IO (Buffer CharBufElem)
    readTextDevice Handle__
    handle_ Buffer CharBufElem
    buf

        -- if the buffer has a single '\r' in it and we're doing newline
        -- translation: read some more
        Int
    1 | Newline
    haInputNL Newline -> Newline -> Bool
    forall a. Eq a => a -> a -> Bool
    == Newline
    CRLF -> do
          (c,_) <- RawBuffer CharBufElem -> Int -> IO (CharBufElem, Int)
    readCharBuf RawBuffer CharBufElem
    bufRaw Int
    bufL
          if c == '\r'
             then do -- shuffle the '\r' to the beginning.  This is only safe
                     -- if we're about to call readTextDevice, otherwise it
                     -- would mess up flushCharBuffer.
                     -- See [note Buffer Flushing], GHC.IO.Handle.Types
                     _ <- writeCharBuf bufRaw 0 '\r'
                     let buf' = Buffer CharBufElem
    buf{ bufL=0, bufR=1 }
                     readTextDevice handle_ buf'
             else do
                     return buf

        -- buffer has some chars in it already: just return it
        Int
    _otherwise -> {-# SCC "otherwise" #-} Buffer CharBufElem -> IO (Buffer CharBufElem)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Buffer CharBufElem
    buf

    -- | Read a single chunk of strict text from a buffer. Used by both
    -- the strict and lazy implementations of hGetContents.
    readChunk :: Handle__ -> CharBuffer -> IO Text
    readChunk :: Handle__ -> Buffer CharBufElem -> IO Text
    readChunk hh :: Handle__
    hh@Handle__{dev
    Maybe (MVar Handle__)
    Maybe TextEncoding
    Maybe (TextEncoder enc_state)
    Maybe (TextDecoder dec_state)
    IORef (dec_state, Buffer Word8)
    IORef (Buffer CharBufElem)
    IORef (Buffer Word8)
    IORef (BufferList CharBufElem)
    Newline
    BufferMode
    HandleType
    haOtherSide :: Handle__ -> Maybe (MVar Handle__)
    haOutputNL :: Handle__ -> Newline
    haInputNL :: Handle__ -> Newline
    haCodec :: Handle__ -> Maybe TextEncoding
    haDecoder :: ()
    haEncoder :: ()
    haBuffers :: Handle__ -> IORef (BufferList CharBufElem)
    haCharBuffer :: Handle__ -> IORef (Buffer CharBufElem)
    haLastDecode :: ()
    haBufferMode :: Handle__ -> BufferMode
    haByteBuffer :: Handle__ -> IORef (Buffer Word8)
    haType :: Handle__ -> HandleType
    haDevice :: ()
    haDevice :: dev
    haType :: HandleType
    haByteBuffer :: IORef (Buffer Word8)
    haBufferMode :: BufferMode
    haLastDecode :: IORef (dec_state, Buffer Word8)
    haCharBuffer :: IORef (Buffer CharBufElem)
    haBuffers :: IORef (BufferList CharBufElem)
    haEncoder :: Maybe (TextEncoder enc_state)
    haDecoder :: Maybe (TextDecoder dec_state)
    haCodec :: Maybe TextEncoding
    haInputNL :: Newline
    haOutputNL :: Newline
    haOtherSide :: Maybe (MVar Handle__)
    ..} Buffer CharBufElem
    buf = do
      buf'@Buffer{..} <- Handle__ -> Buffer CharBufElem -> IO (Buffer CharBufElem)
    getSomeCharacters Handle__
    hh Buffer CharBufElem
    buf
      (t,r) <- if haInputNL == CRLF
               then unpack_nl bufRaw bufL bufR
               else do t <- unpack bufRaw bufL bufR
                       return (t,bufR)
      writeIORef haCharBuffer (bufferAdjustL r buf')
      return t

    sizeError :: String -> a
    sizeError :: forall a. String -> a
    sizeError String
    loc = String -> a
    forall a. HasCallStack => String -> a
    error (String -> a) -> String -> a
    forall a b. (a -> b) -> a -> b
    $ String
    "Data.Text.IO." String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    loc String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    ": bad internal buffer size"