{-# OPTIONS_GHC -O2 #-}
-- -O2: the decoding loop runs over every byte of every varchar value.
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
-- | Decoding single-byte (@char@, @varchar@, @text@) data according to its
-- collation.
--
-- A collation determines the code page of non-Unicode character data:
--
-- * UTF-8 collations (the @_UTF8@ suffix, flag bit 26) use UTF-8.
-- * SQL collations (@SQL_*@) have a non-zero sort ID, which determines the
--   code page; the LCID does not (e.g. @SQL_Latin1_General_CP1251_CI_AS@ has
--   LCID 1033 but code page 1251).
-- * Windows collations have sort ID 0; the LCID determines the code page.
--
-- The mappings and decode tables below were generated from SQL Server itself
-- (SQL Server 2025), and are checked against it by the test suite:
--
-- > SELECT name, COLLATIONPROPERTY(name, 'CodePage'), COLLATIONPROPERTY(name, 'LCID'),
-- >        COLLATIONPROPERTY(name, 'SortId')
-- > FROM sys.fn_helpcollations()
--
-- and, for each code page, the server's own conversion of every byte value
-- to @nvarchar@.  Bytes a code page leaves undefined decode the way the
-- server (and Windows' @MultiByteToWideChar@) converts them: to the C1
-- control character with the same value (e.g. 0x81 in code page 1252 is
-- U+0081), or, in code pages 874, 1253 and 1255, to a private-use character.
--
-- The double-byte code pages (932, 936, 949, 950) are not supported.
module Hmssql.Tds.CodePage
  ( CodePage
  , collationLcid
  , collationIsUtf8
  , collationCodePage
  , singleByteDecoder
  , collationTextDecoder
  , collationTextEncoder
  , singleByteEncoder
  , TextCodec
  , collationCodec
  , decodeCodecChunks
  , decodeCodec
  , decodeUtf8Lenient
  ) where

import Streaming (Stream, Of)
import qualified Streaming as S
import qualified Streaming.Prelude as S
import Data.Text.Encoding.Error (lenientDecode)
import Control.Monad.ST (RealWorld, stToIO)
import Data.Array.Byte (MutableByteArray (..))
import Data.Bits (shiftL, shiftR, testBit, (.&.), (.|.))
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as BI
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Array as A
import qualified Data.Text.Encoding as T
import qualified Data.Text.Encoding as TE
import qualified Data.IntMap.Strict as IntMap
import Data.Primitive.PrimArray (PrimArray, indexPrimArray, primArrayFromListN, sizeofPrimArray)
import Data.Text.Internal (Text (..))
import Data.Word (Word16, Word32, Word64, Word8, byteSwap32)
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Storable (peekByteOff)
import GHC.ByteOrder (ByteOrder (..), targetByteOrder)
import GHC.Exts (Int (..), writeWord8ArrayAsWord32#, writeWord8ArrayAsWord64#)
import GHC.IO (IO (..), unsafeDupablePerformIO)
import GHC.Word (Word32 (..), Word64 (..))
import Numeric (showHex)

import Hmssql.Tds.Bytes.Unsafe (peekWord64LE)
import Hmssql.Tds.Primitives (Collation (..))

-- | A Windows code page number, e.g. 1252.  UTF-8 is 65001.
type CodePage = Word16

-- | The low 20 bits of the collation DWORD
-- (MS-TDS 2.2.5.1.2 Collation Rule Definition).
collationLcid :: Collation -> Word32
collationLcid :: Collation -> Word32
collationLcid Collation
c = Collation -> Word32
collationInfo Collation
c Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0xFFFFF

-- | Bit 26 of the collation DWORD is fUTF8.
collationIsUtf8 :: Collation -> Bool
collationIsUtf8 :: Collation -> Bool
collationIsUtf8 Collation
c = Word32 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit (Collation -> Word32
collationInfo Collation
c) Int
26

-- | The code page of single-byte character data with this collation, if the
-- collation is known.
collationCodePage :: Collation -> Maybe CodePage
collationCodePage :: Collation -> Maybe Word16
collationCodePage Collation
c
  | Collation -> Bool
collationIsUtf8 Collation
c = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
65001
  | Collation -> Word8
collationSortId Collation
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
0 = Word8 -> Maybe Word16
sortIdCodePage (Collation -> Word8
collationSortId Collation
c)
  | Bool
otherwise = Word32 -> Maybe Word16
lcidCodePage (Collation -> Word32
collationLcid Collation
c)

-- | Decode character data in the given collation, or explain why it can't be
-- decoded as 'Text'.  The outer 'Either' depends only on the collation, so a
-- column can be checked before any of its values are seen.
collationTextDecoder :: Collation -> Either String (B.ByteString -> Either String Text)
collationTextDecoder :: Collation -> Either String (ByteString -> Either String Text)
collationTextDecoder Collation
c = (\TextCodec
codec ByteString
bytes -> Text -> Either String Text
forall a b. b -> Either a b
Right (TextCodec -> ByteString -> Text
decodeCodec TextCodec
codec ByteString
bytes)) (TextCodec -> ByteString -> Either String Text)
-> Either String TextCodec
-> Either String (ByteString -> Either String Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Collation -> Either String TextCodec
collationCodec Collation
c

-- | How a collation's @char@/@varchar@/@text@ values are decoded. The codec
-- is selected once per column and consumes a whole value.
data TextCodec
  = CodecUtf8
  | CodecSingleByte !Table

-- | How to encode 'Text' as a collation's @char@/@varchar@/@text@ bytes,
-- or why hmssql can't: UTF-8 for a @_UTF8@ collation, else the
-- collation's single-byte code page ('singleByteEncoder'); the
-- double-byte code pages aren't supported, as for decoding.  The encoder
-- fails on a character the code page doesn't have (nothing is replaced
-- by @?@, as the server's own conversion would).  Used where a value is
-- written for a column of a known collation ("Hmssql.BulkCopy").
collationTextEncoder :: Collation -> Either String (Text -> Either String B.ByteString)
collationTextEncoder :: Collation -> Either String (Text -> Either String ByteString)
collationTextEncoder Collation
c = case Collation -> Maybe Word16
collationCodePage Collation
c of
  Just Word16
65001 -> (Text -> Either String ByteString)
-> Either String (Text -> Either String ByteString)
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (ByteString -> Either String ByteString)
-> (Text -> ByteString) -> Text -> Either String ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
TE.encodeUtf8)
  Just Word16
cp
    | Just Text -> Either String ByteString
enc <- Word16 -> Maybe (Text -> Either String ByteString)
singleByteEncoder Word16
cp -> (Text -> Either String ByteString)
-> Either String (Text -> Either String ByteString)
forall a b. b -> Either a b
Right Text -> Either String ByteString
enc
    | Bool
otherwise -> String -> Either String (Text -> Either String ByteString)
forall a b. a -> Either a b
Left (String -> Either String (Text -> Either String ByteString))
-> String -> Either String (Text -> Either String ByteString)
forall a b. (a -> b) -> a -> b
$
        String
"cannot encode Text as char/varchar/text data in code page " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word16 -> String
forall a. Show a => a -> String
show Word16
cp
          String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" (collation LCID " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word32 -> String
forall a. Show a => a -> String
show (Collation -> Word32
collationLcid Collation
c) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"): hmssql encodes only"
          String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" UTF-8 and single-byte code pages. " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
advice
  Maybe Word16
Nothing -> String -> Either String (Text -> Either String ByteString)
forall a b. a -> Either a b
Left (String -> Either String (Text -> Either String ByteString))
-> String -> Either String (Text -> Either String ByteString)
forall a b. (a -> b) -> a -> b
$
    String
"cannot encode Text as char/varchar/text data: unknown collation (LCID "
      String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word32 -> String
forall a. Show a => a -> String
show (Collation -> Word32
collationLcid Collation
c) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", sort ID " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word8 -> String
forall a. Show a => a -> String
show (Collation -> Word8
collationSortId Collation
c)
      String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", collation info 0x" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word32 -> String -> String
forall a. Integral a => a -> String -> String
showHex (Collation -> Word32
collationInfo Collation
c) String
"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"). " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
advice
  where
    advice :: String
advice = String
"Send the bytes as ByteString instead, or an nvarchar value the server converts."

-- | Encode 'Text' in a single-byte code page: ASCII as it is, and each
-- other character as the byte whose table entry it is.  'Nothing' for a
-- code page hmssql doesn't have ('singleByteTable'); the encoder fails
-- on a character the code page doesn't have, naming it.
singleByteEncoder :: CodePage -> Maybe (Text -> Either String B.ByteString)
singleByteEncoder :: Word16 -> Maybe (Text -> Either String ByteString)
singleByteEncoder Word16
cp = IntMap Word8 -> Text -> Either String ByteString
encodeWith (IntMap Word8 -> Text -> Either String ByteString)
-> Maybe (IntMap Word8) -> Maybe (Text -> Either String ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word16 -> [(Word16, IntMap Word8)] -> Maybe (IntMap Word8)
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Word16
cp [(Word16, IntMap Word8)]
reverseTables

-- | The reverse tables, built once per code page used.
reverseTables :: [(CodePage, IntMap.IntMap Word8)]
reverseTables :: [(Word16, IntMap Word8)]
reverseTables = [(Word16
cp, Table -> IntMap Word8
reverseTable Table
table) | Word16
cp <- [Word16
437, Word16
850, Word16
874, Word16
1250, Word16
1251, Word16
1252, Word16
1253, Word16
1254, Word16
1255, Word16
1256, Word16
1257, Word16
1258], Just Table
table <- [Word16 -> Maybe Table
singleByteTable Word16
cp]]
{-# NOINLINE reverseTables #-}

-- | Code point to byte, for the bytes 0x80 and up (ASCII needs no
-- table).  A byte the code page leaves undefined is in the table as a
-- C1 control character (its own code point), which is harmless; U+FFFD,
-- if a table used it, would not be.
reverseTable :: Table -> IntMap.IntMap Word8
reverseTable :: Table -> IntMap Word8
reverseTable (Table PrimArray Word32
tbl) = [(Int, Word8)] -> IntMap Word8
forall a. [(Int, a)] -> IntMap a
IntMap.fromList
  [ (Word32 -> Int
codePoint (PrimArray Word32 -> Int -> Word32
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word32
tbl Int
b), Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
b)
  | Int
b <- [Int
0x80 .. Int
0xFF], Word32 -> Int
codePoint (PrimArray Word32 -> Int -> Word32
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word32
tbl Int
b) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0xFFFD ]
  where
    -- The entry's UTF-8 bytes (count in the high byte), decoded.
    codePoint :: Word32 -> Int
    codePoint :: Word32 -> Int
codePoint Word32
w = case Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
24 of
      Word32
1 -> Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32
w Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0xFF)
      Word32
2 -> Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (((Word32
w Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0x1F) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
6) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. ((Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
8) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0x3F))
      Word32
_ -> Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (((Word32
w Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0x0F) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
12) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (((Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
8) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0x3F) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
6) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. ((Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
16) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0x3F))

encodeWith :: IntMap.IntMap Word8 -> Text -> Either String B.ByteString
encodeWith :: IntMap Word8 -> Text -> Either String ByteString
encodeWith IntMap Word8
table Text
t
  | (Char -> Bool) -> Text -> Bool
T.all (Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
< Char
'\x80') Text
t = ByteString -> Either String ByteString
forall a b. b -> Either a b
Right (Text -> ByteString
TE.encodeUtf8 Text
t)
  | Bool
otherwise = [Word8] -> ByteString
B.pack ([Word8] -> ByteString)
-> Either String [Word8] -> Either String ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Either String Word8) -> String -> Either String [Word8]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Char -> Either String Word8
byteOf (Text -> String
T.unpack Text
t)
  where
    byteOf :: Char -> Either String Word8
byteOf Char
ch
      | Char
ch Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
< Char
'\x80' = Word8 -> Either String Word8
forall a b. b -> Either a b
Right (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
ch))
      | Bool
otherwise = case Int -> IntMap Word8 -> Maybe Word8
forall a. Int -> IntMap a -> Maybe a
IntMap.lookup (Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
ch) IntMap Word8
table of
          Just Word8
b -> Word8 -> Either String Word8
forall a b. b -> Either a b
Right Word8
b
          Maybe Word8
Nothing -> String -> Either String Word8
forall a b. a -> Either a b
Left (String -> Either String Word8) -> String -> Either String Word8
forall a b. (a -> b) -> a -> b
$ String
"the character " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Char -> String
forall a. Show a => a -> String
show Char
ch String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" (U+" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String -> String
forall a. Integral a => a -> String -> String
showHex (Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
ch) String
"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") has no encoding in this code page"

