1{-# LANGUAGE BangPatterns, CPP, GeneralizedNewtypeDeriving #-}
3-- Module : Data.Text.Foreign
4-- Copyright : (c) 2009, 2010 Bryan O'Sullivan
7-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
9-- Stability : experimental
12-- Support for using 'Text' data with native code via the Haskell
13-- foreign function interface.
15module Data.Text.Foreign
17 -- * Interoperability with native code
20 -- * Safe conversion functions
24 -- * Unsafe conversion code
27 -- * Low-level manipulation
34import Control.Exception (assert)
36import Control.Monad.ST (unsafeIOToST)
37import Data.Text.Internal (Text(..), empty)
38import Data.Text.Unsafe (lengthWord16)
39import qualified Data.Text.Array as A
40import Data.Word (Word16)
41import Foreign.Marshal.Alloc (allocaBytes)
42import Foreign.Ptr (Ptr, castPtr, plusPtr)
43import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrArray, withForeignPtr)
44import Foreign.Storable (peek, poke)
48-- The 'Text' type is implemented using arrays that are not guaranteed
49-- to have a fixed address in the Haskell heap. All communication with
50-- native code must thus occur by copying data back and forth.
52-- The 'Text' type's internal representation is UTF-16, using the
53-- platform's native endianness. This makes copied data suitable for
54-- use with native libraries that use a similar representation, such
55-- as ICU. To interoperate with native libraries that use different
56-- internal representations, such as UTF-8 or UTF-32, consider using
57-- the functions in the 'Data.Text.Encoding' module.
59-- | A type representing a number of UTF-16 code units.
61 deriving (Bounded, Enum, Eq, Integral, Num, Ord, Read, Real, Show)
63-- | /O(n)/ Create a new 'Text' from a 'Ptr' 'Word16' by copying the
64-- contents of the array.
65fromPtr :: Ptr Word16 -- ^ source array
66 -> I16 -- ^ length of source array (in 'Word16' units)
68fromPtr _ (I16 0) = return empty
69fromPtr ptr (I16 len) =
73 return $! Text arr 0 len
75 arr = A.run (A.new len >>= copy)
76 copy marr = loop ptr 0
78 loop !p !i | i == len = return marr
80 A.unsafeWrite marr i =<< unsafeIOToST (peek p)
81 loop (p `plusPtr` 2) (i + 1)
85-- Foreign functions that use UTF-16 internally may return indices in
86-- units of 'Word16' instead of characters. These functions may
87-- safely be used with such indices, as they will adjust offsets if
88-- necessary to preserve the validity of a Unicode string.
90-- | /O(1)/ Return the prefix of the 'Text' of @n@ 'Word16' units in
93-- If @n@ would cause the 'Text' to end inside a surrogate pair, the
94-- end of the prefix will be advanced by one additional 'Word16' unit
95-- to maintain its validity.
96takeWord16 :: I16 -> Text -> Text
97takeWord16 (I16 n) t@(Text arr off len)
99 | n >= len || m >= len = t
100 | otherwise = Text arr off m
102 m | w < 0xDB00 || w > 0xD8FF = n
104 w = A.unsafeIndex arr (off+n-1)
106-- | /O(1)/ Return the suffix of the 'Text', with @n@ 'Word16' units
107-- dropped from its beginning.
109-- If @n@ would cause the 'Text' to begin inside a surrogate pair, the
110-- beginning of the suffix will be advanced by one additional 'Word16'
111-- unit to maintain its validity.
112dropWord16 :: I16 -> Text -> Text
113dropWord16 (I16 n) t@(Text arr off len)
115 | n >= len || m >= len = empty
116 | otherwise = Text arr (off+m) (len-m)
118 m | w < 0xD800 || w > 0xDBFF = n
120 w = A.unsafeIndex arr (off+n-1)
122-- | /O(n)/ Copy a 'Text' to an array. The array is assumed to be big
123-- enough to hold the contents of the entire 'Text'.
124unsafeCopyToPtr :: Text -> Ptr Word16 -> IO ()
125unsafeCopyToPtr (Text arr off len) ptr = loop ptr off
128 loop !p !i | i == end = return ()
130 poke p (A.unsafeIndex arr i)
131 loop (p `plusPtr` 2) (i + 1)
133-- | /O(n)/ Perform an action on a temporary, mutable copy of a
134-- 'Text'. The copy is freed as soon as the action returns.
135useAsPtr :: Text -> (Ptr Word16 -> I16 -> IO a) -> IO a
136useAsPtr t@(Text _arr _off len) action =
137 allocaBytes (len * 2) $ \buf -> do
138 unsafeCopyToPtr t buf
139 action (castPtr buf) (fromIntegral len)
141-- | /O(n)/ Make a mutable copy of a 'Text'.
142asForeignPtr :: Text -> IO (ForeignPtr Word16, I16)
143asForeignPtr t@(Text _arr _off len) = do
144 fp <- mallocForeignPtrArray len
145 withForeignPtr fp $ unsafeCopyToPtr t
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