on builder help sign in
text/Data/Text/Lazy/Internal.hs
118 lines 3.7 kB history raw
1{-# LANGUAGE BangPatterns, DeriveDataTypeable #-}
2-- |
3-- Module : Data.Text.Lazy.Internal
4-- Copyright : (c) 2009, 2010 Bryan O'Sullivan
5--
6-- License : BSD-style
7-- Maintainer : bos@serpentine.com, rtomharper@googlemail.com,
8-- duncan@haskell.org
9-- Stability : experimental
10-- Portability : GHC
11--
12-- A module containing private 'Text' internals. This exposes the
13-- 'Text' representation and low level construction functions.
14-- Modules which extend the 'Text' system may need to use this module.
15--
16-- You should not use this module unless you are determined to monkey
17-- with the internals, as the functions here do just about nothing to
18-- preserve data invariants. You have been warned!
20module Data.Text.Lazy.Internal
21 (
22 Text(..)
23 , chunk
24 , empty
25 , foldrChunks
26 , foldlChunks
27 -- * Data type invariant and abstraction functions
29 -- $invariant
30 , strictInvariant
31 , lazyInvariant
32 , showStructure
34 -- * Chunk allocation sizes
35 , defaultChunkSize
36 , smallChunkSize
37 , chunkOverhead
38 ) where
40import Data.Text ()
41import Data.Text.UnsafeShift (shiftL)
42import Data.Typeable (Typeable)
43import Foreign.Storable (sizeOf)
44import qualified Data.Text.Internal as T
46data Text = Empty
47 | Chunk {-# UNPACK #-} !T.Text Text
48 deriving (Typeable)
50-- $invariant
51--
52-- The data type invariant for lazy 'Text': Every 'Text' is either 'Empty' or
53-- consists of non-null 'T.Text's. All functions must preserve this,
54-- and the QC properties must check this.
56-- | Check the invariant strictly.
57strictInvariant :: Text -> Bool
58strictInvariant Empty = True
59strictInvariant x@(Chunk (T.Text _ _ len) cs)
60 | len > 0 = strictInvariant cs
61 | otherwise = error $ "Data.Text.Lazy: invariant violation: "
62 ++ showStructure x
64-- | Check the invariant lazily.
65lazyInvariant :: Text -> Text
66lazyInvariant Empty = Empty
67lazyInvariant x@(Chunk c@(T.Text _ _ len) cs)
68 | len > 0 = Chunk c (lazyInvariant cs)
69 | otherwise = error $ "Data.Text.Lazy: invariant violation: "
70 ++ showStructure x
72-- | Display the internal structure of a lazy 'Text'.
73showStructure :: Text -> String
74showStructure Empty = "Empty"
75showStructure (Chunk t Empty) = "Chunk " ++ show t ++ " Empty"
76showStructure (Chunk t ts) =
77 "Chunk " ++ show t ++ " (" ++ showStructure ts ++ ")"
79-- | Smart constructor for 'Chunk'. Guarantees the data type invariant.
80chunk :: T.Text -> Text -> Text
81{-# INLINE chunk #-}
82chunk t@(T.Text _ _ len) ts | len == 0 = ts
83 | otherwise = Chunk t ts
85-- | Smart constructor for 'Empty'.
86empty :: Text
87{-# INLINE [0] empty #-}
88empty = Empty
90-- | Consume the chunks of a lazy 'Text' with a natural right fold.
91foldrChunks :: (T.Text -> a -> a) -> a -> Text -> a
92foldrChunks f z = go
93 where go Empty = z
94 go (Chunk c cs) = f c (go cs)
95{-# INLINE foldrChunks #-}
97-- | Consume the chunks of a lazy 'Text' with a strict, tail-recursive,
98-- accumulating left fold.
99foldlChunks :: (a -> T.Text -> a) -> a -> Text -> a
100foldlChunks f z = go z
101 where go !a Empty = a
102 go !a (Chunk c cs) = go (f a c) cs
103{-# INLINE foldlChunks #-}
105-- | Currently set to 16 KiB, less the memory management overhead.
106defaultChunkSize :: Int
107defaultChunkSize = 16384 - chunkOverhead
108{-# INLINE defaultChunkSize #-}
110-- | Currently set to 128 bytes, less the memory management overhead.
111smallChunkSize :: Int
112smallChunkSize = 128 - chunkOverhead
113{-# INLINE smallChunkSize #-}
115-- | The memory management overhead. Currently this is tuned for GHC only.
116chunkOverhead :: Int
117chunkOverhead = sizeOf (undefined :: Int) `shiftL` 1
118{-# INLINE chunkOverhead #-}