Skip to content

Commit

Permalink
Merge pull request #3 from haskell/index-and-write-word16-array
Browse files Browse the repository at this point in the history
Index and write word16 array
  • Loading branch information
hasufell authored Dec 2, 2023
2 parents 13d2830 + e0b6a51 commit ccfab36
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 50 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
ghc: ['8.0', '8.2', '8.4', '8.6', '8.8', '8.10', '9.0', '9.2', '9.4', '9.6', '9.8']
ghc: ['8.6', '8.8', '8.10', '9.0', '9.2', '9.4', '9.6', '9.8']
cabal: ['3.8.1.0']
include:
- os: macOS-latest
Expand Down
62 changes: 19 additions & 43 deletions System/OsString/Data/ByteString/Short/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE UnliftedFFITypes #-}

-- Required for WORDS_BIGENDIAN
#include <ghcautoconf.h>

-- |
-- Module : System.OsString.Data.ByteString.Short.Internal
-- Copyright : © 2022 Julian Ospald
Expand All @@ -21,7 +24,6 @@ module System.OsString.Data.ByteString.Short.Internal where

import Control.Monad.ST
import Control.Exception (assert, throwIO)
import Data.Bits (Bits(..))
import Data.ByteString.Short.Internal (ShortByteString(..), length)
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup
Expand Down Expand Up @@ -282,64 +284,38 @@ packLenWord16Rev len ws0 =
go mba (i - 2) ws


-- | This isn't strictly Word16 array write. Instead it's two consecutive Word8 array
-- writes to avoid endianness issues due to primops doing automatic alignment based
-- on host platform. We want to always write LE to the byte array.
-- | Encode Word16 as little-endian.
writeWord16Array :: MBA s
-> Int -- ^ Word8 index (not Word16)
-> Word16
-> ST s ()
writeWord16Array (MBA# mba#) (I# i#) (W16# w#) =
case encodeWord16LE# w# of
(# lsb#, msb# #) ->
ST (\s -> case writeWord8Array# mba# i# lsb# s of
s' -> (# s', () #)) >>
ST (\s -> case writeWord8Array# mba# (i# +# 1#) msb# s of
s' -> (# s', () #))
writeWord16Array (MBA# mba#) (I# i#) (W16# w#) = ST $ \s ->
case writeWord8ArrayAsWord16# mba# i# (word16ToLE# w#) s of
s' -> (# s', () #)

indexWord8Array :: BA
-> Int -- ^ Word8 index
-> Word8
indexWord8Array (BA# ba#) (I# i#) = W8# (indexWord8Array# ba# i#)

-- | This isn't strictly Word16 array read. Instead it's two Word8 array reads
-- to avoid endianness issues due to primops doing automatic alignment based
-- on host platform. We expect the byte array to be LE always.
-- | Decode Word16 from little-endian.
indexWord16Array :: BA
-> Int -- ^ Word8 index (not Word16)
-> Word16
indexWord16Array ba i = fromIntegral lsb .|. (fromIntegral msb `shiftL` 8)
where
lsb = indexWord8Array ba i
msb = indexWord8Array ba (i + 1)

#if !MIN_VERSION_base(4,16,0)

encodeWord16LE# :: Word# -- ^ Word16
-> (# Word#, Word# #) -- ^ Word8 (LSB, MSB)
encodeWord16LE# x# = (# x# `and#` int2Word# 0xff#
, x# `and#` int2Word# 0xff00# `shiftRL#` 8# #)

decodeWord16LE# :: (# Word#, Word# #) -- ^ Word8 (LSB, MSB)
-> Word# -- ^ Word16
decodeWord16LE# (# lsb#, msb# #) = msb# `shiftL#` 8# `or#` lsb#
indexWord16Array (BA# ba#) (I# i#) =
W16# (word16FromLE# (indexWord8ArrayAsWord16# ba# i#))

#if MIN_VERSION_base(4,16,0)
word16ToLE#, word16FromLE# :: Word16# -> Word16#
#else

encodeWord16LE# :: Word16# -- ^ Word16
-> (# Word8#, Word8# #) -- ^ Word8 (LSB, MSB)
encodeWord16LE# x# = (# word16ToWord8# x#
, word16ToWord8# (x# `uncheckedShiftRLWord16#` 8#) #)
where
word16ToWord8# y = wordToWord8# (word16ToWord# y)

decodeWord16LE# :: (# Word8#, Word8# #) -- ^ Word8 (LSB, MSB)
-> Word16# -- ^ Word16
decodeWord16LE# (# lsb#, msb# #) = ((word8ToWord16# msb# `uncheckedShiftLWord16#` 8#) `orWord16#` word8ToWord16# lsb#)
where
word8ToWord16# y = wordToWord16# (word8ToWord# y)

word16ToLE#, word16FromLE# :: Word# -> Word#
#endif
#ifdef WORDS_BIGENDIAN
word16ToLE# = byteSwap16#
#else
word16ToLE# w# = w#
#endif
word16FromLE# = word16ToLE#

setByteArray :: MBA s -> Int -> Int -> Int -> ST s ()
setByteArray (MBA# dst#) (I# off#) (I# len#) (I# c#) =
Expand Down
12 changes: 6 additions & 6 deletions os-string.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ category: System
build-type: Simple
synopsis: Library for manipulating Operating system strings.
tested-with:
GHC ==8.0.2
|| ==8.2.2
|| ==8.4.4
|| ==8.6.5
GHC ==8.6.5
|| ==8.8.4
|| ==8.10.7
|| ==9.0.2
|| ==9.2.3
|| ==9.2.8
|| ==9.4.8
|| ==9.6.3
|| ==9.8.1

description:
This package provides functionality for manipulating @OsString@ values, and is shipped with <https://www.haskell.org/ghc/ GHC>.
Expand Down Expand Up @@ -63,7 +63,7 @@ library

default-language: Haskell2010
build-depends:
, base >=4.9 && <4.20
, base >=4.12.0.0 && <4.20
, bytestring >=0.11.3.0
, deepseq
, exceptions
Expand Down

0 comments on commit ccfab36

Please sign in to comment.