stringprep-1.0.0/0000755000000000000000000000000012262474164012103 5ustar0000000000000000stringprep-1.0.0/stringprep.cabal0000644000000000000000000000224512262474164015267 0ustar0000000000000000Name: stringprep Version: 1.0.0 Description: Implements the "StringPrep" algorithm Synopsis: Implements the "StringPrep" algorithm License: BSD3 Author: George Pollard Maintainer: George Pollard Build-Type: Simple Cabal-Version: >=1.8 License-file: LICENSE Category: data extra-source-files: Text/*.hs source-repository head type: git location: https://github.com/Porges/stringprep-hs.git source-repository this type: git location: https://github.com/Porges/stringprep-hs.git tag: v1.0.0 Library Build-Depends: base >=3 && < 5 , containers >=0.2 , text-icu >=0.6 , text >=0.9 Exposed-modules: Text.StringPrep , Text.StringPrep.Profiles , Text.CharRanges ghc-options: -O2 -Wall -fno-warn-name-shadowing test-suite tests Build-Depends: base , QuickCheck , containers , text , text-icu , tasty , tasty-quickcheck , tasty-th type: exitcode-stdio-1.0 main-is: Tests.hs Other-modules: Ranges hs-source-dirs: tests . stringprep-1.0.0/Setup.hs0000644000000000000000000000005612262474164013540 0ustar0000000000000000import Distribution.Simple main = defaultMain stringprep-1.0.0/LICENSE0000644000000000000000000000273412262474164013116 0ustar0000000000000000Copyright (c) 2011, George Pollard All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.stringprep-1.0.0/tests/0000755000000000000000000000000012262474164013245 5ustar0000000000000000stringprep-1.0.0/tests/Tests.hs0000644000000000000000000000477412262474164014717 0ustar0000000000000000{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} module Main where import Control.Applicative import qualified Data.Set as Set import qualified Ranges as R import Test.QuickCheck import Test.Tasty import Test.Tasty.QuickCheck import Test.Tasty.TH import qualified Text.CharRanges as CR import qualified Text.StringPrep as SP import Unsafe.Coerce (unsafeCoerce) instance Arbitrary SP.Range where arbitrary = oneof [ CR.Single <$> arbitrary , do (x,y) <- (,) <$> arbitrary <*> arbitrary return $ case compare x y of LT -> CR.Range x y EQ -> CR.Single x GT -> CR.Range y x ] shrink (CR.Single _) = [] shrink (CR.Range x y) = [CR.Single x, CR.Single y] newtype KnownRanges = KR {unKR :: [CR.Range]} deriving (Show) newtype RandomRanges = RR {unRR :: [CR.Range]} deriving (Show) instance Arbitrary KnownRanges where arbitrary = KR . concat <$> (listOf1 $ elements spRanges) shrink (KR xs) = KR <$> shrink xs instance Arbitrary RandomRanges where arbitrary = RR <$> listOf1 arbitrary shrink (RR xs) = RR <$> shrink xs toRange :: SP.Range -> R.Range Char toRange (CR.Single x) = R.Single x toRange (CR.Range x y) = R.Range x y spRanges = [SP.c11, SP.c12, SP.c21, SP.c22, SP.c3, SP.c4, SP.c5 , SP.c6, SP.c7, SP.c8, SP.c9, SP.a1] eqRange :: SP.Range -> R.Range Char -> Bool eqRange (CR.Range x y) (R.Range x' y') = x == x' && y == y' eqRange (CR.Single x) (R.Single x') = x == x' eqRange _ _ = False rangeSetsEqual :: [SP.Range] -> Bool rangeSetsEqual rs = eqRanges (Set.toAscList . unsafeCoerce $ CR.toSet rs) (Set.toAscList . R.toSet . R.ranges $ map toRange rs) where eqRanges [] [] = True eqRanges (x:xs) (y:ys) = eqRange x y && eqRanges xs ys eqRanges _ _ = False prop_knowRangesToSetEqual :: KnownRanges -> Bool prop_knowRangesToSetEqual (KR rs) = rangeSetsEqual rs prop_randomRangesToSetEqual :: RandomRanges -> Bool prop_randomRangesToSetEqual (RR rs) = rangeSetsEqual rs -- This example came up during testing as a range where the second Single blocked the first one from being merged with the Range in one-pass merging badRange :: [SP.Range] badRange = [CR.Single 'v', CR.Single '\234', CR.Range 'g' '\238'] prop_badRangeToSetEqual = rangeSetsEqual badRange main = $(defaultMainGenerator) stringprep-1.0.0/tests/Ranges.hs0000644000000000000000000000470412262474164015025 0ustar0000000000000000module Ranges where import Data.Set (Set) import qualified Data.Set as Set data Ord a => Range a = Single !a | Range !a !a instance (Ord a, Show a) => Show (Range a) where show (Single x) = concat ["(", show x, ")"] show (Range x y) = concat ["(", show x, "–", show y, ")"] newtype Ord a => Ranges a = Ranges [Range a] deriving Show -- | A rather hacked-up instance. -- This is to support fast lookups using 'Data.Set' (see 'toSet'). instance (Ord a) => Eq (Range a) where (Single x) == (Single y) = x == y (Single a) == (Range x y) = x <= a && a <= y (Range x y) == (Single a) = x <= a && a <= y (Range lx ux) == (Range ly uy) = (lx <= uy && ux >= ly) || (ly <= ux && uy >= lx) instance (Ord a) => Ord (Range a) where (Single x) <= (Single y) = x <= y (Single x) <= (Range y _) = x <= y (Range _ x) <= (Single y) = x <= y (Range _ x) <= (Range y _) = x <= y -- | A range consisting of a single value. single :: (Ord a) => a -> Range a single x = Single x -- | Construct a 'Range' from a lower and upper bound. range :: (Ord a) => a -> a -> Range a range l u | l <= u = Range l u | otherwise = error "lower bound must be smaller than upper bound" -- | Construct a 'Ranges' from a list of lower and upper bounds. ranges :: (Ord a) => [Range a] -> Ranges a ranges = Ranges . foldr (flip mergeRanges) [] -- | Tests if a given range contains a particular value. inRange :: (Ord a) => a -> Range a -> Bool inRange x y = Single x == y -- | Tests if any of the ranges contains a particular value. inRanges :: (Ord a) => a -> Ranges a -> Bool inRanges x (Ranges xs) = or . map (x `inRange`) $ xs mergeRange :: (Ord a) => Range a -> Range a -> Either (Range a) (Range a) mergeRange x y = if x == y then Right $ minMax x y else Left $ x minMax :: (Ord a) => Range a -> Range a -> Range a minMax (Range lx ux) (Range ly uy) = Range (min lx ly) (max ux uy) minMax (Single _) y = y minMax x@(Range _ _) (Single _) = x -- | Allows quick lookups using ranges. toSet :: (Ord a) => Ranges a -> Set (Range a) toSet (Ranges x) = Set.fromList x addRange :: (Ord a) => Ranges a -> Range a -> Ranges a addRange (Ranges x) = Ranges . mergeRanges x mergeRanges :: (Ord a) => [Range a] -> Range a -> [Range a] mergeRanges [] y = [y] mergeRanges (x:xs) y = case mergeRange x y of Right z -> mergeRanges xs z Left x -> x : (mergeRanges xs y) stringprep-1.0.0/Text/0000755000000000000000000000000012262474164013027 5ustar0000000000000000stringprep-1.0.0/Text/CharRanges.hs0000644000000000000000000000523112262474164015401 0ustar0000000000000000{-# LANGUAGE PatternGuards #-} module Text.CharRanges ( Range(..) , range , single , CharSet , toSet , member ) where import Data.List import Data.Set (Set) import qualified Data.Set as Set data Range = Single {-# UNPACK #-} !Char | Range {-# UNPACK #-} !Char {-# UNPACK #-} !Char deriving (Eq, Show) newtype CharRange = CR { unCR :: Range } -- | A rather hacked-up instance. -- This is to support fast lookups using 'Data.Set' (see 'toSet'). -- x == y iff x and y overlap instance Eq CharRange where CR (Single x) == CR (Single y) = x == y CR (Single a) == CR (Range x y) = x <= a && a <= y CR (Range x y) == CR (Single a) = x <= a && a <= y CR (Range lx ux) == CR (Range ly uy) = (lx <= uy && ly <= ux) || (lx <= uy && ly <= ux) -- INTENTIONAL -- For some strange reason GHC -- (7.6.3) seems to have problems -- optimizing this expressions -- without the additional or instance Ord CharRange where CR (Single x) <= CR (Single y) = x <= y CR (Single x) <= CR (Range y _) = x <= y CR (Range _ x) <= CR (Single y) = x <= y CR (Range _ x) <= CR (Range y _) = x <= y newtype CharSet = CharSet (Set CharRange) -- | Allows quick lookups using ranges. toSet :: [Range] -> CharSet toSet = CharSet . Set.fromDistinctAscList . prepareRanges where prepareRanges :: [Range] -> [CharRange] prepareRanges = go . sort . map CR -- we could use unsafeCoerce to -- avoid the cost of mapping go (r1:r2:rs) | Just r' <- maybeMergeRanges r1 r2 = go (r':rs) | rss@(r3:rs') <- go (r2:rs) = case maybeMergeRanges r1 r3 of Nothing -> r1:rss Just r' -> r':rs' go rs = rs maybeMergeRanges :: CharRange -> CharRange -> Maybe CharRange maybeMergeRanges x y = if x == y -- overlap then Just . CR $ minMax (unCR x) (unCR y) else Nothing {-# INLINE maybeMergeRanges #-} minMax :: Range -> Range -> Range minMax (Range lx ux) (Range ly uy) = Range (min lx ly) (max ux uy) minMax (Single _) y = y minMax x (Single _) = x {-# INLINE minMax #-} range :: Char -> Char -> Range range x y = if x < y then Range x y else error "range: x not smaller than y" {-# INLINE range #-} single :: Char -> Range single = Single {-# INLINE single #-} member :: Char -> CharSet -> Bool member x (CharSet cs) = Set.member (CR $ Single x) cs stringprep-1.0.0/Text/StringPrep.hs0000644000000000000000000015455312262474164015475 0ustar0000000000000000module Text.StringPrep ( StringPrepProfile(..), Range, Map, range, single, runStringPrep, a1, b1,b2, c11,c12,c21,c22,c3,c4,c5,c6,c7,c8,c9 ) where import Data.Text (Text) import qualified Data.Text as Text import Data.Text.ICU.Normalize (NormalizationMode(NFKC),normalize) import qualified Data.Set as Set import qualified Data.Map as Map import Text.CharRanges data StringPrepProfile = Profile { maps :: [Map], shouldNormalize :: Bool, prohibited :: [Prohibited], shouldCheckBidi :: Bool } runStringPrep :: StringPrepProfile -> Text -> Maybe Text runStringPrep (Profile maps norm prohibs bidi) s = result where prohibited = toSet $ concat prohibs mapped = foldr Text.concatMap s maps normed = if norm then normalize NFKC mapped else mapped bidid = if bidi then if checkBidi normed then Just normed else Nothing else Just normed result = case bidid of Nothing -> Nothing Just t -> if Text.any (\x -> member x prohibited) t then Nothing else Just t checkBidi :: Text -> Bool checkBidi t = not containsRandL || not containsAL && firstRandL && lastRandL where containsRandL = Text.any (\x -> member x randl) t containsAL = Text.any (\x -> member x l) t firstRandL = member (Text.head t) randl lastRandL = member (Text.last t) randl type Map = Char -> Text type Prohibited = [Range] b1 :: Map b1 c = if c `Set.member` mapToNothings then Text.empty else Text.singleton c mapToNothings :: Set.Set Char mapToNothings = Set.fromAscList ['\x00AD', '\x034F', '\x1806', '\x180B', '\x180C','\x180D', '\x200B', '\x200C', '\x200D', '\x2060', '\xFE00', '\xFE01', '\xFE02','\xFE03', '\xFE04', '\xFE05', '\xFE06', '\xFE07', '\xFE08', '\xFE09', '\xFE0A', '\xFE0B', '\xFE0C', '\xFE0D', '\xFE0E', '\xFE0F', '\xFEFF'] b2 :: Map b2 c = case Map.lookup c b2map of Nothing -> Text.singleton c Just t -> t c11 :: [Range] c11 = [single ' '] c12 :: [Range] c12 = map single ['\x00A0','\x1680','\x2000','\x2001','\x2002','\x2003','\x2004','\x2005','\x2006','\x2007','\x2008','\x2009','\x200A','\x200B','\x202F','\x205F','\x3000'] c21 :: [Range] c21 = [range '\x0' '\x1f', single '\x7f'] c22 :: [Range] c22 = [ range '\x80' '\x9f', single '\x6dd', single '\x070F', single '\x180E', single '\x200C', single '\x200D', single '\x2028', single '\x2029', single '\x2060', single '\x2061', single '\x2062', single '\x2063', range '\x206a' '\x206f', single '\xfeff', range '\xfff9' '\xfffc', range '\x1d173' '\x1d17a'] c3 :: [Range] c3 = [ range '\xe000' '\xf8ff', range '\xf0000' '\xffffd', range '\x100000' '\x10fffd'] c4 :: [Range] c4 = [ range '\xFDD0' '\xFDEF', range '\xFFFE' '\xFFFF', range '\x1FFFE' '\x1FFFF', range '\x2FFFE' '\x2FFFF', range '\x3FFFE' '\x3FFFF', range '\x4FFFE' '\x4FFFF', range '\x5FFFE' '\x5FFFF', range '\x6FFFE' '\x6FFFF', range '\x7FFFE' '\x7FFFF', range '\x8FFFE' '\x8FFFF', range '\x9FFFE' '\x9FFFF', range '\xAFFFE' '\xAFFFF', range '\xBFFFE' '\xBFFFF', range '\xCFFFE' '\xCFFFF', range '\xDFFFE' '\xDFFFF', range '\xEFFFE' '\xEFFFF', range '\xFFFFE' '\xFFFFF', range '\x10FFFE' '\x10FFFF'] c5 :: [Range] c5 = [range '\xd800' '\xdfff'] c6 :: [Range] c6 = [range '\xfff9' '\xfffd'] c7 :: [Range] c7 = [range '\x2ff0' '\x2ffb'] c8 :: [Range] c8 = [ single '\x340', single '\x341', single '\x200e', single '\x200f', range '\x202a' '\x202e', range '\x206a' '\x206f'] c9 :: [Range] c9 = [single '\xe0001', range '\xe0020' '\xe007f'] randl :: CharSet randl = toSet [ single '\x05BE', single '\x05C0', single '\x05C3', range '\x05D0' '\x05EA', range '\x05F0' '\x05F4', single '\x061B', single '\x061F', range '\x0621' '\x063A', range '\x0640' '\x064A', range '\x066D' '\x066F', range '\x0671' '\x06D5', single '\x06DD', range '\x06E5' '\x06E6', range '\x06FA' '\x06FE', range '\x0700' '\x070D', single '\x0710', range '\x0712' '\x072C', range '\x0780' '\x07A5', single '\x07B1', single '\x200F', single '\xFB1D', range '\xFB1F' '\xFB28', range '\xFB2A' '\xFB36', range '\xFB38' '\xFB3C', single '\xFB3E', range '\xFB40' '\xFB41', range '\xFB43' '\xFB44', range '\xFB46' '\xFBB1', range '\xFBD3' '\xFD3D', range '\xFD50' '\xFD8F', range '\xFD92' '\xFDC7', range '\xFDF0' '\xFDFC', range '\xFE70' '\xFE74', range '\xFE76' '\xFEFC'] l :: CharSet l = toSet [ range '\x0041' '\x005A', range '\x0061' '\x007A', single '\x00AA', single '\x00B5', single '\x00BA', range '\x00C0' '\x00D6', range '\x00D8' '\x00F6', range '\x00F8' '\x0220', range '\x0222' '\x0233', range '\x0250' '\x02AD', range '\x02B0' '\x02B8', range '\x02BB' '\x02C1', range '\x02D0' '\x02D1', range '\x02E0' '\x02E4', single '\x02EE', single '\x037A', single '\x0386', range '\x0388' '\x038A', single '\x038C', range '\x038E' '\x03A1', range '\x03A3' '\x03CE', range '\x03D0' '\x03F5', range '\x0400' '\x0482', range '\x048A' '\x04CE', range '\x04D0' '\x04F5', range '\x04F8' '\x04F9', range '\x0500' '\x050F', range '\x0531' '\x0556', range '\x0559' '\x055F', range '\x0561' '\x0587', single '\x0589', single '\x0903', range '\x0905' '\x0939', range '\x093D' '\x0940', range '\x0949' '\x094C', single '\x0950', range '\x0958' '\x0961', range '\x0964' '\x0970', range '\x0982' '\x0983', range '\x0985' '\x098C', range '\x098F' '\x0990', range '\x0993' '\x09A8', range '\x09AA' '\x09B0', single '\x09B2', range '\x09B6' '\x09B9', range '\x09BE' '\x09C0', range '\x09C7' '\x09C8', range '\x09CB' '\x09CC', single '\x09D7', range '\x09DC' '\x09DD', range '\x09DF' '\x09E1', range '\x09E6' '\x09F1', range '\x09F4' '\x09FA', range '\x0A05' '\x0A0A', range '\x0A0F' '\x0A10', range '\x0A13' '\x0A28', range '\x0A2A' '\x0A30', range '\x0A32' '\x0A33', range '\x0A35' '\x0A36', range '\x0A38' '\x0A39', range '\x0A3E' '\x0A40', range '\x0A59' '\x0A5C', single '\x0A5E', range '\x0A66' '\x0A6F', range '\x0A72' '\x0A74', single '\x0A83', range '\x0A85' '\x0A8B', single '\x0A8D', range '\x0A8F' '\x0A91', range '\x0A93' '\x0AA8', range '\x0AAA' '\x0AB0', range '\x0AB2' '\x0AB3', range '\x0AB5' '\x0AB9', range '\x0ABD' '\x0AC0', single '\x0AC9', range '\x0ACB' '\x0ACC', single '\x0AD0', single '\x0AE0', range '\x0AE6' '\x0AEF', range '\x0B02' '\x0B03', range '\x0B05' '\x0B0C', range '\x0B0F' '\x0B10', range '\x0B13' '\x0B28', range '\x0B2A' '\x0B30', range '\x0B32' '\x0B33', range '\x0B36' '\x0B39', range '\x0B3D' '\x0B3E', single '\x0B40', range '\x0B47' '\x0B48', range '\x0B4B' '\x0B4C', single '\x0B57', range '\x0B5C' '\x0B5D', range '\x0B5F' '\x0B61', range '\x0B66' '\x0B70', single '\x0B83', range '\x0B85' '\x0B8A', range '\x0B8E' '\x0B90', range '\x0B92' '\x0B95', range '\x0B99' '\x0B9A', single '\x0B9C', range '\x0B9E' '\x0B9F', range '\x0BA3' '\x0BA4', range '\x0BA8' '\x0BAA', range '\x0BAE' '\x0BB5', range '\x0BB7' '\x0BB9', range '\x0BBE' '\x0BBF', range '\x0BC1' '\x0BC2', range '\x0BC6' '\x0BC8', range '\x0BCA' '\x0BCC', single '\x0BD7', range '\x0BE7' '\x0BF2', range '\x0C01' '\x0C03', range '\x0C05' '\x0C0C', range '\x0C0E' '\x0C10', range '\x0C12' '\x0C28', range '\x0C2A' '\x0C33', range '\x0C35' '\x0C39', range '\x0C41' '\x0C44', range '\x0C60' '\x0C61', range '\x0C66' '\x0C6F', range '\x0C82' '\x0C83', range '\x0C85' '\x0C8C', range '\x0C8E' '\x0C90', range '\x0C92' '\x0CA8', range '\x0CAA' '\x0CB3', range '\x0CB5' '\x0CB9', single '\x0CBE', range '\x0CC0' '\x0CC4', range '\x0CC7' '\x0CC8', range '\x0CCA' '\x0CCB', range '\x0CD5' '\x0CD6', single '\x0CDE', range '\x0CE0' '\x0CE1', range '\x0CE6' '\x0CEF', range '\x0D02' '\x0D03', range '\x0D05' '\x0D0C', range '\x0D0E' '\x0D10', range '\x0D12' '\x0D28', range '\x0D2A' '\x0D39', range '\x0D3E' '\x0D40', range '\x0D46' '\x0D48', range '\x0D4A' '\x0D4C', single '\x0D57', range '\x0D60' '\x0D61', range '\x0D66' '\x0D6F', range '\x0D82' '\x0D83', range '\x0D85' '\x0D96', range '\x0D9A' '\x0DB1', range '\x0DB3' '\x0DBB', single '\x0DBD', range '\x0DC0' '\x0DC6', range '\x0DCF' '\x0DD1', range '\x0DD8' '\x0DDF', range '\x0DF2' '\x0DF4', range '\x0E01' '\x0E30', range '\x0E32' '\x0E33', range '\x0E40' '\x0E46', range '\x0E4F' '\x0E5B', range '\x0E81' '\x0E82', single '\x0E84', range '\x0E87' '\x0E88', single '\x0E8A', single '\x0E8D', range '\x0E94' '\x0E97', range '\x0E99' '\x0E9F', range '\x0EA1' '\x0EA3', single '\x0EA5', single '\x0EA7', range '\x0EAA' '\x0EAB', range '\x0EAD' '\x0EB0', range '\x0EB2' '\x0EB3', single '\x0EBD', range '\x0EC0' '\x0EC4', single '\x0EC6', range '\x0ED0' '\x0ED9', range '\x0EDC' '\x0EDD', range '\x0F00' '\x0F17', range '\x0F1A' '\x0F34', single '\x0F36', single '\x0F38', range '\x0F3E' '\x0F47', range '\x0F49' '\x0F6A', single '\x0F7F', single '\x0F85', range '\x0F88' '\x0F8B', range '\x0FBE' '\x0FC5', range '\x0FC7' '\x0FCC', single '\x0FCF', range '\x1000' '\x1021', range '\x1023' '\x1027', range '\x1029' '\x102A', single '\x102C', single '\x1031', single '\x1038', range '\x1040' '\x1057', range '\x10A0' '\x10C5', range '\x10D0' '\x10F8', single '\x10FB', range '\x1100' '\x1159', range '\x115F' '\x11A2', range '\x11A8' '\x11F9', range '\x1200' '\x1206', range '\x1208' '\x1246', single '\x1248', range '\x124A' '\x124D', range '\x1250' '\x1256', single '\x1258', range '\x125A' '\x125D', range '\x1260' '\x1286', single '\x1288', range '\x128A' '\x128D', range '\x1290' '\x12AE', single '\x12B0', range '\x12B2' '\x12B5', range '\x12B8' '\x12BE', single '\x12C0', range '\x12C2' '\x12C5', range '\x12C8' '\x12CE', range '\x12D0' '\x12D6', range '\x12D8' '\x12EE', range '\x12F0' '\x130E', single '\x1310', range '\x1312' '\x1315', range '\x1318' '\x131E', range '\x1320' '\x1346', range '\x1348' '\x135A', range '\x1361' '\x137C', range '\x13A0' '\x13F4', range '\x1401' '\x1676', range '\x1681' '\x169A', range '\x16A0' '\x16F0', range '\x1700' '\x170C', range '\x170E' '\x1711', range '\x1720' '\x1731', range '\x1735' '\x1736', range '\x1740' '\x1751', range '\x1760' '\x176C', range '\x176E' '\x1770', range '\x1780' '\x17B6', range '\x17BE' '\x17C5', range '\x17C7' '\x17C8', range '\x17D4' '\x17DA', single '\x17DC', range '\x17E0' '\x17E9', range '\x1810' '\x1819', range '\x1820' '\x1877', range '\x1880' '\x18A8', range '\x1E00' '\x1E9B', range '\x1EA0' '\x1EF9', range '\x1F00' '\x1F15', range '\x1F18' '\x1F1D', range '\x1F20' '\x1F45', range '\x1F48' '\x1F4D', range '\x1F50' '\x1F57', single '\x1F59', single '\x1F5B', single '\x1F5D', range '\x1F5F' '\x1F7D', range '\x1F80' '\x1FB4', range '\x1FB6' '\x1FBC', single '\x1FBE', range '\x1FC2' '\x1FC4', range '\x1FC6' '\x1FCC', range '\x1FD0' '\x1FD3', range '\x1FD6' '\x1FDB', range '\x1FE0' '\x1FEC', range '\x1FF2' '\x1FF4', range '\x1FF6' '\x1FFC', single '\x200E', single '\x2071', single '\x207F', single '\x2102', single '\x2107', range '\x210A' '\x2113', single '\x2115', range '\x2119' '\x211D', single '\x2124', single '\x2126', single '\x2128', range '\x212A' '\x212D', range '\x212F' '\x2131', range '\x2133' '\x2139', range '\x213D' '\x213F', range '\x2145' '\x2149', range '\x2160' '\x2183', range '\x2336' '\x237A', single '\x2395', range '\x249C' '\x24E9', range '\x3005' '\x3007', range '\x3021' '\x3029', range '\x3031' '\x3035', range '\x3038' '\x303C', range '\x3041' '\x3096', range '\x309D' '\x309F', range '\x30A1' '\x30FA', range '\x30FC' '\x30FF', range '\x3105' '\x312C', range '\x3131' '\x318E', range '\x3190' '\x31B7', range '\x31F0' '\x321C', range '\x3220' '\x3243', range '\x3260' '\x327B', range '\x327F' '\x32B0', range '\x32C0' '\x32CB', range '\x32D0' '\x32FE', range '\x3300' '\x3376', range '\x337B' '\x33DD', range '\x33E0' '\x33FE', range '\x3400' '\x4DB5', range '\x4E00' '\x9FA5', range '\xA000' '\xA48C', range '\xAC00' '\xD7A3', range '\xD800' '\xFA2D', range '\xFA30' '\xFA6A', range '\xFB00' '\xFB06', range '\xFB13' '\xFB17', range '\xFF21' '\xFF3A', range '\xFF41' '\xFF5A', range '\xFF66' '\xFFBE', range '\xFFC2' '\xFFC7', range '\xFFCA' '\xFFCF', range '\xFFD2' '\xFFD7', range '\xFFDA' '\xFFDC', range '\x10300' '\x1031E', range '\x10320' '\x10323', range '\x10330' '\x1034A', range '\x10400' '\x10425', range '\x10428' '\x1044D', range '\x1D000' '\x1D0F5', range '\x1D100' '\x1D126', range '\x1D12A' '\x1D166', range '\x1D16A' '\x1D172', range '\x1D183' '\x1D184', range '\x1D18C' '\x1D1A9', range '\x1D1AE' '\x1D1DD', range '\x1D400' '\x1D454', range '\x1D456' '\x1D49C', range '\x1D49E' '\x1D49F', single '\x1D4A2', range '\x1D4A5' '\x1D4A6', range '\x1D4A9' '\x1D4AC', range '\x1D4AE' '\x1D4B9', single '\x1D4BB', range '\x1D4BD' '\x1D4C0', range '\x1D4C2' '\x1D4C3', range '\x1D4C5' '\x1D505', range '\x1D507' '\x1D50A', range '\x1D50D' '\x1D514', range '\x1D516' '\x1D51C', range '\x1D51E' '\x1D539', range '\x1D53B' '\x1D53E', range '\x1D540' '\x1D544', single '\x1D546', range '\x1D54A' '\x1D550', range '\x1D552' '\x1D6A3', range '\x1D6A8' '\x1D7C9', range '\x20000' '\x2A6D6', range '\x2F800' '\x2FA1D', range '\xF0000' '\xFFFFD', range '\x100000' '\x10FFFD'] b2map :: Map.Map Char Text b2map = Map.fromAscList . map (\(x,y) -> (x, Text.pack y)) $ [ ('\x0041', "\x0061"), ('\x0042', "\x0062"), ('\x0043', "\x0063"), ('\x0044', "\x0064"), ('\x0045', "\x0065"), ('\x0046', "\x0066"), ('\x0047', "\x0067"), ('\x0048', "\x0068"), ('\x0049', "\x0069"), ('\x004A', "\x006A"), ('\x004B', "\x006B"), ('\x004C', "\x006C"), ('\x004D', "\x006D"), ('\x004E', "\x006E"), ('\x004F', "\x006F"), ('\x0050', "\x0070"), ('\x0051', "\x0071"), ('\x0052', "\x0072"), ('\x0053', "\x0073"), ('\x0054', "\x0074"), ('\x0055', "\x0075"), ('\x0056', "\x0076"), ('\x0057', "\x0077"), ('\x0058', "\x0078"), ('\x0059', "\x0079"), ('\x005A', "\x007A"), ('\x00B5', "\x03BC"), ('\x00C0', "\x00E0"), ('\x00C1', "\x00E1"), ('\x00C2', "\x00E2"), ('\x00C3', "\x00E3"), ('\x00C4', "\x00E4"), ('\x00C5', "\x00E5"), ('\x00C6', "\x00E6"), ('\x00C7', "\x00E7"), ('\x00C8', "\x00E8"), ('\x00C9', "\x00E9"), ('\x00CA', "\x00EA"), ('\x00CB', "\x00EB"), ('\x00CC', "\x00EC"), ('\x00CD', "\x00ED"), ('\x00CE', "\x00EE"), ('\x00CF', "\x00EF"), ('\x00D0', "\x00F0"), ('\x00D1', "\x00F1"), ('\x00D2', "\x00F2"), ('\x00D3', "\x00F3"), ('\x00D4', "\x00F4"), ('\x00D5', "\x00F5"), ('\x00D6', "\x00F6"), ('\x00D8', "\x00F8"), ('\x00D9', "\x00F9"), ('\x00DA', "\x00FA"), ('\x00DB', "\x00FB"), ('\x00DC', "\x00FC"), ('\x00DD', "\x00FD"), ('\x00DE', "\x00FE"), ('\x00DF', "\x0073\x0073"), ('\x0100', "\x0101"), ('\x0102', "\x0103"), ('\x0104', "\x0105"), ('\x0106', "\x0107"), ('\x0108', "\x0109"), ('\x010A', "\x010B"), ('\x010C', "\x010D"), ('\x010E', "\x010F"), ('\x0110', "\x0111"), ('\x0112', "\x0113"), ('\x0114', "\x0115"), ('\x0116', "\x0117"), ('\x0118', "\x0119"), ('\x011A', "\x011B"), ('\x011C', "\x011D"), ('\x011E', "\x011F"), ('\x0120', "\x0121"), ('\x0122', "\x0123"), ('\x0124', "\x0125"), ('\x0126', "\x0127"), ('\x0128', "\x0129"), ('\x012A', "\x012B"), ('\x012C', "\x012D"), ('\x012E', "\x012F"), ('\x0130', "\x0069\x0307"), ('\x0132', "\x0133"), ('\x0134', "\x0135"), ('\x0136', "\x0137"), ('\x0139', "\x013A"), ('\x013B', "\x013C"), ('\x013D', "\x013E"), ('\x013F', "\x0140"), ('\x0141', "\x0142"), ('\x0143', "\x0144"), ('\x0145', "\x0146"), ('\x0147', "\x0148"), ('\x0149', "\x02BC\x006E"), ('\x014A', "\x014B"), ('\x014C', "\x014D"), ('\x014E', "\x014F"), ('\x0150', "\x0151"), ('\x0152', "\x0153"), ('\x0154', "\x0155"), ('\x0156', "\x0157"), ('\x0158', "\x0159"), ('\x015A', "\x015B"), ('\x015C', "\x015D"), ('\x015E', "\x015F"), ('\x0160', "\x0161"), ('\x0162', "\x0163"), ('\x0164', "\x0165"), ('\x0166', "\x0167"), ('\x0168', "\x0169"), ('\x016A', "\x016B"), ('\x016C', "\x016D"), ('\x016E', "\x016F"), ('\x0170', "\x0171"), ('\x0172', "\x0173"), ('\x0174', "\x0175"), ('\x0176', "\x0177"), ('\x0178', "\x00FF"), ('\x0179', "\x017A"), ('\x017B', "\x017C"), ('\x017D', "\x017E"), ('\x017F', "\x0073"), ('\x0181', "\x0253"), ('\x0182', "\x0183"), ('\x0184', "\x0185"), ('\x0186', "\x0254"), ('\x0187', "\x0188"), ('\x0189', "\x0256"), ('\x018A', "\x0257"), ('\x018B', "\x018C"), ('\x018E', "\x01DD"), ('\x018F', "\x0259"), ('\x0190', "\x025B"), ('\x0191', "\x0192"), ('\x0193', "\x0260"), ('\x0194', "\x0263"), ('\x0196', "\x0269"), ('\x0197', "\x0268"), ('\x0198', "\x0199"), ('\x019C', "\x026F"), ('\x019D', "\x0272"), ('\x019F', "\x0275"), ('\x01A0', "\x01A1"), ('\x01A2', "\x01A3"), ('\x01A4', "\x01A5"), ('\x01A6', "\x0280"), ('\x01A7', "\x01A8"), ('\x01A9', "\x0283"), ('\x01AC', "\x01AD"), ('\x01AE', "\x0288"), ('\x01AF', "\x01B0"), ('\x01B1', "\x028A"), ('\x01B2', "\x028B"), ('\x01B3', "\x01B4"), ('\x01B5', "\x01B6"), ('\x01B7', "\x0292"), ('\x01B8', "\x01B9"), ('\x01BC', "\x01BD"), ('\x01C4', "\x01C6"), ('\x01C5', "\x01C6"), ('\x01C7', "\x01C9"), ('\x01C8', "\x01C9"), ('\x01CA', "\x01CC"), ('\x01CB', "\x01CC"), ('\x01CD', "\x01CE"), ('\x01CF', "\x01D0"), ('\x01D1', "\x01D2"), ('\x01D3', "\x01D4"), ('\x01D5', "\x01D6"), ('\x01D7', "\x01D8"), ('\x01D9', "\x01DA"), ('\x01DB', "\x01DC"), ('\x01DE', "\x01DF"), ('\x01E0', "\x01E1"), ('\x01E2', "\x01E3"), ('\x01E4', "\x01E5"), ('\x01E6', "\x01E7"), ('\x01E8', "\x01E9"), ('\x01EA', "\x01EB"), ('\x01EC', "\x01ED"), ('\x01EE', "\x01EF"), ('\x01F0', "\x006A\x030C"), ('\x01F1', "\x01F3"), ('\x01F2', "\x01F3"), ('\x01F4', "\x01F5"), ('\x01F6', "\x0195"), ('\x01F7', "\x01BF"), ('\x01F8', "\x01F9"), ('\x01FA', "\x01FB"), ('\x01FC', "\x01FD"), ('\x01FE', "\x01FF"), ('\x0200', "\x0201"), ('\x0202', "\x0203"), ('\x0204', "\x0205"), ('\x0206', "\x0207"), ('\x0208', "\x0209"), ('\x020A', "\x020B"), ('\x020C', "\x020D"), ('\x020E', "\x020F"), ('\x0210', "\x0211"), ('\x0212', "\x0213"), ('\x0214', "\x0215"), ('\x0216', "\x0217"), ('\x0218', "\x0219"), ('\x021A', "\x021B"), ('\x021C', "\x021D"), ('\x021E', "\x021F"), ('\x0220', "\x019E"), ('\x0222', "\x0223"), ('\x0224', "\x0225"), ('\x0226', "\x0227"), ('\x0228', "\x0229"), ('\x022A', "\x022B"), ('\x022C', "\x022D"), ('\x022E', "\x022F"), ('\x0230', "\x0231"), ('\x0232', "\x0233"), ('\x0345', "\x03B9"), ('\x037A', "\x0020\x03B9"), ('\x0386', "\x03AC"), ('\x0388', "\x03AD"), ('\x0389', "\x03AE"), ('\x038A', "\x03AF"), ('\x038C', "\x03CC"), ('\x038E', "\x03CD"), ('\x038F', "\x03CE"), ('\x0390', "\x03B9\x0308\x0301"), ('\x0391', "\x03B1"), ('\x0392', "\x03B2"), ('\x0393', "\x03B3"), ('\x0394', "\x03B4"), ('\x0395', "\x03B5"), ('\x0396', "\x03B6"), ('\x0397', "\x03B7"), ('\x0398', "\x03B8"), ('\x0399', "\x03B9"), ('\x039A', "\x03BA"), ('\x039B', "\x03BB"), ('\x039C', "\x03BC"), ('\x039D', "\x03BD"), ('\x039E', "\x03BE"), ('\x039F', "\x03BF"), ('\x03A0', "\x03C0"), ('\x03A1', "\x03C1"), ('\x03A3', "\x03C3"), ('\x03A4', "\x03C4"), ('\x03A5', "\x03C5"), ('\x03A6', "\x03C6"), ('\x03A7', "\x03C7"), ('\x03A8', "\x03C8"), ('\x03A9', "\x03C9"), ('\x03AA', "\x03CA"), ('\x03AB', "\x03CB"), ('\x03B0', "\x03C5\x0308\x0301"), ('\x03C2', "\x03C3"), ('\x03D0', "\x03B2"), ('\x03D1', "\x03B8"), ('\x03D2', "\x03C5"), ('\x03D3', "\x03CD"), ('\x03D4', "\x03CB"), ('\x03D5', "\x03C6"), ('\x03D6', "\x03C0"), ('\x03D8', "\x03D9"), ('\x03DA', "\x03DB"), ('\x03DC', "\x03DD"), ('\x03DE', "\x03DF"), ('\x03E0', "\x03E1"), ('\x03E2', "\x03E3"), ('\x03E4', "\x03E5"), ('\x03E6', "\x03E7"), ('\x03E8', "\x03E9"), ('\x03EA', "\x03EB"), ('\x03EC', "\x03ED"), ('\x03EE', "\x03EF"), ('\x03F0', "\x03BA"), ('\x03F1', "\x03C1"), ('\x03F2', "\x03C3"), ('\x03F4', "\x03B8"), ('\x03F5', "\x03B5"), ('\x0400', "\x0450"), ('\x0401', "\x0451"), ('\x0402', "\x0452"), ('\x0403', "\x0453"), ('\x0404', "\x0454"), ('\x0405', "\x0455"), ('\x0406', "\x0456"), ('\x0407', "\x0457"), ('\x0408', "\x0458"), ('\x0409', "\x0459"), ('\x040A', "\x045A"), ('\x040B', "\x045B"), ('\x040C', "\x045C"), ('\x040D', "\x045D"), ('\x040E', "\x045E"), ('\x040F', "\x045F"), ('\x0410', "\x0430"), ('\x0411', "\x0431"), ('\x0412', "\x0432"), ('\x0413', "\x0433"), ('\x0414', "\x0434"), ('\x0415', "\x0435"), ('\x0416', "\x0436"), ('\x0417', "\x0437"), ('\x0418', "\x0438"), ('\x0419', "\x0439"), ('\x041A', "\x043A"), ('\x041B', "\x043B"), ('\x041C', "\x043C"), ('\x041D', "\x043D"), ('\x041E', "\x043E"), ('\x041F', "\x043F"), ('\x0420', "\x0440"), ('\x0421', "\x0441"), ('\x0422', "\x0442"), ('\x0423', "\x0443"), ('\x0424', "\x0444"), ('\x0425', "\x0445"), ('\x0426', "\x0446"), ('\x0427', "\x0447"), ('\x0428', "\x0448"), ('\x0429', "\x0449"), ('\x042A', "\x044A"), ('\x042B', "\x044B"), ('\x042C', "\x044C"), ('\x042D', "\x044D"), ('\x042E', "\x044E"), ('\x042F', "\x044F"), ('\x0460', "\x0461"), ('\x0462', "\x0463"), ('\x0464', "\x0465"), ('\x0466', "\x0467"), ('\x0468', "\x0469"), ('\x046A', "\x046B"), ('\x046C', "\x046D"), ('\x046E', "\x046F"), ('\x0470', "\x0471"), ('\x0472', "\x0473"), ('\x0474', "\x0475"), ('\x0476', "\x0477"), ('\x0478', "\x0479"), ('\x047A', "\x047B"), ('\x047C', "\x047D"), ('\x047E', "\x047F"), ('\x0480', "\x0481"), ('\x048A', "\x048B"), ('\x048C', "\x048D"), ('\x048E', "\x048F"), ('\x0490', "\x0491"), ('\x0492', "\x0493"), ('\x0494', "\x0495"), ('\x0496', "\x0497"), ('\x0498', "\x0499"), ('\x049A', "\x049B"), ('\x049C', "\x049D"), ('\x049E', "\x049F"), ('\x04A0', "\x04A1"), ('\x04A2', "\x04A3"), ('\x04A4', "\x04A5"), ('\x04A6', "\x04A7"), ('\x04A8', "\x04A9"), ('\x04AA', "\x04AB"), ('\x04AC', "\x04AD"), ('\x04AE', "\x04AF"), ('\x04B0', "\x04B1"), ('\x04B2', "\x04B3"), ('\x04B4', "\x04B5"), ('\x04B6', "\x04B7"), ('\x04B8', "\x04B9"), ('\x04BA', "\x04BB"), ('\x04BC', "\x04BD"), ('\x04BE', "\x04BF"), ('\x04C1', "\x04C2"), ('\x04C3', "\x04C4"), ('\x04C5', "\x04C6"), ('\x04C7', "\x04C8"), ('\x04C9', "\x04CA"), ('\x04CB', "\x04CC"), ('\x04CD', "\x04CE"), ('\x04D0', "\x04D1"), ('\x04D2', "\x04D3"), ('\x04D4', "\x04D5"), ('\x04D6', "\x04D7"), ('\x04D8', "\x04D9"), ('\x04DA', "\x04DB"), ('\x04DC', "\x04DD"), ('\x04DE', "\x04DF"), ('\x04E0', "\x04E1"), ('\x04E2', "\x04E3"), ('\x04E4', "\x04E5"), ('\x04E6', "\x04E7"), ('\x04E8', "\x04E9"), ('\x04EA', "\x04EB"), ('\x04EC', "\x04ED"), ('\x04EE', "\x04EF"), ('\x04F0', "\x04F1"), ('\x04F2', "\x04F3"), ('\x04F4', "\x04F5"), ('\x04F8', "\x04F9"), ('\x0500', "\x0501"), ('\x0502', "\x0503"), ('\x0504', "\x0505"), ('\x0506', "\x0507"), ('\x0508', "\x0509"), ('\x050A', "\x050B"), ('\x050C', "\x050D"), ('\x050E', "\x050F"), ('\x0531', "\x0561"), ('\x0532', "\x0562"), ('\x0533', "\x0563"), ('\x0534', "\x0564"), ('\x0535', "\x0565"), ('\x0536', "\x0566"), ('\x0537', "\x0567"), ('\x0538', "\x0568"), ('\x0539', "\x0569"), ('\x053A', "\x056A"), ('\x053B', "\x056B"), ('\x053C', "\x056C"), ('\x053D', "\x056D"), ('\x053E', "\x056E"), ('\x053F', "\x056F"), ('\x0540', "\x0570"), ('\x0541', "\x0571"), ('\x0542', "\x0572"), ('\x0543', "\x0573"), ('\x0544', "\x0574"), ('\x0545', "\x0575"), ('\x0546', "\x0576"), ('\x0547', "\x0577"), ('\x0548', "\x0578"), ('\x0549', "\x0579"), ('\x054A', "\x057A"), ('\x054B', "\x057B"), ('\x054C', "\x057C"), ('\x054D', "\x057D"), ('\x054E', "\x057E"), ('\x054F', "\x057F"), ('\x0550', "\x0580"), ('\x0551', "\x0581"), ('\x0552', "\x0582"), ('\x0553', "\x0583"), ('\x0554', "\x0584"), ('\x0555', "\x0585"), ('\x0556', "\x0586"), ('\x0587', "\x0565\x0582"), ('\x1E00', "\x1E01"), ('\x1E02', "\x1E03"), ('\x1E04', "\x1E05"), ('\x1E06', "\x1E07"), ('\x1E08', "\x1E09"), ('\x1E0A', "\x1E0B"), ('\x1E0C', "\x1E0D"), ('\x1E0E', "\x1E0F"), ('\x1E10', "\x1E11"), ('\x1E12', "\x1E13"), ('\x1E14', "\x1E15"), ('\x1E16', "\x1E17"), ('\x1E18', "\x1E19"), ('\x1E1A', "\x1E1B"), ('\x1E1C', "\x1E1D"), ('\x1E1E', "\x1E1F"), ('\x1E20', "\x1E21"), ('\x1E22', "\x1E23"), ('\x1E24', "\x1E25"), ('\x1E26', "\x1E27"), ('\x1E28', "\x1E29"), ('\x1E2A', "\x1E2B"), ('\x1E2C', "\x1E2D"), ('\x1E2E', "\x1E2F"), ('\x1E30', "\x1E31"), ('\x1E32', "\x1E33"), ('\x1E34', "\x1E35"), ('\x1E36', "\x1E37"), ('\x1E38', "\x1E39"), ('\x1E3A', "\x1E3B"), ('\x1E3C', "\x1E3D"), ('\x1E3E', "\x1E3F"), ('\x1E40', "\x1E41"), ('\x1E42', "\x1E43"), ('\x1E44', "\x1E45"), ('\x1E46', "\x1E47"), ('\x1E48', "\x1E49"), ('\x1E4A', "\x1E4B"), ('\x1E4C', "\x1E4D"), ('\x1E4E', "\x1E4F"), ('\x1E50', "\x1E51"), ('\x1E52', "\x1E53"), ('\x1E54', "\x1E55"), ('\x1E56', "\x1E57"), ('\x1E58', "\x1E59"), ('\x1E5A', "\x1E5B"), ('\x1E5C', "\x1E5D"), ('\x1E5E', "\x1E5F"), ('\x1E60', "\x1E61"), ('\x1E62', "\x1E63"), ('\x1E64', "\x1E65"), ('\x1E66', "\x1E67"), ('\x1E68', "\x1E69"), ('\x1E6A', "\x1E6B"), ('\x1E6C', "\x1E6D"), ('\x1E6E', "\x1E6F"), ('\x1E70', "\x1E71"), ('\x1E72', "\x1E73"), ('\x1E74', "\x1E75"), ('\x1E76', "\x1E77"), ('\x1E78', "\x1E79"), ('\x1E7A', "\x1E7B"), ('\x1E7C', "\x1E7D"), ('\x1E7E', "\x1E7F"), ('\x1E80', "\x1E81"), ('\x1E82', "\x1E83"), ('\x1E84', "\x1E85"), ('\x1E86', "\x1E87"), ('\x1E88', "\x1E89"), ('\x1E8A', "\x1E8B"), ('\x1E8C', "\x1E8D"), ('\x1E8E', "\x1E8F"), ('\x1E90', "\x1E91"), ('\x1E92', "\x1E93"), ('\x1E94', "\x1E95"), ('\x1E96', "\x0068\x0331"), ('\x1E97', "\x0074\x0308"), ('\x1E98', "\x0077\x030A"), ('\x1E99', "\x0079\x030A"), ('\x1E9A', "\x0061\x02BE"), ('\x1E9B', "\x1E61"), ('\x1EA0', "\x1EA1"), ('\x1EA2', "\x1EA3"), ('\x1EA4', "\x1EA5"), ('\x1EA6', "\x1EA7"), ('\x1EA8', "\x1EA9"), ('\x1EAA', "\x1EAB"), ('\x1EAC', "\x1EAD"), ('\x1EAE', "\x1EAF"), ('\x1EB0', "\x1EB1"), ('\x1EB2', "\x1EB3"), ('\x1EB4', "\x1EB5"), ('\x1EB6', "\x1EB7"), ('\x1EB8', "\x1EB9"), ('\x1EBA', "\x1EBB"), ('\x1EBC', "\x1EBD"), ('\x1EBE', "\x1EBF"), ('\x1EC0', "\x1EC1"), ('\x1EC2', "\x1EC3"), ('\x1EC4', "\x1EC5"), ('\x1EC6', "\x1EC7"), ('\x1EC8', "\x1EC9"), ('\x1ECA', "\x1ECB"), ('\x1ECC', "\x1ECD"), ('\x1ECE', "\x1ECF"), ('\x1ED0', "\x1ED1"), ('\x1ED2', "\x1ED3"), ('\x1ED4', "\x1ED5"), ('\x1ED6', "\x1ED7"), ('\x1ED8', "\x1ED9"), ('\x1EDA', "\x1EDB"), ('\x1EDC', "\x1EDD"), ('\x1EDE', "\x1EDF"), ('\x1EE0', "\x1EE1"), ('\x1EE2', "\x1EE3"), ('\x1EE4', "\x1EE5"), ('\x1EE6', "\x1EE7"), ('\x1EE8', "\x1EE9"), ('\x1EEA', "\x1EEB"), ('\x1EEC', "\x1EED"), ('\x1EEE', "\x1EEF"), ('\x1EF0', "\x1EF1"), ('\x1EF2', "\x1EF3"), ('\x1EF4', "\x1EF5"), ('\x1EF6', "\x1EF7"), ('\x1EF8', "\x1EF9"), ('\x1F08', "\x1F00"), ('\x1F09', "\x1F01"), ('\x1F0A', "\x1F02"), ('\x1F0B', "\x1F03"), ('\x1F0C', "\x1F04"), ('\x1F0D', "\x1F05"), ('\x1F0E', "\x1F06"), ('\x1F0F', "\x1F07"), ('\x1F18', "\x1F10"), ('\x1F19', "\x1F11"), ('\x1F1A', "\x1F12"), ('\x1F1B', "\x1F13"), ('\x1F1C', "\x1F14"), ('\x1F1D', "\x1F15"), ('\x1F28', "\x1F20"), ('\x1F29', "\x1F21"), ('\x1F2A', "\x1F22"), ('\x1F2B', "\x1F23"), ('\x1F2C', "\x1F24"), ('\x1F2D', "\x1F25"), ('\x1F2E', "\x1F26"), ('\x1F2F', "\x1F27"), ('\x1F38', "\x1F30"), ('\x1F39', "\x1F31"), ('\x1F3A', "\x1F32"), ('\x1F3B', "\x1F33"), ('\x1F3C', "\x1F34"), ('\x1F3D', "\x1F35"), ('\x1F3E', "\x1F36"), ('\x1F3F', "\x1F37"), ('\x1F48', "\x1F40"), ('\x1F49', "\x1F41"), ('\x1F4A', "\x1F42"), ('\x1F4B', "\x1F43"), ('\x1F4C', "\x1F44"), ('\x1F4D', "\x1F45"), ('\x1F50', "\x03C5\x0313"), ('\x1F52', "\x03C5\x0313\x0300"), ('\x1F54', "\x03C5\x0313\x0301"), ('\x1F56', "\x03C5\x0313\x0342"), ('\x1F59', "\x1F51"), ('\x1F5B', "\x1F53"), ('\x1F5D', "\x1F55"), ('\x1F5F', "\x1F57"), ('\x1F68', "\x1F60"), ('\x1F69', "\x1F61"), ('\x1F6A', "\x1F62"), ('\x1F6B', "\x1F63"), ('\x1F6C', "\x1F64"), ('\x1F6D', "\x1F65"), ('\x1F6E', "\x1F66"), ('\x1F6F', "\x1F67"), ('\x1F80', "\x1F00\x03B9"), ('\x1F81', "\x1F01\x03B9"), ('\x1F82', "\x1F02\x03B9"), ('\x1F83', "\x1F03\x03B9"), ('\x1F84', "\x1F04\x03B9"), ('\x1F85', "\x1F05\x03B9"), ('\x1F86', "\x1F06\x03B9"), ('\x1F87', "\x1F07\x03B9"), ('\x1F88', "\x1F00\x03B9"), ('\x1F89', "\x1F01\x03B9"), ('\x1F8A', "\x1F02\x03B9"), ('\x1F8B', "\x1F03\x03B9"), ('\x1F8C', "\x1F04\x03B9"), ('\x1F8D', "\x1F05\x03B9"), ('\x1F8E', "\x1F06\x03B9"), ('\x1F8F', "\x1F07\x03B9"), ('\x1F90', "\x1F20\x03B9"), ('\x1F91', "\x1F21\x03B9"), ('\x1F92', "\x1F22\x03B9"), ('\x1F93', "\x1F23\x03B9"), ('\x1F94', "\x1F24\x03B9"), ('\x1F95', "\x1F25\x03B9"), ('\x1F96', "\x1F26\x03B9"), ('\x1F97', "\x1F27\x03B9"), ('\x1F98', "\x1F20\x03B9"), ('\x1F99', "\x1F21\x03B9"), ('\x1F9A', "\x1F22\x03B9"), ('\x1F9B', "\x1F23\x03B9"), ('\x1F9C', "\x1F24\x03B9"), ('\x1F9D', "\x1F25\x03B9"), ('\x1F9E', "\x1F26\x03B9"), ('\x1F9F', "\x1F27\x03B9"), ('\x1FA0', "\x1F60\x03B9"), ('\x1FA1', "\x1F61\x03B9"), ('\x1FA2', "\x1F62\x03B9"), ('\x1FA3', "\x1F63\x03B9"), ('\x1FA4', "\x1F64\x03B9"), ('\x1FA5', "\x1F65\x03B9"), ('\x1FA6', "\x1F66\x03B9"), ('\x1FA7', "\x1F67\x03B9"), ('\x1FA8', "\x1F60\x03B9"), ('\x1FA9', "\x1F61\x03B9"), ('\x1FAA', "\x1F62\x03B9"), ('\x1FAB', "\x1F63\x03B9"), ('\x1FAC', "\x1F64\x03B9"), ('\x1FAD', "\x1F65\x03B9"), ('\x1FAE', "\x1F66\x03B9"), ('\x1FAF', "\x1F67\x03B9"), ('\x1FB2', "\x1F70\x03B9"), ('\x1FB3', "\x03B1\x03B9"), ('\x1FB4', "\x03AC\x03B9"), ('\x1FB6', "\x03B1\x0342"), ('\x1FB7', "\x03B1\x0342\x03B9"), ('\x1FB8', "\x1FB0"), ('\x1FB9', "\x1FB1"), ('\x1FBA', "\x1F70"), ('\x1FBB', "\x1F71"), ('\x1FBC', "\x03B1\x03B9"), ('\x1FBE', "\x03B9"), ('\x1FC2', "\x1F74\x03B9"), ('\x1FC3', "\x03B7\x03B9"), ('\x1FC4', "\x03AE\x03B9"), ('\x1FC6', "\x03B7\x0342"), ('\x1FC7', "\x03B7\x0342\x03B9"), ('\x1FC8', "\x1F72"), ('\x1FC9', "\x1F73"), ('\x1FCA', "\x1F74"), ('\x1FCB', "\x1F75"), ('\x1FCC', "\x03B7\x03B9"), ('\x1FD2', "\x03B9\x0308\x0300"), ('\x1FD3', "\x03B9\x0308\x0301"), ('\x1FD6', "\x03B9\x0342"), ('\x1FD7', "\x03B9\x0308\x0342"), ('\x1FD8', "\x1FD0"), ('\x1FD9', "\x1FD1"), ('\x1FDA', "\x1F76"), ('\x1FDB', "\x1F77"), ('\x1FE2', "\x03C5\x0308\x0300"), ('\x1FE3', "\x03C5\x0308\x0301"), ('\x1FE4', "\x03C1\x0313"), ('\x1FE6', "\x03C5\x0342"), ('\x1FE7', "\x03C5\x0308\x0342"), ('\x1FE8', "\x1FE0"), ('\x1FE9', "\x1FE1"), ('\x1FEA', "\x1F7A"), ('\x1FEB', "\x1F7B"), ('\x1FEC', "\x1FE5"), ('\x1FF2', "\x1F7C\x03B9"), ('\x1FF3', "\x03C9\x03B9"), ('\x1FF4', "\x03CE\x03B9"), ('\x1FF6', "\x03C9\x0342"), ('\x1FF7', "\x03C9\x0342\x03B9"), ('\x1FF8', "\x1F78"), ('\x1FF9', "\x1F79"), ('\x1FFA', "\x1F7C"), ('\x1FFB', "\x1F7D"), ('\x1FFC', "\x03C9\x03B9"), ('\x20A8', "\x0072\x0073"), ('\x2102', "\x0063"), ('\x2103', "\x00B0\x0063"), ('\x2107', "\x025B"), ('\x2109', "\x00B0\x0066"), ('\x210B', "\x0068"), ('\x210C', "\x0068"), ('\x210D', "\x0068"), ('\x2110', "\x0069"), ('\x2111', "\x0069"), ('\x2112', "\x006C"), ('\x2115', "\x006E"), ('\x2116', "\x006E\x006F"), ('\x2119', "\x0070"), ('\x211A', "\x0071"), ('\x211B', "\x0072"), ('\x211C', "\x0072"), ('\x211D', "\x0072"), ('\x2120', "\x0073\x006D"), ('\x2121', "\x0074\x0065\x006C"), ('\x2122', "\x0074\x006D"), ('\x2124', "\x007A"), ('\x2126', "\x03C9"), ('\x2128', "\x007A"), ('\x212A', "\x006B"), ('\x212B', "\x00E5"), ('\x212C', "\x0062"), ('\x212D', "\x0063"), ('\x2130', "\x0065"), ('\x2131', "\x0066"), ('\x2133', "\x006D"), ('\x213E', "\x03B3"), ('\x213F', "\x03C0"), ('\x2145', "\x0064"), ('\x2160', "\x2170"), ('\x2161', "\x2171"), ('\x2162', "\x2172"), ('\x2163', "\x2173"), ('\x2164', "\x2174"), ('\x2165', "\x2175"), ('\x2166', "\x2176"), ('\x2167', "\x2177"), ('\x2168', "\x2178"), ('\x2169', "\x2179"), ('\x216A', "\x217A"), ('\x216B', "\x217B"), ('\x216C', "\x217C"), ('\x216D', "\x217D"), ('\x216E', "\x217E"), ('\x216F', "\x217F"), ('\x24B6', "\x24D0"), ('\x24B7', "\x24D1"), ('\x24B8', "\x24D2"), ('\x24B9', "\x24D3"), ('\x24BA', "\x24D4"), ('\x24BB', "\x24D5"), ('\x24BC', "\x24D6"), ('\x24BD', "\x24D7"), ('\x24BE', "\x24D8"), ('\x24BF', "\x24D9"), ('\x24C0', "\x24DA"), ('\x24C1', "\x24DB"), ('\x24C2', "\x24DC"), ('\x24C3', "\x24DD"), ('\x24C4', "\x24DE"), ('\x24C5', "\x24DF"), ('\x24C6', "\x24E0"), ('\x24C7', "\x24E1"), ('\x24C8', "\x24E2"), ('\x24C9', "\x24E3"), ('\x24CA', "\x24E4"), ('\x24CB', "\x24E5"), ('\x24CC', "\x24E6"), ('\x24CD', "\x24E7"), ('\x24CE', "\x24E8"), ('\x24CF', "\x24E9"), ('\x3371', "\x0068\x0070\x0061"), ('\x3373', "\x0061\x0075"), ('\x3375', "\x006F\x0076"), ('\x3380', "\x0070\x0061"), ('\x3381', "\x006E\x0061"), ('\x3382', "\x03BC\x0061"), ('\x3383', "\x006D\x0061"), ('\x3384', "\x006B\x0061"), ('\x3385', "\x006B\x0062"), ('\x3386', "\x006D\x0062"), ('\x3387', "\x0067\x0062"), ('\x338A', "\x0070\x0066"), ('\x338B', "\x006E\x0066"), ('\x338C', "\x03BC\x0066"), ('\x3390', "\x0068\x007A"), ('\x3391', "\x006B\x0068\x007A"), ('\x3392', "\x006D\x0068\x007A"), ('\x3393', "\x0067\x0068\x007A"), ('\x3394', "\x0074\x0068\x007A"), ('\x33A9', "\x0070\x0061"), ('\x33AA', "\x006B\x0070\x0061"), ('\x33AB', "\x006D\x0070\x0061"), ('\x33AC', "\x0067\x0070\x0061"), ('\x33B4', "\x0070\x0076"), ('\x33B5', "\x006E\x0076"), ('\x33B6', "\x03BC\x0076"), ('\x33B7', "\x006D\x0076"), ('\x33B8', "\x006B\x0076"), ('\x33B9', "\x006D\x0076"), ('\x33BA', "\x0070\x0077"), ('\x33BB', "\x006E\x0077"), ('\x33BC', "\x03BC\x0077"), ('\x33BD', "\x006D\x0077"), ('\x33BE', "\x006B\x0077"), ('\x33BF', "\x006D\x0077"), ('\x33C0', "\x006B\x03C9"), ('\x33C1', "\x006D\x03C9"), ('\x33C3', "\x0062\x0071"), ('\x33C6', "\x0063\x2215\x006B\x0067"), ('\x33C7', "\x0063\x006F\x002E"), ('\x33C8', "\x0064\x0062"), ('\x33C9', "\x0067\x0079"), ('\x33CB', "\x0068\x0070"), ('\x33CD', "\x006B\x006B"), ('\x33CE', "\x006B\x006D"), ('\x33D7', "\x0070\x0068"), ('\x33D9', "\x0070\x0070\x006D"), ('\x33DA', "\x0070\x0072"), ('\x33DC', "\x0073\x0076"), ('\x33DD', "\x0077\x0062"), ('\xFB00', "\x0066\x0066"), ('\xFB01', "\x0066\x0069"), ('\xFB02', "\x0066\x006C"), ('\xFB03', "\x0066\x0066\x0069"), ('\xFB04', "\x0066\x0066\x006C"), ('\xFB05', "\x0073\x0074"), ('\xFB06', "\x0073\x0074"), ('\xFB13', "\x0574\x0576"), ('\xFB14', "\x0574\x0565"), ('\xFB15', "\x0574\x056B"), ('\xFB16', "\x057E\x0576"), ('\xFB17', "\x0574\x056D"), ('\xFF21', "\xFF41"), ('\xFF22', "\xFF42"), ('\xFF23', "\xFF43"), ('\xFF24', "\xFF44"), ('\xFF25', "\xFF45"), ('\xFF26', "\xFF46"), ('\xFF27', "\xFF47"), ('\xFF28', "\xFF48"), ('\xFF29', "\xFF49"), ('\xFF2A', "\xFF4A"), ('\xFF2B', "\xFF4B"), ('\xFF2C', "\xFF4C"), ('\xFF2D', "\xFF4D"), ('\xFF2E', "\xFF4E"), ('\xFF2F', "\xFF4F"), ('\xFF30', "\xFF50"), ('\xFF31', "\xFF51"), ('\xFF32', "\xFF52"), ('\xFF33', "\xFF53"), ('\xFF34', "\xFF54"), ('\xFF35', "\xFF55"), ('\xFF36', "\xFF56"), ('\xFF37', "\xFF57"), ('\xFF38', "\xFF58"), ('\xFF39', "\xFF59"), ('\xFF3A', "\xFF5A"), ('\x10400', "\x10428"), ('\x10401', "\x10429"), ('\x10402', "\x1042A"), ('\x10403', "\x1042B"), ('\x10404', "\x1042C"), ('\x10405', "\x1042D"), ('\x10406', "\x1042E"), ('\x10407', "\x1042F"), ('\x10408', "\x10430"), ('\x10409', "\x10431"), ('\x1040A', "\x10432"), ('\x1040B', "\x10433"), ('\x1040C', "\x10434"), ('\x1040D', "\x10435"), ('\x1040E', "\x10436"), ('\x1040F', "\x10437"), ('\x10410', "\x10438"), ('\x10411', "\x10439"), ('\x10412', "\x1043A"), ('\x10413', "\x1043B"), ('\x10414', "\x1043C"), ('\x10415', "\x1043D"), ('\x10416', "\x1043E"), ('\x10417', "\x1043F"), ('\x10418', "\x10440"), ('\x10419', "\x10441"), ('\x1041A', "\x10442"), ('\x1041B', "\x10443"), ('\x1041C', "\x10444"), ('\x1041D', "\x10445"), ('\x1041E', "\x10446"), ('\x1041F', "\x10447"), ('\x10420', "\x10448"), ('\x10421', "\x10449"), ('\x10422', "\x1044A"), ('\x10423', "\x1044B"), ('\x10424', "\x1044C"), ('\x10425', "\x1044D"), ('\x1D400', "\x0061"), ('\x1D401', "\x0062"), ('\x1D402', "\x0063"), ('\x1D403', "\x0064"), ('\x1D404', "\x0065"), ('\x1D405', "\x0066"), ('\x1D406', "\x0067"), ('\x1D407', "\x0068"), ('\x1D408', "\x0069"), ('\x1D409', "\x006A"), ('\x1D40A', "\x006B"), ('\x1D40B', "\x006C"), ('\x1D40C', "\x006D"), ('\x1D40D', "\x006E"), ('\x1D40E', "\x006F"), ('\x1D40F', "\x0070"), ('\x1D410', "\x0071"), ('\x1D411', "\x0072"), ('\x1D412', "\x0073"), ('\x1D413', "\x0074"), ('\x1D414', "\x0075"), ('\x1D415', "\x0076"), ('\x1D416', "\x0077"), ('\x1D417', "\x0078"), ('\x1D418', "\x0079"), ('\x1D419', "\x007A"), ('\x1D434', "\x0061"), ('\x1D435', "\x0062"), ('\x1D436', "\x0063"), ('\x1D437', "\x0064"), ('\x1D438', "\x0065"), ('\x1D439', "\x0066"), ('\x1D43A', "\x0067"), ('\x1D43B', "\x0068"), ('\x1D43C', "\x0069"), ('\x1D43D', "\x006A"), ('\x1D43E', "\x006B"), ('\x1D43F', "\x006C"), ('\x1D440', "\x006D"), ('\x1D441', "\x006E"), ('\x1D442', "\x006F"), ('\x1D443', "\x0070"), ('\x1D444', "\x0071"), ('\x1D445', "\x0072"), ('\x1D446', "\x0073"), ('\x1D447', "\x0074"), ('\x1D448', "\x0075"), ('\x1D449', "\x0076"), ('\x1D44A', "\x0077"), ('\x1D44B', "\x0078"), ('\x1D44C', "\x0079"), ('\x1D44D', "\x007A"), ('\x1D468', "\x0061"), ('\x1D469', "\x0062"), ('\x1D46A', "\x0063"), ('\x1D46B', "\x0064"), ('\x1D46C', "\x0065"), ('\x1D46D', "\x0066"), ('\x1D46E', "\x0067"), ('\x1D46F', "\x0068"), ('\x1D470', "\x0069"), ('\x1D471', "\x006A"), ('\x1D472', "\x006B"), ('\x1D473', "\x006C"), ('\x1D474', "\x006D"), ('\x1D475', "\x006E"), ('\x1D476', "\x006F"), ('\x1D477', "\x0070"), ('\x1D478', "\x0071"), ('\x1D479', "\x0072"), ('\x1D47A', "\x0073"), ('\x1D47B', "\x0074"), ('\x1D47C', "\x0075"), ('\x1D47D', "\x0076"), ('\x1D47E', "\x0077"), ('\x1D47F', "\x0078"), ('\x1D480', "\x0079"), ('\x1D481', "\x007A"), ('\x1D49C', "\x0061"), ('\x1D49E', "\x0063"), ('\x1D49F', "\x0064"), ('\x1D4A2', "\x0067"), ('\x1D4A5', "\x006A"), ('\x1D4A6', "\x006B"), ('\x1D4A9', "\x006E"), ('\x1D4AA', "\x006F"), ('\x1D4AB', "\x0070"), ('\x1D4AC', "\x0071"), ('\x1D4AE', "\x0073"), ('\x1D4AF', "\x0074"), ('\x1D4B0', "\x0075"), ('\x1D4B1', "\x0076"), ('\x1D4B2', "\x0077"), ('\x1D4B3', "\x0078"), ('\x1D4B4', "\x0079"), ('\x1D4B5', "\x007A"), ('\x1D4D0', "\x0061"), ('\x1D4D1', "\x0062"), ('\x1D4D2', "\x0063"), ('\x1D4D3', "\x0064"), ('\x1D4D4', "\x0065"), ('\x1D4D5', "\x0066"), ('\x1D4D6', "\x0067"), ('\x1D4D7', "\x0068"), ('\x1D4D8', "\x0069"), ('\x1D4D9', "\x006A"), ('\x1D4DA', "\x006B"), ('\x1D4DB', "\x006C"), ('\x1D4DC', "\x006D"), ('\x1D4DD', "\x006E"), ('\x1D4DE', "\x006F"), ('\x1D4DF', "\x0070"), ('\x1D4E0', "\x0071"), ('\x1D4E1', "\x0072"), ('\x1D4E2', "\x0073"), ('\x1D4E3', "\x0074"), ('\x1D4E4', "\x0075"), ('\x1D4E5', "\x0076"), ('\x1D4E6', "\x0077"), ('\x1D4E7', "\x0078"), ('\x1D4E8', "\x0079"), ('\x1D4E9', "\x007A"), ('\x1D504', "\x0061"), ('\x1D505', "\x0062"), ('\x1D507', "\x0064"), ('\x1D508', "\x0065"), ('\x1D509', "\x0066"), ('\x1D50A', "\x0067"), ('\x1D50D', "\x006A"), ('\x1D50E', "\x006B"), ('\x1D50F', "\x006C"), ('\x1D510', "\x006D"), ('\x1D511', "\x006E"), ('\x1D512', "\x006F"), ('\x1D513', "\x0070"), ('\x1D514', "\x0071"), ('\x1D516', "\x0073"), ('\x1D517', "\x0074"), ('\x1D518', "\x0075"), ('\x1D519', "\x0076"), ('\x1D51A', "\x0077"), ('\x1D51B', "\x0078"), ('\x1D51C', "\x0079"), ('\x1D538', "\x0061"), ('\x1D539', "\x0062"), ('\x1D53B', "\x0064"), ('\x1D53C', "\x0065"), ('\x1D53D', "\x0066"), ('\x1D53E', "\x0067"), ('\x1D540', "\x0069"), ('\x1D541', "\x006A"), ('\x1D542', "\x006B"), ('\x1D543', "\x006C"), ('\x1D544', "\x006D"), ('\x1D546', "\x006F"), ('\x1D54A', "\x0073"), ('\x1D54B', "\x0074"), ('\x1D54C', "\x0075"), ('\x1D54D', "\x0076"), ('\x1D54E', "\x0077"), ('\x1D54F', "\x0078"), ('\x1D550', "\x0079"), ('\x1D56C', "\x0061"), ('\x1D56D', "\x0062"), ('\x1D56E', "\x0063"), ('\x1D56F', "\x0064"), ('\x1D570', "\x0065"), ('\x1D571', "\x0066"), ('\x1D572', "\x0067"), ('\x1D573', "\x0068"), ('\x1D574', "\x0069"), ('\x1D575', "\x006A"), ('\x1D576', "\x006B"), ('\x1D577', "\x006C"), ('\x1D578', "\x006D"), ('\x1D579', "\x006E"), ('\x1D57A', "\x006F"), ('\x1D57B', "\x0070"), ('\x1D57C', "\x0071"), ('\x1D57D', "\x0072"), ('\x1D57E', "\x0073"), ('\x1D57F', "\x0074"), ('\x1D580', "\x0075"), ('\x1D581', "\x0076"), ('\x1D582', "\x0077"), ('\x1D583', "\x0078"), ('\x1D584', "\x0079"), ('\x1D585', "\x007A"), ('\x1D5A0', "\x0061"), ('\x1D5A1', "\x0062"), ('\x1D5A2', "\x0063"), ('\x1D5A3', "\x0064"), ('\x1D5A4', "\x0065"), ('\x1D5A5', "\x0066"), ('\x1D5A6', "\x0067"), ('\x1D5A7', "\x0068"), ('\x1D5A8', "\x0069"), ('\x1D5A9', "\x006A"), ('\x1D5AA', "\x006B"), ('\x1D5AB', "\x006C"), ('\x1D5AC', "\x006D"), ('\x1D5AD', "\x006E"), ('\x1D5AE', "\x006F"), ('\x1D5AF', "\x0070"), ('\x1D5B0', "\x0071"), ('\x1D5B1', "\x0072"), ('\x1D5B2', "\x0073"), ('\x1D5B3', "\x0074"), ('\x1D5B4', "\x0075"), ('\x1D5B5', "\x0076"), ('\x1D5B6', "\x0077"), ('\x1D5B7', "\x0078"), ('\x1D5B8', "\x0079"), ('\x1D5B9', "\x007A"), ('\x1D5D4', "\x0061"), ('\x1D5D5', "\x0062"), ('\x1D5D6', "\x0063"), ('\x1D5D7', "\x0064"), ('\x1D5D8', "\x0065"), ('\x1D5D9', "\x0066"), ('\x1D5DA', "\x0067"), ('\x1D5DB', "\x0068"), ('\x1D5DC', "\x0069"), ('\x1D5DD', "\x006A"), ('\x1D5DE', "\x006B"), ('\x1D5DF', "\x006C"), ('\x1D5E0', "\x006D"), ('\x1D5E1', "\x006E"), ('\x1D5E2', "\x006F"), ('\x1D5E3', "\x0070"), ('\x1D5E4', "\x0071"), ('\x1D5E5', "\x0072"), ('\x1D5E6', "\x0073"), ('\x1D5E7', "\x0074"), ('\x1D5E8', "\x0075"), ('\x1D5E9', "\x0076"), ('\x1D5EA', "\x0077"), ('\x1D5EB', "\x0078"), ('\x1D5EC', "\x0079"), ('\x1D5ED', "\x007A"), ('\x1D608', "\x0061"), ('\x1D609', "\x0062"), ('\x1D60A', "\x0063"), ('\x1D60B', "\x0064"), ('\x1D60C', "\x0065"), ('\x1D60D', "\x0066"), ('\x1D60E', "\x0067"), ('\x1D60F', "\x0068"), ('\x1D610', "\x0069"), ('\x1D611', "\x006A"), ('\x1D612', "\x006B"), ('\x1D613', "\x006C"), ('\x1D614', "\x006D"), ('\x1D615', "\x006E"), ('\x1D616', "\x006F"), ('\x1D617', "\x0070"), ('\x1D618', "\x0071"), ('\x1D619', "\x0072"), ('\x1D61A', "\x0073"), ('\x1D61B', "\x0074"), ('\x1D61C', "\x0075"), ('\x1D61D', "\x0076"), ('\x1D61E', "\x0077"), ('\x1D61F', "\x0078"), ('\x1D620', "\x0079"), ('\x1D621', "\x007A"), ('\x1D63C', "\x0061"), ('\x1D63D', "\x0062"), ('\x1D63E', "\x0063"), ('\x1D63F', "\x0064"), ('\x1D640', "\x0065"), ('\x1D641', "\x0066"), ('\x1D642', "\x0067"), ('\x1D643', "\x0068"), ('\x1D644', "\x0069"), ('\x1D645', "\x006A"), ('\x1D646', "\x006B"), ('\x1D647', "\x006C"), ('\x1D648', "\x006D"), ('\x1D649', "\x006E"), ('\x1D64A', "\x006F"), ('\x1D64B', "\x0070"), ('\x1D64C', "\x0071"), ('\x1D64D', "\x0072"), ('\x1D64E', "\x0073"), ('\x1D64F', "\x0074"), ('\x1D650', "\x0075"), ('\x1D651', "\x0076"), ('\x1D652', "\x0077"), ('\x1D653', "\x0078"), ('\x1D654', "\x0079"), ('\x1D655', "\x007A"), ('\x1D670', "\x0061"), ('\x1D671', "\x0062"), ('\x1D672', "\x0063"), ('\x1D673', "\x0064"), ('\x1D674', "\x0065"), ('\x1D675', "\x0066"), ('\x1D676', "\x0067"), ('\x1D677', "\x0068"), ('\x1D678', "\x0069"), ('\x1D679', "\x006A"), ('\x1D67A', "\x006B"), ('\x1D67B', "\x006C"), ('\x1D67C', "\x006D"), ('\x1D67D', "\x006E"), ('\x1D67E', "\x006F"), ('\x1D67F', "\x0070"), ('\x1D680', "\x0071"), ('\x1D681', "\x0072"), ('\x1D682', "\x0073"), ('\x1D683', "\x0074"), ('\x1D684', "\x0075"), ('\x1D685', "\x0076"), ('\x1D686', "\x0077"), ('\x1D687', "\x0078"), ('\x1D688', "\x0079"), ('\x1D689', "\x007A"), ('\x1D6A8', "\x03B1"), ('\x1D6A9', "\x03B2"), ('\x1D6AA', "\x03B3"), ('\x1D6AB', "\x03B4"), ('\x1D6AC', "\x03B5"), ('\x1D6AD', "\x03B6"), ('\x1D6AE', "\x03B7"), ('\x1D6AF', "\x03B8"), ('\x1D6B0', "\x03B9"), ('\x1D6B1', "\x03BA"), ('\x1D6B2', "\x03BB"), ('\x1D6B3', "\x03BC"), ('\x1D6B4', "\x03BD"), ('\x1D6B5', "\x03BE"), ('\x1D6B6', "\x03BF"), ('\x1D6B7', "\x03C0"), ('\x1D6B8', "\x03C1"), ('\x1D6B9', "\x03B8"), ('\x1D6BA', "\x03C3"), ('\x1D6BB', "\x03C4"), ('\x1D6BC', "\x03C5"), ('\x1D6BD', "\x03C6"), ('\x1D6BE', "\x03C7"), ('\x1D6BF', "\x03C8"), ('\x1D6C0', "\x03C9"), ('\x1D6D3', "\x03C3"), ('\x1D6E2', "\x03B1"), ('\x1D6E3', "\x03B2"), ('\x1D6E4', "\x03B3"), ('\x1D6E5', "\x03B4"), ('\x1D6E6', "\x03B5"), ('\x1D6E7', "\x03B6"), ('\x1D6E8', "\x03B7"), ('\x1D6E9', "\x03B8"), ('\x1D6EA', "\x03B9"), ('\x1D6EB', "\x03BA"), ('\x1D6EC', "\x03BB"), ('\x1D6ED', "\x03BC"), ('\x1D6EE', "\x03BD"), ('\x1D6EF', "\x03BE"), ('\x1D6F0', "\x03BF"), ('\x1D6F1', "\x03C0"), ('\x1D6F2', "\x03C1"), ('\x1D6F3', "\x03B8"), ('\x1D6F4', "\x03C3"), ('\x1D6F5', "\x03C4"), ('\x1D6F6', "\x03C5"), ('\x1D6F7', "\x03C6"), ('\x1D6F8', "\x03C7"), ('\x1D6F9', "\x03C8"), ('\x1D6FA', "\x03C9"), ('\x1D70D', "\x03C3"), ('\x1D71C', "\x03B1"), ('\x1D71D', "\x03B2"), ('\x1D71E', "\x03B3"), ('\x1D71F', "\x03B4"), ('\x1D720', "\x03B5"), ('\x1D721', "\x03B6"), ('\x1D722', "\x03B7"), ('\x1D723', "\x03B8"), ('\x1D724', "\x03B9"), ('\x1D725', "\x03BA"), ('\x1D726', "\x03BB"), ('\x1D727', "\x03BC"), ('\x1D728', "\x03BD"), ('\x1D729', "\x03BE"), ('\x1D72A', "\x03BF"), ('\x1D72B', "\x03C0"), ('\x1D72C', "\x03C1"), ('\x1D72D', "\x03B8"), ('\x1D72E', "\x03C3"), ('\x1D72F', "\x03C4"), ('\x1D730', "\x03C5"), ('\x1D731', "\x03C6"), ('\x1D732', "\x03C7"), ('\x1D733', "\x03C8"), ('\x1D734', "\x03C9"), ('\x1D747', "\x03C3"), ('\x1D756', "\x03B1"), ('\x1D757', "\x03B2"), ('\x1D758', "\x03B3"), ('\x1D759', "\x03B4"), ('\x1D75A', "\x03B5"), ('\x1D75B', "\x03B6"), ('\x1D75C', "\x03B7"), ('\x1D75D', "\x03B8"), ('\x1D75E', "\x03B9"), ('\x1D75F', "\x03BA"), ('\x1D760', "\x03BB"), ('\x1D761', "\x03BC"), ('\x1D762', "\x03BD"), ('\x1D763', "\x03BE"), ('\x1D764', "\x03BF"), ('\x1D765', "\x03C0"), ('\x1D766', "\x03C1"), ('\x1D767', "\x03B8"), ('\x1D768', "\x03C3"), ('\x1D769', "\x03C4"), ('\x1D76A', "\x03C5"), ('\x1D76B', "\x03C6"), ('\x1D76C', "\x03C7"), ('\x1D76D', "\x03C8"), ('\x1D76E', "\x03C9"), ('\x1D781', "\x03C3"), ('\x1D790', "\x03B1"), ('\x1D791', "\x03B2"), ('\x1D792', "\x03B3"), ('\x1D793', "\x03B4"), ('\x1D794', "\x03B5"), ('\x1D795', "\x03B6"), ('\x1D796', "\x03B7"), ('\x1D797', "\x03B8"), ('\x1D798', "\x03B9"), ('\x1D799', "\x03BA"), ('\x1D79A', "\x03BB"), ('\x1D79B', "\x03BC"), ('\x1D79C', "\x03BD"), ('\x1D79D', "\x03BE"), ('\x1D79E', "\x03BF"), ('\x1D79F', "\x03C0"), ('\x1D7A0', "\x03C1"), ('\x1D7A1', "\x03B8"), ('\x1D7A2', "\x03C3"), ('\x1D7A3', "\x03C4"), ('\x1D7A4', "\x03C5"), ('\x1D7A5', "\x03C6"), ('\x1D7A6', "\x03C7"), ('\x1D7A7', "\x03C8"), ('\x1D7A8', "\x03C9"), ('\x1D7BB', "\x03C3")] a1 :: [Range] a1 = [ single '\x0221', range '\x0234' '\x024F', range '\x02AE' '\x02AF', range '\x02EF' '\x02FF', range '\x0350' '\x035F', range '\x0370' '\x0373', range '\x0376' '\x0379', range '\x037B' '\x037D', range '\x037F' '\x0383', single '\x038B', single '\x038D', single '\x03A2', single '\x03CF', range '\x03F7' '\x03FF', single '\x0487', single '\x04CF', range '\x04F6' '\x04F7', range '\x04FA' '\x04FF', range '\x0510' '\x0530', range '\x0557' '\x0558', single '\x0560', single '\x0588', range '\x058B' '\x0590', single '\x05A2', single '\x05BA', range '\x05C5' '\x05CF', range '\x05EB' '\x05EF', range '\x05F5' '\x060B', range '\x060D' '\x061A', range '\x061C' '\x061E', single '\x0620', range '\x063B' '\x063F', range '\x0656' '\x065F', range '\x06EE' '\x06EF', single '\x06FF', single '\x070E', range '\x072D' '\x072F', range '\x074B' '\x077F', range '\x07B2' '\x0900', single '\x0904', range '\x093A' '\x093B', range '\x094E' '\x094F', range '\x0955' '\x0957', range '\x0971' '\x0980', single '\x0984', range '\x098D' '\x098E', range '\x0991' '\x0992', single '\x09A9', single '\x09B1', range '\x09B3' '\x09B5', range '\x09BA' '\x09BB', single '\x09BD', range '\x09C5' '\x09C6', range '\x09C9' '\x09CA', range '\x09CE' '\x09D6', range '\x09D8' '\x09DB', single '\x09DE', range '\x09E4' '\x09E5', range '\x09FB' '\x0A01', range '\x0A03' '\x0A04', range '\x0A0B' '\x0A0E', range '\x0A11' '\x0A12', single '\x0A29', single '\x0A31', single '\x0A34', single '\x0A37', range '\x0A3A' '\x0A3B', single '\x0A3D', range '\x0A43' '\x0A46', range '\x0A49' '\x0A4A', range '\x0A4E' '\x0A58', single '\x0A5D', range '\x0A5F' '\x0A65', range '\x0A75' '\x0A80', single '\x0A84', single '\x0A8C', single '\x0A8E', single '\x0A92', single '\x0AA9', single '\x0AB1', single '\x0AB4', range '\x0ABA' '\x0ABB', single '\x0AC6', single '\x0ACA', range '\x0ACE' '\x0ACF', range '\x0AD1' '\x0ADF', range '\x0AE1' '\x0AE5', range '\x0AF0' '\x0B00', single '\x0B04', range '\x0B0D' '\x0B0E', range '\x0B11' '\x0B12', single '\x0B29', single '\x0B31', range '\x0B34' '\x0B35', range '\x0B3A' '\x0B3B', range '\x0B44' '\x0B46', range '\x0B49' '\x0B4A', range '\x0B4E' '\x0B55', range '\x0B58' '\x0B5B', single '\x0B5E', range '\x0B62' '\x0B65', range '\x0B71' '\x0B81', single '\x0B84', range '\x0B8B' '\x0B8D', single '\x0B91', range '\x0B96' '\x0B98', single '\x0B9B', single '\x0B9D', range '\x0BA0' '\x0BA2', range '\x0BA5' '\x0BA7', range '\x0BAB' '\x0BAD', single '\x0BB6', range '\x0BBA' '\x0BBD', range '\x0BC3' '\x0BC5', single '\x0BC9', range '\x0BCE' '\x0BD6', range '\x0BD8' '\x0BE6', range '\x0BF3' '\x0C00', single '\x0C04', single '\x0C0D', single '\x0C11', single '\x0C29', single '\x0C34', range '\x0C3A' '\x0C3D', single '\x0C45', single '\x0C49', range '\x0C4E' '\x0C54', range '\x0C57' '\x0C5F', range '\x0C62' '\x0C65', range '\x0C70' '\x0C81', single '\x0C84', single '\x0C8D', single '\x0C91', single '\x0CA9', single '\x0CB4', range '\x0CBA' '\x0CBD', single '\x0CC5', single '\x0CC9', range '\x0CCE' '\x0CD4', range '\x0CD7' '\x0CDD', single '\x0CDF', range '\x0CE2' '\x0CE5', range '\x0CF0' '\x0D01', single '\x0D04', single '\x0D0D', single '\x0D11', single '\x0D29', range '\x0D3A' '\x0D3D', range '\x0D44' '\x0D45', single '\x0D49', range '\x0D4E' '\x0D56', range '\x0D58' '\x0D5F', range '\x0D62' '\x0D65', range '\x0D70' '\x0D81', single '\x0D84', range '\x0D97' '\x0D99', single '\x0DB2', single '\x0DBC', range '\x0DBE' '\x0DBF', range '\x0DC7' '\x0DC9', range '\x0DCB' '\x0DCE', single '\x0DD5', single '\x0DD7', range '\x0DE0' '\x0DF1', range '\x0DF5' '\x0E00', range '\x0E3B' '\x0E3E', range '\x0E5C' '\x0E80', single '\x0E83', range '\x0E85' '\x0E86', single '\x0E89', range '\x0E8B' '\x0E8C', range '\x0E8E' '\x0E93', single '\x0E98', single '\x0EA0', single '\x0EA4', single '\x0EA6', range '\x0EA8' '\x0EA9', single '\x0EAC', single '\x0EBA', range '\x0EBE' '\x0EBF', single '\x0EC5', single '\x0EC7', range '\x0ECE' '\x0ECF', range '\x0EDA' '\x0EDB', range '\x0EDE' '\x0EFF', single '\x0F48', range '\x0F6B' '\x0F70', range '\x0F8C' '\x0F8F', single '\x0F98', single '\x0FBD', range '\x0FCD' '\x0FCE', range '\x0FD0' '\x0FFF', single '\x1022', single '\x1028', single '\x102B', range '\x1033' '\x1035', range '\x103A' '\x103F', range '\x105A' '\x109F', range '\x10C6' '\x10CF', range '\x10F9' '\x10FA', range '\x10FC' '\x10FF', range '\x115A' '\x115E', range '\x11A3' '\x11A7', range '\x11FA' '\x11FF', single '\x1207', single '\x1247', single '\x1249', range '\x124E' '\x124F', single '\x1257', single '\x1259', range '\x125E' '\x125F', single '\x1287', single '\x1289', range '\x128E' '\x128F', single '\x12AF', single '\x12B1', range '\x12B6' '\x12B7', single '\x12BF', single '\x12C1', range '\x12C6' '\x12C7', single '\x12CF', single '\x12D7', single '\x12EF', single '\x130F', single '\x1311', range '\x1316' '\x1317', single '\x131F', single '\x1347', range '\x135B' '\x1360', range '\x137D' '\x139F', range '\x13F5' '\x1400', range '\x1677' '\x167F', range '\x169D' '\x169F', range '\x16F1' '\x16FF', single '\x170D', range '\x1715' '\x171F', range '\x1737' '\x173F', range '\x1754' '\x175F', single '\x176D', single '\x1771', range '\x1774' '\x177F', range '\x17DD' '\x17DF', range '\x17EA' '\x17FF', single '\x180F', range '\x181A' '\x181F', range '\x1878' '\x187F', range '\x18AA' '\x1DFF', range '\x1E9C' '\x1E9F', range '\x1EFA' '\x1EFF', range '\x1F16' '\x1F17', range '\x1F1E' '\x1F1F', range '\x1F46' '\x1F47', range '\x1F4E' '\x1F4F', single '\x1F58', single '\x1F5A', single '\x1F5C', single '\x1F5E', range '\x1F7E' '\x1F7F', single '\x1FB5', single '\x1FC5', range '\x1FD4' '\x1FD5', single '\x1FDC', range '\x1FF0' '\x1FF1', single '\x1FF5', single '\x1FFF', range '\x2053' '\x2056', range '\x2058' '\x205E', range '\x2064' '\x2069', range '\x2072' '\x2073', range '\x208F' '\x209F', range '\x20B2' '\x20CF', range '\x20EB' '\x20FF', range '\x213B' '\x213C', range '\x214C' '\x2152', range '\x2184' '\x218F', range '\x23CF' '\x23FF', range '\x2427' '\x243F', range '\x244B' '\x245F', single '\x24FF', range '\x2614' '\x2615', single '\x2618', range '\x267E' '\x267F', range '\x268A' '\x2700', single '\x2705', range '\x270A' '\x270B', single '\x2728', single '\x274C', single '\x274E', range '\x2753' '\x2755', single '\x2757', range '\x275F' '\x2760', range '\x2795' '\x2797', single '\x27B0', range '\x27BF' '\x27CF', range '\x27EC' '\x27EF', range '\x2B00' '\x2E7F', single '\x2E9A', range '\x2EF4' '\x2EFF', range '\x2FD6' '\x2FEF', range '\x2FFC' '\x2FFF', single '\x3040', range '\x3097' '\x3098', range '\x3100' '\x3104', range '\x312D' '\x3130', single '\x318F', range '\x31B8' '\x31EF', range '\x321D' '\x321F', range '\x3244' '\x3250', range '\x327C' '\x327E', range '\x32CC' '\x32CF', single '\x32FF', range '\x3377' '\x337A', range '\x33DE' '\x33DF', single '\x33FF', range '\x4DB6' '\x4DFF', range '\x9FA6' '\x9FFF', range '\xA48D' '\xA48F', range '\xA4C7' '\xABFF', range '\xD7A4' '\xD7FF', range '\xFA2E' '\xFA2F', range '\xFA6B' '\xFAFF', range '\xFB07' '\xFB12', range '\xFB18' '\xFB1C', single '\xFB37', single '\xFB3D', single '\xFB3F', single '\xFB42', single '\xFB45', range '\xFBB2' '\xFBD2', range '\xFD40' '\xFD4F', range '\xFD90' '\xFD91', range '\xFDC8' '\xFDCF', range '\xFDFD' '\xFDFF', range '\xFE10' '\xFE1F', range '\xFE24' '\xFE2F', range '\xFE47' '\xFE48', single '\xFE53', single '\xFE67', range '\xFE6C' '\xFE6F', single '\xFE75', range '\xFEFD' '\xFEFE', single '\xFF00', range '\xFFBF' '\xFFC1', range '\xFFC8' '\xFFC9', range '\xFFD0' '\xFFD1', range '\xFFD8' '\xFFD9', range '\xFFDD' '\xFFDF', single '\xFFE7', range '\xFFEF' '\xFFF8', range '\x10000' '\x102FF', single '\x1031F', range '\x10324' '\x1032F', range '\x1034B' '\x103FF', range '\x10426' '\x10427', range '\x1044E' '\x1CFFF', range '\x1D0F6' '\x1D0FF', range '\x1D127' '\x1D129', range '\x1D1DE' '\x1D3FF', single '\x1D455', single '\x1D49D', range '\x1D4A0' '\x1D4A1', range '\x1D4A3' '\x1D4A4', range '\x1D4A7' '\x1D4A8', single '\x1D4AD', single '\x1D4BA', single '\x1D4BC', single '\x1D4C1', single '\x1D4C4', single '\x1D506', range '\x1D50B' '\x1D50C', single '\x1D515', single '\x1D51D', single '\x1D53A', single '\x1D53F', single '\x1D545', range '\x1D547' '\x1D549', single '\x1D551', range '\x1D6A4' '\x1D6A7', range '\x1D7CA' '\x1D7CD', range '\x1D800' '\x1FFFD', range '\x2A6D7' '\x2F7FF', range '\x2FA1E' '\x2FFFD', range '\x30000' '\x3FFFD', range '\x40000' '\x4FFFD', range '\x50000' '\x5FFFD', range '\x60000' '\x6FFFD', range '\x70000' '\x7FFFD', range '\x80000' '\x8FFFD', range '\x90000' '\x9FFFD', range '\xA0000' '\xAFFFD', range '\xB0000' '\xBFFFD', range '\xC0000' '\xCFFFD', range '\xD0000' '\xDFFFD', single '\xE0000', range '\xE0002' '\xE001F', range '\xE0080' '\xEFFFD'] stringprep-1.0.0/Text/StringPrep/0000755000000000000000000000000012262474164015124 5ustar0000000000000000stringprep-1.0.0/Text/StringPrep/Profiles.hs0000644000000000000000000000272212262474164017246 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} -- | Profiles as defined by various sources module Text.StringPrep.Profiles ( namePrepProfile , saslPrepProfile ) where import qualified Data.Set as Set import Data.Text (Text, singleton) import Text.StringPrep -- | Nameprep profile (RFC 3491) namePrepProfile :: Bool -> StringPrepProfile namePrepProfile allowUnassigned = Profile { maps = [b1,b2], shouldNormalize = True, prohibited = (if allowUnassigned then id else (a1:)) [c12,c22,c3,c4,c5,c6,c7,c8,c9], shouldCheckBidi = True } nonAsciiSpaces :: Set.Set Char nonAsciiSpaces = Set.fromList [ '\x00A0', '\x1680', '\x2000', '\x2001', '\x2002' , '\x2003', '\x2004', '\x2005', '\x2006', '\x2007' , '\x2008', '\x2009', '\x200A', '\x200B', '\x202F' , '\x205F', '\x3000' ] toSpace :: Char -> Text toSpace x = if x `Set.member` nonAsciiSpaces then " " else singleton x -- | SASLPrep profile (RFC 4013). The parameter determines whether unassigned -- charater are allowed (query behaviour) or disallowed (store) saslPrepProfile :: Bool -> StringPrepProfile saslPrepProfile allowUnassigned = Profile { maps = [b1, toSpace] , shouldNormalize = True , prohibited = (if allowUnassigned then id else (a1:)) [c12, c21, c22, c3, c4, c5, c6, c7, c8, c9] , shouldCheckBidi = True }