Movatterモバイル変換


[0]ホーム

URL:


{-# 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,bufferAddOffset,bufferAdjustOffset,-- ** InspectingisEmptyBuffer,isFullBuffer,isFullCharBuffer,isWriteBuffer,bufferElems,bufferAvailable,bufferOffset,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.NumimportGHC.PtrimportGHC.WordimportGHC.ShowimportGHC.RealimportGHC.ListimportGHC.ForeignPtr(unsafeWithForeignPtr)importForeign.C.TypesimportForeign.ForeignPtrimportForeign.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.---- Tamar: We need to do this eventually for Windows, as we have to re-encode-- the text as UTF-16 anyway, so if we can avoid it it would be great.-- ----------------------------------------------------------------------------- Raw blocks of datatypeRawBuffere=ForeignPtrereadWord8Buf::RawBufferWord8->Int->IOWord8readWord8Buf :: RawBuffer Word8 -> Int -> IO Word8readWord8BufRawBuffer Word8fpIntix=RawBuffer Word8 -> (Ptr Word8 -> IO Word8) -> IO Word8forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO bunsafeWithForeignPtrRawBuffer Word8fp((Ptr Word8 -> IO Word8) -> IO Word8)-> (Ptr Word8 -> IO Word8) -> IO Word8forall a b. (a -> b) -> a -> b$\Ptr Word8p->Ptr Word8 -> Int -> IO Word8forall b. Ptr b -> Int -> IO Word8forall a b. Storable a => Ptr b -> Int -> IO apeekByteOffPtr Word8pIntixwriteWord8Buf::RawBufferWord8->Int->Word8->IO()writeWord8Buf :: RawBuffer Word8 -> Int -> Word8 -> IO ()writeWord8BufRawBuffer Word8fpIntixWord8w=RawBuffer Word8 -> (Ptr Word8 -> IO ()) -> IO ()forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO bunsafeWithForeignPtrRawBuffer Word8fp((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()forall a b. (a -> b) -> a -> b$\Ptr Word8p->Ptr Word8 -> Int -> Word8 -> IO ()forall b. Ptr b -> Int -> Word8 -> IO ()forall a b. Storable a => Ptr b -> Int -> a -> IO ()pokeByteOffPtr Word8pIntixWord8w#if defined(CHARBUF_UTF16)typeCharBufElem=Word16#elsetypeCharBufElem=Char#endiftypeRawCharBuffer=RawBufferCharBufElempeekCharBuf::RawCharBuffer->Int->IOCharpeekCharBuf :: RawCharBuffer -> Int -> IO CharpeekCharBufRawCharBufferarrIntix=RawCharBuffer -> (Ptr Char -> IO Char) -> IO Charforall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO bunsafeWithForeignPtrRawCharBufferarr((Ptr Char -> IO Char) -> IO Char)-> (Ptr Char -> IO Char) -> IO Charforall a b. (a -> b) -> a -> b$\Ptr Charp->do(Charc,Int_)<-Ptr Char -> Int -> IO (Char, Int)readCharBufPtrPtr CharpIntixChar -> IO Charforall a. a -> IO aforall (m :: * -> *) a. Monad m => a -> m areturnCharc{-# INLINEreadCharBuf#-}readCharBuf::RawCharBuffer->Int->IO(Char,Int)readCharBuf :: RawCharBuffer -> Int -> IO (Char, Int)readCharBufRawCharBufferarrIntix=RawCharBuffer -> (Ptr Char -> IO (Char, Int)) -> IO (Char, Int)forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO bunsafeWithForeignPtrRawCharBufferarr((Ptr Char -> IO (Char, Int)) -> IO (Char, Int))-> (Ptr Char -> IO (Char, Int)) -> IO (Char, Int)forall a b. (a -> b) -> a -> b$\Ptr Charp->Ptr Char -> Int -> IO (Char, Int)readCharBufPtrPtr CharpIntix{-# INLINEwriteCharBuf#-}writeCharBuf::RawCharBuffer->Int->Char->IOIntwriteCharBuf :: RawCharBuffer -> Int -> Char -> IO IntwriteCharBufRawCharBufferarrIntixCharc=RawCharBuffer -> (Ptr Char -> IO Int) -> IO Intforall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO bunsafeWithForeignPtrRawCharBufferarr((Ptr Char -> IO Int) -> IO Int) -> (Ptr Char -> IO Int) -> IO Intforall a b. (a -> b) -> a -> b$\Ptr Charp->Ptr Char -> Int -> Char -> IO IntwriteCharBufPtrPtr CharpIntixCharc{-# INLINEreadCharBufPtr#-}readCharBufPtr::PtrCharBufElem->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)#elsereadCharBufPtr :: Ptr Char -> Int -> IO (Char, Int)readCharBufPtrPtr CharpIntix=doCharc<-Ptr Char -> Int -> IO Charforall a. Storable a => Ptr a -> Int -> IO apeekElemOff(Ptr Char -> Ptr Charforall a b. Ptr a -> Ptr bcastPtrPtr Charp)Intix;(Char, Int) -> IO (Char, Int)forall a. a -> IO aforall (m :: * -> *) a. Monad m => a -> m areturn(Charc,IntixInt -> Int -> Intforall a. Num a => a -> a -> a+Int1)#endif{-# INLINEwriteCharBufPtr#-}writeCharBufPtr::PtrCharBufElem->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#elsewriteCharBufPtr :: Ptr Char -> Int -> Char -> IO IntwriteCharBufPtrPtr CharpIntixCharch=doPtr Char -> Int -> Char -> IO ()forall a. Storable a => Ptr a -> Int -> a -> IO ()pokeElemOff(Ptr Char -> Ptr Charforall a b. Ptr a -> Ptr bcastPtrPtr Charp)IntixCharch;Int -> IO Intforall a. a -> IO aforall (m :: * -> *) a. Monad m => a -> m areturn(IntixInt -> Int -> Intforall a. Num a => a -> a -> a+Int1)#endifcharSize::Int#if defined(CHARBUF_UTF16)charSize=2#elsecharSize :: IntcharSize=Int4#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.---- On Posix systems the I/O manager has an implicit reliance on doing a file-- read moving the file pointer.  However on Windows async operations the kernel-- object representing a file does not use the file pointer offset.  Logically-- this makes sense since operations can be performed in any arbitrary order.-- OVERLAPPED operations don't respect the file pointer offset as their-- intention is to support arbitrary async reads to anywhere at a much lower-- level.  As such we should explicitly keep track of the file offsets of the-- target in the buffer.  Any operation to seek should also update this entry.---- In order to keep us sane we try to uphold the invariant that any function-- being passed a Handle is responsible for updating the handles offset unless-- other behaviour is documented.dataBuffere=Buffer{forall e. Buffer e -> RawBuffer ebufRaw::!(RawBuffere),forall e. Buffer e -> BufferStatebufState::BufferState,forall e. Buffer e -> IntbufSize::!Int,-- in elements, not bytesforall e. Buffer e -> Word64bufOffset::!Word64,-- start location for next read/writeforall e. Buffer e -> IntbufL::!Int,-- offset of first item in the bufferforall e. Buffer e -> IntbufR::!Int-- offset of last item + 1}#if defined(CHARBUF_UTF16)typeCharBuffer=BufferWord16#elsetypeCharBuffer=BufferChar#endifdataBufferState=ReadBuffer|WriteBufferderivingBufferState -> BufferState -> Bool(BufferState -> BufferState -> Bool)-> (BufferState -> BufferState -> Bool) -> Eq BufferStateforall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a$c== :: BufferState -> BufferState -> Bool== :: BufferState -> BufferState -> Bool$c/= :: BufferState -> BufferState -> Bool/= :: BufferState -> BufferState -> BoolEq-- ^ @since 4.2.0.0withBuffer::Buffere->(Ptre->IOa)->IOawithBuffer :: forall e a. Buffer e -> (Ptr e -> IO a) -> IO awithBufferBuffer{bufRaw :: forall e. Buffer e -> RawBuffer ebufRaw=RawBuffer eraw}Ptr e -> IO af=RawBuffer e -> (Ptr e -> IO a) -> IO aforall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO bwithForeignPtr(RawBuffer e -> RawBuffer eforall a b. ForeignPtr a -> ForeignPtr bcastForeignPtrRawBuffer eraw)Ptr e -> IO afwithRawBuffer::RawBuffere->(Ptre->IOa)->IOawithRawBuffer :: forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO bwithRawBufferRawBuffer erawPtr e -> IO af=RawBuffer e -> (Ptr e -> IO a) -> IO aforall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO bwithForeignPtr(RawBuffer e -> RawBuffer eforall a b. ForeignPtr a -> ForeignPtr bcastForeignPtrRawBuffer eraw)Ptr e -> IO afisEmptyBuffer::Buffere->BoolisEmptyBuffer :: forall e. Buffer e -> BoolisEmptyBufferBuffer{bufL :: forall e. Buffer e -> IntbufL=Intl,bufR :: forall e. Buffer e -> IntbufR=Intr}=IntlInt -> Int -> Boolforall a. Eq a => a -> a -> Bool==IntrisFullBuffer::Buffere->BoolisFullBuffer :: forall e. Buffer e -> BoolisFullBufferBuffer{bufR :: forall e. Buffer e -> IntbufR=Intw,bufSize :: forall e. Buffer e -> IntbufSize=Ints}=IntsInt -> Int -> Boolforall a. Eq a => a -> a -> Bool==Intw-- if a Char buffer does not have room for a surrogate pair, it is "full"isFullCharBuffer::Buffere->Bool#if defined(CHARBUF_UTF16)isFullCharBufferbuf=bufferAvailablebuf<2#elseisFullCharBuffer :: forall e. Buffer e -> BoolisFullCharBuffer=Buffer e -> Boolforall e. Buffer e -> BoolisFullBuffer#endifisWriteBuffer::Buffere->BoolisWriteBuffer :: forall e. Buffer e -> BoolisWriteBufferBuffer ebuf=caseBuffer e -> BufferStateforall e. Buffer e -> BufferStatebufStateBuffer ebufofBufferStateWriteBuffer->BoolTrueBufferStateReadBuffer->BoolFalsebufferElems::Buffere->IntbufferElems :: forall e. Buffer e -> IntbufferElemsBuffer{bufR :: forall e. Buffer e -> IntbufR=Intw,bufL :: forall e. Buffer e -> IntbufL=Intr}=IntwInt -> Int -> Intforall a. Num a => a -> a -> a-IntrbufferAvailable::Buffere->IntbufferAvailable :: forall e. Buffer e -> IntbufferAvailableBuffer{bufR :: forall e. Buffer e -> IntbufR=Intw,bufSize :: forall e. Buffer e -> IntbufSize=Ints}=IntsInt -> Int -> Intforall a. Num a => a -> a -> a-IntwbufferRemove::Int->Buffere->BufferebufferRemove :: forall e. Int -> Buffer e -> Buffer ebufferRemoveIntibuf :: Buffer ebuf@Buffer{bufL :: forall e. Buffer e -> IntbufL=Intr}=Int -> Buffer e -> Buffer eforall e. Int -> Buffer e -> Buffer ebufferAdjustL(IntrInt -> Int -> Intforall a. Num a => a -> a -> a+Inti)Buffer ebufbufferAdjustL::Int->Buffere->BufferebufferAdjustL :: forall e. Int -> Buffer e -> Buffer ebufferAdjustLIntlbuf :: Buffer ebuf@Buffer{bufR :: forall e. Buffer e -> IntbufR=Intw}|IntlInt -> Int -> Boolforall a. Eq a => a -> a -> Bool==Intw=Buffer ebuf{bufL=0,bufR=0}|Boolotherwise=Buffer ebuf{bufL=l,bufR=w}bufferAdd::Int->Buffere->BufferebufferAdd :: forall e. Int -> Buffer e -> Buffer ebufferAddIntibuf :: Buffer ebuf@Buffer{bufR :: forall e. Buffer e -> IntbufR=Intw}=Buffer ebuf{bufR=w+i}bufferOffset::Buffere->Word64bufferOffset :: forall e. Buffer e -> Word64bufferOffsetBuffer{bufOffset :: forall e. Buffer e -> Word64bufOffset=Word64off}=Word64offbufferAdjustOffset::Word64->Buffere->BufferebufferAdjustOffset :: forall e. Word64 -> Buffer e -> Buffer ebufferAdjustOffsetWord64offsBuffer ebuf=Buffer ebuf{bufOffset=offs}-- The adjustment to the offset can be 32bit int on 32 platforms.-- This is fine, we only use this after reading into/writing from-- the buffer so we will never overflow here.bufferAddOffset::Int->Buffere->BufferebufferAddOffset :: forall e. Int -> Buffer e -> Buffer ebufferAddOffsetIntoffsbuf :: Buffer ebuf@Buffer{bufOffset :: forall e. Buffer e -> Word64bufOffset=Word64w}=Buffer ebuf{bufOffset=w+(fromIntegraloffs)}emptyBuffer::RawBuffere->Int->BufferState->BuffereemptyBuffer :: forall e. RawBuffer e -> Int -> BufferState -> Buffer eemptyBufferRawBuffer erawIntszBufferStatestate=Buffer{bufRaw :: RawBuffer ebufRaw=RawBuffer eraw,bufState :: BufferStatebufState=BufferStatestate,bufOffset :: Word64bufOffset=Word640,bufR :: IntbufR=Int0,bufL :: IntbufL=Int0,bufSize :: IntbufSize=Intsz}newByteBuffer::Int->BufferState->IO(BufferWord8)newByteBuffer :: Int -> BufferState -> IO (Buffer Word8)newByteBufferIntcBufferStatest=Int -> Int -> BufferState -> IO (Buffer Word8)forall e. Int -> Int -> BufferState -> IO (Buffer e)newBufferIntcIntcBufferStatestnewCharBuffer::Int->BufferState->IOCharBuffernewCharBuffer :: Int -> BufferState -> IO CharBuffernewCharBufferIntcBufferStatest=Int -> Int -> BufferState -> IO CharBufferforall e. Int -> Int -> BufferState -> IO (Buffer e)newBuffer(IntcInt -> Int -> Intforall a. Num a => a -> a -> a*IntcharSize)IntcBufferStatestnewBuffer::Int->Int->BufferState->IO(Buffere)newBuffer :: forall e. Int -> Int -> BufferState -> IO (Buffer e)newBufferIntbytesIntszBufferStatestate=doForeignPtr efp<-Int -> IO (ForeignPtr e)forall a. Int -> IO (ForeignPtr a)mallocForeignPtrBytesIntbytesBuffer e -> IO (Buffer e)forall a. a -> IO aforall (m :: * -> *) a. Monad m => a -> m areturn(ForeignPtr e -> Int -> BufferState -> Buffer eforall e. RawBuffer e -> Int -> BufferState -> Buffer eemptyBufferForeignPtr efpIntszBufferStatestate)-- | slides the contents of the buffer to the beginningslideContents::BufferWord8->IO(BufferWord8)slideContents :: Buffer Word8 -> IO (Buffer Word8)slideContentsbuf :: Buffer Word8buf@Buffer{bufL :: forall e. Buffer e -> IntbufL=Intl,bufR :: forall e. Buffer e -> IntbufR=Intr,bufRaw :: forall e. Buffer e -> RawBuffer ebufRaw=RawBuffer Word8raw}=doletelems :: Intelems=IntrInt -> Int -> Intforall a. Num a => a -> a -> a-IntlRawBuffer Word8 -> (Ptr Word8 -> IO ()) -> IO ()forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO bwithRawBufferRawBuffer Word8raw((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()forall a b. (a -> b) -> a -> b$\Ptr Word8p->doPtr Word8_<-Ptr Word8 -> Ptr Word8 -> CSize -> IO (Ptr Word8)forall a. Ptr a -> Ptr a -> CSize -> IO (Ptr a)memmovePtr Word8p(Ptr Word8pPtr Word8 -> Int -> Ptr Word8forall a b. Ptr a -> Int -> Ptr b`plusPtr`Intl)(Int -> CSizeforall a b. (Integral a, Num b) => a -> bfromIntegralIntelems)() -> IO ()forall a. a -> IO aforall (m :: * -> *) a. Monad m => a -> m areturn()Buffer Word8 -> IO (Buffer Word8)forall a. a -> IO aforall (m :: * -> *) a. Monad m => a -> m areturnBuffer Word8buf{bufL=0,bufR=elems}foreignimportccallunsafe"memmove"memmove::Ptra->Ptra->CSize->IO(Ptra)summaryBuffer::Buffera->StringsummaryBuffer :: forall a. Buffer a -> StringsummaryBuffer!Buffer abuf-- Strict => slightly better code=String -> Stringppr(RawBuffer a -> Stringforall a. Show a => a -> Stringshow(RawBuffer a -> String) -> RawBuffer a -> Stringforall a b. (a -> b) -> a -> b$Buffer a -> RawBuffer aforall e. Buffer e -> RawBuffer ebufRawBuffer abuf)String -> String -> Stringforall a. [a] -> [a] -> [a]++String"@buf"String -> String -> Stringforall a. [a] -> [a] -> [a]++Int -> Stringforall a. Show a => a -> Stringshow(Buffer a -> Intforall e. Buffer e -> IntbufSizeBuffer abuf)String -> String -> Stringforall a. [a] -> [a] -> [a]++String"("String -> String -> Stringforall a. [a] -> [a] -> [a]++Int -> Stringforall a. Show a => a -> Stringshow(Buffer a -> Intforall e. Buffer e -> IntbufLBuffer abuf)String -> String -> Stringforall a. [a] -> [a] -> [a]++String"-"String -> String -> Stringforall a. [a] -> [a] -> [a]++Int -> Stringforall a. Show a => a -> Stringshow(Buffer a -> Intforall e. Buffer e -> IntbufRBuffer abuf)String -> String -> Stringforall a. [a] -> [a] -> [a]++String")"String -> String -> Stringforall a. [a] -> [a] -> [a]++String" (>="String -> String -> Stringforall a. [a] -> [a] -> [a]++Word64 -> Stringforall a. Show a => a -> Stringshow(Buffer a -> Word64forall e. Buffer e -> Word64bufOffsetBuffer abuf)String -> String -> Stringforall a. [a] -> [a] -> [a]++String")"whereppr::String->Stringppr :: String -> Stringppr(Char'0':Char'x':Stringxs)=letp :: Stringp=(Char -> Bool) -> String -> Stringforall a. (a -> Bool) -> [a] -> [a]dropWhile(Char -> Char -> Boolforall a. Eq a => a -> a -> Bool==Char'0')StringxsinifString -> Boolforall a. [a] -> BoolnullStringpthenString"0x0"elseChar'0'Char -> String -> Stringforall a. a -> [a] -> [a]:Char'x'Char -> String -> Stringforall a. a -> [a] -> [a]:StringppprStringx=Stringx-- Note [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::Buffera->IO()checkBuffer :: forall a. Buffer a -> IO ()checkBufferbuf :: Buffer abuf@Buffer{bufState :: forall e. Buffer e -> BufferStatebufState=BufferStatestate,bufL :: forall e. Buffer e -> IntbufL=Intr,bufR :: forall e. Buffer e -> IntbufR=Intw,bufSize :: forall e. Buffer e -> IntbufSize=Intsize}=Buffer a -> Bool -> IO ()forall a. Buffer a -> Bool -> IO ()checkBuffer abuf(IntsizeInt -> Int -> Boolforall a. Ord a => a -> a -> Bool>Int0Bool -> Bool -> Bool&&IntrInt -> Int -> Boolforall a. Ord a => a -> a -> Bool<=IntwBool -> Bool -> Bool&&IntwInt -> Int -> Boolforall a. Ord a => a -> a -> Bool<=IntsizeBool -> Bool -> Bool&&(IntrInt -> Int -> Boolforall a. Eq a => a -> a -> Bool/=IntwBool -> Bool -> Bool||BufferStatestateBufferState -> BufferState -> Boolforall a. Eq a => a -> a -> Bool==BufferStateWriteBufferBool -> Bool -> Bool||(IntrInt -> Int -> Boolforall a. Eq a => a -> a -> Bool==Int0Bool -> Bool -> Bool&&IntwInt -> Int -> Boolforall a. Eq a => a -> a -> Bool==Int0))Bool -> Bool -> Bool&&(BufferStatestateBufferState -> BufferState -> Boolforall a. Eq a => a -> a -> Bool/=BufferStateWriteBufferBool -> Bool -> Bool||IntwInt -> Int -> Boolforall a. Ord a => a -> a -> Bool<Intsize)-- write buffer is never full)check::Buffera->Bool->IO()check :: forall a. Buffer a -> Bool -> IO ()checkBuffer a_BoolTrue=() -> IO ()forall a. a -> IO aforall (m :: * -> *) a. Monad m => a -> m areturn()checkBuffer abufBoolFalse=String -> IO ()forall a. String -> aerrorWithoutStackTrace(String"buffer invariant violation: "String -> String -> Stringforall a. [a] -> [a] -> [a]++Buffer a -> Stringforall a. Buffer a -> StringsummaryBufferBuffer abuf)

[8]ページ先頭

©2009-2025 Movatter.jp