summaryrefslogtreecommitdiff
path: root/external/semver/src/quickcheck/Semver.hsc
blob: c96eb00cbe92672668b2c673530f94cc0f74351a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
{-# LANGUAGE ForeignFunctionInterface #-}
module Semver where

#include "semantic_version_ffi.h"

import Foreign hiding (unsafePerformIO)
import Foreign.C.String
import Foreign.Storable
import System.IO.Unsafe (unsafePerformIO)

data Semver = Semver
    { vMajor :: #{type unsigned int}
    , vMinor :: #{type unsigned int}
    , vPatch :: #{type unsigned int}
    , vPrerelease :: String
    , vBuild :: String
    } deriving (Eq, Show)

-- don't bother with the strings for now

instance Storable Semver where
    sizeOf _    = #{size semver_t}
    alignment _ = alignment (undefined :: Word32)

    peek ptr = do
        r1 <- #{peek semver_t, major} ptr
        r2 <- #{peek semver_t, minor} ptr
        r3 <- #{peek semver_t, patch} ptr
        return (Semver r1 r2 r3 "" "")

    poke ptr (Semver r1 r2 r3 _ _) = do
        #{poke semver_t, major} ptr r1
        #{poke semver_t, minor} ptr r2
        #{poke semver_t, patch} ptr r3

-- c functions

foreign import ccall "semantic_version_ffi.h satisfies"
    c_satisfies :: Ptr Semver -> Ptr Semver -> IO Int
foreign import ccall "semantic_version_ffi.h lessThan"
    c_lessThan :: Ptr Semver -> Ptr Semver -> IO Int
foreign import ccall "semantic_version_ffi.h nextMajor"
    c_nextMajor :: Ptr Semver -> Ptr Semver -> IO ()
foreign import ccall "semantic_version_ffi.h nextMinor"
    c_nextMinor :: Ptr Semver -> Ptr Semver -> IO ()
foreign import ccall "semantic_version_ffi.h nextPatch"
    c_nextPatch :: Ptr Semver -> Ptr Semver -> IO ()

-- haskell wrappers

satisfies :: Semver -> Semver -> Bool
satisfies a b =
  unsafePerformIO $
  alloca $ \a_ptr ->
  alloca $ \b_ptr -> do
    poke a_ptr a
    poke b_ptr b
    r <- c_satisfies a_ptr b_ptr
    return $ if (r == 1) then True else False

lessThan :: Semver -> Semver -> Bool
lessThan a b =
  unsafePerformIO $
  alloca $ \a_ptr ->
  alloca $ \b_ptr -> do
    poke a_ptr a
    poke b_ptr b
    r <- c_lessThan a_ptr b_ptr
    return $ if (r == 1) then True else False

nextFunc :: (Ptr Semver -> Ptr Semver -> IO ()) -> Semver -> Semver
nextFunc f a =
  unsafePerformIO $
  alloca $ \a_ptr ->
  alloca $ \b_ptr -> do
    poke a_ptr a
    f a_ptr b_ptr
    peek b_ptr

nextMajor :: Semver -> Semver
nextMajor = nextFunc c_nextMajor

nextMinor :: Semver -> Semver
nextMinor = nextFunc c_nextMinor

nextPatch :: Semver -> Semver
nextPatch = nextFunc c_nextPatch