- buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r } <- readIORef ref
- if bufferEmpty buf
- then readChunk fd is_stream ptr count
+ bufRead fd ref is_stream ptr 0 count can_block
+
+bufRead fd ref is_stream ptr so_far count can_block =
+ seq fd $ seq so_far $ seq count $ do -- strictness hack
+ buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r, bufSize=sz } <- readIORef ref
+ if bufferEmpty buf
+ then if count < sz
+ then do
+ mb_buf <- maybeFillReadBuffer fd (not can_block) is_stream buf
+ case mb_buf of
+ Nothing -> return 0
+ Just new_buf -> do
+ writeIORef ref new_buf
+ bufRead fd ref is_stream ptr so_far count can_block
+ else if can_block
+ then readChunk fd is_stream ptr count
+ else readChunkNonBlocking fd is_stream ptr count
+ else do
+ let avail = w - r
+ if (count == avail)
+ then do
+ memcpy_ptr_baoff ptr raw r (fromIntegral count)
+ writeIORef ref buf{ bufWPtr=0, bufRPtr=0 }
+ return (so_far + count)
+ else do
+ if (count < avail)
+ then do
+ memcpy_ptr_baoff ptr raw r (fromIntegral count)
+ writeIORef ref buf{ bufRPtr = r + count }
+ return (so_far + count)
+ else do
+
+ memcpy_ptr_baoff ptr raw r (fromIntegral avail)
+ writeIORef ref buf{ bufWPtr=0, bufRPtr=0 }
+
+ let remaining = count - avail
+ so_far' = so_far + avail
+ ptr' = ptr `plusPtr` avail
+
+ if remaining < sz
+ then bufRead fd ref is_stream ptr' so_far' remaining can_block