io-storage (empty) → 0.3
raw patch · 4 files changed
+160/−0 lines, 4 filesdep +basedep +containerssetup-changed
Dependencies added: base, containers
Files
- LICENSE +28/−0
- Setup.hs +3/−0
- System/IO/Storage.hs +99/−0
- io-storage.cabal +30/−0
+ LICENSE view
@@ -0,0 +1,28 @@+Copyright (c) 2009, Will Donnelly+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++ * Neither the name of the software nor the names of its contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED+OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+import Distribution.Simple+main = defaultMain
+ System/IO/Storage.hs view
@@ -0,0 +1,99 @@+{- |+Conceptually, this library provides a way to arbitrarily extend the+global state represented by the IO monad. Viewed another way, this+library provides a basic facility for setting and retrieving values+from global variables.++The interface takes the form of a very basic key-value store, with+multiple different stores made available through the 'withStore'+function. Stores are referenced by arbitrary strings, and keys+within those stores are treated likewise. The 'putValue', 'getValue',+and 'delValue' functions allow you to store, retrieve, and delete+data from the store.++Internally, data is stored within an IORef which is created using the+'unsafePerformIO hack', but this is hidden within the library so that+it can easily be modified if and when a more 'proper' solution is+implemented.+-}+module System.IO.Storage+ ( withStore+ , putValue+ , getValue+ , getDefaultValue+ , delValue+ ) where++import Data.IORef ( IORef, newIORef, modifyIORef, readIORef )+import Data.List as L ( lookup, deleteFirstsBy )+import Data.Map as M ( Map, empty, lookup, insert, delete )+import Data.Dynamic ( Dynamic, toDyn, fromDyn, fromDynamic )+import Data.Typeable ( Typeable )+import Data.Function ( on )+import Control.Exception ( bracket )+import System.IO.Unsafe ( unsafePerformIO )++type ValueStore = M.Map String Dynamic++-- | This is the magic bit that makes the data-stores global to the+-- entire program. Sure, it cheats a little, but who doesn't?+globalPeg :: IORef [(String, IORef ValueStore)]+{-# NOINLINE globalPeg #-}+globalPeg = unsafePerformIO (newIORef [])++-- | Create a named key-value store, and then execute the given+-- IO action within its extent. Calls to 'withStore' can be+-- nested, and calling it again with the name of a data-store+-- that has already been initialized will cause the original+-- to be shadowed for the duration of the call to 'withStore'.+withStore :: String -> IO a -> IO a+withStore storeName action = do+ store <- newIORef M.empty+ let emptyStore = (storeName, store)+ let create = modifyIORef globalPeg (emptyStore:)+ let delete = modifyIORef globalPeg deleteStore+ bracket create (const delete) (const action)+ where deleteStore xs = deleteFirstsBy ((==) `on` fst) xs dummyStore+ dummyStore = [(storeName, undefined)]++getPrimitive :: String -> String -> IO (Maybe Dynamic)+getPrimitive storeName key = do+ storeList <- readIORef globalPeg+ case storeName `L.lookup` storeList of+ Nothing -> return Nothing+ Just st -> do map <- readIORef st+ return $ key `M.lookup` map++-- | Get a value from the given data-store, if it exists. If it+-- doesn't exist, obviously, 'Nothing' will be returned.+getValue :: Typeable a => String -> String -> IO (Maybe a)+getValue storeName key = do+ value <- getPrimitive storeName key+ case value of+ Nothing -> return $ Nothing+ Just dy -> return $ fromDynamic dy++-- | Get a value from the given store, with a default if it+-- doesn't exist.+getDefaultValue :: Typeable a => String -> String -> a -> IO a+getDefaultValue storeName key val = do+ value <- getPrimitive storeName key+ case value of+ Nothing -> return $ val+ Just dy -> return $ fromDyn dy val++-- | Put a value into the given data-store.+putValue :: Typeable a => String -> String -> a -> IO ()+putValue storeName key value = do+ storeList <- readIORef globalPeg+ case storeName `L.lookup` storeList of+ Nothing -> return ()+ Just st -> modifyIORef st . M.insert key . toDyn $ value++-- | Delete a value from the given data-store.+delValue :: String -> String -> IO ()+delValue storeName key = do+ storeList <- readIORef globalPeg+ case storeName `L.lookup` storeList of+ Nothing -> return ()+ Just st -> modifyIORef st . M.delete $ key
+ io-storage.cabal view
@@ -0,0 +1,30 @@+name: io-storage+version: 0.3+category: Database, Data, System+synopsis: A key-value store in the IO monad.++description: This library allows an application to extend the 'global state'+ hidden inside the IO monad with semi-arbitrary data. Data is+ required to be 'Typeable'. The library provides an essentially+ unbounded number of key-value stores indexed by strings, with+ each key within the stores also being a string.++homepage: http://github.com/willdonnelly/io-storage+bug-reports: http://github.com/willdonnelly/io-storage/issues+stability: alpha+author: Will Donnelly+maintainer: Will Donnelly <will.donnelly@gmail.com>+copyright: (c) 2009 Will Donnelly+license: BSD3+license-file: LICENSE++build-type: Simple+cabal-version: >= 1.6++library+ exposed-modules: System.IO.Storage+ build-depends: base >= 4 && < 5, containers++source-repository head+ type: git+ location: git://github.com/willdonnelly/io-storage.git