Adjust to new libdpkg API
[sat-britney.git] / DebVersionCmp.hs
1 {-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}
2 -- |
3 -- Module: DebVersionCmp
4 -- Copyright: (c) 2011 Joachim Breitner
5 -- License: GPL-2
6 --
7 module DebVersionCmp where
8
9 import System.IO.Unsafe
10 import Foreign.Ptr
11 import Foreign.Marshal
12 import Foreign.C.Types
13 import Foreign.C.String
14
15 import qualified Data.ByteString as BS
16
17 data ParsedVersion
18
19 data DpkgError
20
21 foreign import ccall unsafe "dpkg/dpkg-db.h parseversion"
22     c_ParseVersion :: Ptr ParsedVersion -> CString -> Ptr DpkgError -> IO CInt
23
24 foreign import ccall unsafe "dpkg/version.h dpkg_version_compare"
25     c_VersionCompare :: Ptr ParsedVersion -> Ptr ParsedVersion -> IO CInt
26
27 foreign export ccall "thisname" blubb :: ()
28
29 blubb :: ()
30 blubb = ()
31
32 versionCompare :: BS.ByteString -> BS.ByteString -> Ordering
33 versionCompare v1 v2 = unsafePerformIO $
34     -- 12 bytes is enough to carry a struct versionrevision
35     allocaBytes 12 $ \ptr1 -> allocaBytes 12 $ \ptr2 ->  
36     allocaBytes 16 $ \eptr -> 
37     BS.useAsCString v1 $ \v1p -> BS.useAsCString v2 $ \v2p -> do
38         r1 <- c_ParseVersion ptr1 v1p eptr
39         if (r1 /= 0)
40             then peekCString (castPtr (eptr `plusPtr` 8)) >>= \err -> error $ "Failed to parse " ++ show v1 ++ ": " ++ err
41             else do
42         r2 <- c_ParseVersion ptr2 v2p eptr
43         if (r2 /= 0) 
44             then peekCString (castPtr (eptr `plusPtr` 8)) >>= \err -> error $ "Failed to parse " ++ show v2 ++ ": " ++ err
45             else do
46         r3 <- c_VersionCompare ptr1 ptr2
47         return $ if r3 < 0 then LT else if r3 == 0 then EQ else GT