on builder help sign in
text/Data/Text/Internal.hs
103 lines 3.1 kB history raw
1{-# LANGUAGE CPP, DeriveDataTypeable #-}
3-- |
4-- Module : Data.Text.Internal
5-- Copyright : (c) 2008, 2009 Tom Harper,
6-- (c) 2009, 2010 Bryan O'Sullivan,
7-- (c) 2009 Duncan Coutts
8--
9-- License : BSD-style
10-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
11-- duncan@haskell.org
12-- Stability : experimental
13-- Portability : GHC
14--
15-- A module containing private 'Text' internals. This exposes the
16-- 'Text' representation and low level construction functions.
17-- Modules which extend the 'Text' system may need to use this module.
18--
19-- You should not use this module unless you are determined to monkey
20-- with the internals, as the functions here do just about nothing to
21-- preserve data invariants. You have been warned!
23module Data.Text.Internal
24 (
25 -- * Types
26 Text(..)
27 -- * Construction
28 , text
29 , textP
30 -- * Safety
31 , safe
32 -- * Code that must be here for accessibility
33 , empty
34 -- * Utilities
35 , firstf
36 -- * Debugging
37 , showText
38 ) where
40#if defined(ASSERTS)
41import Control.Exception (assert)
42#endif
43import Data.Bits ((.&.))
44import qualified Data.Text.Array as A
45import Data.Text.UnsafeChar (ord)
46import Data.Typeable (Typeable)
48-- | A space efficient, packed, unboxed Unicode text type.
49data Text = Text
50 {-# UNPACK #-} !A.Array -- payload
51 {-# UNPACK #-} !Int -- offset
52 {-# UNPACK #-} !Int -- length
53 deriving (Typeable)
55-- | Smart constructor.
56text :: A.Array -> Int -> Int -> Text
57text arr off len =
58#if defined(ASSERTS)
59 let c = A.unsafeIndex arr off
60 alen = A.length arr
61 in assert (len >= 0) .
62 assert (off >= 0) .
63 assert (alen == 0 || len == 0 || off < alen) .
64 assert (len == 0 || c < 0xDC00 || c > 0xDFFF) $
65#endif
66 Text arr off len
67{-# INLINE text #-}
69-- | /O(1)/ The empty 'Text'.
70empty :: Text
71empty = Text A.empty 0 0
72{-# INLINE [1] empty #-}
74-- | Construct a 'Text' without invisibly pinning its byte array in
75-- memory if its length has dwindled to zero.
76textP :: A.Array -> Int -> Int -> Text
77textP arr off len | len == 0 = empty
78 | otherwise = text arr off len
79{-# INLINE textP #-}
81-- | A useful 'show'-like function for debugging purposes.
82showText :: Text -> String
83showText (Text arr off len) =
84 "Text " ++ show (A.toList arr off len) ++ ' ' :
85 show off ++ ' ' : show len
87-- | Map a 'Char' to a 'Text'-safe value.
88--
89-- UTF-16 surrogate code points are not included in the set of Unicode
90-- scalar values, but are unfortunately admitted as valid 'Char'
91-- values by Haskell. They cannot be represented in a 'Text'. This
92-- function remaps those code points to the Unicode replacement
93-- character \"&#xfffd;\", and leaves other code points unchanged.
94safe :: Char -> Char
95safe c
96 | ord c .&. 0x1ff800 /= 0xd800 = c
97 | otherwise = '\xfffd'
98{-# INLINE safe #-}
100-- | Apply a function to the first element of an optional pair.
101firstf :: (a -> c) -> Maybe (a,b) -> Maybe (c,b)
102firstf f (Just (a, b)) = Just (f a, b)
103firstf _ Nothing = Nothing