~jaro/balkon

ref: 3d78355411f15c6d8ebf001921a5167657992712 balkon/src/Data/Text/ParagraphLayout/TextContainer.hs -rw-r--r-- 1.3 KiB
3d783554Jaro Minimise working with Data.Text.Internal. 1 year, 8 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
module Data.Text.ParagraphLayout.TextContainer
    (TextContainer
    ,getText
    ,splitTextAt8
    ,splitTextsAt8
    )
where

import Data.Text (Text)
import Data.Text.Foreign (I8, lengthWord8)

class TextContainer a where

    -- | Unwrap text from the container.
    getText :: a -> Text

    -- | Split a text container at the given number of `Word8` units
    -- from its beginning.
    splitTextAt8 :: I8 -> a -> (a, a)
    splitTextAt8 _ _ = error "container cannot be split"

-- | Treat a list of text containers as a contiguous sequence,
-- and make a split at the given number of `Word8` from the beginning
-- of this sequence.
--
-- If @n@ falls on a container boundary, the total number of output containers
-- will equal the number of input containers; otherwise, it will be one larger.
splitTextsAt8 :: TextContainer a => I8 -> [a] -> ([a], [a])
splitTextsAt8 n rs = (pre, post)
    where
        pre = reverse rpre
        (rpre, post) = splitTextsAt8' n [] rs

splitTextsAt8' :: TextContainer a => I8 -> [a] -> [a] -> ([a], [a])
splitTextsAt8' _ rpre [] = (rpre, [])
splitTextsAt8' n rpre (r:rs)
    | n <= 0 = (rpre, r:rs)
    | n >= l = splitTextsAt8' (n - l) (r:rpre) (rs)
    | otherwise = let (r1, r2) = splitTextAt8 n r in (r1:rpre, r2:rs)
    where
        l = fromIntegral $ lengthWord8 $ getText r