module EntryDB (getEntry, loadEntries, addEntry, updateEntry) where import Entry import Control.Monad import Data.Char import Data.List import System.Directory import System.IO dataDir = "data" entryFile = dataDir ++ "/" ++ "entries.db" getEntry :: EntryID -> IO Entry getEntry eid = do es <- loadEntries case filter ((==eid) . entryID) es of [e] -> return e xs -> fail $ "Entry " ++ show eid ++ ": " ++ show xs loadEntries :: IO [Entry] loadEntries = do e <- doesFileExist entryFile if e then readFile entryFile >>= readEntries else return [] saveEntries :: [Entry] -> IO () saveEntries es = do (f,h) <- openTempFile dataDir "entries.tmp" mapM_ (hPutStrLn h . show) es hClose h renameFile f entryFile modifyEntries :: ([Entry] -> [Entry]) -> IO () modifyEntries f = loadEntries >>= saveEntries . f -- | Overwrites the 'entryID' field. addEntry :: Entry -> IO () addEntry e = modifyEntries $ \es -> let eid = case sort (map entryID es) of { [] -> 0; xs -> last xs + 1 } e' = e { entryID = eid } in (e':es) updateEntry :: Entry -> IO () updateEntry e = modifyEntries $ (e:) . filter ((/= entryID e) . entryID) readEntries :: Monad m => String -> m [Entry] readEntries "" = return [] readEntries s = case reads s of [(e,rest)] -> liftM (e:) $ readEntries (dropWhile isSpace rest) _ -> fail $ "Corrupted database: " ++ show s