Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perf #129

Merged
merged 5 commits into from
Jun 18, 2024
Merged

Perf #129

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions ucd2haskell/exe/UCD2Haskell/Generator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -559,12 +559,10 @@ generateShamochuBitmaps name rawInt powersStage1 powersStage2 convert xs =
, mkAnd "n" "mask" ]
, "\n"
, " where\n"
-- , " mask = (1 `shiftL` ", BB.wordDec (Shamochu.dataChunkSizeLog2 stats), ") - 1\n"
, " ", mkMask "mask" (Shamochu.dataChunkSizeLog2 stats)
, " !(Ptr data#) = ", dataBitMap, "\n"
, " !(Ptr offsets#) = ", offsetsBitMap, "\n"
, "\n"
, "{-# NOINLINE ", dataBitMap, " #-}\n"
, dataBitMap, " :: Ptr ", dataType, "\n"
, dataBitMap, " = Ptr\n"
, " \"", enumMapToAddrLiteral'
Expand All @@ -574,7 +572,6 @@ generateShamochuBitmaps name rawInt powersStage1 powersStage2 convert xs =
(Exts.toList array)
"\"#\n"
, "\n"
, "{-# NOINLINE ", offsetsBitMap, " #-}\n"
, offsetsBitMap, " :: Ptr ", offsetType, "\n"
, offsetsBitMap, " = Ptr\n"
, " \"", enumMapToAddrLiteral'
Expand Down Expand Up @@ -614,15 +611,12 @@ generateShamochuBitmaps name rawInt powersStage1 powersStage2 convert xs =
, mkAnd "n" "maskData" ]
, "\n"
, " where\n"
-- , " maskData = (1 `shiftL` ", BB.wordDec (Shamochu.dataChunkSizeLog2 stats), ") - 1\n"
-- , " maskOffsets = (1 `shiftL` ", BB.wordDec (Shamochu.offsets1ChunkSizeLog2 stats), ") - 1\n"
, " ", mkMask "maskData" (Shamochu.dataChunkSizeLog2 stats)
, " ", mkMask "maskOffsets" (Shamochu.offsets1ChunkSizeLog2 stats)
, " !(Ptr data#) = ", dataBitMap, "\n"
, " !(Ptr offsets1#) = ", offsets1BitMap, "\n"
, " !(Ptr offsets2#) = ", offsets2BitMap, "\n"
, "\n"
, "{-# NOINLINE ", dataBitMap, " #-}\n"
, dataBitMap, " :: Ptr ", dataType, "\n"
, dataBitMap, " = Ptr\n"
, " \"", enumMapToAddrLiteral'
Expand All @@ -632,7 +626,6 @@ generateShamochuBitmaps name rawInt powersStage1 powersStage2 convert xs =
(Exts.toList dataArray)
"\"#\n"
, "\n"
, "{-# NOINLINE ", offsets1BitMap, " #-}\n"
, offsets1BitMap, " :: Ptr ", offset1Type, "\n"
, offsets1BitMap, " = Ptr\n"
, " \"", enumMapToAddrLiteral'
Expand All @@ -642,7 +635,6 @@ generateShamochuBitmaps name rawInt powersStage1 powersStage2 convert xs =
(Exts.toList offset1Array)
"\"#\n"
, "\n"
, "{-# NOINLINE ", offsets2BitMap, " #-}\n"
, offsets2BitMap, " :: Ptr ", offset2Type, "\n"
, offsets2BitMap, " = Ptr\n"
, " \"", enumMapToAddrLiteral'
Expand Down
57 changes: 28 additions & 29 deletions ucd2haskell/exe/UCD2Haskell/Modules/Blocks.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ recipe = ModuleRecipe
genBlocksModule

