{-# LANGUAGE ScopedTypeVariables, CPP, ForeignFunctionInterface, MagicHash, UnboxedTuples #-}{-# OPTIONS_HADDOCK not-home #-}#if __GLASGOW_HASKELL__ >= 701 {-# LANGUAGE Trustworthy #-}#endif -- | Copyright : (c) 2010 - 2011 Simon Meier-- License : BSD3-style (see LICENSE)---- Maintainer : Simon Meier <iridcode@gmail.com>-- Portability : GHC---- Constructing 'Builder's using ASCII-based encodings.--moduleData.ByteString.Builder.ASCII(-- ** Formatting numbers as text-- | Formatting of numbers as ASCII text.---- Note that you can also use these functions for the ISO/IEC 8859-1 and-- UTF-8 encodings, as the ASCII encoding is equivalent on the -- codepoints 0-127.-- *** Decimal numbers-- | Decimal encoding of numbers using ASCII encoded characters.int8Dec ,int16Dec ,int32Dec ,int64Dec ,intDec ,integerDec ,word8Dec ,word16Dec ,word32Dec ,word64Dec ,wordDec ,floatDec ,doubleDec -- *** Hexadecimal numbers-- | Encoding positive integers as hexadecimal numbers using lower-case-- ASCII characters. The shortest-- possible representation is used. For example,---- >>> toLazyByteString (word16Hex 0x0a10)-- Chunk "a10" Empty---- Note that there is no support for using upper-case characters. Please-- contact the maintainer, if your application cannot work without-- hexadecimal encodings that use upper-case characters.--,word8Hex ,word16Hex ,word32Hex ,word64Hex ,wordHex -- *** Fixed-width hexadecimal numbers--,int8HexFixed ,int16HexFixed ,int32HexFixed ,int64HexFixed ,word8HexFixed ,word16HexFixed ,word32HexFixed ,word64HexFixed ,floatHexFixed ,doubleHexFixed ,byteStringHex ,lazyByteStringHex )whereimportData.ByteString asSimportData.ByteString.Lazy asLimportData.ByteString.Builder.Internal (Builder )importqualifiedData.ByteString.Builder.Prim asPimportForeign#if defined(INTEGER_GMP) #if !(MIN_VERSION_base(4,8,0)) importData.Monoid(mappend)# endif importForeign.C.TypesimportqualifiedData.ByteString.Builder.Prim.Internal asPimportData.ByteString.Builder.Prim.Internal.UncheckedShifts (caseWordSize_32_64 )# if __GLASGOW_HASKELL__ < 710 importGHC.Num(quotRemInteger)# endif importGHC.Types(Int(..))# if __GLASGOW_HASKELL__ < 611 importGHC.Integer.Internals# else importGHC.Integer.GMP.Internals# endif #endif -------------------------------------------------------------------------------- Decimal Encoding-------------------------------------------------------------------------------- | Encode a 'String' using 'P.char7'.{-# INLINEstring7#-}string7::String->Builder string7 =P.primMapListFixed P.char7 -------------------------------------------------------------------------------- Decimal Encoding-------------------------------------------------------------------------------- Signed integers-------------------- | Decimal encoding of an 'Int8' using the ASCII digits.---- e.g.---- > toLazyByteString (int8Dec 42) = "42"-- > toLazyByteString (int8Dec (-1)) = "-1"--{-# INLINEint8Dec#-}int8Dec::Int8->Builder int8Dec =P.primBounded P.int8Dec -- | Decimal encoding of an 'Int16' using the ASCII digits.{-# INLINEint16Dec#-}int16Dec::Int16->Builder int16Dec =P.primBounded P.int16Dec -- | Decimal encoding of an 'Int32' using the ASCII digits.{-# INLINEint32Dec#-}int32Dec::Int32->Builder int32Dec =P.primBounded P.int32Dec -- | Decimal encoding of an 'Int64' using the ASCII digits.{-# INLINEint64Dec#-}int64Dec::Int64->Builder int64Dec =P.primBounded P.int64Dec -- | Decimal encoding of an 'Int' using the ASCII digits.{-# INLINEintDec#-}intDec::Int->Builder intDec =P.primBounded P.intDec -- Unsigned integers---------------------- | Decimal encoding of a 'Word8' using the ASCII digits.{-# INLINEword8Dec#-}word8Dec::Word8->Builder word8Dec =P.primBounded P.word8Dec -- | Decimal encoding of a 'Word16' using the ASCII digits.{-# INLINEword16Dec#-}word16Dec::Word16->Builder word16Dec =P.primBounded P.word16Dec -- | Decimal encoding of a 'Word32' using the ASCII digits.{-# INLINEword32Dec#-}word32Dec::Word32->Builder word32Dec =P.primBounded P.word32Dec -- | Decimal encoding of a 'Word64' using the ASCII digits.{-# INLINEword64Dec#-}word64Dec::Word64->Builder word64Dec =P.primBounded P.word64Dec -- | Decimal encoding of a 'Word' using the ASCII digits.{-# INLINEwordDec#-}wordDec::Word->Builder wordDec =P.primBounded P.wordDec -- Floating point numbers--------------------------- TODO: Use Bryan O'Sullivan's double-conversion package to speed it up.-- | /Currently slow./ Decimal encoding of an IEEE 'Float'.{-# INLINEfloatDec#-}floatDec::Float->Builder floatDec =string7 .show-- | /Currently slow./ Decimal encoding of an IEEE 'Double'.{-# INLINEdoubleDec#-}doubleDec::Double->Builder doubleDec =string7 .show-------------------------------------------------------------------------------- Hexadecimal Encoding-------------------------------------------------------------------------------- without lead----------------- | Shortest hexadecimal encoding of a 'Word8' using lower-case characters.{-# INLINEword8Hex#-}word8Hex::Word8->Builder word8Hex =P.primBounded P.word8Hex -- | Shortest hexadecimal encoding of a 'Word16' using lower-case characters.{-# INLINEword16Hex#-}word16Hex::Word16->Builder word16Hex =P.primBounded P.word16Hex -- | Shortest hexadecimal encoding of a 'Word32' using lower-case characters.{-# INLINEword32Hex#-}word32Hex::Word32->Builder word32Hex =P.primBounded P.word32Hex -- | Shortest hexadecimal encoding of a 'Word64' using lower-case characters.{-# INLINEword64Hex#-}word64Hex::Word64->Builder word64Hex =P.primBounded P.word64Hex -- | Shortest hexadecimal encoding of a 'Word' using lower-case characters.{-# INLINEwordHex#-}wordHex::Word->Builder wordHex =P.primBounded P.wordHex -- fixed width; leading zeroes-------------------------------- | Encode a 'Int8' using 2 nibbles (hexadecimal digits).{-# INLINEint8HexFixed#-}int8HexFixed::Int8->Builder int8HexFixed =P.primFixed P.int8HexFixed -- | Encode a 'Int16' using 4 nibbles.{-# INLINEint16HexFixed#-}int16HexFixed::Int16->Builder int16HexFixed =P.primFixed P.int16HexFixed -- | Encode a 'Int32' using 8 nibbles.{-# INLINEint32HexFixed#-}int32HexFixed::Int32->Builder int32HexFixed =P.primFixed P.int32HexFixed -- | Encode a 'Int64' using 16 nibbles.{-# INLINEint64HexFixed#-}int64HexFixed::Int64->Builder int64HexFixed =P.primFixed P.int64HexFixed -- | Encode a 'Word8' using 2 nibbles (hexadecimal digits).{-# INLINEword8HexFixed#-}word8HexFixed::Word8->Builder word8HexFixed =P.primFixed P.word8HexFixed -- | Encode a 'Word16' using 4 nibbles.{-# INLINEword16HexFixed#-}word16HexFixed::Word16->Builder word16HexFixed =P.primFixed P.word16HexFixed -- | Encode a 'Word32' using 8 nibbles.{-# INLINEword32HexFixed#-}word32HexFixed::Word32->Builder word32HexFixed =P.primFixed P.word32HexFixed -- | Encode a 'Word64' using 16 nibbles.{-# INLINEword64HexFixed#-}word64HexFixed::Word64->Builder word64HexFixed =P.primFixed P.word64HexFixed -- | Encode an IEEE 'Float' using 8 nibbles.{-# INLINEfloatHexFixed#-}floatHexFixed::Float->Builder floatHexFixed =P.primFixed P.floatHexFixed -- | Encode an IEEE 'Double' using 16 nibbles.{-# INLINEdoubleHexFixed#-}doubleHexFixed::Double->Builder doubleHexFixed =P.primFixed P.doubleHexFixed -- | Encode each byte of a 'S.ByteString' using its fixed-width hex encoding.{-# NOINLINEbyteStringHex#-}-- share codebyteStringHex::S.ByteString ->Builder byteStringHex =P.primMapByteStringFixed P.word8HexFixed -- | Encode each byte of a lazy 'L.ByteString' using its fixed-width hex encoding.{-# NOINLINElazyByteStringHex#-}-- share codelazyByteStringHex::L.ByteString ->Builder lazyByteStringHex =P.primMapLazyByteStringFixed P.word8HexFixed -------------------------------------------------------------------------------- Fast decimal 'Integer' encoding.------------------------------------------------------------------------------#if defined(INTEGER_GMP) -- An optimized version of the integer serialization code-- in blaze-textual (c) 2011 MailRank, Inc. Bryan O'Sullivan-- <bos@mailrank.com>. It is 2.5x faster on Int-sized integers and 4.5x faster-- on larger integers.# define PAIR(a,b) (# a,b #) -- | Maximal power of 10 fitting into an 'Int' without using the MSB.-- 10 ^ 9 for 32 bit ints (31 * log 2 / log 10 = 9.33)-- 10 ^ 18 for 64 bit ints (63 * log 2 / log 10 = 18.96)---- FIXME: Think about also using the MSB. For 64 bit 'Int's this makes a-- difference.maxPow10::IntegermaxPow10 =toInteger$(10::Int)^caseWordSize_32_64 (9::Int)18-- | Decimal encoding of an 'Integer' using the ASCII digits.integerDec::Integer->Builder integerDec (S#i# )=intDec (I#i# )integerDeci |i <0=P.primFixed P.char8 '-'`mappend`go (-i )|otherwise=go (i )whereerrImpossible fun =error$"integerDec: "++fun ++": the impossible happened."go::Integer->Builder go n |n <maxPow10 =intDec (fromIntegern )|otherwise=caseputH (splitf (maxPow10 *maxPow10 )n )of(x :xs )->intDec x `mappend`P.primMapListBounded intDecPadded xs []->errImpossible "integerDec: go"splitf::Integer->Integer->[Integer]splitf pow10 n0 |pow10 >n0 =[n0 ]|otherwise=splith (splitf (pow10 *pow10 )n0 )wheresplith []=errImpossible "splith"splith(n :ns )=casen `quotRemInteger`pow10 ofPAIR(q ,r)|q >0->q :r :splitb ns |otherwise->r :splitb ns splitb []=[]splitb(n :ns )=casen `quotRemInteger`pow10 ofPAIR(q ,r)->q :r :splitb ns putH::[Integer]->[Int]putH []=errImpossible "putH"putH(n :ns )=casen `quotRemInteger`maxPow10 ofPAIR(x ,y)|q >0->q :r :putB ns |otherwise->r :putB ns whereq =fromIntegerx r =fromIntegery putB::[Integer]->[Int]putB []=[]putB(n :ns )=casen `quotRemInteger`maxPow10 ofPAIR(q ,r)->fromIntegerq :fromIntegerr :putB ns foreignimportccallunsafe"static _hs_bytestring_int_dec_padded9"c_int_dec_padded9::CInt->PtrWord8->IO()foreignimportccallunsafe"static _hs_bytestring_long_long_int_dec_padded18"c_long_long_int_dec_padded18::CLLong->PtrWord8->IO(){-# INLINEintDecPadded#-}intDecPadded::P.BoundedPrim IntintDecPadded =P.liftFixedToBounded $caseWordSize_32_64 (P.fixedPrim 9$c_int_dec_padded9 .fromIntegral)(P.fixedPrim 18$c_long_long_int_dec_padded18 .fromIntegral)#else -- compilers other than GHC-- | Decimal encoding of an 'Integer' using the ASCII digits. Implemented-- using via the 'Show' instance of 'Integer's.integerDec::Integer->BuilderintegerDec=string7.show#endif