1{-# LANGUAGE CPP, MagicHash, UnboxedTuples #-}
3-- Module : Data.Text.Unsafe
4-- Copyright : (c) 2009, 2010, 2011 Bryan O'Sullivan
6-- Maintainer : bos@serpentine.com
7-- Stability : experimental
8-- Portability : portable
10-- A module containing unsafe 'Text' operations, for very very careful
11-- use in heavily tested code.
12module Data.Text.Unsafe
16 , unsafeDupablePerformIO
30import Control.Exception (assert)
32import Data.Text.Internal.Encoding.Utf16 (chr2)
33import Data.Text.Internal (Text(..))
34import Data.Text.Internal.Unsafe (inlineInterleaveST, inlinePerformIO)
35import Data.Text.Internal.Unsafe.Char (unsafeChr)
36import qualified Data.Text.Array as A
37import GHC.IO (unsafeDupablePerformIO)
39-- | /O(1)/ A variant of 'head' for non-empty 'Text'. 'unsafeHead'
40-- omits the check for the empty case, so there is an obligation on
41-- the programmer to provide a proof that the 'Text' is non-empty.
42unsafeHead :: Text -> Char
43unsafeHead (Text arr off _len)
44 | m < 0xD800 || m > 0xDBFF = unsafeChr m
45 | otherwise = chr2 m n
46 where m = A.unsafeIndex arr off
47 n = A.unsafeIndex arr (off+1)
48{-# INLINE unsafeHead #-}
50-- | /O(1)/ A variant of 'tail' for non-empty 'Text'. 'unsafeTail'
51-- omits the check for the empty case, so there is an obligation on
52-- the programmer to provide a proof that the 'Text' is non-empty.
53unsafeTail :: Text -> Text
54unsafeTail t@(Text arr off len) =
58 Text arr (off+d) (len-d)
60{-# INLINE unsafeTail #-}
62data Iter = Iter {-# UNPACK #-} !Char {-# UNPACK #-} !Int
64-- | /O(1)/ Iterate (unsafely) one step forwards through a UTF-16
65-- array, returning the current character and the delta to add to give
66-- the next offset to iterate at.
67iter :: Text -> Int -> Iter
68iter (Text arr off _len) i
69 | m < 0xD800 || m > 0xDBFF = Iter (unsafeChr m) 1
70 | otherwise = Iter (chr2 m n) 2
71 where m = A.unsafeIndex arr j
72 n = A.unsafeIndex arr k
77-- | /O(1)/ Iterate one step through a UTF-16 array, returning the
78-- delta to add to give the next offset to iterate at.
79iter_ :: Text -> Int -> Int
80iter_ (Text arr off _len) i | m < 0xD800 || m > 0xDBFF = 1
82 where m = A.unsafeIndex arr (off+i)
85-- | /O(1)/ Iterate one step backwards through a UTF-16 array,
86-- returning the current character and the delta to add (i.e. a
87-- negative number) to give the next offset to iterate at.
88reverseIter :: Text -> Int -> (Char,Int)
89reverseIter (Text arr off _len) i
90 | m < 0xDC00 || m > 0xDFFF = (unsafeChr m, -1)
91 | otherwise = (chr2 n m, -2)
92 where m = A.unsafeIndex arr j
93 n = A.unsafeIndex arr k
96{-# INLINE reverseIter #-}
98-- | /O(1)/ Iterate one step backwards through a UTF-16 array,
99-- returning the delta to add (i.e. a negative number) to give the
100-- next offset to iterate at.
101reverseIter_ :: Text -> Int -> Int
102reverseIter_ (Text arr off _len) i
103 | m < 0xDC00 || m > 0xDFFF = -1
105 where m = A.unsafeIndex arr (off+i)
106{-# INLINE reverseIter_ #-}
108-- | /O(1)/ Return the length of a 'Text' in units of 'Word16'. This
109-- is useful for sizing a target array appropriately before using
111lengthWord16 :: Text -> Int
112lengthWord16 (Text _arr _off len) = len
113{-# INLINE lengthWord16 #-}
115-- | /O(1)/ Unchecked take of 'k' 'Word16's from the front of a 'Text'.
116takeWord16 :: Int -> Text -> Text
117takeWord16 k (Text arr off _len) = Text arr off k
118{-# INLINE takeWord16 #-}
120-- | /O(1)/ Unchecked drop of 'k' 'Word16's from the front of a 'Text'.
121dropWord16 :: Int -> Text -> Text
122dropWord16 k (Text arr off len) = Text arr (off+k) (len-k)
123{-# INLINE dropWord16 #-}
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list