data Acc = Acc
{ blocks :: ![BB.Builder]
{ count :: !Word
, blocks :: ![BB.Builder]
, defs :: ![BB.Builder]
, ranges :: ![(Int, Int)] }

Expand All @@ -33,10 +34,11 @@ genBlocksModule moduleName = Fold step initial done

done Acc{..} = let ranges' = reverse ranges in unlinesBB
[ apacheLicense 2022 moduleName
, "{-# LANGUAGE LambdaCase #-}"
, "{-# OPTIONS_HADDOCK hide #-}"
, ""
, "module " <> moduleName
, "(Block(..), BlockDefinition(..), block, blockDefinition)"
, "(Block(..), block, blockDefinition)"
, "where"
, ""
, "import Data.Ix (Ix)"
Expand All @@ -53,25 +55,25 @@ genBlocksModule moduleName = Fold step initial done
, " = " <> mconcat (L.intersperse "\n | " (reverse blocks))
, " deriving (Enum, Bounded, Eq, Ord, Ix, Show)"
, ""
, "-- | Block definition: range and name."
, "--"
, "-- @since 0.3.1"
, "data BlockDefinition = BlockDefinition"
, " { blockRange :: !(Int, Int) -- ^ Range"
, " , blockName :: !String -- ^ Name"
, " } deriving (Eq, Ord, Show)"
, ""
, "-- | Block definition"
, "--"
, "-- Undefined for values greater than " <> BB.wordDec (pred count) <> "."
, "--"
, "-- Returned value:"
, "--"
, "-- * Lower bound"
, "-- * Upper bound"
, "-- * Name (null terminated ASCII string)"
, "--"
, "-- @since 0.3.1"
, "blockDefinition :: Block -> BlockDefinition"
, "blockDefinition b = case b of"
, "blockDefinition :: Int# -> (# Int#, Int#, Addr# #)"
, "blockDefinition = \\case"
, mconcat (reverse defs)
, "-- | Character block, if defined."
, "-- | Character block, if defined, else -1."
, "--"
, "-- @since 0.3.1"
, "block :: Char -> Maybe Int"
, "block (C# c#) = getBlock 0# " <> BB.intDec (length ranges - 1) <> BB.char7 '#'
, "block :: Char# -> Int#"
, "block c# = getBlock 0# " <> BB.intDec (length ranges - 1) <> BB.char7 '#'
, " where"
, " -- [NOTE] Encoding"
, " -- A range is encoded as two LE Word32:"
Expand All @@ -83,7 +85,7 @@ genBlocksModule moduleName = Fold step initial done
, ""
, " -- Binary search"
, " getBlock l# u# = if isTrue# (l# ># u#)"
, " then Nothing"
, " then -1#"
, " else"
, " let k# = l# +# uncheckedIShiftRL# (u# -# l#) 1#"
, " j# = k# `uncheckedIShiftL#` 1#"
Expand All @@ -99,7 +101,7 @@ genBlocksModule moduleName = Fold step initial done
, " then getBlock l# (k# -# 1#)"
, " -- cp in block: get block index"
, " else let block# = cpL0# `uncheckedShiftRL#` 21#"
, " in Just (I# (word2Int# block#))"
, " in word2Int# block#"
, ""
, " getRawCodePoint# = lookupWord32# ranges#"
, ""
Expand All @@ -111,7 +113,7 @@ genBlocksModule moduleName = Fold step initial done
, " \"" <> enumMapToAddrLiteral 4 0xff (mkRanges ranges') "\"#"
]

initial = Acc mempty mempty mempty
initial = Acc 0 mempty mempty mempty

step Acc{..} (Prop.Entry range blockName) = case range of
U.SingleChar c -> error ("genBlocksModule: expected range, got: " <> show c)
Expand All @@ -120,8 +122,9 @@ genBlocksModule moduleName = Fold step initial done
blockRange = (ord start, ord end)
blockName' = BB.shortByteString blockName
in Acc
{ blocks = mkBlockConstructor blockID blockName' blockRange : blocks
, defs = mkBlockDef blockID blockName' blockRange : defs
{ count = succ count
, blocks = mkBlockConstructor blockID blockName' blockRange : blocks
, defs = mkBlockDef count blockName' blockRange : defs
, ranges = blockRange : ranges }

mkBlockConstructor blockID blockName (l, u) = mconcat
Expand All @@ -135,16 +138,12 @@ genBlocksModule moduleName = Fold step initial done
, "."
]

mkBlockDef blockID blockName (l, u) = mconcat
mkBlockDef blockIndex blockName (l, u) = mconcat
[ " "
, blockID
, " -> BlockDefinition (0x"
, showPaddedHexB l
, ", 0x"
, showPaddedHexB u
, ") \""
, blockName
, "\"\n"
, if u == ord maxBound then "_ " else BB.wordDec blockIndex <> "#"
, " -> (# 0x", showPaddedHexB l, "#, 0x", showPaddedHexB u, "#, \""
, blockName -- NOTE: name is ASCII
, "\\0\"# #)\n"
]

-- [NOTE] Encoding: a range is encoded as two LE Word32:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ genNumericValuesModule moduleName = Fold step mempty done
, ""
, "import Data.Ratio ((%))"
, ""
, "{-# NOINLINE numericValue #-}"
, "numericValue :: Char -> Maybe Rational"
, "numericValue = \\case" <> mkEntries values
, " _ -> Nothing"
Expand Down
11 changes: 5 additions & 6 deletions ucd2haskell/exe/UCD2Haskell/Modules/Security/Confusables.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ genConfusablesModule moduleName = Fold step mempty done
mkConfusable c s = mconcat
[ "\n "
, showB c
, " -> Just (Ptr \""
, " -> \""
, stringToAddrLiteral s
, "\\0\"#)"
, "\\0\"#"
]

-- Encode string with UTF-8
Expand All @@ -55,15 +55,14 @@ genConfusablesModule moduleName = Fold step mempty done
, "(confusablePrototype)"
, "where"
, ""
, "import Foreign.C.String (CString)"
, "import GHC.Exts (Ptr(..))"
, "import GHC.Exts (Addr#)"
, ""
, "-- | Returns the /prototype/ of a character, if it is confusable."
, "--"
, "-- The resulting 'CString' is null-terminated and encoded in UTF-8."
, "--"
, "-- @since 0.1.0"
, "confusablePrototype :: Char -> Maybe CString"
, "confusablePrototype :: Char -> Addr#"
, "confusablePrototype = \\case" <> Map.foldMapWithKey mkConfusable confusables
, " _ -> Nothing"
, " _ -> \"\\0\"#"
]
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ generate moduleName = Fold step mempty done
mkConfusable c cs = mconcat
[ "\n "
, showB c
, " -> Just (Ptr \""
, " -> \""
, stringToAddrLiteral (Set.toList cs)
, "\\0\"#)"
, "\\0\"#"
]

-- Encode string with UTF-8
Expand All @@ -55,15 +55,14 @@ generate moduleName = Fold step mempty done
, "(intentionalConfusables)"
, "where"
, ""
, "import Foreign.C.String (CString)"
, "import GHC.Exts (Ptr(..))"
, "import GHC.Exts (Addr#)"
, ""
, "-- | Returns the /intentional/ confusables of a character, if any."
, "--"
, "-- The resulting 'CString' is null-terminated and encoded in UTF-8."
, "--"
, "-- @since 0.1.0"
, "intentionalConfusables :: Char -> Maybe CString"
, "intentionalConfusables :: Char -> Addr#"
, "intentionalConfusables = \\case" <> Map.foldMapWithKey mkConfusable confusables
, " _ -> Nothing"
, " _ -> \"\\0\"#"
]
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ lookupEncodedScriptExtensionsPlanes0To3BitMap n =
!(Ptr offsets1#) = encodedScriptExtensionsPlanes0To3Offsets1BitMap
!(Ptr offsets2#) = encodedScriptExtensionsPlanes0To3Offsets2BitMap

{-# NOINLINE encodedScriptExtensionsPlanes0To3DataBitMap #-}
encodedScriptExtensionsPlanes0To3DataBitMap :: Ptr Int8
encodedScriptExtensionsPlanes0To3DataBitMap = Ptr
"\70\70\24\24\156\156\156\156\82\82\82\82\82\216\82\82\82\82\156\123\123\123\123\123\123\123\123\156\156\156\156\156\156\180\31\180\199\31\175\175\204\202\31\204\204\31\31\203\175\31\
Expand Down Expand Up @@ -200,7 +199,6 @@ encodedScriptExtensionsPlanes0To3DataBitMap = Ptr
\\119\119\119\119\119\119\119\119\89\89\89\89\89\89\89\89\112\112\112\112\112\112\112\112\108\108\108\108\108\108\108\108\111\111\111\111\111\111\111\111\128\128\128\128\128\128\128\128\163\163\
\\163\163\163\163\163\163"#

{-# NOINLINE encodedScriptExtensionsPlanes0To3Offsets1BitMap #-}
encodedScriptExtensionsPlanes0To3Offsets1BitMap :: Ptr Word16
encodedScriptExtensionsPlanes0To3Offsets1BitMap = Ptr
"\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\79\14\117\1\79\14\149\2\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\
Expand Down Expand Up @@ -297,7 +295,6 @@ encodedScriptExtensionsPlanes0To3Offsets1BitMap = Ptr
\\40\9\40\9\40\9\181\5\39\9\36\9\142\5\186\5\34\7\181\5\32\7\181\5\36\9\36\9\137\5\40\9\37\9\40\9\6\4\38\7\37\9\40\9\6\4\117\1\117\1\117\1\117\1\117\1\117\1\8\4\117\1\6\11\117\1\163\4\163\4\163\4\163\4\163\4\99\0\163\4\92\1\129\5\117\1\97\0\117\1\117\1\117\1\117\1\117\1\117\1\
\\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\117\1\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\163\4\79\8\163\4\163\4\163\4\163\4\163\4\163\4\90\1\117\1\117\1\117\1\117\1\163\4\91\1"#

{-# NOINLINE encodedScriptExtensionsPlanes0To3Offsets2BitMap #-}
encodedScriptExtensionsPlanes0To3Offsets2BitMap :: Ptr Word16
encodedScriptExtensionsPlanes0To3Offsets2BitMap = Ptr
"\141\0\19\1\28\1\229\9\135\7\161\7\164\6\5\10\37\10\69\10\101\10\133\10\165\10\197\10\229\10\5\11\37\11\69\11\234\8\8\9\122\3\122\3\138\3\101\11\133\11\165\11\197\11\229\11\5\12\172\0\19\1\37\12\71\9\238\3\174\1\174\1\162\1\174\1\174\1\174\1\69\12\174\1\174\1\212\4\101\12\107\7\166\5\100\1\133\12\165\12\
Expand Down Expand Up @@ -331,12 +328,10 @@ lookupEncodedScriptExtensionsPlane14BitMap n =
!(Ptr data#) = encodedScriptExtensionsPlane14DataBitMap
!(Ptr offsets#) = encodedScriptExtensionsPlane14OffsetsBitMap

{-# NOINLINE encodedScriptExtensionsPlane14DataBitMap #-}
encodedScriptExtensionsPlane14DataBitMap :: Ptr Int8
encodedScriptExtensionsPlane14DataBitMap = Ptr
"\156\24\156\156\156\156\156\156\156\156\24\24\24\24\24\24\24\24\55\55\55\55\55\55\55\55"#

{-# NOINLINE encodedScriptExtensionsPlane14OffsetsBitMap #-}
encodedScriptExtensionsPlane14OffsetsBitMap :: Ptr Word8
encodedScriptExtensionsPlane14OffsetsBitMap = Ptr
"\0\2\2\2\10\10\10\10\10\10\10\10\10\10\10\10\2\2\2\2\2\2\2\2\2\2\2\2\2\2\2\2\18\18\18\18\18\18\18\18\18\18\18\18\18\18\18\18\18\18\
Expand Down
3 changes: 0 additions & 3 deletions unicode-data-scripts/lib/Unicode/Internal/Char/Scripts.hs
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,6 @@ lookupScriptPlanes0To1BitMap n =
!(Ptr offsets1#) = scriptPlanes0To1Offsets1BitMap
!(Ptr offsets2#) = scriptPlanes0To1Offsets2BitMap

{-# NOINLINE scriptPlanes0To1DataBitMap #-}
scriptPlanes0To1DataBitMap :: Ptr Int8
scriptPlanes0To1DataBitMap = Ptr
"\49\49\49\49\49\49\49\49\156\156\156\156\156\156\123\123\123\123\123\123\123\123\156\156\156\156\156\156\70\70\24\24\156\156\156\156\143\143\143\143\143\143\143\143\156\156\156\156\156\55\
Expand Down Expand Up @@ -674,7 +673,6 @@ scriptPlanes0To1DataBitMap = Ptr
\\119\119\119\119\119\119\119\89\89\89\89\89\89\89\89\112\112\112\112\112\112\112\112\108\108\108\108\108\108\108\108\111\111\111\111\111\111\111\111\128\128\128\128\128\128\128\128\163\163\163\
\\163\163\163\163\163"#

{-# NOINLINE scriptPlanes0To1Offsets1BitMap #-}
scriptPlanes0To1Offsets1BitMap :: Ptr Word16
scriptPlanes0To1Offsets1BitMap = Ptr
"\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\56\11\200\3\56\11\103\11\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\
Expand Down Expand Up @@ -767,7 +765,6 @@ scriptPlanes0To1Offsets1BitMap = Ptr
\\114\4\114\4\114\4\96\3\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\96\3\200\3\114\4\115\4\46\5\114\4\46\5\114\4\46\5\114\4\114\4\114\4\116\4\200\3\131\10\200\3\114\4\114\4\114\4\114\4\114\4\96\3\114\4\35\4\34\4\200\3\116\4\200\3\200\3\200\3\200\3\200\3\200\3\200\3\
\\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\200\3\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\114\4\78\3\114\4\114\4\114\4\114\4\114\4\114\4\33\4\200\3\200\3\200\3\200\3\114\4\45\13"#

{-# NOINLINE scriptPlanes0To1Offsets2BitMap #-}
scriptPlanes0To1Offsets2BitMap :: Ptr Word16
scriptPlanes0To1Offsets2BitMap = Ptr
"\137\0\254\0\7\1\192\0\91\7\117\7\120\6\124\9\156\9\188\9\220\9\252\9\28\10\60\10\92\10\124\10\156\10\188\10\129\8\159\8\79\3\79\3\95\3\220\10\252\10\28\11\60\11\92\11\124\11\168\0\254\0\222\0\222\8\225\3\81\1\81\1\69\1\81\1\81\1\81\1\156\11\81\1\81\1\217\1\188\11\63\7\176\5\220\11\252\11\199\4\
Expand Down
2 changes: 2 additions & 0 deletions unicode-data-security/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## 0.2.1 TBD

- Changed the type of `confusablePrototype` and `intentionalConfusables` from
`Char -> Maybe String` to `Char -> String`.
- Add `unicodeVersion` to `Unicode.Char.Identifiers.Security`.

## 0.2.0 (September 2022)
Expand Down
13 changes: 7 additions & 6 deletions unicode-data-security/bench/Main.hs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{-# LANGUAGE ExistentialQuantification #-}

import Control.DeepSeq (NFData, deepseq)
import Data.Ix (Ix(..))
import Test.Tasty.Bench (Benchmark, bgroup, bcompare, bench, nf, defaultMain)
import Data.Ix (Ix (..))
import GHC.Exts (Ptr (..))
import Test.Tasty.Bench (Benchmark, bcompare, bench, bgroup, defaultMain, nf)

import qualified Unicode.Char.Identifiers.Security as Security
import qualified Unicode.Internal.Char.Security.Confusables as Confusables
Expand All @@ -18,19 +19,19 @@ main :: IO ()
main = defaultMain
[ bgroup "Unicode.Char.Identifiers.Security"
[ bgroup "Identifier Status"
[ benchNF "isAllowedInIdentifier" (show . Security.isAllowedInIdentifier)
[ benchNF "isAllowedInIdentifier" Security.isAllowedInIdentifier
]
, bgroup "Identifier Types"
[ benchNF "identifierTypes" (show . Security.identifierTypes)
[ benchNF "identifierTypes" (fmap fromEnum . Security.identifierTypes)
]
, bgroup "Confusables"
[ bgroup' "confusablePrototype"
[ Bench "CString" Confusables.confusablePrototype
[ Bench "CString" (\c -> Ptr (Confusables.confusablePrototype c))
, Bench "String" Security.confusablePrototype
]
-- , benchNF "prototype" Security.prototype
, bgroup' "intentionalConfusables"
[ Bench "CString" Confusables.intentionalConfusables
[ Bench "CString" (\c -> Ptr (Confusables.intentionalConfusables c))
, Bench "String" Security.intentionalConfusables
]
, benchNF "isIntentionallyConfusable" Security.intentionalConfusables
Expand Down
23 changes: 10 additions & 13 deletions unicode-data-security/lib/Unicode/Char/Identifiers/Security.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,10 @@ module Unicode.Char.Identifiers.Security
)
where

import Data.List.NonEmpty (NonEmpty)
import Data.Maybe (isJust)
import qualified GHC.Foreign as Foreign
import qualified GHC.IO.Encoding as Encoding
import System.IO.Unsafe (unsafePerformIO)
import Data.List.NonEmpty (NonEmpty)
import GHC.Exts (eqChar#, indexCharOffAddr#, isTrue#)

import Unicode.Internal.Bits.Security (unpackCStringUtf8#)
import qualified Unicode.Internal.Char.Security.Confusables as C
import qualified Unicode.Internal.Char.Security.IdentifierStatus as S
import qualified Unicode.Internal.Char.Security.IdentifierType as T
Expand Down Expand Up @@ -76,10 +74,8 @@ identifierTypes = T.decodeIdentifierTypes . T.identifierTypes
--
-- @since 0.1.0
{-# INLINE confusablePrototype #-}
confusablePrototype :: Char -> Maybe String
confusablePrototype = fmap decode . C.confusablePrototype
where
decode = unsafePerformIO . Foreign.peekCString Encoding.utf8
confusablePrototype :: Char -> String
confusablePrototype c = unpackCStringUtf8# (C.confusablePrototype c)

-- [TODO] Assess the need for this function
-- -- | Returns the /prototype/ of a character.
Expand All @@ -96,13 +92,14 @@ confusablePrototype = fmap decode . C.confusablePrototype
-- @since 0.1.0
{-# INLINE intentionalConfusables #-}
intentionalConfusables :: Char -> String
intentionalConfusables = maybe mempty decode . IC.intentionalConfusables
where
decode = unsafePerformIO . Foreign.peekCString Encoding.utf8
intentionalConfusables c = unpackCStringUtf8# (IC.intentionalConfusables c)

-- | Returns 'True' if the character is /intentionally/ confusable.
--
-- @since 0.1.0
{-# INLINE isIntentionallyConfusable #-}
isIntentionallyConfusable :: Char -> Bool
isIntentionallyConfusable = isJust . IC.intentionalConfusables
isIntentionallyConfusable c = isTrue# (c# `eqChar#` '\0'#)
where
!addr = IC.intentionalConfusables c
!c# = indexCharOffAddr# addr 0#
Loading
Loading