PageRenderTime 147ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/compiler/utils/Binary.hs

https://bitbucket.org/khibino/ghc-hack
Haskell | 770 lines | 538 code | 117 blank | 115 comment | 14 complexity | e9ed3caf965cb85088b5ea3220056570 MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause, LGPL-3.0
  1. {-# OPTIONS -cpp #-}
  2. {-# OPTIONS_GHC -O -funbox-strict-fields #-}
  3. -- We always optimise this, otherwise performance of a non-optimised
  4. -- compiler is severely affected
  5. --
  6. -- (c) The University of Glasgow 2002-2006
  7. --
  8. -- Binary I/O library, with special tweaks for GHC
  9. --
  10. -- Based on the nhc98 Binary library, which is copyright
  11. -- (c) Malcolm Wallace and Colin Runciman, University of York, 1998.
  12. -- Under the terms of the license for that software, we must tell you
  13. -- where you can obtain the original version of the Binary library, namely
  14. -- http://www.cs.york.ac.uk/fp/nhc98/
  15. module Binary
  16. ( {-type-} Bin,
  17. {-class-} Binary(..),
  18. {-type-} BinHandle,
  19. SymbolTable, Dictionary,
  20. openBinIO, openBinIO_,
  21. openBinMem,
  22. -- closeBin,
  23. seekBin,
  24. seekBy,
  25. tellBin,
  26. castBin,
  27. writeBinMem,
  28. readBinMem,
  29. fingerprintBinMem,
  30. computeFingerprint,
  31. isEOFBin,
  32. putAt, getAt,
  33. -- for writing instances:
  34. putByte,
  35. getByte,
  36. -- lazy Bin I/O
  37. lazyGet,
  38. lazyPut,
  39. #ifdef __GLASGOW_HASKELL__
  40. -- GHC only:
  41. ByteArray(..),
  42. getByteArray,
  43. putByteArray,
  44. #endif
  45. UserData(..), getUserData, setUserData,
  46. newReadState, newWriteState,
  47. putDictionary, getDictionary, putFS,
  48. ) where
  49. #include "HsVersions.h"
  50. -- The *host* architecture version:
  51. #include "../includes/MachDeps.h"
  52. import {-# SOURCE #-} Name (Name)
  53. import FastString
  54. import Panic
  55. import UniqFM
  56. import FastMutInt
  57. import Fingerprint
  58. import BasicTypes
  59. import Foreign
  60. import Data.Array
  61. import Data.IORef
  62. import Data.Char ( ord, chr )
  63. import Data.Typeable
  64. #if __GLASGOW_HASKELL__ >= 701
  65. import Data.Typeable.Internal
  66. #endif
  67. import Control.Monad ( when )
  68. import System.IO as IO
  69. import System.IO.Unsafe ( unsafeInterleaveIO )
  70. import System.IO.Error ( mkIOError, eofErrorType )
  71. import GHC.Real ( Ratio(..) )
  72. import GHC.Exts
  73. import GHC.Word ( Word8(..) )
  74. import GHC.IO ( IO(..) )
  75. type BinArray = ForeignPtr Word8
  76. ---------------------------------------------------------------
  77. -- BinHandle
  78. ---------------------------------------------------------------
  79. data BinHandle
  80. = BinMem { -- binary data stored in an unboxed array
  81. bh_usr :: UserData, -- sigh, need parameterized modules :-)
  82. _off_r :: !FastMutInt, -- the current offset
  83. _sz_r :: !FastMutInt, -- size of the array (cached)
  84. _arr_r :: !(IORef BinArray) -- the array (bounds: (0,size-1))
  85. }
  86. -- XXX: should really store a "high water mark" for dumping out
  87. -- the binary data to a file.
  88. | BinIO { -- binary data stored in a file
  89. bh_usr :: UserData,
  90. _off_r :: !FastMutInt, -- the current offset (cached)
  91. _hdl :: !IO.Handle -- the file handle (must be seekable)
  92. }
  93. -- cache the file ptr in BinIO; using hTell is too expensive
  94. -- to call repeatedly. If anyone else is modifying this Handle
  95. -- at the same time, we'll be screwed.
  96. getUserData :: BinHandle -> UserData
  97. getUserData bh = bh_usr bh
  98. setUserData :: BinHandle -> UserData -> BinHandle
  99. setUserData bh us = bh { bh_usr = us }
  100. ---------------------------------------------------------------
  101. -- Bin
  102. ---------------------------------------------------------------
  103. newtype Bin a = BinPtr Int
  104. deriving (Eq, Ord, Show, Bounded)
  105. castBin :: Bin a -> Bin b
  106. castBin (BinPtr i) = BinPtr i
  107. ---------------------------------------------------------------
  108. -- class Binary
  109. ---------------------------------------------------------------
  110. class Binary a where
  111. put_ :: BinHandle -> a -> IO ()
  112. put :: BinHandle -> a -> IO (Bin a)
  113. get :: BinHandle -> IO a
  114. -- define one of put_, put. Use of put_ is recommended because it
  115. -- is more likely that tail-calls can kick in, and we rarely need the
  116. -- position return value.
  117. put_ bh a = do _ <- put bh a; return ()
  118. put bh a = do p <- tellBin bh; put_ bh a; return p
  119. putAt :: Binary a => BinHandle -> Bin a -> a -> IO ()
  120. putAt bh p x = do seekBin bh p; put_ bh x; return ()
  121. getAt :: Binary a => BinHandle -> Bin a -> IO a
  122. getAt bh p = do seekBin bh p; get bh
  123. openBinIO_ :: IO.Handle -> IO BinHandle
  124. openBinIO_ h = openBinIO h
  125. openBinIO :: IO.Handle -> IO BinHandle
  126. openBinIO h = do
  127. r <- newFastMutInt
  128. writeFastMutInt r 0
  129. return (BinIO noUserData r h)
  130. openBinMem :: Int -> IO BinHandle
  131. openBinMem size
  132. | size <= 0 = error "Data.Binary.openBinMem: size must be >= 0"
  133. | otherwise = do
  134. arr <- mallocForeignPtrBytes size
  135. arr_r <- newIORef arr
  136. ix_r <- newFastMutInt
  137. writeFastMutInt ix_r 0
  138. sz_r <- newFastMutInt
  139. writeFastMutInt sz_r size
  140. return (BinMem noUserData ix_r sz_r arr_r)
  141. tellBin :: BinHandle -> IO (Bin a)
  142. tellBin (BinIO _ r _) = do ix <- readFastMutInt r; return (BinPtr ix)
  143. tellBin (BinMem _ r _ _) = do ix <- readFastMutInt r; return (BinPtr ix)
  144. seekBin :: BinHandle -> Bin a -> IO ()
  145. seekBin (BinIO _ ix_r h) (BinPtr p) = do
  146. writeFastMutInt ix_r p
  147. hSeek h AbsoluteSeek (fromIntegral p)
  148. seekBin h@(BinMem _ ix_r sz_r _) (BinPtr p) = do
  149. sz <- readFastMutInt sz_r
  150. if (p >= sz)
  151. then do expandBin h p; writeFastMutInt ix_r p
  152. else writeFastMutInt ix_r p
  153. seekBy :: BinHandle -> Int -> IO ()
  154. seekBy (BinIO _ ix_r h) off = do
  155. ix <- readFastMutInt ix_r
  156. let ix' = ix + off
  157. writeFastMutInt ix_r ix'
  158. hSeek h AbsoluteSeek (fromIntegral ix')
  159. seekBy h@(BinMem _ ix_r sz_r _) off = do
  160. sz <- readFastMutInt sz_r
  161. ix <- readFastMutInt ix_r
  162. let ix' = ix + off
  163. if (ix' >= sz)
  164. then do expandBin h ix'; writeFastMutInt ix_r ix'
  165. else writeFastMutInt ix_r ix'
  166. isEOFBin :: BinHandle -> IO Bool
  167. isEOFBin (BinMem _ ix_r sz_r _) = do
  168. ix <- readFastMutInt ix_r
  169. sz <- readFastMutInt sz_r
  170. return (ix >= sz)
  171. isEOFBin (BinIO _ _ h) = hIsEOF h
  172. writeBinMem :: BinHandle -> FilePath -> IO ()
  173. writeBinMem (BinIO _ _ _) _ = error "Data.Binary.writeBinMem: not a memory handle"
  174. writeBinMem (BinMem _ ix_r _ arr_r) fn = do
  175. h <- openBinaryFile fn WriteMode
  176. arr <- readIORef arr_r
  177. ix <- readFastMutInt ix_r
  178. withForeignPtr arr $ \p -> hPutBuf h p ix
  179. hClose h
  180. readBinMem :: FilePath -> IO BinHandle
  181. -- Return a BinHandle with a totally undefined State
  182. readBinMem filename = do
  183. h <- openBinaryFile filename ReadMode
  184. filesize' <- hFileSize h
  185. let filesize = fromIntegral filesize'
  186. arr <- mallocForeignPtrBytes (filesize*2)
  187. count <- withForeignPtr arr $ \p -> hGetBuf h p filesize
  188. when (count /= filesize) $
  189. error ("Binary.readBinMem: only read " ++ show count ++ " bytes")
  190. hClose h
  191. arr_r <- newIORef arr
  192. ix_r <- newFastMutInt
  193. writeFastMutInt ix_r 0
  194. sz_r <- newFastMutInt
  195. writeFastMutInt sz_r filesize
  196. return (BinMem noUserData ix_r sz_r arr_r)
  197. fingerprintBinMem :: BinHandle -> IO Fingerprint
  198. fingerprintBinMem (BinIO _ _ _) = error "Binary.md5BinMem: not a memory handle"
  199. fingerprintBinMem (BinMem _ ix_r _ arr_r) = do
  200. arr <- readIORef arr_r
  201. ix <- readFastMutInt ix_r
  202. withForeignPtr arr $ \p -> fingerprintData p ix
  203. computeFingerprint :: Binary a
  204. => (BinHandle -> Name -> IO ())
  205. -> a
  206. -> IO Fingerprint
  207. computeFingerprint put_name a = do
  208. bh <- openBinMem (3*1024) -- just less than a block
  209. bh <- return $ setUserData bh $ newWriteState put_name putFS
  210. put_ bh a
  211. fingerprintBinMem bh
  212. -- expand the size of the array to include a specified offset
  213. expandBin :: BinHandle -> Int -> IO ()
  214. expandBin (BinMem _ _ sz_r arr_r) off = do
  215. sz <- readFastMutInt sz_r
  216. let sz' = head (dropWhile (<= off) (iterate (* 2) sz))
  217. arr <- readIORef arr_r
  218. arr' <- mallocForeignPtrBytes sz'
  219. withForeignPtr arr $ \old ->
  220. withForeignPtr arr' $ \new ->
  221. copyBytes new old sz
  222. writeFastMutInt sz_r sz'
  223. writeIORef arr_r arr'
  224. when False $ -- disabled
  225. hPutStrLn stderr ("Binary: expanding to size: " ++ show sz')
  226. return ()
  227. expandBin (BinIO _ _ _) _ = return ()
  228. -- no need to expand a file, we'll assume they expand by themselves.
  229. -- -----------------------------------------------------------------------------
  230. -- Low-level reading/writing of bytes
  231. putWord8 :: BinHandle -> Word8 -> IO ()
  232. putWord8 h@(BinMem _ ix_r sz_r arr_r) w = do
  233. ix <- readFastMutInt ix_r
  234. sz <- readFastMutInt sz_r
  235. -- double the size of the array if it overflows
  236. if (ix >= sz)
  237. then do expandBin h ix
  238. putWord8 h w
  239. else do arr <- readIORef arr_r
  240. withForeignPtr arr $ \p -> pokeByteOff p ix w
  241. writeFastMutInt ix_r (ix+1)
  242. return ()
  243. putWord8 (BinIO _ ix_r h) w = do
  244. ix <- readFastMutInt ix_r
  245. hPutChar h (chr (fromIntegral w)) -- XXX not really correct
  246. writeFastMutInt ix_r (ix+1)
  247. return ()
  248. getWord8 :: BinHandle -> IO Word8
  249. getWord8 (BinMem _ ix_r sz_r arr_r) = do
  250. ix <- readFastMutInt ix_r
  251. sz <- readFastMutInt sz_r
  252. when (ix >= sz) $
  253. ioError (mkIOError eofErrorType "Data.Binary.getWord8" Nothing Nothing)
  254. arr <- readIORef arr_r
  255. w <- withForeignPtr arr $ \p -> peekByteOff p ix
  256. writeFastMutInt ix_r (ix+1)
  257. return w
  258. getWord8 (BinIO _ ix_r h) = do
  259. ix <- readFastMutInt ix_r
  260. c <- hGetChar h
  261. writeFastMutInt ix_r (ix+1)
  262. return $! (fromIntegral (ord c)) -- XXX not really correct
  263. putByte :: BinHandle -> Word8 -> IO ()
  264. putByte bh w = put_ bh w
  265. getByte :: BinHandle -> IO Word8
  266. getByte = getWord8
  267. -- -----------------------------------------------------------------------------
  268. -- Primitve Word writes
  269. instance Binary Word8 where
  270. put_ = putWord8
  271. get = getWord8
  272. instance Binary Word16 where
  273. put_ h w = do -- XXX too slow.. inline putWord8?
  274. putByte h (fromIntegral (w `shiftR` 8))
  275. putByte h (fromIntegral (w .&. 0xff))
  276. get h = do
  277. w1 <- getWord8 h
  278. w2 <- getWord8 h
  279. return $! ((fromIntegral w1 `shiftL` 8) .|. fromIntegral w2)
  280. instance Binary Word32 where
  281. put_ h w = do
  282. putByte h (fromIntegral (w `shiftR` 24))
  283. putByte h (fromIntegral ((w `shiftR` 16) .&. 0xff))
  284. putByte h (fromIntegral ((w `shiftR` 8) .&. 0xff))
  285. putByte h (fromIntegral (w .&. 0xff))
  286. get h = do
  287. w1 <- getWord8 h
  288. w2 <- getWord8 h
  289. w3 <- getWord8 h
  290. w4 <- getWord8 h
  291. return $! ((fromIntegral w1 `shiftL` 24) .|.
  292. (fromIntegral w2 `shiftL` 16) .|.
  293. (fromIntegral w3 `shiftL` 8) .|.
  294. (fromIntegral w4))
  295. instance Binary Word64 where
  296. put_ h w = do
  297. putByte h (fromIntegral (w `shiftR` 56))
  298. putByte h (fromIntegral ((w `shiftR` 48) .&. 0xff))
  299. putByte h (fromIntegral ((w `shiftR` 40) .&. 0xff))
  300. putByte h (fromIntegral ((w `shiftR` 32) .&. 0xff))
  301. putByte h (fromIntegral ((w `shiftR` 24) .&. 0xff))
  302. putByte h (fromIntegral ((w `shiftR` 16) .&. 0xff))
  303. putByte h (fromIntegral ((w `shiftR` 8) .&. 0xff))
  304. putByte h (fromIntegral (w .&. 0xff))
  305. get h = do
  306. w1 <- getWord8 h
  307. w2 <- getWord8 h
  308. w3 <- getWord8 h
  309. w4 <- getWord8 h
  310. w5 <- getWord8 h
  311. w6 <- getWord8 h
  312. w7 <- getWord8 h
  313. w8 <- getWord8 h
  314. return $! ((fromIntegral w1 `shiftL` 56) .|.
  315. (fromIntegral w2 `shiftL` 48) .|.
  316. (fromIntegral w3 `shiftL` 40) .|.
  317. (fromIntegral w4 `shiftL` 32) .|.
  318. (fromIntegral w5 `shiftL` 24) .|.
  319. (fromIntegral w6 `shiftL` 16) .|.
  320. (fromIntegral w7 `shiftL` 8) .|.
  321. (fromIntegral w8))
  322. -- -----------------------------------------------------------------------------
  323. -- Primitve Int writes
  324. instance Binary Int8 where
  325. put_ h w = put_ h (fromIntegral w :: Word8)
  326. get h = do w <- get h; return $! (fromIntegral (w::Word8))
  327. instance Binary Int16 where
  328. put_ h w = put_ h (fromIntegral w :: Word16)
  329. get h = do w <- get h; return $! (fromIntegral (w::Word16))
  330. instance Binary Int32 where
  331. put_ h w = put_ h (fromIntegral w :: Word32)
  332. get h = do w <- get h; return $! (fromIntegral (w::Word32))
  333. instance Binary Int64 where
  334. put_ h w = put_ h (fromIntegral w :: Word64)
  335. get h = do w <- get h; return $! (fromIntegral (w::Word64))
  336. -- -----------------------------------------------------------------------------
  337. -- Instances for standard types
  338. instance Binary () where
  339. put_ _ () = return ()
  340. get _ = return ()
  341. instance Binary Bool where
  342. put_ bh b = putByte bh (fromIntegral (fromEnum b))
  343. get bh = do x <- getWord8 bh; return $! (toEnum (fromIntegral x))
  344. instance Binary Char where
  345. put_ bh c = put_ bh (fromIntegral (ord c) :: Word32)
  346. get bh = do x <- get bh; return $! (chr (fromIntegral (x :: Word32)))
  347. instance Binary Int where
  348. put_ bh i = put_ bh (fromIntegral i :: Int64)
  349. get bh = do
  350. x <- get bh
  351. return $! (fromIntegral (x :: Int64))
  352. instance Binary a => Binary [a] where
  353. put_ bh l = do
  354. let len = length l
  355. if (len < 0xff)
  356. then putByte bh (fromIntegral len :: Word8)
  357. else do putByte bh 0xff; put_ bh (fromIntegral len :: Word32)
  358. mapM_ (put_ bh) l
  359. get bh = do
  360. b <- getByte bh
  361. len <- if b == 0xff
  362. then get bh
  363. else return (fromIntegral b :: Word32)
  364. let loop 0 = return []
  365. loop n = do a <- get bh; as <- loop (n-1); return (a:as)
  366. loop len
  367. instance (Binary a, Binary b) => Binary (a,b) where
  368. put_ bh (a,b) = do put_ bh a; put_ bh b
  369. get bh = do a <- get bh
  370. b <- get bh
  371. return (a,b)
  372. instance (Binary a, Binary b, Binary c) => Binary (a,b,c) where
  373. put_ bh (a,b,c) = do put_ bh a; put_ bh b; put_ bh c
  374. get bh = do a <- get bh
  375. b <- get bh
  376. c <- get bh
  377. return (a,b,c)
  378. instance (Binary a, Binary b, Binary c, Binary d) => Binary (a,b,c,d) where
  379. put_ bh (a,b,c,d) = do put_ bh a; put_ bh b; put_ bh c; put_ bh d
  380. get bh = do a <- get bh
  381. b <- get bh
  382. c <- get bh
  383. d <- get bh
  384. return (a,b,c,d)
  385. instance (Binary a, Binary b, Binary c, Binary d, Binary e) => Binary (a,b,c,d, e) where
  386. put_ bh (a,b,c,d, e) = do put_ bh a; put_ bh b; put_ bh c; put_ bh d; put_ bh e;
  387. get bh = do a <- get bh
  388. b <- get bh
  389. c <- get bh
  390. d <- get bh
  391. e <- get bh
  392. return (a,b,c,d,e)
  393. instance (Binary a, Binary b, Binary c, Binary d, Binary e, Binary f) => Binary (a,b,c,d, e, f) where
  394. put_ bh (a,b,c,d, e, f) = do put_ bh a; put_ bh b; put_ bh c; put_ bh d; put_ bh e; put_ bh f;
  395. get bh = do a <- get bh
  396. b <- get bh
  397. c <- get bh
  398. d <- get bh
  399. e <- get bh
  400. f <- get bh
  401. return (a,b,c,d,e,f)
  402. instance Binary a => Binary (Maybe a) where
  403. put_ bh Nothing = putByte bh 0
  404. put_ bh (Just a) = do putByte bh 1; put_ bh a
  405. get bh = do h <- getWord8 bh
  406. case h of
  407. 0 -> return Nothing
  408. _ -> do x <- get bh; return (Just x)
  409. instance (Binary a, Binary b) => Binary (Either a b) where
  410. put_ bh (Left a) = do putByte bh 0; put_ bh a
  411. put_ bh (Right b) = do putByte bh 1; put_ bh b
  412. get bh = do h <- getWord8 bh
  413. case h of
  414. 0 -> do a <- get bh ; return (Left a)
  415. _ -> do b <- get bh ; return (Right b)
  416. #if defined(__GLASGOW_HASKELL__) || 1
  417. --to quote binary-0.3 on this code idea,
  418. --
  419. -- TODO This instance is not architecture portable. GMP stores numbers as
  420. -- arrays of machine sized words, so the byte format is not portable across
  421. -- architectures with different endianess and word size.
  422. --
  423. -- This makes it hard (impossible) to make an equivalent instance
  424. -- with code that is compilable with non-GHC. Do we need any instance
  425. -- Binary Integer, and if so, does it have to be blazing fast? Or can
  426. -- we just change this instance to be portable like the rest of the
  427. -- instances? (binary package has code to steal for that)
  428. --
  429. -- yes, we need Binary Integer and Binary Rational in basicTypes/Literal.lhs
  430. instance Binary Integer where
  431. -- XXX This is hideous
  432. put_ bh i = put_ bh (show i)
  433. get bh = do str <- get bh
  434. case reads str of
  435. [(i, "")] -> return i
  436. _ -> fail ("Binary Integer: got " ++ show str)
  437. {-
  438. put_ bh (S# i#) = do putByte bh 0; put_ bh (I# i#)
  439. put_ bh (J# s# a#) = do
  440. putByte bh 1
  441. put_ bh (I# s#)
  442. let sz# = sizeofByteArray# a# -- in *bytes*
  443. put_ bh (I# sz#) -- in *bytes*
  444. putByteArray bh a# sz#
  445. get bh = do
  446. b <- getByte bh
  447. case b of
  448. 0 -> do (I# i#) <- get bh
  449. return (S# i#)
  450. _ -> do (I# s#) <- get bh
  451. sz <- get bh
  452. (BA a#) <- getByteArray bh sz
  453. return (J# s# a#)
  454. -}
  455. -- As for the rest of this code, even though this module
  456. -- exports it, it doesn't seem to be used anywhere else
  457. -- in GHC!
  458. putByteArray :: BinHandle -> ByteArray# -> Int# -> IO ()
  459. putByteArray bh a s# = loop 0#
  460. where loop n#
  461. | n# ==# s# = return ()
  462. | otherwise = do
  463. putByte bh (indexByteArray a n#)
  464. loop (n# +# 1#)
  465. getByteArray :: BinHandle -> Int -> IO ByteArray
  466. getByteArray bh (I# sz) = do
  467. (MBA arr) <- newByteArray sz
  468. let loop n
  469. | n ==# sz = return ()
  470. | otherwise = do
  471. w <- getByte bh
  472. writeByteArray arr n w
  473. loop (n +# 1#)
  474. loop 0#
  475. freezeByteArray arr
  476. data ByteArray = BA ByteArray#
  477. data MBA = MBA (MutableByteArray# RealWorld)
  478. newByteArray :: Int# -> IO MBA
  479. newByteArray sz = IO $ \s ->
  480. case newByteArray# sz s of { (# s, arr #) ->
  481. (# s, MBA arr #) }
  482. freezeByteArray :: MutableByteArray# RealWorld -> IO ByteArray
  483. freezeByteArray arr = IO $ \s ->
  484. case unsafeFreezeByteArray# arr s of { (# s, arr #) ->
  485. (# s, BA arr #) }
  486. writeByteArray :: MutableByteArray# RealWorld -> Int# -> Word8 -> IO ()
  487. writeByteArray arr i (W8# w) = IO $ \s ->
  488. case writeWord8Array# arr i w s of { s ->
  489. (# s, () #) }
  490. indexByteArray :: ByteArray# -> Int# -> Word8
  491. indexByteArray a# n# = W8# (indexWord8Array# a# n#)
  492. instance (Integral a, Binary a) => Binary (Ratio a) where
  493. put_ bh (a :% b) = do put_ bh a; put_ bh b
  494. get bh = do a <- get bh; b <- get bh; return (a :% b)
  495. #endif
  496. instance Binary (Bin a) where
  497. put_ bh (BinPtr i) = put_ bh (fromIntegral i :: Int32)
  498. get bh = do i <- get bh; return (BinPtr (fromIntegral (i :: Int32)))
  499. -- -----------------------------------------------------------------------------
  500. -- Instances for Data.Typeable stuff
  501. #if __GLASGOW_HASKELL__ >= 701
  502. instance Binary TyCon where
  503. put_ bh (TyCon _ p m n) = do
  504. put_ bh (p,m,n)
  505. get bh = do
  506. (p,m,n) <- get bh
  507. return (mkTyCon3 p m n)
  508. #else
  509. instance Binary TyCon where
  510. put_ bh ty_con = do
  511. let s = tyConString ty_con
  512. put_ bh s
  513. get bh = do
  514. s <- get bh
  515. return (mkTyCon s)
  516. #endif
  517. instance Binary TypeRep where
  518. put_ bh type_rep = do
  519. let (ty_con, child_type_reps) = splitTyConApp type_rep
  520. put_ bh ty_con
  521. put_ bh child_type_reps
  522. get bh = do
  523. ty_con <- get bh
  524. child_type_reps <- get bh
  525. return (mkTyConApp ty_con child_type_reps)
  526. -- -----------------------------------------------------------------------------
  527. -- Lazy reading/writing
  528. lazyPut :: Binary a => BinHandle -> a -> IO ()
  529. lazyPut bh a = do
  530. -- output the obj with a ptr to skip over it:
  531. pre_a <- tellBin bh
  532. put_ bh pre_a -- save a slot for the ptr
  533. put_ bh a -- dump the object
  534. q <- tellBin bh -- q = ptr to after object
  535. putAt bh pre_a q -- fill in slot before a with ptr to q
  536. seekBin bh q -- finally carry on writing at q
  537. lazyGet :: Binary a => BinHandle -> IO a
  538. lazyGet bh = do
  539. p <- get bh -- a BinPtr
  540. p_a <- tellBin bh
  541. a <- unsafeInterleaveIO (getAt bh p_a)
  542. seekBin bh p -- skip over the object for now
  543. return a
  544. -- -----------------------------------------------------------------------------
  545. -- UserData
  546. -- -----------------------------------------------------------------------------
  547. data UserData =
  548. UserData {
  549. -- for *deserialising* only:
  550. ud_get_name :: BinHandle -> IO Name,
  551. ud_get_fs :: BinHandle -> IO FastString,
  552. -- for *serialising* only:
  553. ud_put_name :: BinHandle -> Name -> IO (),
  554. ud_put_fs :: BinHandle -> FastString -> IO ()
  555. }
  556. newReadState :: (BinHandle -> IO Name)
  557. -> (BinHandle -> IO FastString)
  558. -> UserData
  559. newReadState get_name get_fs
  560. = UserData { ud_get_name = get_name,
  561. ud_get_fs = get_fs,
  562. ud_put_name = undef "put_name",
  563. ud_put_fs = undef "put_fs"
  564. }
  565. newWriteState :: (BinHandle -> Name -> IO ())
  566. -> (BinHandle -> FastString -> IO ())
  567. -> UserData
  568. newWriteState put_name put_fs
  569. = UserData { ud_get_name = undef "get_name",
  570. ud_get_fs = undef "get_fs",
  571. ud_put_name = put_name,
  572. ud_put_fs = put_fs
  573. }
  574. noUserData :: a
  575. noUserData = undef "UserData"
  576. undef :: String -> a
  577. undef s = panic ("Binary.UserData: no " ++ s)
  578. ---------------------------------------------------------
  579. -- The Dictionary
  580. ---------------------------------------------------------
  581. type Dictionary = Array Int FastString -- The dictionary
  582. -- Should be 0-indexed
  583. putDictionary :: BinHandle -> Int -> UniqFM (Int,FastString) -> IO ()
  584. putDictionary bh sz dict = do
  585. put_ bh sz
  586. mapM_ (putFS bh) (elems (array (0,sz-1) (eltsUFM dict)))
  587. getDictionary :: BinHandle -> IO Dictionary
  588. getDictionary bh = do
  589. sz <- get bh
  590. elems <- sequence (take sz (repeat (getFS bh)))
  591. return (listArray (0,sz-1) elems)
  592. ---------------------------------------------------------
  593. -- The Symbol Table
  594. ---------------------------------------------------------
  595. -- On disk, the symbol table is an array of IfaceExtName, when
  596. -- reading it in we turn it into a SymbolTable.
  597. type SymbolTable = Array Int Name
  598. ---------------------------------------------------------
  599. -- Reading and writing FastStrings
  600. ---------------------------------------------------------
  601. putFS :: BinHandle -> FastString -> IO ()
  602. putFS bh (FastString _ l _ buf _) = do
  603. put_ bh l
  604. withForeignPtr buf $ \ptr ->
  605. let
  606. go n | n == l = return ()
  607. | otherwise = do
  608. b <- peekElemOff ptr n
  609. putByte bh b
  610. go (n+1)
  611. in
  612. go 0
  613. {- -- possible faster version, not quite there yet:
  614. getFS bh@BinMem{} = do
  615. (I# l) <- get bh
  616. arr <- readIORef (arr_r bh)
  617. off <- readFastMutInt (off_r bh)
  618. return $! (mkFastSubStringBA# arr off l)
  619. -}
  620. getFS :: BinHandle -> IO FastString
  621. getFS bh = do
  622. l <- get bh
  623. fp <- mallocForeignPtrBytes l
  624. withForeignPtr fp $ \ptr -> do
  625. let
  626. go n | n == l = mkFastStringForeignPtr ptr fp l
  627. | otherwise = do
  628. b <- getByte bh
  629. pokeElemOff ptr n b
  630. go (n+1)
  631. --
  632. go 0
  633. instance Binary FastString where
  634. put_ bh f =
  635. case getUserData bh of
  636. UserData { ud_put_fs = put_fs } -> put_fs bh f
  637. get bh =
  638. case getUserData bh of
  639. UserData { ud_get_fs = get_fs } -> get_fs bh
  640. -- Here to avoid loop
  641. instance Binary Fingerprint where
  642. put_ h (Fingerprint w1 w2) = do put_ h w1; put_ h w2
  643. get h = do w1 <- get h; w2 <- get h; return (Fingerprint w1 w2)
  644. instance Binary FunctionOrData where
  645. put_ bh IsFunction = putByte bh 0
  646. put_ bh IsData = putByte bh 1
  647. get bh = do
  648. h <- getByte bh
  649. case h of
  650. 0 -> return IsFunction
  651. 1 -> return IsData
  652. _ -> panic "Binary FunctionOrData"