Partially improve the cabalisation
This commit is contained in:
194
Language/Hi/PrimPacked.hs
Normal file
194
Language/Hi/PrimPacked.hs
Normal file
@ -0,0 +1,194 @@
|
||||
{-# OPTIONS -cpp -fglasgow-exts #-}
|
||||
{-# OPTIONS -fno-warn-name-shadowing -fno-warn-unused-matches #-}
|
||||
|
||||
{-# OPTIONS -#include "hschooks.h" #-}
|
||||
|
||||
--
|
||||
-- Copyright (C) 2004 Don Stewart - http://www.cse.unsw.edu.au/~dons
|
||||
--
|
||||
-- This library is free software; you can redistribute it and/or
|
||||
-- modify it under the terms of the GNU Lesser General Public
|
||||
-- License as published by the Free Software Foundation; either
|
||||
-- version 2.1 of the License, or (at your option) any later version.
|
||||
--
|
||||
-- This library is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
-- Lesser General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU Lesser General Public
|
||||
-- License along with this library; if not, write to the Free Software
|
||||
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
-- USA
|
||||
--
|
||||
-- Based on $fptools/ghc/compiler/utils/PrimPacked.lhs
|
||||
--
|
||||
-- (c) The GRASP/AQUA Project, Glasgow University, 1997-1998
|
||||
--
|
||||
--
|
||||
-- Basic ops on packed representations
|
||||
--
|
||||
-- Some basic operations for working on packed representations of series
|
||||
-- of bytes (character strings). Used by the interface lexer input
|
||||
-- subsystem, mostly.
|
||||
|
||||
{-# OPTIONS -optc-DNON_POSIX_SOURCE #-}
|
||||
|
||||
module Language.Hi.PrimPacked (
|
||||
Ptr(..), nullPtr, plusAddr#,
|
||||
BA(..),
|
||||
packString, -- :: String -> (Int, BA)
|
||||
unpackNBytesBA, -- :: BA -> Int -> [Char]
|
||||
strLength, -- :: Ptr CChar -> Int
|
||||
copyPrefixStr, -- :: Addr# -> Int -> BA
|
||||
copySubStrBA, -- :: BA -> Int -> Int -> BA
|
||||
eqStrPrefix, -- :: Addr# -> ByteArray# -> Int# -> Bool
|
||||
eqStrPrefixBA, -- :: ByteArray# -> ByteArray# -> Int# -> Int# -> Bool
|
||||
) where
|
||||
|
||||
import Foreign
|
||||
import GHC.Exts
|
||||
import GHC.ST
|
||||
|
||||
-- Wrapper types for bytearrays
|
||||
|
||||
data BA = BA ByteArray#
|
||||
data MBA s = MBA (MutableByteArray# s)
|
||||
|
||||
packString :: String -> (Int, BA)
|
||||
packString str = (l, arr)
|
||||
where
|
||||
l@(I# length#) = length str
|
||||
|
||||
arr = runST (do
|
||||
ch_array <- new_ps_array length#
|
||||
-- fill in packed string from "str"
|
||||
fill_in ch_array 0# str
|
||||
-- freeze the puppy:
|
||||
freeze_ps_array ch_array length#
|
||||
)
|
||||
|
||||
fill_in :: MBA s -> Int# -> [Char] -> ST s ()
|
||||
fill_in arr_in# idx [] =
|
||||
return ()
|
||||
fill_in arr_in# idx (C# c : cs) =
|
||||
write_ps_array arr_in# idx c >>
|
||||
fill_in arr_in# (idx +# 1#) cs
|
||||
|
||||
-- Unpacking a string
|
||||
|
||||
unpackNBytesBA :: BA -> Int -> [Char]
|
||||
unpackNBytesBA (BA bytes) (I# len)
|
||||
= unpack 0#
|
||||
where
|
||||
unpack nh
|
||||
| nh >=# len = []
|
||||
| otherwise = C# ch : unpack (nh +# 1#)
|
||||
where
|
||||
ch = indexCharArray# bytes nh
|
||||
|
||||
-- Copying a char string prefix into a byte array.
|
||||
|
||||
copyPrefixStr :: Addr# -> Int -> BA
|
||||
copyPrefixStr a# len@(I# length#) = copy' length#
|
||||
where
|
||||
copy' length# = runST (do
|
||||
{- allocate an array that will hold the string
|
||||
-}
|
||||
ch_array <- new_ps_array length#
|
||||
{- Revert back to Haskell-only solution for the moment.
|
||||
_ccall_ memcpy ch_array (A# a) len >>= \ () ->
|
||||
write_ps_array ch_array length# (chr# 0#) >>
|
||||
-}
|
||||
-- fill in packed string from "addr"
|
||||
fill_in ch_array 0#
|
||||
-- freeze the puppy:
|
||||
freeze_ps_array ch_array length#
|
||||
)
|
||||
|
||||
fill_in :: MBA s -> Int# -> ST s ()
|
||||
fill_in arr_in# idx
|
||||
| idx ==# length#
|
||||
= return ()
|
||||
| otherwise
|
||||
= case (indexCharOffAddr# a# idx) of { ch ->
|
||||
write_ps_array arr_in# idx ch >>
|
||||
fill_in arr_in# (idx +# 1#) }
|
||||
|
||||
-- Copying out a substring, assume a 0-indexed string:
|
||||
-- (and positive lengths, thank you).
|
||||
|
||||
copySubStrBA :: BA -> Int -> Int -> BA
|
||||
copySubStrBA (BA barr#) (I# start#) len@(I# length#) = ba
|
||||
where
|
||||
ba = runST (do
|
||||
-- allocate an array that will hold the string
|
||||
ch_array <- new_ps_array length#
|
||||
-- fill in packed string from "addr"
|
||||
fill_in ch_array 0#
|
||||
-- freeze the puppy:
|
||||
freeze_ps_array ch_array length#
|
||||
)
|
||||
|
||||
fill_in :: MBA s -> Int# -> ST s ()
|
||||
fill_in arr_in# idx
|
||||
| idx ==# length#
|
||||
= return ()
|
||||
| otherwise
|
||||
= case (indexCharArray# barr# (start# +# idx)) of { ch ->
|
||||
write_ps_array arr_in# idx ch >>
|
||||
fill_in arr_in# (idx +# 1#) }
|
||||
|
||||
-- (Very :-) ``Specialised'' versions of some CharArray things...
|
||||
-- [Copied from PackBase; no real reason -- UGH]
|
||||
|
||||
new_ps_array :: Int# -> ST s (MBA s)
|
||||
write_ps_array :: MBA s -> Int# -> Char# -> ST s ()
|
||||
freeze_ps_array :: MBA s -> Int# -> ST s BA
|
||||
|
||||
#if __GLASGOW_HASKELL__ < 411
|
||||
#define NEW_BYTE_ARRAY newCharArray#
|
||||
#else
|
||||
#define NEW_BYTE_ARRAY newByteArray#
|
||||
#endif
|
||||
|
||||
new_ps_array size = ST $ \ s ->
|
||||
case (NEW_BYTE_ARRAY size s) of { (# s2#, barr# #) ->
|
||||
(# s2#, MBA barr# #) }
|
||||
|
||||
write_ps_array (MBA barr#) n ch = ST $ \ s# ->
|
||||
case writeCharArray# barr# n ch s# of { s2# ->
|
||||
(# s2#, () #) }
|
||||
|
||||
-- same as unsafeFreezeByteArray
|
||||
freeze_ps_array (MBA arr#) len# = ST $ \ s# ->
|
||||
case unsafeFreezeByteArray# arr# s# of { (# s2#, frozen# #) ->
|
||||
(# s2#, BA frozen# #) }
|
||||
|
||||
-- Compare two equal-length strings for equality:
|
||||
|
||||
eqStrPrefix :: Addr# -> ByteArray# -> Int# -> Bool
|
||||
eqStrPrefix a# barr# len# =
|
||||
unsafePerformIO $ do
|
||||
x <- memcmp_ba a# barr# (I# len#)
|
||||
return (x == 0)
|
||||
|
||||
eqStrPrefixBA :: ByteArray# -> ByteArray# -> Int# -> Int# -> Bool
|
||||
eqStrPrefixBA b1# b2# start# len# =
|
||||
unsafePerformIO $ do
|
||||
x <- memcmp_baoff_ba b2# (I# start#) b1# (I# len#)
|
||||
return (x == 0)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- in hschooks
|
||||
--
|
||||
|
||||
foreign import ccall unsafe "plugin_strlen"
|
||||
strLength :: Ptr () -> Int
|
||||
|
||||
foreign import ccall unsafe "plugin_memcmp"
|
||||
memcmp_ba :: Addr# -> ByteArray# -> Int -> IO Int
|
||||
|
||||
foreign import ccall unsafe "plugin_memcmp_off"
|
||||
memcmp_baoff_ba :: ByteArray# -> Int -> ByteArray# -> Int -> IO Int
|
||||
|
Reference in New Issue
Block a user