summaryrefslogtreecommitdiff
path: root/testsuite/tests/ghc-regress/eyeball/T3116.hs
blob: ba2439c897081a80c5b24241166bfa2f848dbefc (plain)
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
{-# OPTIONS -O2 -XBangPatterns #-}

-- The thing to look for here is that the implementation
-- of 'length' does not allocate in the inner loop
--
-- See Trac #3116

module T3116 where

import Foreign

data SByteString
   = BS  {-# UNPACK #-} !(ForeignPtr Word8)  -- payload
         {-# UNPACK #-} !Int                 -- offset
         {-# UNPACK #-} !Int                 -- length

data ByteString
    =  Empty
    |  Chunk {-# UNPACK #-} !SByteString ByteString

bnull :: ByteString -> Bool
bnull Empty = True
bnull _     = False

btail :: ByteString -> ByteString
btail Empty = error "empty tail"
btail (Chunk (BS fp s 1) cs) = cs
btail (Chunk (BS fp s l) cs) = Chunk (BS fp (s+1) (l-1)) cs

length :: ByteString -> Int
length = go 0
  where
    go !n bs  | bnull bs   = n
              | otherwise  = go (n+1) (btail bs)