-- | The codec of a collation, or why hmssql can't decode it.
collationCodec :: Collation -> Either String TextCodec
collationCodec :: Collation -> Either String TextCodec
collationCodec Collation
c = case Collation -> Maybe Word16
collationCodePage Collation
c of
  Just Word16
65001 -> TextCodec -> Either String TextCodec
forall a b. b -> Either a b
Right TextCodec
CodecUtf8
  Just Word16
cp
    | Just Table
table <- Word16 -> Maybe Table
singleByteTable Word16
cp -> TextCodec -> Either String TextCodec
forall a b. b -> Either a b
Right (Table -> TextCodec
CodecSingleByte Table
table)
    | Bool
otherwise -> String -> Either String TextCodec
forall a b. a -> Either a b
Left (String -> Either String TextCodec)
-> String -> Either String TextCodec
forall a b. (a -> b) -> a -> b
$
        String
"cannot decode char/varchar/text data in code page " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word16 -> String
forall a. Show a => a -> String
show Word16
cp String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word16 -> String
describe Word16
cp
          String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" (collation LCID " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word32 -> String
forall a. Show a => a -> String
show (Collation -> Word32
collationLcid Collation
c) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") as Text: hmssql decodes only"
          String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" UTF-8 and single-byte code pages. " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
advice
  Maybe Word16
Nothing -> String -> Either String TextCodec
forall a b. a -> Either a b
Left (String -> Either String TextCodec)
-> String -> Either String TextCodec
forall a b. (a -> b) -> a -> b
$
    String
"cannot decode char/varchar/text data as Text: unknown collation (LCID "
      String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word32 -> String
forall a. Show a => a -> String
show (Collation -> Word32
collationLcid Collation
c) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", sort ID " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word8 -> String
forall a. Show a => a -> String
show (Collation -> Word8
collationSortId Collation
c)
      String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", collation info 0x" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Word32 -> String -> String
forall a. Integral a => a -> String -> String
showHex (Collation -> Word32
collationInfo Collation
c) String
"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"). " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
advice
  where
    advice :: String
advice = String
"Decode it as ByteString instead, or CAST it to nvarchar in the query."
    describe :: Word16 -> String
describe = \case
      Word16
932 -> String
", Japanese Shift-JIS, a double-byte code page"
      Word16
936 -> String
", Simplified Chinese GBK, a double-byte code page"
      Word16
949 -> String
", Korean, a double-byte code page"
      Word16
950 -> String
", Traditional Chinese Big5, a double-byte code page"
      Word16
_ -> String
""

-- | Decode a whole value with the codec selected for its column.
decodeCodec :: TextCodec -> B.ByteString -> Text
decodeCodec :: TextCodec -> ByteString -> Text
decodeCodec TextCodec
codec ByteString
bytes = case TextCodec
codec of
  TextCodec
CodecUtf8 -> ByteString -> Text
decodeUtf8Lenient ByteString
bytes
  CodecSingleByte Table
table -> Table -> ByteString -> Text
decodeWith Table
table ByteString
bytes

-- | 'decodeCodec' for a value that arrives in chunks.  A chunk can end inside a
-- UTF-8 sequence, so @text@'s incremental decoder holds its bytes back, and
-- whatever is held at the end decodes leniently as a whole value would.  In a
-- single-byte code page every chunk stands alone.
decodeCodecChunks :: Monad m => TextCodec -> Stream (Of B.ByteString) m r -> Stream (Of Text) m r
decodeCodecChunks :: forall (m :: * -> *) r.
Monad m =>
TextCodec -> Stream (Of ByteString) m r -> Stream (Of Text) m r
decodeCodecChunks TextCodec
codec = case TextCodec
codec of
  TextCodec
CodecUtf8 -> ByteString
-> (ByteString -> Decoding)
-> Stream (Of ByteString) m r
-> Stream (Of Text) m r
forall {m :: * -> *} {r}.
Monad m =>
ByteString
-> (ByteString -> Decoding)
-> Stream (Of ByteString) m r
-> Stream (Of Text) m r
go ByteString
B.empty (OnDecodeError -> ByteString -> Decoding
TE.streamDecodeUtf8With OnDecodeError
lenientDecode)
  TextCodec
_ -> (ByteString -> Text)
-> Stream (Of ByteString) m r -> Stream (Of Text) m r
forall (m :: * -> *) a b r.
Monad m =>
(a -> b) -> Stream (Of a) m r -> Stream (Of b) m r
S.map (TextCodec -> ByteString -> Text
decodeCodec TextCodec
codec)
  where
    go :: ByteString
-> (ByteString -> Decoding)
-> Stream (Of ByteString) m r
-> Stream (Of Text) m r
go ByteString
pending ByteString -> Decoding
decode Stream (Of ByteString) m r
source = m (Stream (Of Text) m r) -> Stream (Of Text) m r
forall (m :: * -> *) (f :: * -> *) r.
(Monad m, Functor f) =>
m (Stream f m r) -> Stream f m r
S.effect (m (Stream (Of Text) m r) -> Stream (Of Text) m r)
-> m (Stream (Of Text) m r) -> Stream (Of Text) m r
forall a b. (a -> b) -> a -> b
$ Stream (Of ByteString) m r
-> m (Either r (ByteString, Stream (Of ByteString) m r))
forall (m :: * -> *) a r.
Monad m =>
Stream (Of a) m r -> m (Either r (a, Stream (Of a) m r))
S.next Stream (Of ByteString) m r
source m (Either r (ByteString, Stream (Of ByteString) m r))
-> (Either r (ByteString, Stream (Of ByteString) m r)
    -> m (Stream (Of Text) m r))
