module System.Win32.DHCP.LengthBuffer ( LengthBuffer (..) , lengthBuffer ) where import Control.Applicative import Foreign.Ptr import Foreign.Storable import System.Win32.Types (DWORD) import System.Win32.DHCP.DhcpStructure import Utils (freeptr) -- |A LengthBuffer is a list of items which can be marshalled in and out -- of memory with a `DhcpArray` instance. data LengthBuffer a = LengthBuffer { lbLength :: Int , buffer :: [a] } lengthBuffer :: DhcpArray a -> DhcpStructure (LengthBuffer a) lengthBuffer dict = DhcpStructure { peekDhcp = peekLb dict , freeDhcp = freeLb dict , withDhcp' = withLb' dict , sizeDhcp = 8 } peekLb :: DhcpArray a -> Ptr (LengthBuffer a) -> IO (LengthBuffer a) peekLb dict ptr = do len <- fromIntegral <$> peek (pNumElements ptr) pElements <- peek $ ppElements ptr LengthBuffer len <$> peekDhcpArray dict len pElements freeLb :: DhcpArray a -> (Ptr x -> IO ()) -> Ptr (LengthBuffer a) -> IO () freeLb dict freefunc ptr = do len <- fromIntegral <$> peek (pNumElements ptr) pElements <- peek $ ppElements ptr freeDhcpArray dict freefunc len pElements withLb' :: DhcpArray a -> LengthBuffer a -> Ptr (LengthBuffer a) -> IO r -> IO r withLb' dict (LengthBuffer _ elems) ptr f = withDhcpArray dict elems $ \size pelems -> do pokeByteOff ptr 0 (fromIntegral size :: DWORD) poke (ppElements ptr) (castPtr pelems) f pNumElements :: Ptr (LengthBuffer a) -> Ptr DWORD pNumElements ptr = castPtr ptr ppElements :: Ptr (LengthBuffer a) -> Ptr (Ptr a) ppElements ptr = castPtr ptr `plusPtr` 4