{-# INCLUDE #-} {-# INCLUDE #-} {-# LANGUAGE ForeignFunctionInterface #-} -- | -- Module : Data.UUID -- Copyright : (c) 2008 Antoine Latter -- -- License : BSD-style -- -- Maintainer : aslatter@gmail.com -- Stability : experimental -- Portability : portable -- -- Haskell bindings to /libuuid/. -- The library /libuuid/ is available as a part of e2fsprogs: -- . -- -- This library is useful for creating, comparing, parsing and -- printing Universally Unique Identifiers. -- See for the general idea. module Data.UUID(UUID ,fromString ,toString ,toStringUpper ,toStringLower ,generate ,generateRandom ,generateTime ,null ) where import Foreign.C.String import Foreign.C import Foreign.ForeignPtr import Foreign import Data.Typeable import Data.Generics.Basics import Prelude hiding (null) import Data.UUID.Internal instance Eq UUID where a == b = compare a b == EQ instance Ord UUID where compare (U fp1) (U fp2) = unsafePerformIO $ withForeignPtr fp1 $ \p1 -> withForeignPtr fp2 $ \p2 -> case c_compare p1 p2 of 0 -> return EQ n|n<0 -> return LT |n>0 -> return GT instance Show UUID where show = toString instance Read UUID where readsPrec _ str = case fromString (take 36 str) of Nothing -> [] Just u -> [(u,drop 36 str)] instance Typeable UUID where typeOf _ = mkTyConApp (mkTyCon "Data.UUID.UUID") [] instance Storable UUID where sizeOf _ = (16 *) $ alignment (undefined :: CChar) alignment _ = alignment (undefined :: CChar) peek psource = do fp <- mallocForeignPtrArray 16 withForeignPtr fp $ \pdest -> memcpy pdest psource $ fromIntegral $ sizeOf (undefined :: UUID) return $ U fp poke pdest (U fp) = withForeignPtr fp $ \psource -> memcpy pdest psource $ fromIntegral $ sizeOf (undefined :: UUID) -- My goal with this instance was to make it work just enough to do what -- I want when used with the HStringTemplate library. instance Data UUID where toConstr uu = mkConstr uuidType (show uu) [] (error "fixity") gunfold _ _ = error "gunfold" dataTypeOf _ = uuidType uuidType = mkNorepType "Data.UUID.UUID" -- |Creates a new 'UUID'. If \/dev\/urandom is available, it will be used. -- Otherwise a UUID will be generated based on the current time and the -- hardware MAC address, if available. generate :: IO UUID generate = do fp <- mallocForeignPtrArray 16 withForeignPtr fp $ \p -> c_generate p return $ U fp -- |Create a new 'UUID'. If \/dev\/urandom is available, it will be used. -- Otherwise a psuedorandom generator will be used. generateRandom :: IO UUID generateRandom = do fp <- mallocForeignPtrArray 16 withForeignPtr fp $ \p -> c_generate_random p return $ U fp -- |Create a new 'UUID'. The UUID will be generated based on the -- current time and the hardware MAC address, if available. generateTime :: IO UUID generateTime = do fp <- mallocForeignPtrArray 16 withForeignPtr fp $ \p -> c_generate_time p return $ U fp -- |Returns 'True' if the passed-in 'UUID' is the null UUID. null :: UUID -> Bool null (U fp) = unsafePerformIO $ withForeignPtr fp $ \p -> return $ c_null p == 1 -- |If the passed in 'String' can be parsed as a 'UUID', it will be. -- The hyphens may not be omitted. -- Example: -- -- @ -- fromString \"c2cc10e1-57d6-4b6f-9899-38d972112d8c\" -- @ -- -- Hex digits may be upper or lower-case. fromString :: String -> Maybe UUID fromString s = unsafePerformIO $ do fp <- mallocForeignPtrArray 16 res <- withCAString s $ \chars -> withForeignPtr fp $ \p -> c_read (castPtr chars) p case res of 0 -> return . Just $ U fp _ -> return Nothing -- |Returns a 'String' representation of the passed in 'UUID'. -- Hex digits occuring in the output will be either upper or -- lower-case depending on system defaults and locale. toString :: UUID -> String toString (U fp) = unsafePerformIO $ do chars <- mallocBytes 37 withForeignPtr fp $ \p -> c_show p chars st <- peekCAString chars free chars return st -- |Returns a 'String' representation of the passed in 'UUID'. -- Hex digits occuring in the output will be lower-case. toStringLower :: UUID -> String toStringLower (U fp) = unsafePerformIO $ do chars <- mallocBytes 37 withForeignPtr fp $ \p -> c_show_lower p chars st <- peekCAString chars free chars return st -- |Returns a 'String' representation of the passed in 'UUID'. -- Hex digits occuring in the output will be upper-case. toStringUpper :: UUID -> String toStringUpper (U fp) = unsafePerformIO $ do chars <- mallocBytes 37 withForeignPtr fp $ \p -> c_show_upper p chars st <- peekCAString chars free chars return st -- FFI calls to do the work type C_UUID = Ptr CChar -- comparing UUIDs foreign import ccall unsafe "uuid_compare" c_compare :: C_UUID -> C_UUID -> CInt -- making random UUIDs foreign import ccall unsafe "uuid_generate" c_generate :: C_UUID -> IO () foreign import ccall unsafe "uuid_generate_time" c_generate_time :: C_UUID -> IO () foreign import ccall unsafe "uuid_generate_random" c_generate_random :: C_UUID -> IO () -- Null check foreign import ccall unsafe "uuid_is_null" c_null :: C_UUID -> CInt -- Parsing foreign import ccall unsafe "uuid_parse" c_read :: CString -> C_UUID ->IO CInt -- Showing foreign import ccall unsafe "uuid_unparse" c_show :: C_UUID -> CString -> IO () foreign import ccall unsafe "uuid_unparse_lower" c_show_lower :: C_UUID -> CString -> IO () foreign import ccall unsafe "uuid_unparse_upper" c_show_upper :: C_UUID -> CString -> IO () -- Queries foreign import ccall unsafe "uuid_type" c_type :: C_UUID -> CInt foreign import ccall unsafe "uuid_variant" c_variant :: C_UUID -> CInt -- Other foreign import ccall unsafe "memcpy" memcpy :: Ptr a -> Ptr b -> CSize -> IO ()