-> m (Stream (Of Text) m r)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Left r
r -> Stream (Of Text) m r -> m (Stream (Of Text) m r)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Stream (Of Text) m ()
forall {m :: * -> *}. Monad m => Text -> Stream (Of Text) m ()
emit (ByteString -> Text
decodeUtf8Lenient ByteString
pending) Stream (Of Text) m ()
-> Stream (Of Text) m r -> Stream (Of Text) m r
forall a b.
Stream (Of Text) m a
-> Stream (Of Text) m b -> Stream (Of Text) m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> r -> Stream (Of Text) m r
forall a. a -> Stream (Of Text) m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure r
r)
      Right (ByteString
bs, Stream (Of ByteString) m r
next) -> case ByteString -> Decoding
decode ByteString
bs of
        TE.Some Text
text ByteString
rest ByteString -> Decoding
continuation -> Stream (Of Text) m r -> m (Stream (Of Text) m r)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Stream (Of Text) m ()
forall {m :: * -> *}. Monad m => Text -> Stream (Of Text) m ()
emit Text
text Stream (Of Text) m ()
-> Stream (Of Text) m r -> Stream (Of Text) m r
forall a b.
Stream (Of Text) m a
-> Stream (Of Text) m b -> Stream (Of Text) m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ByteString
-> (ByteString -> Decoding)
-> Stream (Of ByteString) m r
-> Stream (Of Text) m r
go ByteString
rest ByteString -> Decoding
continuation Stream (Of ByteString) m r
next)
    emit :: Text -> Stream (Of Text) m ()
emit Text
text = if Text -> Bool
T.null Text
text then () -> Stream (Of Text) m ()
forall a. a -> Stream (Of Text) m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure () else Text -> Stream (Of Text) m ()
forall (m :: * -> *) a. Monad m => a -> Stream (Of a) m ()
S.yield Text
text

-- | Decode UTF-8 from a @_UTF8@-collated @char@/@varchar@/@text@ value,
-- never failing: ill-formed sequences become U+FFFD.
--
-- The server stores such values without fully validating them (a
-- @varbinary@ value converted to a @_UTF8@ @varchar@ keeps most ill-formed
-- sequences), and its own conversion to @nvarchar@ also turns ill-formed
-- sequences into U+FFFD.  The well-formed parts decode the same, but the
-- number of U+FFFD replacing an ill-formed sequence may differ from the
-- server's (e.g. @ED A0 80@, an encoded surrogate, is two U+FFFD in the
-- server's conversion and may be three here).  This is text's
-- 'T.decodeUtf8Lenient'.
decodeUtf8Lenient :: B.ByteString -> Text
decodeUtf8Lenient :: ByteString -> Text
decodeUtf8Lenient = ByteString -> Text
T.decodeUtf8Lenient

-- | The decoder for a supported single-byte code page.
singleByteDecoder :: CodePage -> Maybe (B.ByteString -> Text)
singleByteDecoder :: Word16 -> Maybe (ByteString -> Text)
singleByteDecoder Word16
cp = Table -> ByteString -> Text
decodeWith (Table -> ByteString -> Text)
-> Maybe Table -> Maybe (ByteString -> Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word16 -> Maybe Table
singleByteTable Word16
cp

-- | A single-byte code page's table.
singleByteTable :: CodePage -> Maybe Table
singleByteTable :: Word16 -> Maybe Table
singleByteTable Word16
cp = case Word16
cp of
  Word16
437 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp437
  Word16
850 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp850
  Word16
874 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp874
  Word16
1250 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp1250
  Word16
1251 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp1251
  Word16
1252 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp1252
  Word16
1253 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp1253
  Word16
1254 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp1254
  Word16
1255 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp1255
  Word16
1256 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp1256
  Word16
1257 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp1257
  Word16
1258 -> Table -> Maybe Table
forall a. a -> Maybe a
Just Table
cp1258
  Word16
_ -> Maybe Table
forall a. Maybe a
Nothing

-- | Code page of a SQL collation, by sort ID.  (Looked up once per
-- column, when its decoder is chosen: a list is plenty.)
sortIdCodePage :: Word8 -> Maybe CodePage
sortIdCodePage :: Word8 -> Maybe Word16
sortIdCodePage Word8
s
  | Word8
s Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8
30, Word8
31, Word8
32, Word8
33, Word8
34] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
437
  | Word8
s Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8
40, Word8
41, Word8
42, Word8
43, Word8
44, Word8
49, Word8
55, Word8
56, Word8
57, Word8
58, Word8
59, Word8
60, Word8
61] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
850
  | Word8
s Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8
81 .. Word8
96] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1250
  | Word8
s Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8
105, Word8
106, Word8
107, Word8
108] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1251
  | Word8
s Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8
51, Word8
52, Word8
53, Word8
54, Word8
183, Word8
184, Word8
185, Word8
186] [Word8] -> [Word8] -> [Word8]
forall a. [a] -> [a] -> [a]
++ [Word8
210 .. Word8
219] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1252
  | Word8
s Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8
113, Word8
114, Word8
120, Word8
122, Word8
124] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1253
  | Word8
s Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8
129, Word8
130] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1254
  | Word8
s Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8
137, Word8
138] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1255
  | Word8
s Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8
145, Word8
146] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1256
  | Word8
s Word8 -> [Word8] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word8
153 .. Word8
160] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1257
  | Bool
otherwise = Maybe Word16
forall a. Maybe a
Nothing

-- | Code page of a Windows collation, by LCID.  LCIDs used only by
-- Unicode-only collations (which can't be applied to char/varchar/text) are
-- absent.
lcidCodePage :: Word32 -> Maybe CodePage
lcidCodePage :: Word32 -> Maybe Word16
lcidCodePage Word32
l
  | Word32
l Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
1054 = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
874
  | Word32
l Word32 -> [Word32] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word32
1041, Word32
66577, Word32
263185] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
932
  | Word32
l Word32 -> [Word32] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word32
2052, Word32
133124] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
936
  | Word32
l Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
1042 = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
949
  | Word32
l Word32 -> [Word32] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word32
1028, Word32
3076, Word32
5124, Word32
136196, Word32
197636] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
950
  | Word32
l Word32 -> [Word32] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word32
1029, Word32
1038, Word32
1045, Word32
1048, Word32
1050, Word32
1051, Word32
1052, Word32
1060, Word32
1090, Word32
2074, Word32
5146, Word32
66574] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1250
  | Word32
l Word32 -> [Word32] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word32
1049, Word32
1058, Word32
1071, Word32
1087, Word32
1092, Word32
1133, Word32
1157, Word32
2092, Word32
3098, Word32
8218] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1251
  | Word32
l Word32 -> [Word32] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ Word32
1030, Word32
1033, Word32
1034, Word32
1035, Word32
1036, Word32
1039, Word32
1044, Word32
1047, Word32
1070, Word32
1083, Word32
1106, Word32
1122
             , Word32
1146, Word32
1148, Word32
1150, Word32
1155, Word32
2107, Word32
2143, Word32
3082, Word32
66567, Word32
66615 ] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1252
  | Word32
l Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
1032 = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1253
  | Word32
l Word32 -> [Word32] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word32
1055, Word32
1068, Word32
1091] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1254
  | Word32
l Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
1037 = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1255
  | Word32
l Word32 -> [Word32] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word32
1025, Word32
1056, Word32
1065, Word32
1152, Word32
1164] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1256
  | Word32
l Word32 -> [Word32] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word32
1061, Word32
1062, Word32
1063] = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1257
  | Word32
l Word32 -> Word32 -> Bool
forall a. Eq a => a -> a -> Bool
== Word32
1066 = Word16 -> Maybe Word16
forall a. a -> Maybe a
Just Word16
1258
  | Bool
otherwise = Maybe Word16
forall a. Maybe a
Nothing

------------------------------------------------------------------------------
-- Decode tables

-- | The UTF-8 of each of the 256 byte values: a 'Word32' per byte value
-- holding the (one to three) bytes in its low bytes (the first lowest)
-- and the count in the high one.  Built (once per code page) from the
-- characters of bytes 0x80..0xFF, all in the Basic Multilingual Plane;
-- bytes 0x00..0x7F are ASCII in every supported code page.  256 entries
-- always, so a byte indexes it within bounds.
newtype Table = Table (PrimArray Word32)

mkTable :: [Word16] -> Table
mkTable :: [Word16] -> Table
mkTable [Word16]
ws
  | [Word16] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Word16]
ws Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
128 = String -> Table
forall a. HasCallStack => String -> a
error String
"Hmssql.Tds.CodePage.mkTable: a table needs 128 entries"
  | Bool
otherwise = PrimArray Word32 -> Table
Table (Int -> [Word32] -> PrimArray Word32
forall a. Prim a => Int -> [a] -> PrimArray a
primArrayFromListN Int
256 ((Word16 -> Word32) -> [Word16] -> [Word32]
forall a b. (a -> b) -> [a] -> [b]
map (Word32 -> Word32
entry (Word32 -> Word32) -> (Word16 -> Word32) -> Word16 -> Word32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral) ([Word16
0 .. Word16
0x7F] [Word16] -> [Word16] -> [Word16]
forall a. [a] -> [a] -> [a]
++ [Word16]
ws)))
  where
    entry :: Word32 -> Word32
    entry :: Word32 -> Word32
