+-- ---------------------------------------------------------------------------
+-- hGetBufSome
+
+-- | 'hGetBufSome' @hdl buf count@ reads data from the handle @hdl@
+-- into the buffer @buf@. If there is any data available to read,
+-- then 'hGetBufSome' returns it immediately; it only blocks if there
+-- is no data to be read.
+--
+-- It returns the number of bytes actually read. This may be zero if
+-- EOF was reached before any data was read (or if @count@ is zero).
+--
+-- 'hGetBufSome' never raises an EOF exception, instead it returns a value
+-- smaller than @count@.
+--
+-- If the handle is a pipe or socket, and the writing end
+-- is closed, 'hGetBufSome' will behave as if EOF was reached.
+--
+-- 'hGetBufSome' ignores the prevailing 'TextEncoding' and 'NewlineMode'
+-- on the 'Handle', and reads bytes directly.
+
+hGetBufSome :: Handle -> Ptr a -> Int -> IO Int
+hGetBufSome h ptr count
+ | count == 0 = return 0
+ | count < 0 = illegalBufferSize h "hGetBufSome" count
+ | otherwise =
+ wantReadableHandle_ "hGetBufSome" h $ \ h_@Handle__{..} -> do
+ flushCharReadBuffer h_
+ buf@Buffer{ bufSize=sz } <- readIORef haByteBuffer
+ if isEmptyBuffer buf
+ then if count > sz -- large read?
+ then do RawIO.read (haFD h_) (castPtr ptr) count
+ else do (r,buf') <- Buffered.fillReadBuffer haDevice buf
+ if r == 0
+ then return 0
+ else do writeIORef haByteBuffer buf'
+ bufReadNBNonEmpty h_ buf' (castPtr ptr) 0 (min r count)
+ -- new count is (min r count), so
+ -- that bufReadNBNonEmpty will not
+ -- issue another read.
+ else
+ bufReadNBEmpty h_ buf (castPtr ptr) 0 count
+
+haFD :: Handle__ -> FD
+haFD h_@Handle__{..} =
+ case cast haDevice of
+ Nothing -> error "not an FD"
+ Just fd -> fd
+