<commit_before>{- arch-tag: I/O utilities, binary tools
Copyright (C) 2004-2005 <NAME> <<EMAIL>>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-}

{- |
   Module     : MissingH.IO.Binary
   Copyright  : Copyright (C) 2004-2005 <NAME>
   License    : GNU GPL, version 2 or above

   Maintainer : <NAME> <<EMAIL>> 
   Stability  : provisional
   Portability: portable to platforms supporting binary I\/O

This module provides various helpful utilities for dealing with binary
input and output.

You can use this module to deal with binary blocks of data as either Strings 
or lists of Word8.  The BinaryConvertable class provides this abstraction.

Wherever you see HVIO, you can transparently substite a regular Handle.
This module can work with any HVIO object, however.  See
'MissingH.IO.HVIO' for more details.

Versions of MissingH prior 0.11.6 lacked the BinaryConvertable class
and worked only with Strings and Handles.

Important note: /binary functions are not supported in all Haskell
implementations/.  Do not import or use this module unless you know you
are using an implementation that supports them.  At this time, here
is the support status:

 * GHC 6.2 and above: yes
 
 * GHC 6.x, earlier versions: unknown

 * GHC 5.x: no

 * nhc98: no

 * Hugs: partial (maybe complete; needs more testing)

Non-binary functions may be found in "MissingH.IO".

Written by <NAME>, <EMAIL>
-}

module MissingH.IO.Binary(
                       -- * Support for different types of blocks
                       BinaryConvertable(..),
                       -- * Entire File\/Handle Utilities
                       -- ** Opened Handle Data Copying
                       hBlockCopy, blockCopy,
                       -- ** Disk File Data Copying
                       copyFileBlocksToFile,
                       -- * Binary Single-Block I\/O
                       hPutBufStr, putBufStr, hGetBufStr, getBufStr,
                       hFullGetBufStr, fullGetBufStr,
                       -- * Binary Multi-Block I\/O
                       hGetBlocks, getBlocks, hFullGetBlocks, fullGetBlocks,
                       -- * Lazy Interaction
                       readBinaryFile, writeBinaryFile,
                       -- ** Binary Block-based
                       hBlockInteract, blockInteract,
                       hFullBlockInteract, fullBlockInteract
                        ) where

import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.C.String
import Foreign.C.Types
import Foreign.Storable
import Foreign.Marshal.Array
import Data.Word
import System.IO.Unsafe
import System.IO
import MissingH.IO.HVIO

{- | Provides support for handling binary blocks with convenient
types. -}
class BinaryConvertable a where
    toBuf :: a -> (Ptr CChar -> IO c) -> IO c
    fromBuf :: Int -> (Ptr CChar -> IO a) -> IO a
    byteSize :: a -> Int

instance BinaryConvertable String where
    toBuf = withCString
    fromBuf len func = 
        do fbuf <- mallocForeignPtrArray (len + 1)
           withForeignPtr fbuf func
    byteSize = length

instance BinaryConvertable [Word8] where
    toBuf hslist func = withArray hslist (\ptr -> func (castPtr ptr))
    fromBuf len func =
        do (fbuf::(ForeignPtr Word8)) <- mallocForeignPtrArray (len + 1)
           withForeignPtr fbuf (\ptr -> func (castPtr ptr))
    byteSize = length


-- . **************************************************
-- . Binary Files
-- . **************************************************


{- | As a wrapper around the standard function 'System.IO.hPutBuf',
this function takes a standard Haskell 'String' instead of the far less
convenient 'Ptr a'.  The entire contents of the string will be written
as a binary buffer using 'hPutBuf'.  The length of the output will be
the length of the passed String or list..

If it helps, you can thing of this function as being of type
@Handle -> String -> IO ()@. -}
hPutBufStr :: (HVIO a, BinaryConvertable b) => a -> b -> IO ()
hPutBufStr f s = toBuf s (\cs -> vPutBuf f cs (byteSize s))

-- | An alias for 'hPutBufStr' 'stdout'
putBufStr :: (BinaryConvertable b) => b -> IO ()
putBufStr = hPutBufStr stdout

{- | As a wrapper around the standard function 'System.IO.hGetBuf',
this function returns a standard Haskell string instead of modifying
a 'Ptr a' buffer.  The length is the maximum length to read and the
semantice are the same as with 'hGetBuf'; namely, the empty string
is returned with EOF is reached, and any given read may read fewer
bytes than the given length. -}
hGetBufStr :: Handle -> Int -> IO String
hGetBufStr f count = do
   fbuf <- mallocForeignPtrArray (count + 1)
   withForeignPtr fbuf (\buf -> do
                        bytesread <- hGetBuf f buf count
                        haskstring <- peekCStringLen (buf, bytesread)
                        return haskstring)

-- | An alias for 'hGetBufStr' 'stdin'
getBufStr :: Int -> IO String
getBufStr = hGetBufStr stdin

{- | Like 'hGetBufStr', but guarantees that it will only return fewer than
the requested number of bytes when EOF is encountered. -}<commit_msg>Start of adapting for getBufStr<commit_after>{- arch-tag: I/O utilities, binary tools
Copyright (C) 2004-2005 <NAME> <<EMAIL>>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-}

