packages feed

io-storage (empty) → 0.3

raw patch · 4 files changed

+160/−0 lines, 4 filesdep +basedep +containerssetup-changed

Dependencies added: base, containers

Files

+ 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