{-# LANGUAGE MagicHash #-}

-- ---------------------------------------------------------------------------
-- |
-- Module      : Text.Show.ByteString.Util
-- Copyright   : (c) 2008 Dan Doel
-- Maintainer  : Dan Doel
-- Stability   : Experimental
-- Portability : Non-portable (magic hash, GHC libraries)
--
-- Utility functions for producing readable byte strings.

module Text.Show.ByteString.Util ( putAscii
                                 , putUTF8
                                 , putAsciiStr
                                 , putUTF8Str
                                 , unsafePutDigit
                                 , unsafePutDigit#
                                 ) where

import GHC.Base
import GHC.Word

import Data.Binary
import Data.Bits

import Data.ByteString.Internal (c2w)

-- | Writes a single Char to a byte string, assuming it's ascii.
putAscii :: Char -> Put
putAscii :: Char -> Put
putAscii = Word8 -> Put
putWord8 (Word8 -> Put) -> (Char -> Word8) -> Char -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Word8
c2w

-- | Writes a single Char to a byte string, properly UTF-8 encoded
putUTF8 :: Char -> Put
putUTF8 :: Char -> Put
putUTF8 c :: Char
c
  | Int
oc Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 0x7f   = Word8 -> Put
putWord8 (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
oc)
  | Int
oc Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 0x7ff  = do Word8 -> Put
putWord8 (Word8 -> Put) -> (Int -> Word8) -> Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ 0xc0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
oc Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` 6)
                      Word8 -> Put
putWord8 (Word8 -> Put) -> (Int -> Word8) -> Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ 0x80 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
oc Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. 0x3f
  | Int
oc Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= 0xffff = do Word8 -> Put
putWord8 (Word8 -> Put) -> (Int -> Word8) -> Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ 0xf0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
oc Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` 12)
                      Word8 -> Put
putWord8 (Word8 -> Put) -> (Int -> Word8) -> Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ 0x80 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ((Int
oc Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` 6) Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. 0x3f)
                      Word8 -> Put
putWord8 (Word8 -> Put) -> (Int -> Word8) -> Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ 0x80 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
oc Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. 0x3f
  | Bool
otherwise    = do Word8 -> Put
putWord8 (Word8 -> Put) -> (Int -> Word8) -> Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ 0xf0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
oc Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` 18)
                      Word8 -> Put
putWord8 (Word8 -> Put) -> (Int -> Word8) -> Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ 0x80 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ((Int
oc Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` 12) Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. 0x3f)
                      Word8 -> Put
putWord8 (Word8 -> Put) -> (Int -> Word8) -> Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ 0x80 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ((Int
oc Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` 6) Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. 0x3f)
                      Word8 -> Put
putWord8 (Word8 -> Put) -> (Int -> Word8) -> Int -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Put) -> Int -> Put
forall a b. (a -> b) -> a -> b
$ 0x80 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
oc Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. 0x3f
 where
 oc :: Int
oc = Char -> Int
ord Char
c

-- | Writes a string of ascii characters to a byte string
putAsciiStr :: String -> Put
putAsciiStr :: String -> Put
putAsciiStr = (Char -> Put) -> String -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Char -> Put
putAscii

-- | Writes a string of unicode characters to a byte string,
-- properly UTF-8 encoded
putUTF8Str :: String -> Put
putUTF8Str :: String -> Put
putUTF8Str = (Char -> Put) -> String -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Char -> Put
putUTF8

-- | Puts the decimal digit corresponding to the given Int without
-- checking that it is in the interval [0,9]
unsafePutDigit :: Int -> Put
unsafePutDigit :: Int -> Put
unsafePutDigit (I# i# :: Int#
i#) = Word# -> Put
unsafePutDigit# (Int# -> Word#
int2Word# Int#
i#)

unsafePutDigit# :: Word# -> Put
unsafePutDigit# :: Word# -> Put
unsafePutDigit# w# :: Word#
w# = Word8 -> Put
putWord8 (Word# -> Word8
W8# (Word#
w# Word# -> Word# -> Word#
`plusWord#` Int# -> Word#
int2Word# 48#))