{- |
   Module     : MissingH.IO.Binary
   Copyright  : Copyright (C) 2004-2005 <NAME>
   License    : GNU GPL, version 2 or above

   Maintainer : <NAME> <<EMAIL>> 
   Stability  : provisional
   Portability: portable to platforms supporting binary I\/O

This module provides various helpful utilities for dealing with binary
input and output.

You can use this module to deal with binary blocks of data as either Strings 
or lists of Word8.  The BinaryConvertable class provides this abstraction.

Wherever you see HVIO, you can transparently substite a regular Handle.
This module can work with any HVIO object, however.  See
'MissingH.IO.HVIO' for more details.

Versions of MissingH prior 0.11.6 lacked the BinaryConvertable class
and worked only with Strings and Handles.

Important note: /binary functions are not supported in all Haskell
implementations/.  Do not import or use this module unless you know you
are using an implementation that supports them.  At this time, here
is the support status:

 * GHC 6.2 and above: yes
 
 * GHC 6.x, earlier versions: unknown

 * GHC 5.x: no

 * nhc98: no

 * Hugs: partial (maybe complete; needs more testing)

Non-binary functions may be found in "MissingH.IO".

Written by <NAME>, <EMAIL>
-}

module MissingH.IO.Binary(
                       -- * Support for different types of blocks
                       BinaryConvertable(..),
                       -- * Entire File\/Handle Utilities
                       -- ** Opened Handle Data Copying
                       hBlockCopy, blockCopy,
                       -- ** Disk File Data Copying
                       copyFileBlocksToFile,
                       -- * Binary Single-Block I\/O
                       hPutBufStr, putBufStr, hGetBufStr, getBufStr,
                       hFullGetBufStr, fullGetBufStr,
                       -- * Binary Multi-Block I\/O
                       hGetBlocks, getBlocks, hFullGetBlocks, fullGetBlocks,
                       -- * Lazy Interaction
                       readBinaryFile, writeBinaryFile,
                       -- ** Binary Block-based
                       hBlockInteract, blockInteract,
                       hFullBlockInteract, fullBlockInteract
                        ) where

import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.C.String
import Foreign.C.Types
import Foreign.Storable
import Foreign.Marshal.Array
import Data.Word
import System.IO.Unsafe
import System.IO
import MissingH.IO.HVIO

{- | Provides support for handling binary blocks with convenient
types. -}
class BinaryConvertable a where
    toBuf :: a -> (Ptr CChar -> IO c) -> IO c
    fromBuf :: Int -> (Ptr CChar -> IO Int) -> IO a
    byteSize :: a -> Int

instance BinaryConvertable String where
    toBuf = withCString
    fromBuf len func = 
        do fbuf <- mallocForeignPtrArray (len + 1)
           withForeignPtr fbuf func
    byteSize = length

instance BinaryConvertable [Word8] where
    toBuf hslist func = withArray hslist (\ptr -> func (castPtr ptr))
    fromBuf len func =
        do (fbuf::(ForeignPtr Word8)) <- mallocForeignPtrArray (len + 1)
           withForeignPtr fbuf (\ptr -> func (castPtr ptr))
    byteSize = length


-- . **************************************************
-- . Binary Files
-- . **************************************************


{- | As a wrapper around the standard function 'System.IO.hPutBuf',
this function takes a standard Haskell 'String' instead of the far less
convenient 'Ptr a'.  The entire contents of the string will be written
as a binary buffer using 'hPutBuf'.  The length of the output will be
the length of the passed String or list..

If it helps, you can thing of this function as being of type
@Handle -> String -> IO ()@. -}
hPutBufStr :: (HVIO a, BinaryConvertable b) => a -> b -> IO ()
hPutBufStr f s = toBuf s (\cs -> vPutBuf f cs (byteSize s))

-- | An alias for 'hPutBufStr' 'stdout'
putBufStr :: (BinaryConvertable b) => b -> IO ()
putBufStr = hPutBufStr stdout

{- | Acts a wrapper around the standard function 'System.IO.hGetBuf',
this function returns a standard Haskell String (or Word8) instead of modifying
a 'Ptr a' buffer.  The length is the maximum length to read and the
semantice are the same as with 'hGetBuf'; namely, the empty string
is returned with EOF is reached, and any given read may read fewer
bytes than the given length.

(Actually, it's a wrapper around "MissingH.IO.HVIO.vGetBuf") -}
hGetBufStr :: (HVIO a, BinaryConvertable b) => a -> Int -> IO b
hGetBufStr f count = fromBuf count (
   fbuf <- mallocForeignPtrArray (count + 1)
   withForeignPtr fbuf (\buf -> do
                        bytesread <- hGetBuf f buf count
                        haskstring <- peekCStringLen (buf, bytesread)
                        return haskstring)

-- | An alias for 'hGetBufStr' 'stdin'
getBufStr :: Int -> IO String
getBufStr = hGetBufStr stdin

{- | Like 'hGetBufStr', but guarantees that it will only return fewer than
the requested number of bytes when EOF is encountered. -}
{'fraction_non_alphanumeric': 0.08902979240858161, 'fraction_numerical': 0.00842525840354382, 'mean_word_length': 2.6482889733840302, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4586109', 'n_tokens_mistral': 3237, 'n_tokens_neox': 2993, 'n_words': 1365}