1 {-# LANGUAGE NoImplicitPrelude, ExistentialQuantification #-}
2 {-# OPTIONS_GHC -funbox-strict-fields #-}
4 -----------------------------------------------------------------------------
6 -- Module : GHC.IO.Encoding.Types
7 -- Copyright : (c) The University of Glasgow, 2008-2009
8 -- License : see libraries/base/LICENSE
10 -- Maintainer : libraries@haskell.org
11 -- Stability : internal
12 -- Portability : non-portable
14 -- Types for text encoding/decoding
16 -----------------------------------------------------------------------------
18 module GHC.IO.Encoding.Types (
21 TextEncoder, TextDecoder,
22 EncodeBuffer, DecodeBuffer,
32 -- -----------------------------------------------------------------------------
33 -- Text encoders/decoders
35 data BufferCodec from to state = BufferCodec {
36 encode :: Buffer from -> Buffer to -> IO (CodingProgress, Buffer from, Buffer to),
37 -- ^ The @encode@ function translates elements of the buffer @from@
38 -- to the buffer @to@. It should translate as many elements as possible
39 -- given the sizes of the buffers, including translating zero elements
40 -- if there is either not enough room in @to@, or @from@ does not
41 -- contain a complete multibyte sequence.
43 -- The fact that as many elements as possible are translated is used by the IO
44 -- library in order to report translation errors at the point they
45 -- actually occur, rather than when the buffer is translated.
47 recover :: Buffer from -> Buffer to -> IO (Buffer from, Buffer to),
48 -- ^ The @recover@ function is used to continue decoding
49 -- in the presence of invalid or unrepresentable sequences. This includes
50 -- both those detected by @encode@ returning @InvalidSequence@ and those
51 -- that occur because the input byte sequence appears to be truncated.
53 -- Progress will usually be made by skipping the first element of the @from@
54 -- buffer. This function should only be called if you are certain that you
55 -- wish to do this skipping, and if the @to@ buffer has at least one element
58 -- @recover@ may raise an exception rather than skipping anything.
61 -- ^ Resources associated with the encoding may now be released.
62 -- The @encode@ function may not be called again after calling
66 -- ^ Return the current state of the codec.
68 -- Many codecs are not stateful, and in these case the state can be
69 -- represented as '()'. Other codecs maintain a state. For
70 -- example, UTF-16 recognises a BOM (byte-order-mark) character at
71 -- the beginning of the input, and remembers thereafter whether to
72 -- use big-endian or little-endian mode. In this case, the state
73 -- of the codec would include two pieces of information: whether we
74 -- are at the beginning of the stream (the BOM only occurs at the
75 -- beginning), and if not, whether to use the big or little-endian
78 setState :: state -> IO ()
79 -- restore the state of the codec using the state from a previous
80 -- call to 'getState'.
83 type DecodeBuffer = Buffer Word8 -> Buffer Char
84 -> IO (CodingProgress, Buffer Word8, Buffer Char)
86 type EncodeBuffer = Buffer Char -> Buffer Word8
87 -> IO (CodingProgress, Buffer Char, Buffer Word8)
89 type TextDecoder state = BufferCodec Word8 CharBufElem state
90 type TextEncoder state = BufferCodec CharBufElem Word8 state
92 -- | A 'TextEncoding' is a specification of a conversion scheme
93 -- between sequences of bytes and sequences of Unicode characters.
95 -- For example, UTF-8 is an encoding of Unicode characters into a sequence
96 -- of bytes. The 'TextEncoding' for UTF-8 is 'utf8'.
98 = forall dstate estate . TextEncoding {
99 textEncodingName :: String,
100 -- ^ a string that can be passed to 'mkTextEncoding' to
101 -- create an equivalent 'TextEncoding'.
102 mkTextDecoder :: IO (TextDecoder dstate),
103 -- ^ Creates a means of decoding bytes into characters: the result must not
104 -- be shared between several byte sequences or simultaneously across threads
105 mkTextEncoder :: IO (TextEncoder estate)
106 -- ^ Creates a means of encode characters into bytes: the result must not
107 -- be shared between several character sequences or simultaneously across threads
110 instance Show TextEncoding where
111 -- | Returns the value of 'textEncodingName'
112 show te = textEncodingName te
114 data CodingProgress = InputUnderflow -- ^ Stopped because the input contains insufficient available elements,
115 -- or all of the input sequence has been sucessfully translated.
116 | OutputUnderflow -- ^ Stopped because the output contains insufficient free elements
117 | InvalidSequence -- ^ Stopped because there are sufficient free elements in the output
118 -- to output at least one encoded ASCII character, but the input contains
119 -- an invalid or unrepresentable sequence