{-# LANGUAGE Trustworthy, BangPatterns #-}{-# LANGUAGE CPP, NoImplicitPrelude #-}{-# OPTIONS_GHC -funbox-strict-fields #-}------------------------------------------------------------------------------- |-- Module : GHC.IO.Buffer-- Copyright : (c) The University of Glasgow 2008-- License : see libraries/base/LICENSE---- Maintainer : cvs-ghc@haskell.org-- Stability : internal-- Portability : non-portable (GHC Extensions)---- Buffers used in the IO system-------------------------------------------------------------------------------moduleGHC.IO.Buffer(-- * Buffers of any elementBuffer (..),BufferState (..),CharBuffer ,CharBufElem ,-- ** CreationnewByteBuffer ,newCharBuffer ,newBuffer ,emptyBuffer ,-- ** Insertion/removalbufferRemove ,bufferAdd ,slideContents ,bufferAdjustL ,-- ** InspectingisEmptyBuffer ,isFullBuffer ,isFullCharBuffer ,isWriteBuffer ,bufferElems ,bufferAvailable ,summaryBuffer ,-- ** Operating on the raw buffer as a PtrwithBuffer ,withRawBuffer ,-- ** AssertionscheckBuffer ,-- * Raw buffersRawBuffer ,readWord8Buf ,writeWord8Buf ,RawCharBuffer ,peekCharBuf ,readCharBuf ,writeCharBuf ,readCharBufPtr ,writeCharBufPtr ,charSize ,)whereimportGHC.Base -- import GHC.IOimportGHC.Num importGHC.Ptr importGHC.Word importGHC.Show importGHC.Real importForeign.C.Types importForeign.ForeignPtr importForeign.Storable -- Char buffers use either UTF-16 or UTF-32, with the endianness matching-- the endianness of the host.---- Invariants:-- * a Char buffer consists of *valid* UTF-16 or UTF-32-- * only whole characters: no partial surrogate pairs
#define CHARBUF_UTF32
-- #define CHARBUF_UTF16---- NB. it won't work to just change this to CHARBUF_UTF16. Some of-- the code to make this work is there, and it has been tested with-- the Iconv codec, but there are some pieces that are known to be-- broken. In particular, the built-in codecs-- e.g. GHC.IO.Encoding.UTF{8,16,32} need to use isFullCharBuffer or-- similar in place of the ow >= os comparisons.-- ----------------------------------------------------------------------------- Raw blocks of datatypeRawBuffer e =ForeignPtr e readWord8Buf ::RawBuffer Word8 ->Int->IOWord8 readWord8Buf :: RawBuffer Word8 -> Int -> IO Word8
readWord8Buf RawBuffer Word8
arr Int
ix =RawBuffer Word8 -> (Ptr Word8 -> IO Word8) -> IO Word8
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr RawBuffer Word8
arr ((Ptr Word8 -> IO Word8) -> IO Word8)
-> (Ptr Word8 -> IO Word8) -> IO Word8
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p ->Ptr Word8 -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr Word8
p Int
ix writeWord8Buf ::RawBuffer Word8 ->Int->Word8 ->IO()writeWord8Buf :: RawBuffer Word8 -> Int -> Word8 -> IO ()
writeWord8Buf RawBuffer Word8
arr Int
ix Word8
w =RawBuffer Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr RawBuffer Word8
arr ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p ->Ptr Word8 -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Word8
p Int
ix Word8
w 
#if defined(CHARBUF_UTF16)
typeCharBufElem=Word16
#else
typeCharBufElem =Char
#endif
typeRawCharBuffer =RawBuffer CharBufElem peekCharBuf ::RawCharBuffer ->Int->IOCharpeekCharBuf :: RawCharBuffer -> Int -> IO Char
peekCharBuf RawCharBuffer
arr Int
ix =RawCharBuffer -> (Ptr Char -> IO Char) -> IO Char
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr RawCharBuffer
arr ((Ptr Char -> IO Char) -> IO Char)
-> (Ptr Char -> IO Char) -> IO Char
forall a b. (a -> b) -> a -> b
$ \Ptr Char
p ->do(Char
c ,Int
_)<-Ptr Char -> Int -> IO (Char, Int)
readCharBufPtr Ptr Char
p Int
ix Char -> IO Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
c {-# INLINEreadCharBuf #-}readCharBuf ::RawCharBuffer ->Int->IO(Char,Int)readCharBuf :: RawCharBuffer -> Int -> IO (Char, Int)
readCharBuf RawCharBuffer
arr Int
ix =RawCharBuffer -> (Ptr Char -> IO (Char, Int)) -> IO (Char, Int)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr RawCharBuffer
arr ((Ptr Char -> IO (Char, Int)) -> IO (Char, Int))
-> (Ptr Char -> IO (Char, Int)) -> IO (Char, Int)
forall a b. (a -> b) -> a -> b
$ \Ptr Char
p ->Ptr Char -> Int -> IO (Char, Int)
readCharBufPtr Ptr Char
p Int
ix {-# INLINEwriteCharBuf #-}writeCharBuf ::RawCharBuffer ->Int->Char->IOIntwriteCharBuf :: RawCharBuffer -> Int -> Char -> IO Int
writeCharBuf RawCharBuffer
arr Int
ix Char
c =RawCharBuffer -> (Ptr Char -> IO Int) -> IO Int
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr RawCharBuffer
arr ((Ptr Char -> IO Int) -> IO Int) -> (Ptr Char -> IO Int) -> IO Int
forall a b. (a -> b) -> a -> b
$ \Ptr Char
p ->Ptr Char -> Int -> Char -> IO Int
writeCharBufPtr Ptr Char
p Int
ix Char
c {-# INLINEreadCharBufPtr #-}readCharBufPtr ::Ptr CharBufElem ->Int->IO(Char,Int)
#if defined(CHARBUF_UTF16)
readCharBufPtrpix=doc1<-peekElemOffpixif(c1<0xd800||c1>0xdbff)thenreturn(chr(fromIntegralc1),ix+1)elsedoc2<-peekElemOffp(ix+1)return(unsafeChr((fromIntegralc1-0xd800)*0x400+(fromIntegralc2-0xdc00)+0x10000),ix+2)
#else
readCharBufPtr :: Ptr Char -> Int -> IO (Char, Int)
readCharBufPtr Ptr Char
p Int
ix =doChar
c <-Ptr Char -> Int -> IO Char
forall a. Storable a => Ptr a -> Int -> IO a
peekElemOff (Ptr Char -> Ptr Char
forall a b. Ptr a -> Ptr b
castPtr Ptr Char
p )Int
ix ;(Char, Int) -> IO (Char, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (Char
c ,Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
#endif
{-# INLINEwriteCharBufPtr #-}writeCharBufPtr ::Ptr CharBufElem ->Int->Char->IOInt
#if defined(CHARBUF_UTF16)
writeCharBufPtrpixch|c<0x10000=dopokeElemOffpix(fromIntegralc)return(ix+1)|otherwise=doletc'=c-0x10000pokeElemOffpix(fromIntegral(c'`div`0x400+0xd800))pokeElemOffp(ix+1)(fromIntegral(c'`mod`0x400+0xdc00))return(ix+2)wherec=ordch
#else
writeCharBufPtr :: Ptr Char -> Int -> Char -> IO Int
writeCharBufPtr Ptr Char
p Int
ix Char
ch =doPtr Char -> Int -> Char -> IO ()
forall a. Storable a => Ptr a -> Int -> a -> IO ()
pokeElemOff (Ptr Char -> Ptr Char
forall a b. Ptr a -> Ptr b
castPtr Ptr Char
p )Int
ix Char
ch ;Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
#endif
charSize ::Int
#if defined(CHARBUF_UTF16)
charSize=2
#else
charSize :: Int
charSize =Int
4
#endif
-- ----------------------------------------------------------------------------- Buffers-- | A mutable array of bytes that can be passed to foreign functions.---- The buffer is represented by a record, where the record contains-- the raw buffer and the start/end points of the filled portion. The-- buffer contents itself is mutable, but the rest of the record is-- immutable. This is a slightly odd mix, but it turns out to be-- quite practical: by making all the buffer metadata immutable, we-- can have operations on buffer metadata outside of the IO monad.---- The "live" elements of the buffer are those between the 'bufL' and-- 'bufR' offsets. In an empty buffer, 'bufL' is equal to 'bufR', but-- they might not be zero: for example, the buffer might correspond to-- a memory-mapped file and in which case 'bufL' will point to the-- next location to be written, which is not necessarily the beginning-- of the file.dataBuffer e =Buffer {Buffer e -> RawBuffer e
bufRaw ::!(RawBuffer e ),Buffer e -> BufferState
bufState ::BufferState ,Buffer e -> Int
bufSize ::!Int,-- in elements, not bytesBuffer e -> Int
bufL ::!Int,-- offset of first item in the bufferBuffer e -> Int
bufR ::!Int-- offset of last item + 1}
#if defined(CHARBUF_UTF16)
typeCharBuffer=BufferWord16
#else
typeCharBuffer =Buffer Char
#endif
dataBufferState =ReadBuffer |WriteBuffer derivingEq-- ^ @since 4.2.0.0withBuffer ::Buffer e ->(Ptr e ->IOa )->IOa withBuffer :: Buffer e -> (Ptr e -> IO a) -> IO a
withBuffer Buffer {bufRaw :: forall e. Buffer e -> RawBuffer e
bufRaw =RawBuffer e
raw }Ptr e -> IO a
f =RawBuffer e -> (Ptr e -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (RawBuffer e -> RawBuffer e
forall a b. ForeignPtr a -> ForeignPtr b
castForeignPtr RawBuffer e
raw )Ptr e -> IO a
f withRawBuffer ::RawBuffer e ->(Ptr e ->IOa )->IOa withRawBuffer :: RawBuffer e -> (Ptr e -> IO a) -> IO a
withRawBuffer RawBuffer e
raw Ptr e -> IO a
f =RawBuffer e -> (Ptr e -> IO a) -> IO a
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr (RawBuffer e -> RawBuffer e
forall a b. ForeignPtr a -> ForeignPtr b
castForeignPtr RawBuffer e
raw )Ptr e -> IO a
f isEmptyBuffer ::Buffer e ->BoolisEmptyBuffer :: Buffer e -> Bool
isEmptyBuffer Buffer {bufL :: forall e. Buffer e -> Int
bufL =Int
l ,bufR :: forall e. Buffer e -> Int
bufR =Int
r }=Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
==Int
r isFullBuffer ::Buffer e ->BoolisFullBuffer :: Buffer e -> Bool
isFullBuffer Buffer {bufR :: forall e. Buffer e -> Int
bufR =Int
w ,bufSize :: forall e. Buffer e -> Int
bufSize =Int
s }=Int
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
==Int
w -- if a Char buffer does not have room for a surrogate pair, it is "full"isFullCharBuffer ::Buffer e ->Bool
#if defined(CHARBUF_UTF16)
isFullCharBufferbuf=bufferAvailablebuf<2
#else
isFullCharBuffer :: Buffer e -> Bool
isFullCharBuffer =Buffer e -> Bool
forall e. Buffer e -> Bool
isFullBuffer 
#endif
isWriteBuffer ::Buffer e ->BoolisWriteBuffer :: Buffer e -> Bool
isWriteBuffer Buffer e
buf =caseBuffer e -> BufferState
forall e. Buffer e -> BufferState
bufState Buffer e
buf ofBufferState
WriteBuffer ->Bool
TrueBufferState
ReadBuffer ->Bool
FalsebufferElems ::Buffer e ->IntbufferElems :: Buffer e -> Int
bufferElems Buffer {bufR :: forall e. Buffer e -> Int
bufR =Int
w ,bufL :: forall e. Buffer e -> Int
bufL =Int
r }=Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
r bufferAvailable ::Buffer e ->IntbufferAvailable :: Buffer e -> Int
bufferAvailable Buffer {bufR :: forall e. Buffer e -> Int
bufR =Int
w ,bufSize :: forall e. Buffer e -> Int
bufSize =Int
s }=Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
w bufferRemove ::Int->Buffer e ->Buffer e bufferRemove :: Int -> Buffer e -> Buffer e
bufferRemove Int
i buf :: Buffer e
buf @Buffer {bufL :: forall e. Buffer e -> Int
bufL =Int
r }=Int -> Buffer e -> Buffer e
forall e. Int -> Buffer e -> Buffer e
bufferAdjustL (Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i )Buffer e
buf bufferAdjustL ::Int->Buffer e ->Buffer e bufferAdjustL :: Int -> Buffer e -> Buffer e
bufferAdjustL Int
l buf :: Buffer e
buf @Buffer {bufR :: forall e. Buffer e -> Int
bufR =Int
w }|Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
==Int
w =Buffer e
buf {bufL :: Int
bufL =Int
0,bufR :: Int
bufR =Int
0}|Bool
otherwise =Buffer e
buf {bufL :: Int
bufL =Int
l ,bufR :: Int
bufR =Int
w }bufferAdd ::Int->Buffer e ->Buffer e bufferAdd :: Int -> Buffer e -> Buffer e
bufferAdd Int
i buf :: Buffer e
buf @Buffer {bufR :: forall e. Buffer e -> Int
bufR =Int
w }=Buffer e
buf {bufR :: Int
bufR =Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i }emptyBuffer ::RawBuffer e ->Int->BufferState ->Buffer e emptyBuffer :: RawBuffer e -> Int -> BufferState -> Buffer e
emptyBuffer RawBuffer e
raw Int
sz BufferState
state =Buffer :: forall e.
RawBuffer e -> BufferState -> Int -> Int -> Int -> Buffer e
Buffer {bufRaw :: RawBuffer e
bufRaw =RawBuffer e
raw ,bufState :: BufferState
bufState =BufferState
state ,bufR :: Int
bufR =Int
0,bufL :: Int
bufL =Int
0,bufSize :: Int
bufSize =Int
sz }newByteBuffer ::Int->BufferState ->IO(Buffer Word8 )newByteBuffer :: Int -> BufferState -> IO (Buffer Word8)
newByteBuffer Int
c BufferState
st =Int -> Int -> BufferState -> IO (Buffer Word8)
forall e. Int -> Int -> BufferState -> IO (Buffer e)
newBuffer Int
c Int
c BufferState
st newCharBuffer ::Int->BufferState ->IOCharBuffer newCharBuffer :: Int -> BufferState -> IO CharBuffer
newCharBuffer Int
c BufferState
st =Int -> Int -> BufferState -> IO CharBuffer
forall e. Int -> Int -> BufferState -> IO (Buffer e)
newBuffer (Int
c Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
charSize )Int
c BufferState
st newBuffer ::Int->Int->BufferState ->IO(Buffer e )newBuffer :: Int -> Int -> BufferState -> IO (Buffer e)
newBuffer Int
bytes Int
sz BufferState
state =doForeignPtr e
fp <-Int -> IO (ForeignPtr e)
forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes Int
bytes Buffer e -> IO (Buffer e)
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr e -> Int -> BufferState -> Buffer e
forall e. RawBuffer e -> Int -> BufferState -> Buffer e
emptyBuffer ForeignPtr e
fp Int
sz BufferState
state )-- | slides the contents of the buffer to the beginningslideContents ::Buffer Word8 ->IO(Buffer Word8 )slideContents :: Buffer Word8 -> IO (Buffer Word8)
slideContents buf :: Buffer Word8
buf @Buffer {bufL :: forall e. Buffer e -> Int
bufL =Int
l ,bufR :: forall e. Buffer e -> Int
bufR =Int
r ,bufRaw :: forall e. Buffer e -> RawBuffer e
bufRaw =RawBuffer Word8
raw }=doletelems :: Int
elems =Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
l RawBuffer Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withRawBuffer RawBuffer Word8
raw ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p ->doPtr Word8
_<-Ptr Word8 -> Ptr Word8 -> CSize -> IO (Ptr Word8)
forall a. Ptr a -> Ptr a -> CSize -> IO (Ptr a)
memmove Ptr Word8
p (Ptr Word8
p Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
l )(Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
elems )() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()Buffer Word8 -> IO (Buffer Word8)
forall (m :: * -> *) a. Monad m => a -> m a
return Buffer Word8
buf {bufL :: Int
bufL =Int
0,bufR :: Int
bufR =Int
elems }foreignimportccallunsafe"memmove"memmove ::Ptr a ->Ptr a ->CSize ->IO(Ptr a )summaryBuffer ::Buffer a ->String summaryBuffer :: Buffer a -> String
summaryBuffer !Buffer a
buf -- Strict => slightly better code=String
"buf"String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (Buffer a -> Int
forall e. Buffer e -> Int
bufSize Buffer a
buf )String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"("String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (Buffer a -> Int
forall e. Buffer e -> Int
bufL Buffer a
buf )String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-"String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (Buffer a -> Int
forall e. Buffer e -> Int
bufR Buffer a
buf )String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")"-- INVARIANTS on Buffers:-- * r <= w-- * if r == w, and the buffer is for reading, then r == 0 && w == 0-- * a write buffer is never full. If an operation-- fills up the buffer, it will always flush it before-- returning.-- * a read buffer may be full as a result of hLookAhead. In normal-- operation, a read buffer always has at least one character of space.checkBuffer ::Buffer a ->IO()checkBuffer :: Buffer a -> IO ()
checkBuffer buf :: Buffer a
buf @Buffer {bufState :: forall e. Buffer e -> BufferState
bufState =BufferState
state ,bufL :: forall e. Buffer e -> Int
bufL =Int
r ,bufR :: forall e. Buffer e -> Int
bufR =Int
w ,bufSize :: forall e. Buffer e -> Int
bufSize =Int
size }=doBuffer a -> Bool -> IO ()
forall a. Buffer a -> Bool -> IO ()
check Buffer a
buf (Int
size Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>Int
0Bool -> Bool -> Bool
&&Int
r Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
w Bool -> Bool -> Bool
&&Int
w Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<=Int
size Bool -> Bool -> Bool
&&(Int
r Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/=Int
w Bool -> Bool -> Bool
||BufferState
state BufferState -> BufferState -> Bool
forall a. Eq a => a -> a -> Bool
==BufferState
WriteBuffer Bool -> Bool -> Bool
||(Int
r Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
==Int
0Bool -> Bool -> Bool
&&Int
w Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
==Int
0))Bool -> Bool -> Bool
&&(BufferState
state BufferState -> BufferState -> Bool
forall a. Eq a => a -> a -> Bool
/=BufferState
WriteBuffer Bool -> Bool -> Bool
||Int
w Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<Int
size )-- write buffer is never full)check ::Buffer a ->Bool->IO()check :: Buffer a -> Bool -> IO ()
check Buffer a
_Bool
True=() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()check Buffer a
buf Bool
False=String -> IO ()
forall a. String -> a
errorWithoutStackTrace (String
"buffer invariant violation: "String -> String -> String
forall a. [a] -> [a] -> [a]
++ Buffer a -> String
forall a. Buffer a -> String
summaryBuffer Buffer a
buf )

AltStyle によって変換されたページ (->オリジナル) /