@@ -23,6 +23,9 @@ module Data.Text.Foreign
2323 -- * Unsafe conversion code
2424 , lengthWord16
2525 , unsafeCopyToPtr
26+ -- * Low-level manipulation
27+ , dropWord16
28+ , takeWord16
2629 ) where
2730
2831#if defined(ASSERTS)
@@ -76,6 +79,38 @@ lengthWord16 :: Text -> Int
7679lengthWord16 (Text _arr _off len) = len
7780{-# INLINE lengthWord16 #-}
7881
82+-- | /O(1)/ Return the prefix of the 'Text' of @n@ 'Word16' units in
83+-- length.
84+--
85+-- If @n@ would cause the 'Text' to end inside a surrogate pair, the
86+-- end of the prefix will be advanced by one additional 'Word16' unit
87+-- to maintain its validity.
88+takeWord16 :: Int -> Text -> Text
89+takeWord16 n t@(Text arr off len)
90+ | n <= 0 = empty
91+ | n >= len || m >= len = t
92+ | otherwise = Text arr off m
93+ where
94+ m | w < 0xDB00 || w > 0xD8FF = n
95+ | otherwise = n+1
96+ w = A.unsafeIndex arr (off+n-1)
97+
98+-- | /O(1)/ Return the suffix of the 'Text', with @n@ 'Word16' units
99+-- dropped from its beginning.
100+--
101+-- If @n@ would cause the 'Text' to begin inside a surrogate pair, the
102+-- beginning of the suffix will be advanced by one additional 'Word16'
103+-- unit to maintain its validity.
104+dropWord16 :: Int -> Text -> Text
105+dropWord16 n t@(Text arr off len)
106+ | n <= 0 = t
107+ | n >= len || m >= len = empty
108+ | otherwise = Text arr (off+m) (len-m)
109+ where
110+ m | w < 0xD800 || w > 0xDBFF = n
111+ | otherwise = n+1
112+ w = A.unsafeIndex arr (off+n-1)
113+
79114-- | /O(n)/ Copy a 'Text' to an array. The array is assumed to be big
80115-- enough to hold the contents of the entire 'Text'.
81116unsafeCopyToPtr :: Text -> Ptr Word16 -> IO ()