entry Word32
c
      | Word32
c Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
< Word32
0x80 = Word32
c Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Word32
1 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
24)
      | Word32
c Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
< Word32
0x800 = (Word32
0xC0 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Word32
c Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
6)) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. ((Word32
0x80 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Word32
c Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0x3F)) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
8) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Word32
2 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
24)
      | Bool
otherwise =
          (Word32
0xE0 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Word32
c Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
12)) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. ((Word32
0x80 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. ((Word32
c Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftR` Int
6) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0x3F)) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
8)
            Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. ((Word32
0x80 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Word32
c Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0x3F)) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
16) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. (Word32
3 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`shiftL` Int
24)

-- | Decode with a table, writing UTF-8 into a 'Text' array: ASCII eight
-- bytes at a time into an array of one byte per input byte, and from the
-- first byte that isn't ASCII on, each byte's table entry as one four-byte
-- store, into an array grown to three bytes per remaining byte (plus one
-- of slack).  The array is then cut to its length (copied, if it is large
-- and a good part of it is unused).
--
-- The bytes are read in 'IO', with the buffer kept alive for the whole
-- decode ('withForeignPtr'); the decode is pure from outside. Each read
-- stays within the value's length.
decodeWith :: Table -> B.ByteString -> Text
decodeWith :: Table -> ByteString -> Text
decodeWith (Table PrimArray Word32
tbl) (BI.BS ForeignPtr Word8
fp Int
len)
  | PrimArray Word32 -> Int
forall a. Prim a => PrimArray a -> Int
sizeofPrimArray PrimArray Word32
tbl Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
256 = String -> Text
forall a. HasCallStack => String -> a
error String
"Hmssql.Tds.CodePage.decodeWith: a table of 256 entries is needed"
  | Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = Text
T.empty
  | Bool
otherwise = IO Text -> Text
forall a. IO a -> a
unsafeDupablePerformIO (IO Text -> Text) -> IO Text -> Text
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> (Ptr Word8 -> IO Text) -> IO Text
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp ((Ptr Word8 -> IO Text) -> IO Text)
-> (Ptr Word8 -> IO Text) -> IO Text
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p -> do
      marr0 <- ST RealWorld (MArray RealWorld) -> IO (MArray RealWorld)
forall a. ST RealWorld a -> IO a
stToIO (Int -> ST RealWorld (MArray RealWorld)
forall s. Int -> ST s (MArray s)
A.new Int
len)
      let byteAt :: Int -> IO Word8
          byteAt Int
i = Ptr Word8 -> Int -> IO Word8
forall b. Ptr b -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr Word8
p Int
i
          word64At :: Int -> IO Word64
          word64At Int
i = Ptr Word8 -> Int -> IO Word64
peekWord64LE Ptr Word8
p Int
i
          -- The ASCII prefix: eight bytes at a time while they last, then
          -- one.
          ascii !Int
i
            | ByteOrder
targetByteOrder ByteOrder -> ByteOrder -> Bool
forall a. Eq a => a -> a -> Bool
== ByteOrder
LittleEndian, Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
8 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
len = do
                w <- Int -> IO Word64
word64At Int
i
                if w .&. 0x8080808080808080 == 0
                  then writeW64 marr0 i w >> ascii (i + 8)
                  else asciiByte i
            | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
len = Int -> IO (MArray RealWorld, Int, Int)
asciiByte Int
i
            | Bool
otherwise = (MArray RealWorld, Int, Int) -> IO (MArray RealWorld, Int, Int)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (MArray RealWorld
marr0, Int
len, Int
len)
          asciiByte !Int
i = do
            b <- Int -> IO Word8
byteAt Int
i
            if b < 0x80
              then stToIO (A.unsafeWrite marr0 i b) >> ascii (i + 1)
              else grow i
          -- Not ASCII: room for the most the rest can take, and the
          -- table from here on.
          grow !Int
i = do
            let cap :: Int
cap = Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
            marr <- ST RealWorld (MArray RealWorld) -> IO (MArray RealWorld)
forall a. ST RealWorld a -> IO a
stToIO (MArray RealWorld -> Int -> ST RealWorld (MArray RealWorld)
forall s. MArray s -> Int -> ST s (MArray s)
A.resizeM MArray RealWorld
marr0 Int
cap)
            let go !Int
j !Int
o
                  | Int
j Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
len = Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
o
                  | Bool
otherwise = do
                      b <- Int -> IO Word8
byteAt Int
j
                      let e = PrimArray Word32 -> Int -> Word32
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word32
tbl (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b)
                      writeW32 marr o (e .&. 0xFFFFFF)
                      go (j + 1) (o + fromIntegral (e `shiftR` 24))
            n <- go i i
            pure (marr, cap, n)
      (marr, cap, n) <- ascii 0
      arr <- stToIO $ if
        | n == cap -> A.unsafeFreeze marr
        | cap > 4096 && cap - n > cap `shiftR` 3 -> do
            exact <- A.new n
            A.copyM exact 0 marr 0 n
            A.unsafeFreeze exact
        | otherwise -> A.shrinkM marr n >> A.unsafeFreeze marr
      pure (Text arr 0 n)

-- | Four bytes at a byte offset (unaligned), in the machine's order: the
-- table's entries are little-endian, so on a big-endian machine they are
-- swapped first.
writeW32 :: A.MArray RealWorld -> Int -> Word32 -> IO ()
writeW32 :: MArray RealWorld -> Int -> Word32 -> IO ()
writeW32 (MutableByteArray MutableByteArray# RealWorld
mba) (I# Int#
o) Word32
w0 = (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, () #)) -> IO ())
-> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s -> (# MutableByteArray# RealWorld
-> Int# -> Word32# -> State# RealWorld -> State# RealWorld
forall d.
MutableByteArray# d -> Int# -> Word32# -> State# d -> State# d
writeWord8ArrayAsWord32# MutableByteArray# RealWorld
mba Int#
o Word32#
w State# RealWorld
s, () #)
  where
    !(W32# Word32#
w) = case ByteOrder
targetByteOrder of
      ByteOrder
LittleEndian -> Word32
w0
      ByteOrder
BigEndian -> Word32 -> Word32
byteSwap32 Word32
w0
{-# INLINE writeW32 #-}

-- | Eight bytes at a byte offset (unaligned), as they are in memory.
writeW64 :: A.MArray RealWorld -> Int -> Word64 -> IO ()
writeW64 :: MArray RealWorld -> Int -> Word64 -> IO ()
writeW64 (MutableByteArray MutableByteArray# RealWorld
mba) (I# Int#
o) (W64# Word64#
w) = (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, () #)) -> IO ())
-> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s -> (# MutableByteArray# RealWorld
-> Int# -> Word64# -> State# RealWorld -> State# RealWorld
forall d.
MutableByteArray# d -> Int# -> Word64# -> State# d -> State# d
writeWord8ArrayAsWord64# MutableByteArray# RealWorld
mba Int#
o Word64#
w State# RealWorld
s, () #)
{-# INLINE writeW64 #-}

cp437 :: Table
cp437 :: Table
cp437 = [Word16] -> Table
mkTable
  [ Word16
0x00C7, Word16
0x00FC, Word16
0x00E9, Word16
0x00E2, Word16
0x00E4, Word16
0x00E0, Word16
0x00E5, Word16
0x00E7
  , Word16
0x00EA, Word16
0x00EB, Word16
0x00E8, Word16
0x00EF, Word16
0x00EE, Word16
0x00EC, Word16
0x00C4, Word16
0x00C5
  , Word16
0x00C9, Word16
0x00E6, Word16
0x00C6, Word16
0x00F4, Word16
0x00F6, Word16
0x00F2, Word16
0x00FB, Word16
0x00F9
  , Word16
0x00FF, Word16
0x00D6, Word16
0x00DC, Word16
0x00A2, Word16
0x00A3, Word16
0x00A5, Word16
0x20A7, Word16
0x0192
  , Word16
0x00E1, Word16
0x00ED, Word16
0x00F3, Word16
0x00FA, Word16
0x00F1, Word16
0x00D1, Word16
0x00AA, Word16
0x00BA
  , Word16
0x00BF, Word16
0x2310, Word16
0x00AC, Word16
0x00BD, Word16
0x00BC, Word16
0x00A1, Word16
0x00AB, Word16
0x00BB
  , Word16
0x2591, Word16
0x2592, Word16
0x2593, Word16
0x2502, Word16
0x2524, Word16
0x2561, Word16
0x2562, Word16
0x2556
  , Word16
0x2555, Word16
0x2563, Word16
0x2551, Word16
0x2557, Word16
0x255D, Word16
0x255C, Word16
0x255B, Word16
0x2510
  , Word16
0x2514, Word16
0x2534, Word16
0x252C, Word16
0x251C, Word16
0x2500, Word16
0x253C, Word16
0x255E, Word16
0x255F
  , Word16
0x255A, Word16
0x2554, Word16
0x2569, Word16
0x2566, Word16
0x2560, Word16
0x2550, Word16
0x256C, Word16
0x2567
  , Word16
0x2568, Word16
0x2564, Word16
0x2565, Word16
0x2559, Word16
0x2558, Word16
0x2552, Word16
0x2553, Word16
0x256B
  , Word16
0x256A, Word16
0x2518, Word16
0x250C, Word16
0x2588, Word16
0x2584, Word16
0x258C, Word16
0x2590, Word16
0x2580
  , Word16
0x03B1, Word16
0x00DF, Word16
0x0393, Word16
0x03C0, Word16
0x03A3, Word16
0x03C3, Word16
0x00B5, Word16
0x03C4
  , Word16
0x03A6, Word16
0x0398, Word16
0x03A9, Word16
0x03B4, Word16
0x221E, Word16
0x03C6, Word16
0x03B5, Word16
0x2229
  , Word16
0x2261, Word16
0x00B1, Word16
0x2265, Word16
0x2264, Word16
0x2320, Word16
0x2321, Word16
0x00F7, Word16
0x2248
  , Word16
0x00B0, Word16
0x2219, Word16
0x00B7, Word16
0x221A, Word16
0x207F, Word16
0x00B2, Word16
0x25A0, Word16
0x00A0
  ]

cp850 :: Table
cp850 :: Table
cp850 = [Word16] -> Table
mkTable
  [ Word16
0x00C7, Word16
0x00FC, Word16
0x00E9, Word16
0x00E2, Word16
0x00E4, Word16
0x00E0, Word16
0x00E5, Word16
0x00E7
  , Word16
0x00EA, Word16
0x00EB, Word16
0x00E8, Word16
0x00EF, Word16
0x00EE, Word16
0x00EC, Word16
0x00C4, Word16
0x00C5
  , Word16
0x00C9, Word16
0x00E6, Word16
0x00C6, Word16
0x00F4, Word16
0x00F6, Word16
0x00F2, Word16
0x00FB, Word16
0x00F9
  , Word16
0x00FF, Word16
0x00D6, Word16
0x00DC, Word16
0x00F8, Word16
0x00A3, Word16
0x00D8, Word16
0x00D7, Word16
0x0192
  , Word16
0x00E1, Word16
0x00ED, Word16
0x00F3, Word16
0x00FA, Word16
0x00F1, Word16
0x00D1, Word16
0x00AA, Word16
0x00BA
  , Word16
0x00BF, Word16
0x00AE, Word16
0x00AC, Word16
0x00BD, Word16
0x00BC, Word16
0x00A1, Word16
0x00AB, Word16
0x00BB
  , Word16
0x2591, Word16
0x2592, Word16
0x2593, Word16
0x2502, Word16
0x2524, Word16
0x00C1, Word16
0x00C2, Word16
0x00C0
  , Word16
0x00A9, Word16
0x2563, Word16
0x2551, Word16
0x2557, Word16
0x255D, Word16
0x00A2, Word16
0x00A5, Word16
0x2510
  , Word16
0x2514, Word16
0x2534, Word16
0x252C, Word16
0x251C, Word16
0x2500, Word16
0x253C, Word16
0x00E3, Word16
0x00C3
  , Word16
0x255A, Word16
0x2554, Word16
0x2569, Word16
0x2566, Word16
0x2560, Word16
0x2550, Word16
0x256C, Word16
0x00A4
  , Word16
0x00F0, Word16
0x00D0, Word16
0x00CA, Word16
0x00CB, Word16
0x00C8, Word16
0x0131, Word16
0x00CD, Word16
0x00CE
  , Word16
0x00CF, Word16
0x2518, Word16
0x250C, Word16
0x2588, Word16
0x2584, Word16
0x00A6, Word16
0x00CC, Word16
0x2580
  , Word16
0x00D3, Word16
0x00DF, Word16
0x00D4, Word16
0x00D2, Word16
0x00F5, Word16
0x00D5, Word16
0x00B5, Word16
0x00FE
  , Word16
0x00DE, Word16
0x00DA, Word16
0x00DB, Word16
0x00D9, Word16
0x00FD, Word16
0x00DD, Word16
0x00AF, Word16
0x00B4
  , Word16
0x00AD, Word16
0x00B1, Word16
0x2017, Word16
0x00BE, Word16
0x00B6, Word16
0x00A7, Word16
0x00F7, Word16
0x00B8
  , Word16
0x00B0, Word16
0x00A8, Word16
0x00B7, Word16
0x00B9, Word16
0x00B3, Word16
0x00B2, Word16
0x25A0, Word16
0x00A0
  ]

cp874 :: Table
cp874 :: Table
cp874 = [Word16] -> Table
mkTable
  [ Word16
0x20AC, Word16
0x0081, Word16
0x0082, Word16
0x0083, Word16
0x0084, Word16
0x2026, Word16
0x0086, Word16
0x0087
  , Word16
0x0088, Word16
0x0089, Word16
0x008A, Word16
0x008B, Word16
0x008C, Word16
0x008D, Word16
0x008E, Word16
0x008F
  , Word16
0x0090, Word16
0x2018, Word16
0x2019, Word16
0x201C, Word16
0x201D, Word16
0x2022, Word16
0x2013, Word16
0x2014
  , Word16
0x0098, Word16
0x0099, Word16
0x009A, Word16
0x009B, Word16
0x009C, Word16
0x009D, Word16
0x009E, Word16
0x009F
  , Word16
0x00A0, Word16
0x0E01, Word16
0x0E02, Word16
0x0E03, Word16
0x0E04, Word16
0x0E05, Word16
0x0E06, Word16
0x0E07
  , Word16
0x0E08, Word16
0x0E09, Word16
0x0E0A, Word16
0x0E0B, Word16
0x0E0C, Word16
0x0E0D, Word16
0x0E0E, Word16
0x0E0F
  , Word16
0x0E10, Word16
0x0E11, Word16
0x0E12, Word16
0x0E13, Word16
0x0E14, Word16
0x0E15, Word16
0x0E16, Word16
0x0E17
  , Word16
0x0E18, Word16
0x0E19, Word16
0x0E1A, Word16
0x0E1B, Word16
0x0E1C, Word16
0x0E1D, Word16
0x0E1E, Word16
0x0E1F
  , Word16
0x0E20, Word16
0x0E21, Word16
0x0E22, Word16
0x0E23, Word16
0x0E24, Word16
0x0E25, Word16
0x0E26, Word16
0x0E27
  , Word16
0x0E28, Word16
0x0E29, Word16
0x0E2A, Word16
0x0E2B, Word16
0x0E2C, Word16
0x0E2D, Word16
0x0E2E, Word16
0x0E2F
  , Word16
0x0E30, Word16
0x0E31, Word16
0x0E32, Word16
0x0E33, Word16
0x0E34, Word16
0x0E35, Word16
0x0E36, Word16
0x0E37
  , Word16
0x0E38, Word16
0x0E39, Word16
0x0E3A, Word16
0xF8C1, Word16
0xF8C2, Word16
0xF8C3, Word16
0xF8C4, Word16
0x0E3F
  , Word16
0x0E40, Word16
0x0E41, Word16
0x0E42, Word16
0x0E43, Word16
0x0E44, Word16
0x0E45, Word16
0x0E46, Word16
0x0E47
  , Word16
0x0E48, Word16
0x0E49, Word16
0x0E4A, Word16
0x0E4B, Word16
0x0E4C, Word16
0x0E4D, Word16
0x0E4E, Word16
0x0E4F
  , Word16
0x0E50, Word16
0x0E51, Word16
0x0E52, Word16
0x0E53, Word16
0x0E54, Word16
0x0E55, Word16
0x0E56, Word16
0x0E57
  , Word16
0x0E58, Word16
0x0E59, Word16
0x0E5A, Word16
0x0E5B, Word16
0xF8C5, Word16
0xF8C6, Word16
0xF8C7, Word16
0xF8C8
  ]

cp1250 :: Table
cp1250 :: Table
cp1250 = [Word16] -> Table
mkTable
  [ Word16
0x20AC, Word16
0x0081, Word16
0x201A, Word16
0x0083, Word16
0x201E, Word16
0x2026, Word16
0x2020, Word16
0x2021
  , Word16
0x0088, Word16
0x2030, Word16
0x0160, Word16
0x2039, Word16
0x015A, Word16
0x0164, Word16
0x017D, Word16
0x0179
  , Word16
0x0090, Word16
0x2018, Word16
0x2019, Word16
0x201C, Word16
0x201D, Word16
0x2022, Word16
0x2013, Word16
0x2014
  , Word16
0x0098, Word16
0x2122, Word16
0x0161, Word16
0x203A, Word16
0x015B, Word16
0x0165, Word16
0x017E, Word16
0x017A
  , Word16
0x00A0, Word16
0x02C7, Word16
0x02D8, Word16
0x0141, Word16
0x00A4, Word16
0x0104, Word16
0x00A6, Word16
0x00A7
  , Word16
0x00A8, Word16
0x00A9, Word16
0x015E, Word16
0x00AB, Word16
0x00AC, Word16
0x00AD, Word16
0x00AE, Word16
0x017B
  , Word16
0x00B0, Word16
0x00B1, Word16
0x02DB, Word16
0x0142, Word16
0x00B4, Word16
0x00B5, Word16
0x00B6, Word16
0x00B7
  , Word16
0x00B8, Word16
0x0105, Word16
0x015F, Word16
0x00BB, Word16
0x013D, Word16
0x02DD, Word16
0x013E, Word16
0x017C
  , Word16
0x0154, Word16
0x00C1, Word16
0x00C2, Word16
0x0102, Word16
0x00C4, Word16
0x0139, Word16
0x0106, Word16
0x00C7
  , Word16
0x010C, Word16
0x00C9, Word16
0x0118, Word16
0x00CB, Word16
0x011A, Word16
0x00CD, Word16
0x00CE, Word16
0x010E
  , Word16
0x0110, Word16
0x0143, Word16
0x0147, Word16
0x00D3, Word16
0x00D4, Word16
0x0150, Word16
0x00D6, Word16
0x00D7
  , Word16
0x0158, Word16
0x016E, Word16
0x00DA, Word16
0x0170, Word16
0x00DC, Word16
0x00DD, Word16
0x0162, Word16
0x00DF
  , Word16
0x0155, Word16
0x00E1, Word16
0x00E2, Word16
0x0103, Word16
0x00E4, Word16
0x013A, Word16
0x0107, Word16
0x00E7
  , Word16
0x010D, Word16
0x00E9, Word16
0x0119, Word16
0x00EB, Word16
0x011B, Word16
0x00ED, Word16
0x00EE, Word16
0x010F
  , Word16
0x0111, Word16
0x0144, Word16
0x0148, Word16
0x00F3, Word16
0x00F4, Word16
0x0151, Word16
0x00F6, Word16
0x00F7
  , Word16
0x0159, Word16
0x016F, Word16
0x00FA, Word16
0x0171, Word16
0x00FC, Word16
0x00FD, Word16
0x0163, Word16
0x02D9
  ]

cp1251 :: Table
cp1251 :: Table
cp1251 = [Word16] -> Table
mkTable
  [ Word16
0x0402, Word16
0x0403, Word16
0x201A, Word16
0x0453, Word16
0x201E, Word16
0x2026, Word16
0x2020, Word16
0x2021
  , Word16
0x20AC, Word16
0x2030, Word16
0x0409, Word16
0x2039, Word16
0x040A, Word16
0x040C, Word16
0x040B, Word16
0x040F
  , Word16
0x0452, Word16
0x2018, Word16
0x2019, Word16
0x201C, Word16
0x201D, Word16
0x2022, Word16
0x2013, Word16
0x2014
  , Word16
0x0098, Word16
0x2122, Word16
0x0459, Word16
0x203A, Word16
0x045A, Word16
0x045C, Word16
0x045B, Word16
0x045F
  , Word16
0x00A0, Word16
0x040E, Word16
0x045E, Word16
0x0408, Word16
0x00A4, Word16
0x0490, Word16
0x00A6, Word16
0x00A7
  , Word16
0x0401, Word16
0x00A9, Word16
0x0404, Word16
0x00AB, Word16
0x00AC, Word16
0x00AD, Word16
0x00AE, Word16
0x0407
  , Word16
0x00B0, Word16
0x00B1, Word16
0x0406, Word16
0x0456, Word16
0x0491, Word16
0x00B5, Word16
0x00B6, Word16
0x00B7
  , Word16
0x0451, Word16
0x2116, Word16
0x0454, Word16
0x00BB, Word16
0x0458, Word16
0x0405, Word16
0x0455, Word16
0x0457
  , Word16
0x0410, Word16
0x0411, Word16
0x0412, Word16
0x0413, Word16
0x0414, Word16
0x0415, Word16
0x0416, Word16
0x0417
  , Word16
0x0418, Word16
0x0419, Word16
0x041A, Word16
0x041B, Word16
0x041C, Word16
0x041D, Word16
0x041E, Word16
0x041F
  , Word16
0x0420, Word16
0x0421, Word16
0x0422, Word16
0x0423, Word16
0x0424, Word16
0x0425, Word16
0x0426, Word16
0x0427
  , Word16
0x0428, Word16
0x0429, Word16
0x042A, Word16
0x042B, Word16
0x042C, Word16
0x042D, Word16
0x042E, Word16
0x042F
  , Word16
0x0430, Word16
0x0431, Word16
0x0432, Word16
0x0433, Word16
0x0434, Word16
0x0435, Word16
0x0436, Word16
0x0437
  , Word16
0x0438, Word16
0x0439, Word16
0x043A, Word16
0x043B, Word16
0x043C, Word16
0x043D, Word16
0x043E, Word16
0x043F
  , Word16
0x0440, Word16
0x0441, Word16
0x0442, Word16
0x0443, Word16
0x0444, Word16
0x0445, Word16
0x0446, Word16
0x0447
  , Word16
0x0448, Word16
0x0449, Word16
0x044A, Word16
0x044B, Word16
0x044C, Word16
0x044D, Word16
0x044E, Word16
0x044F
  ]

cp1252 :: Table
cp1252 :: Table
cp1252 = [Word16] -> Table
mkTable
  [ Word16
0x20AC, Word16
0x0081, Word16
0x201A, Word16
0x0192, Word16
0x201E, Word16
0x2026, Word16
0x2020, Word16
0x2021
  , Word16
0x02C6, Word16
0x2030, Word16
0x0160, Word16
0x2039, Word16
0x0152, Word16
0x008D, Word16
0x017D, Word16
0x008F
  , Word16
0x0090, Word16
0x2018, Word16
0x2019, Word16
0x201C, Word16
0x201D, Word16
0x2022, Word16
0x2013, Word16
0x2014
  , Word16
0x02DC, Word16
0x2122, Word16
0x0161, Word16
0x203A, Word16
0x0153, Word16
0x009D, Word16
0x017E, Word16
0x0178
  , Word16
0x00A0, Word16
0x00A1, Word16
0x00A2, Word16
0x00A3, Word16
0x00A4, Word16
0x00A5, Word16
0x00A6, Word16
0x00A7
  , Word16
0x00A8, Word16
0x00A9, Word16
0x00AA, Word16
0x00AB, Word16
0x00AC, Word16
0x00AD, Word16
0x00AE, Word16
0x00AF
  , Word16
0x00B0, Word16
0x00B1, Word16
0x00B2, Word16
0x00B3, Word16
0x00B4, Word16
0x00B5, Word16
0x00B6, Word16
0x00B7
  , Word16
0x00B8, Word16
0x00B9, Word16
0x00BA, Word16
0x00BB, Word16
0x00BC, Word16
0x00BD, Word16
0x00BE, Word16
0x00BF
  , Word16
0x00C0, Word16
0x00C1, Word16
0x00C2, Word16
0x00C3, Word16
0x00C4, Word16
0x00C5, Word16
0x00C6, Word16
0x00C7
  , Word16
0x00C8, Word16
0x00C9, Word16
0x00CA, Word16
0x00CB, Word16
0x00CC, Word16
0x00CD, Word16
0x00CE, Word16
0x00CF
  , Word16
0x00D0, Word16
0x00D1, Word16
0x00D2, Word16
0x00D3, Word16
0x00D4, Word16
0x00D5, Word16
0x00D6, Word16
0x00D7
  , Word16
0x00D8, Word16
0x00D9, Word16
0x00DA, Word16
0x00DB, Word16
0x00DC, Word16
0x00DD, Word16
0x00DE, Word16
0x00DF
  , Word16
0x00E0, Word16
0x00E1, Word16
0x00E2, Word16
0x00E3, Word16
0x00E4, Word16
0x00E5, Word16
0x00E6, Word16
0x00E7
  , Word16
0x00E8, Word16
0x00E9, Word16
0x00EA, Word16
0x00EB, Word16
0x00EC, Word16
0x00ED, Word16
0x00EE, Word16
0x00EF
  , Word16
0x00F0, Word16
0x00F1, Word16
0x00F2, Word16
0x00F3, Word16
0x00F4, Word16
0x00F5, Word16
0x00F6, Word16
0x00F7
  , Word16
0x00F8, Word16
0x00F9, Word16
0x00FA, Word16
0x00FB, Word16
0x00FC, Word16
0x00FD, Word16
0x00FE, Word16
0x00FF
  ]

cp1253 :: Table
cp1253 :: Table
cp1253 = [Word16] -> Table
mkTable
  [ Word16
0x20AC, Word16
0x0081, Word16
0x201A, Word16
0x0192, Word16
0x201E, Word16
0x2026, Word16
0x2020, Word16
0x2021
  , Word16
0x0088, Word16
0x2030, Word16
0x008A, Word16
0x2039, Word16
0x008C, Word16
0x008D, Word16
0x008E, Word16
0x008F
  , Word16
0x0090, Word16
0x2018, Word16
0x2019, Word16
0x201C, Word16
0x201D, Word16
0x2022, Word16
0x2013, Word16
0x2014
  , Word16
0x0098, Word16
0x2122, Word16
0x009A, Word16
0x203A, Word16
0x009C, Word16
0x009D, Word16
0x009E, Word16
0x009F
  , Word16
0x00A0, Word16
0x0385, Word16
0x0386, Word16
0x00A3, Word16
0x00A4, Word16
0x00A5, Word16
0x00A6, Word16
0x00A7
  , Word16
0x00A8, Word16
0x00A9, Word16
0xF8F9, Word16
0x00AB, Word16
0x00AC, Word16
0x00AD, Word16
0x00AE, Word16
0x2015
  , Word16
0x00B0, Word16
0x00B1, Word16
0x00B2, Word16
0x00B3, Word16
0x0384, Word16
0x00B5, Word16
0x00B6, Word16
0x00B7
  , Word16
0x0388, Word16
0x0389, Word16
0x038A, Word16
0x00BB, Word16
0x038C, Word16
0x00BD, Word16
0x038E, Word16
0x038F
  , Word16
0x0390, Word16
0x0391, Word16
0x0392, Word16
0x0393, Word16
0x0394, Word16
0x0395, Word16
0x0396, Word16
0x0397
  , Word16
0x0398, Word16
0x0399, Word16
0x039A, Word16
0x039B, Word16
0x039C, Word16
0x039D, Word16
0x039E, Word16
0x039F
  , Word16
0x03A0, Word16
0x03A1, Word16
0xF8FA, Word16
0x03A3, Word16
0x03A4, Word16
0x03A5, Word16
0x03A6, Word16
0x03A7
  , Word16
0x03A8, Word16
0x03A9, Word16
0x03AA, Word16
0x03AB, Word16
0x03AC, Word16
0x03AD, Word16
0x03AE, Word16
0x03AF
  , Word16
0x03B0, Word16
0x03B1, Word16
0x03B2, Word16
0x03B3, Word16
0x03B4, Word16
0x03B5, Word16
0x03B6, Word16
0x03B7
  , Word16
0x03B8, Word16
0x03B9, Word16
0x03BA, Word16
0x03BB, Word16
0x03BC, Word16
0x03BD, Word16
0x03BE, Word16
0x03BF
  , Word16
0x03C0, Word16
0x03C1, Word16
0x03C2, Word16
0x03C3, Word16
0x03C4, Word16
0x03C5, Word16
0x03C6, Word16
0x03C7
  , Word16
0x03C8, Word16
0x03C9, Word16
0x03CA, Word16
0x03CB, Word16
0x03CC, Word16
0x03CD, Word16
0x03CE, Word16
0xF8FB
  ]

cp1254 :: Table
cp1254 :: Table
cp1254 = [Word16] -> Table
mkTable
  [ Word16
0x20AC, Word16
0x0081, Word16
0x201A, Word16
0x0192, Word16
0x201E, Word16
0x2026, Word16
0x2020, Word16
0x2021
  , Word16
0x02C6, Word16
0x2030, Word16
0x0160, Word16
0x2039, Word16
0x0152, Word16
0x008D, Word16
0x008E, Word16
0x008F
  , Word16
0x0090, Word16
0x2018, Word16
0x2019, Word16
0x201C, Word16
0x201D, Word16
0x2022, Word16
0x2013, Word16
0x2014
  , Word16
0x02DC, Word16
0x2122, Word16
0x0161, Word16
0x203A, Word16
0x0153, Word16
0x009D, Word16
0x009E, Word16
0x0178
  , Word16
0x00A0, Word16
0x00A1, Word16
0x00A2, Word16
0x00A3, Word16
0x00A4, Word16
0x00A5, Word16
0x00A6, Word16
0x00A7
  , Word16
0x00A8, Word16
0x00A9, Word16
0x00AA, Word16
0x00AB, Word16
0x00AC, Word16
0x00AD, Word16
0x00AE, Word16
0x00AF
  , Word16
0x00B0, Word16
0x00B1, Word16
0x00B2, Word16
0x00B3, Word16
0x00B4, Word16
0x00B5, Word16
0x00B6, Word16
0x00B7
  , Word16
0x00B8, Word16
0x00B9, Word16
0x00BA, Word16
0x00BB, Word16
0x00BC, Word16
0x00BD, Word16
0x00BE, Word16
0x00BF
  , Word16
0x00C0, Word16
0x00C1, Word16
0x00C2, Word16
0x00C3, Word16
0x00C4, Word16
0x00C5, Word16
0x00C6, Word16
0x00C7
  , Word16
0x00C8, Word16
0x00C9, Word16
0x00CA, Word16
0x00CB, Word16
0x00CC, Word16
0x00CD, Word16
0x00CE, Word16
0x00CF
  , Word16
0x011E, Word16
0x00D1, Word16
0x00D2, Word16
0x00D3, Word16
0x00D4, Word16
0x00D5, Word16
0x00D6, Word16
0x00D7
  , Word16
0x00D8, Word16
0x00D9, Word16
0x00DA, Word16
0x00DB, Word16
0x00DC, Word16
0x0130, Word16
0x015E, Word16
0x00DF
  , Word16
0x00E0, Word16
0x00E1, Word16
0x00E2, Word16
0x00E3, Word16
0x00E4, Word16
0x00E5, Word16
0x00E6, Word16
0x00E7
  , Word16
0x00E8, Word16
0x00E9, Word16
0x00EA, Word16
0x00EB, Word16
0x00EC, Word16
0x00ED, Word16
0x00EE, Word16
0x00EF
  , Word16
0x011F, Word16
0x00F1, Word16
0x00F2, Word16
0x00F3, Word16
0x00F4, Word16
0x00F5, Word16
0x00F6, Word16
0x00F7
  , Word16
0x00F8, Word16
0x00F9, Word16
0x00FA, Word16
0x00FB, Word16
0x00FC, Word16
0x0131, Word16
0x015F, Word16
0x00FF
  ]

cp1255 :: Table
cp1255 :: Table
cp1255 = [Word16] -> Table
mkTable
  [ Word16
0x20AC, Word16
0x0081, Word16
0x201A, Word16
0x0192, Word16
0x201E, Word16
0x2026, Word16
0x2020, Word16
0x2021
  , Word16
0x02C6, Word16
0x2030, Word16
0x008A, Word16
0x2039, Word16
0x008C, Word16
0x008D, Word16
0x008E, Word16
0x008F
  , Word16
0x0090, Word16
0x2018, Word16
0x2019, Word16
0x201C, Word16
0x201D, Word16
0x2022, Word16
0x2013, Word16
0x2014
  , Word16
0x02DC, Word16
0x2122, Word16
0x009A, Word16
0x203A, Word16
0x009C, Word16
0x009D, Word16
0x009E, Word16
0x009F
  , Word16
0x00A0, Word16
0x00A1, Word16
0x00A2, Word16
0x00A3, Word16
0x20AA, Word16
0x00A5, Word16
0x00A6, Word16
0x00A7
  , Word16
0x00A8, Word16
0x00A9, Word16
0x00D7, Word16
0x00AB, Word16
0x00AC, Word16
0x00AD, Word16
0x00AE, Word16
0x00AF
  , Word16
0x00B0, Word16
0x00B1, Word16
0x00B2, Word16
0x00B3, Word16
0x00B4, Word16
0x00B5, Word16
0x00B6, Word16
0x00B7
  , Word16
0x00B8, Word16
0x00B9, Word16
0x00F7, Word16
0x00BB, Word16
0x00BC, Word16
0x00BD, Word16
0x00BE, Word16
0x00BF
  , Word16
0x05B0, Word16
0x05B1, Word16
0x05B2, Word16
0x05B3, Word16
0x05B4, Word16
0x05B5, Word16
0x05B6, Word16
0x05B7
  , Word16
0x05B8, Word16
0x05B9, Word16
0x05BA, Word16
0x05BB, Word16
0x05BC, Word16
0x05BD, Word16
0x05BE, Word16
0x05BF
  , Word16
0x05C0, Word16
0x05C1, Word16
0x05C2, Word16
0x05C3, Word16
0x05F0, Word16
0x05F1, Word16
0x05F2, Word16
0x05F3
  , Word16
0x05F4, Word16
0xF88D, Word16
0xF88E, Word16
0xF88F, Word16
0xF890, Word16
0xF891, Word16
0xF892, Word16
0xF893
  , Word16
0x05D0, Word16
0x05D1, Word16
0x05D2, Word16
0x05D3, Word16
0x05D4, Word16
0x05D5, Word16
0x05D6, Word16
0x05D7
  , Word16
0x05D8, Word16
0x05D9, Word16
0x05DA, Word16
0x05DB, Word16
0x05DC, Word16
0x05DD, Word16
0x05DE, Word16
0x05DF
  , Word16
0x05E0, Word16
0x05E1, Word16
0x05E2, Word16
0x05E3, Word16
0x05E4, Word16
0x05E5, Word16
0x05E6, Word16
0x05E7
  , Word16
0x05E8, Word16
0x05E9, Word16
0x05EA, Word16
0xF894, Word16
0xF895, Word16
0x200E, Word16
0x200F, Word16
0xF896
  ]

cp1256 :: Table
cp1256 :: Table
cp1256 = [Word16] -> Table
mkTable
  [ Word16
0x20AC, Word16
0x067E, Word16
0x201A, Word16
0x0192, Word16
0x201E, Word16
0x2026, Word16
0x2020, Word16
0x2021
  , Word16
0x02C6, Word16
0x2030, Word16
0x0679, Word16
0x2039, Word16
0x0152, Word16
0x0686, Word16
0x0698, Word16
0x0688
  , Word16
0x06AF, Word16
0x2018, Word16
0x2019, Word16
0x201C, Word16
0x201D, Word16
0x2022, Word16
0x2013, Word16
0x2014
  , Word16
0x06A9, Word16
0x2122, Word16
0x0691, Word16
0x203A, Word16
0x0153, Word16
0x200C, Word16
0x200D, Word16
0x06BA
  , Word16
0x00A0, Word16
0x060C, Word16
0x00A2, Word16
0x00A3, Word16
0x00A4, Word16
0x00A5, Word16
0x00A6, Word16
0x00A7
  , Word16
0x00A8, Word16
0x00A9, Word16
0x06BE, Word16
0x00AB, Word16
0x00AC, Word16
0x00AD, Word16
0x00AE, Word16
0x00AF
  , Word16
0x00B0, Word16
0x00B1, Word16
0x00B2, Word16
0x00B3, Word16
0x00B4, Word16
0x00B5, Word16
0x00B6, Word16
0x00B7
  , Word16
0x00B8, Word16
0x00B9, Word16
0x061B, Word16
0x00BB, Word16
0x00BC, Word16
0x00BD, Word16
0x00BE, Word16
0x061F
  , Word16
0x06C1, Word16
0x0621, Word16
0x0622, Word16
0x0623, Word16
0x0624, Word16
0x0625, Word16
0x0626, Word16
0x0627
  , Word16
0x0628, Word16
0x0629, Word16
0x062A, Word16
0x062B, Word16
0x062C, Word16
0x062D, Word16
0x062E, Word16
0x062F
  , Word16
0x0630, Word16
0x0631, Word16
0x0632, Word16
0x0633, Word16
0x0634, Word16
0x0635, Word16
0x0636, Word16
0x00D7
  , Word16
0x0637, Word16
0x0638, Word16
0x0639, Word16
0x063A, Word16
0x0640, Word16
0x0641, Word16
0x0642, Word16
0x0643
  , Word16
0x00E0, Word16
0x0644, Word16
0x00E2, Word16
0x0645, Word16
0x0646, Word16
0x0647, Word16
0x0648, Word16
0x00E7
  , Word16
0x00E8, Word16
0x00E9, Word16
0x00EA, Word16
0x00EB, Word16
0x0649, Word16
0x064A, Word16
0x00EE, Word16
0x00EF
  , Word16
0x064B, Word16
0x064C, Word16
0x064D, Word16
0x064E, Word16
0x00F4, Word16
0x064F, Word16
0x0650, Word16
0x00F7
  , Word16
0x0651, Word16
0x00F9, Word16
0x0652, Word16
0x00FB, Word16
0x00FC, Word16
0x200E, Word16
0x200F, Word16
0x06D2
  ]

cp1257 :: Table
cp1257 :: Table
cp1257 = [Word16] -> Table
mkTable
  [ Word16
0x20AC, Word16
0x0081, Word16
0x201A, Word16
0x0083, Word16
0x201E, Word16
0x2026, Word16
0x2020, Word16
0x2021
  , Word16
0x0088, Word16
0x2030, Word16
0x008A, Word16
0x2039, Word16
0x008C, Word16
0x00A8, Word16
0x02C7, Word16
0x00B8
  , Word16
0x0090, Word16
0x2018, Word16
0x2019, Word16
0x201C, Word16
0x201D, Word16
0x2022, Word16
0x2013, Word16
0x2014
  , Word16
0x0098, Word16
0x2122, Word16
0x009A, Word16
0x203A, Word16
0x009C, Word16
0x00AF, Word16
0x02DB, Word16
0x009F
  , Word16
0x00A0, Word16
0xF8FC, Word16
0x00A2, Word16
0x00A3, Word16
0x00A4, Word16
0xF8FD, Word16
0x00A6, Word16
0x00A7
  , Word16
0x00D8, Word16
0x00A9, Word16
0x0156, Word16
0x00AB, Word16
0x00AC, Word16
0x00AD, Word16
0x00AE, Word16
0x00C6
  , Word16
0x00B0, Word16
0x00B1, Word16
0x00B2, Word16
0x00B3, Word16
0x00B4, Word16
0x00B5, Word16
0x00B6, Word16
0x00B7
  , Word16
0x00F8, Word16
0x00B9, Word16
0x0157, Word16
0x00BB, Word16
0x00BC, Word16
0x00BD, Word16
0x00BE, Word16
0x00E6
  , Word16
0x0104, Word16
0x012E, Word16
0x0100, Word16
0x0106, Word16
0x00C4, Word16
0x00C5, Word16
0x0118, Word16
0x0112
  , Word16
0x010C, Word16
0x00C9, Word16
0x0179, Word16
0x0116, Word16
0x0122, Word16
0x0136, Word16
0x012A, Word16
0x013B
  , Word16
0x0160, Word16
0x0143, Word16
0x0145, Word16
0x00D3, Word16
0x014C, Word16
0x00D5, Word16
0x00D6, Word16
0x00D7
  , Word16
0x0172, Word16
0x0141, Word16
0x015A, Word16
0x016A, Word16
0x00DC, Word16
0x017B, Word16
0x017D, Word16
0x00DF
  , Word16
0x0105, Word16
0x012F, Word16
0x0101, Word16
0x0107, Word16
0x00E4, Word16
0x00E5, Word16
0x0119, Word16
0x0113
  , Word16
0x010D, Word16
0x00E9, Word16
0x017A, Word16
0x0117, Word16
0x0123, Word16
0x0137, Word16
0x012B, Word16
0x013C
  , Word16
0x0161, Word16
0x0144, Word16
0x0146, Word16
0x00F3, Word16
0x014D, Word16
0x00F5, Word16
0x00F6, Word16
0x00F7
  , Word16
0x0173, Word16
0x0142, Word16
0x015B, Word16
0x016B, Word16
0x00FC, Word16
0x017C, Word16
0x017E, Word16
0x02D9
  ]

cp1258 :: Table
cp1258 :: Table
cp1258 = [Word16] -> Table
mkTable
  [ Word16
0x20AC, Word16
0x0081, Word16
0x201A, Word16
0x0192, Word16
0x201E, Word16
0x2026, Word16
0x2020, Word16
0x2021
  , Word16
0x02C6, Word16
0x2030, Word16
0x008A, Word16
0x2039, Word16
0x0152, Word16
0x008D, Word16
0x008E, Word16
0x008F
  , Word16
0x0090, Word16
0x2018, Word16
0x2019, Word16
0x201C, Word16
0x201D, Word16
0x2022, Word16
0x2013, Word16
0x2014
  , Word16
0x02DC, Word16
0x2122, Word16
0x009A, Word16
0x203A, Word16
0x0153, Word16
0x009D, Word16
0x009E, Word16
0x0178
  , Word16
0x00A0, Word16
0x00A1, Word16
0x00A2, Word16
0x00A3, Word16
0x00A4, Word16
0x00A5, Word16
0x00A6, Word16
0x00A7
  , Word16
0x00A8, Word16
0x00A9, Word16
0x00AA, Word16
0x00AB, Word16
0x00AC, Word16
0x00AD, Word16
0x00AE, Word16
0x00AF
  , Word16
0x00B0, Word16
0x00B1, Word16
0x00B2, Word16
0x00B3, Word16
0x00B4, Word16
0x00B5, Word16
0x00B6, Word16
0x00B7
  , Word16
0x00B8, Word16
0x00B9, Word16
0x00BA, Word16
0x00BB, Word16
0x00BC, Word16
0x00BD, Word16
0x00BE, Word16
0x00BF
  , Word16
0x00C0, Word16
0x00C1, Word16
0x00C2, Word16
0x0102, Word16
0x00C4, Word16
0x00C5, Word16
0x00C6, Word16
0x00C7
  , Word16
0x00C8, Word16
0x00C9, Word16
0x00CA, Word16
0x00CB, Word16
0x0300, Word16
0x00CD, Word16
0x00CE, Word16
0x00CF
  , Word16
0x0110, Word16
0x00D1, Word16
0x0309, Word16
0x00D3, Word16
0x00D4, Word16
0x01A0, Word16
0x00D6, Word16
0x00D7
  , Word16
0x00D8, Word16
0x00D9, Word16
0x00DA, Word16
0x00DB, Word16
0x00DC, Word16
0x01AF, Word16
0x0303, Word16
0x00DF
  , Word16
0x00E0, Word16
0x00E1, Word16
0x00E2, Word16
0x0103, Word16
0x00E4, Word16
0x00E5, Word16
0x00E6, Word16
0x00E7
  , Word16
0x00E8, Word16
0x00E9, Word16
0x00EA, Word16
0x00EB, Word16
0x0301, Word16
0x00ED, Word16
0x00EE, Word16
0x00EF
  , Word16
0x0111, Word16
0x00F1, Word16
0x0323, Word16
0x00F3, Word16
0x00F4, Word16
0x01A1, Word16
0x00F6, Word16
0x00F7
  , Word16
0x00F8, Word16
0x00F9, Word16
0x00FA, Word16
0x00FB, Word16
0x00FC, Word16
0x01B0, Word16
0x20AB, Word16
0x00FF
  ]