content: {-# LANGUAGE Safe #-}
  
  -- |
  -- Module      :  Text.Megaparsec.Unicode
  -- Copyright   :  © 2024–present Megaparsec contributors
  -- License     :  FreeBSD
  --
  -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>
  -- Stability   :  experimental
  -- Portability :  portable
  --
  -- Utility functions for working with Unicode.
  --
  -- @since 9.7.0
  module Text.Megaparsec.Unicode
    ( stringLength,
      charLength,
      isWideChar,
    )
  where
  
  import Data.Array (Array, bounds, listArray, (!))
  import Data.Char (ord)
  
  -- | Calculate length of a string taking into account the fact that certain
  -- 'Char's may span more than 1 column.
  --
  -- @since 9.7.0
  stringLength :: (Traversable t) => t Char -> Int
  stringLength = sum . fmap charLength
  
  -- | Return length of an individual 'Char'.
  --
  -- @since 9.7.0
  charLength :: Char -> Int
  charLength ch = if isWideChar ch then 2 else 1
  
  -- | Determine whether the given 'Char' is “wide”, that is, whether it spans
  -- 2 columns instead of one.
  --
  -- @since 9.7.0
  isWideChar :: Char -> Bool
  isWideChar c = go (bounds wideCharRanges)
    where
      go (lo, hi)
        | hi < lo = False
        | a <= n && n <= b = True
        | n < a = go (lo, pred mid)
        | otherwise = go (succ mid, hi)
        where
          mid = (lo + hi) `div` 2
          (a, b) = wideCharRanges ! mid
      n = ord c
  
  -- | Wide character ranges.
  wideCharRanges :: Array Int (Int, Int)
  wideCharRanges =
    listArray
      (0, 118)
      [ (0x001100, 0x00115f),
        (0x00231a, 0x00231b),
        (0x002329, 0x00232a),
        (0x0023e9, 0x0023ec),
        (0x0023f0, 0x0023f0),
        (0x0023f3, 0x0023f3),
        (0x0025fd, 0x0025fe),
        (0x002614, 0x002615),
        (0x002648, 0x002653),
        (0x00267f, 0x00267f),
        (0x002693, 0x002693),
        (0x0026a1, 0x0026a1),
        (0x0026aa, 0x0026ab),
        (0x0026bd, 0x0026be),
        (0x0026c4, 0x0026c5),
        (0x0026ce, 0x0026ce),
        (0x0026d4, 0x0026d4),
        (0x0026ea, 0x0026ea),
        (0x0026f2, 0x0026f3),
        (0x0026f5, 0x0026f5),
        (0x0026fa, 0x0026fa),
        (0x0026fd, 0x0026fd),
        (0x002705, 0x002705),
        (0x00270a, 0x00270b),
        (0x002728, 0x002728),
        (0x00274c, 0x00274c),
        (0x00274e, 0x00274e),
        (0x002753, 0x002755),
        (0x002757, 0x002757),
        (0x002795, 0x002797),
        (0x0027b0, 0x0027b0),
        (0x0027bf, 0x0027bf),
        (0x002b1b, 0x002b1c),
        (0x002b50, 0x002b50),
        (0x002b55, 0x002b55),
        (0x002e80, 0x002e99),
        (0x002e9b, 0x002ef3),
        (0x002f00, 0x002fd5),
        (0x002ff0, 0x002ffb),
        (0x003000, 0x00303e),
        (0x003041, 0x003096),
        (0x003099, 0x0030ff),
        (0x003105, 0x00312f),
        (0x003131, 0x00318e),
        (0x003190, 0x0031ba),
        (0x0031c0, 0x0031e3),
        (0x0031f0, 0x00321e),
        (0x003220, 0x003247),
        (0x003250, 0x004db5),
        (0x004e00, 0x009fef),
        (0x00a000, 0x00a48c),
        (0x00a490, 0x00a4c6),
        (0x00a960, 0x00a97c),
        (0x00ac00, 0x00d7a3),
        (0x00f900, 0x00fa6d),
        (0x00fa70, 0x00fad9),
        (0x00fe10, 0x00fe19),
        (0x00fe30, 0x00fe52),
        (0x00fe54, 0x00fe66),
        (0x00fe68, 0x00fe6b),
        (0x00ff01, 0x00ff60),
        (0x00ffe0, 0x00ffe6),
        (0x016fe0, 0x016fe3),
        (0x017000, 0x0187f7),
        (0x018800, 0x018af2),
        (0x01b000, 0x01b11e),
        (0x01b150, 0x01b152),
        (0x01b164, 0x01b167),
        (0x01b170, 0x01b2fb),
        (0x01f004, 0x01f004),
        (0x01f0cf, 0x01f0cf),
        (0x01f18e, 0x01f18e),
        (0x01f191, 0x01f19a),
        (0x01f200, 0x01f202),
        (0x01f210, 0x01f23b),
        (0x01f240, 0x01f248),
        (0x01f250, 0x01f251),
        (0x01f260, 0x01f265),
        (0x01f300, 0x01f320),
        (0x01f32d, 0x01f335),
        (0x01f337, 0x01f37c),
        (0x01f37e, 0x01f393),
        (0x01f3a0, 0x01f3ca),
        (0x01f3cf, 0x01f3d3),
        (0x01f3e0, 0x01f3f0),
        (0x01f3f4, 0x01f3f4),
        (0x01f3f8, 0x01f43e),
        (0x01f440, 0x01f440),
        (0x01f442, 0x01f4fc),
        (0x01f4ff, 0x01f53d),
        (0x01f54b, 0x01f54e),
        (0x01f550, 0x01f567),
        (0x01f57a, 0x01f57a),
        (0x01f595, 0x01f596),
        (0x01f5a4, 0x01f5a4),
        (0x01f5fb, 0x01f64f),
        (0x01f680, 0x01f6c5),
        (0x01f6cc, 0x01f6cc),
        (0x01f6d0, 0x01f6d2),
        (0x01f6d5, 0x01f6d5),
        (0x01f6eb, 0x01f6ec),
        (0x01f6f4, 0x01f6fa),
        (0x01f7e0, 0x01f7eb),
        (0x01f90d, 0x01f971),
        (0x01f973, 0x01f976),
        (0x01f97a, 0x01f9a2),
        (0x01f9a5, 0x01f9aa),
        (0x01f9ae, 0x01f9ca),
        (0x01f9cd, 0x01f9ff),
        (0x01fa70, 0x01fa73),
        (0x01fa78, 0x01fa7a),
        (0x01fa80, 0x01fa82),
        (0x01fa90, 0x01fa95),
        (0x020000, 0x02a6d6),
        (0x02a700, 0x02b734),
        (0x02b740, 0x02b81d),
        (0x02b820, 0x02cea1),
        (0x02ceb0, 0x02ebe0),
        (0x02f800, 0x02fa1d)
      ]
  {-# NOINLINE wideCharRanges #-}
  