yaml (empty) → 0.0.0
raw patch · 7 files changed
+730/−0 lines, 7 filesdep +basedep +bytestringdep +bytestring-classsetup-changed
Dependencies added: base, bytestring, bytestring-class, data-object, haskell98
Files
- C2HS.hs +220/−0
- LICENSE +25/−0
- Setup.lhs +7/−0
- Text/Libyaml.chs +299/−0
- Text/Yaml.hs +98/−0
- c/helper.c +55/−0
- yaml.cabal +26/−0
+ C2HS.hs view
@@ -0,0 +1,220 @@+-- C->Haskell Compiler: Marshalling library+--+-- Copyright (c) [1999...2005] Manuel M T Chakravarty+--+-- Redistribution and use in source and binary forms, with or without+-- modification, are permitted provided that the following conditions are met:+-- +-- 1. Redistributions of source code must retain the above copyright notice,+-- this list of conditions and the following disclaimer. +-- 2. 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. +-- 3. The name of the author may not be used to endorse or promote products+-- derived from this software without specific prior written permission. +--+-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.+--+--- Description ---------------------------------------------------------------+--+-- Language: Haskell 98+--+-- This module provides the marshaling routines for Haskell files produced by +-- C->Haskell for binding to C library interfaces. It exports all of the+-- low-level FFI (language-independent plus the C-specific parts) together+-- with the C->HS-specific higher-level marshalling routines.+--++module C2HS (++ -- * Re-export the language-independent component of the FFI + module Foreign,++ -- * Re-export the C language component of the FFI+ module CForeign,++ -- * Composite marshalling functions+ withCStringLenIntConv, peekCStringLenIntConv, withIntConv, withFloatConv,+ peekIntConv, peekFloatConv, withBool, peekBool, withEnum, peekEnum,++ -- * Conditional results using 'Maybe'+ nothingIf, nothingIfNull,++ -- * Bit masks+ combineBitMasks, containsBitMask, extractBitMasks,++ -- * Conversion between C and Haskell types+ cIntConv, cFloatConv, cToBool, cFromBool, cToEnum, cFromEnum+) where +++import Foreign+ hiding (Word)+ -- Should also hide the Foreign.Marshal.Pool exports in+ -- compilers that export them+import CForeign++import Monad (when, liftM)+++-- Composite marshalling functions+-- -------------------------------++-- Strings with explicit length+--+withCStringLenIntConv s f = withCStringLen s $ \(p, n) -> f (p, cIntConv n)+peekCStringLenIntConv (s, n) = peekCStringLen (s, cIntConv n)++-- Marshalling of numerals+--++withIntConv :: (Storable b, Integral a, Integral b) + => a -> (Ptr b -> IO c) -> IO c+withIntConv = with . cIntConv++withFloatConv :: (Storable b, RealFloat a, RealFloat b) + => a -> (Ptr b -> IO c) -> IO c+withFloatConv = with . cFloatConv++peekIntConv :: (Storable a, Integral a, Integral b) + => Ptr a -> IO b+peekIntConv = liftM cIntConv . peek++peekFloatConv :: (Storable a, RealFloat a, RealFloat b) + => Ptr a -> IO b+peekFloatConv = liftM cFloatConv . peek++-- Passing Booleans by reference+--++withBool :: (Integral a, Storable a) => Bool -> (Ptr a -> IO b) -> IO b+withBool = with . fromBool++peekBool :: (Integral a, Storable a) => Ptr a -> IO Bool+peekBool = liftM toBool . peek+++-- Passing enums by reference+--++withEnum :: (Enum a, Integral b, Storable b) => a -> (Ptr b -> IO c) -> IO c+withEnum = with . cFromEnum++peekEnum :: (Enum a, Integral b, Storable b) => Ptr b -> IO a+peekEnum = liftM cToEnum . peek+++-- Storing of 'Maybe' values+-- -------------------------++instance Storable a => Storable (Maybe a) where+ sizeOf _ = sizeOf (undefined :: Ptr ())+ alignment _ = alignment (undefined :: Ptr ())++ peek p = do+ ptr <- peek (castPtr p)+ if ptr == nullPtr+ then return Nothing+ else liftM Just $ peek ptr++ poke p v = do+ ptr <- case v of+ Nothing -> return nullPtr+ Just v' -> new v'+ poke (castPtr p) ptr+++-- Conditional results using 'Maybe'+-- ---------------------------------++-- Wrap the result into a 'Maybe' type.+--+-- * the predicate determines when the result is considered to be non-existing,+-- ie, it is represented by `Nothing'+--+-- * the second argument allows to map a result wrapped into `Just' to some+-- other domain+--+nothingIf :: (a -> Bool) -> (a -> b) -> a -> Maybe b+nothingIf p f x = if p x then Nothing else Just $ f x++-- |Instance for special casing null pointers.+--+nothingIfNull :: (Ptr a -> b) -> Ptr a -> Maybe b+nothingIfNull = nothingIf (== nullPtr)+++-- Support for bit masks+-- ---------------------++-- Given a list of enumeration values that represent bit masks, combine these+-- masks using bitwise disjunction.+--+combineBitMasks :: (Enum a, Bits b) => [a] -> b+combineBitMasks = foldl (.|.) 0 . map (fromIntegral . fromEnum)++-- Tests whether the given bit mask is contained in the given bit pattern+-- (i.e., all bits set in the mask are also set in the pattern).+--+containsBitMask :: (Bits a, Enum b) => a -> b -> Bool+bits `containsBitMask` bm = let bm' = fromIntegral . fromEnum $ bm+ in+ bm' .&. bits == bm'++-- |Given a bit pattern, yield all bit masks that it contains.+--+-- * This does *not* attempt to compute a minimal set of bit masks that when+-- combined yield the bit pattern, instead all contained bit masks are+-- produced.+--+extractBitMasks :: (Bits a, Enum b, Bounded b) => a -> [b]+extractBitMasks bits = + [bm | bm <- [minBound..maxBound], bits `containsBitMask` bm]+++-- Conversion routines+-- -------------------++-- |Integral conversion+--+cIntConv :: (Integral a, Integral b) => a -> b+cIntConv = fromIntegral++-- |Floating conversion+--+cFloatConv :: (RealFloat a, RealFloat b) => a -> b+cFloatConv = realToFrac+-- As this conversion by default goes via `Rational', it can be very slow...+{-# RULES + "cFloatConv/Float->Float" forall (x::Float). cFloatConv x = x;+ "cFloatConv/Double->Double" forall (x::Double). cFloatConv x = x+ #-}++-- |Obtain C value from Haskell 'Bool'.+--+cFromBool :: Num a => Bool -> a+cFromBool = fromBool++-- |Obtain Haskell 'Bool' from C value.+--+cToBool :: Num a => a -> Bool+cToBool = toBool++-- |Convert a C enumeration to Haskell.+--+cToEnum :: (Integral i, Enum e) => i -> e+cToEnum = toEnum . cIntConv++-- |Convert a Haskell enumeration to C.+--+cFromEnum :: (Enum e, Integral i) => e -> i+cFromEnum = cIntConv . fromEnum
+ LICENSE view
@@ -0,0 +1,25 @@+The following license covers this documentation, and the source code, except+where otherwise indicated.++Copyright 2008, Michael Snoyman. 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.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "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 HOLDERS 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.lhs view
@@ -0,0 +1,7 @@+#!/usr/bin/env runhaskell++> module Main where+> import Distribution.Simple++> main :: IO ()+> main = defaultMain
+ Text/Libyaml.chs view
@@ -0,0 +1,299 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module Text.Libyaml+ ( Event (..)+ , parserParse+ , withParser+ , emitEvents+ , withEmitter+ ) where++#include <yaml.h>+#include "../../../c/helper.h"++import C2HS+import qualified Data.ByteString.Internal as B+import Control.Monad++{#context lib="yaml" #}++{#pointer *yaml_parser_t as Parser newtype#}+parserSize :: Int+parserSize = {#sizeof yaml_parser_t#}++{#pointer *yaml_event_t as EventRaw newtype#}+eventSize :: Int+eventSize = {#sizeof yaml_event_t#}++{#fun unsafe yaml_parser_initialize+ { id `Parser'+ } -> `Int' #}++{#fun unsafe yaml_parser_delete+ { id `Parser'+ } -> `()' #}++withParser :: B.ByteString -> (Parser -> IO a) -> IO a+withParser bs f = do+ allocaBytes parserSize $ \p ->+ do+ let p' = Parser p+ _res <- yaml_parser_initialize p'+ -- FIXME check res+ let (fptr, offset, len) = B.toForeignPtr bs+ ret <- withForeignPtr fptr $ \ptr ->+ do+ let ptr' = castPtr ptr `plusPtr` offset+ yaml_parser_set_input_string p' ptr' len+ f p'+ yaml_parser_delete p'+ return ret++withEventRaw :: (EventRaw -> IO a) -> IO a+withEventRaw f = allocaBytes eventSize $ f . EventRaw++{#fun unsafe yaml_parser_set_input_string+ { id `Parser'+ , id `Ptr CUChar'+ , `Int'+ } -> `()' #}++{#fun unsafe yaml_parser_parse+ { id `Parser'+ , id `EventRaw'+ } -> `Int' #}++{#fun unsafe yaml_event_delete+ { id `EventRaw'+ } -> `()' #}++parserParse :: Parser -> IO [Event]+parserParse parser = do+ event <- parserParseOne parser+ case event of+ EventStreamEnd -> return [event]+ _ -> do+ rest <- parserParse parser+ return $! event : rest++{#fun unsafe print_parser_error+ { id `Parser'+ } -> `()' #}++parserParseOne :: Parser -> IO Event+parserParseOne parser = withEventRaw $ \er -> do+ res <- yaml_parser_parse parser er+ when (res == 0) $+ print_parser_error parser >> fail "yaml_parser_parse failed"+ event <- getEvent er+ yaml_event_delete er+ return event++data Event =+ EventNone+ | EventStreamStart+ | EventStreamEnd+ | EventDocumentStart+ | EventDocumentEnd+ | EventAlias+ | EventScalar B.ByteString+ | EventSequenceStart+ | EventSequenceEnd+ | EventMappingStart+ | EventMappingEnd+ deriving (Show)++{#enum yaml_event_type_e as EventType {underscoreToCase} deriving (Show) #}+getEvent :: EventRaw -> IO Event+getEvent (EventRaw ptr') = do+ et <- {#get yaml_event_t.type#} ptr'+ case toEnum $ fromEnum et of+ YamlNoEvent -> return EventNone+ YamlStreamStartEvent -> return EventStreamStart+ YamlStreamEndEvent -> return EventStreamEnd+ YamlDocumentStartEvent -> return EventDocumentStart+ YamlDocumentEndEvent -> return EventDocumentEnd+ YamlAliasEvent -> return EventAlias+ YamlScalarEvent -> do+ yvalue <- {#get yaml_event_t.data.scalar.value#} ptr'+ ylen <- {#get yaml_event_t.data.scalar.length#} ptr'+ let yvalue' = castPtr yvalue+ let ylen' = fromEnum ylen+ let ylen'' = toEnum $ fromEnum ylen+ bs <- B.create ylen' $ \dest -> B.memcpy dest yvalue' ylen''+ return $ EventScalar bs+ YamlSequenceStartEvent -> return EventSequenceStart+ YamlSequenceEndEvent -> return EventSequenceEnd+ YamlMappingStartEvent -> return EventMappingStart+ YamlMappingEndEvent -> return EventMappingEnd++-- Emitter+{#pointer *yaml_emitter_t as Emitter newtype#}+emitterSize :: Int+emitterSize = {#sizeof yaml_emitter_t#}++{#fun unsafe yaml_emitter_initialize+ { id `Emitter'+ } -> `Int' #}++{#fun unsafe yaml_emitter_delete+ { id `Emitter'+ } -> `()' #}++{#pointer *buffer_t as Buffer newtype#}+bufferSize :: Int+bufferSize = {#sizeof buffer_t#}++{#fun unsafe buffer_init+ { id `Buffer'+ } -> `()' #}++withBuffer :: (Buffer -> IO ()) -> IO B.ByteString+withBuffer f = do+ allocaBytes bufferSize $ \b -> do+ let b' = Buffer b+ buffer_init b'+ f b'+ ptr' <- {#get buffer_t.buff#} b+ len <- {#get buffer_t.used#} b+ fptr <- newForeignPtr_ $ castPtr ptr'+ return $! B.fromForeignPtr fptr 0 $ fromIntegral len++{#fun unsafe yaml_emitter_set_output+ { id `Emitter'+ , id `FunPtr (Ptr () -> Ptr CUChar -> CULong -> IO CInt)'+ , id `Ptr ()'+ } -> `()' #}++foreign import ccall "buffer.h &buffer_append"+ buffer_append :: FunPtr (Ptr () -> Ptr CUChar -> CULong -> IO CInt)++withEmitter :: (Emitter -> IO ()) -> IO B.ByteString+withEmitter f = do+ allocaBytes emitterSize $ \e -> do+ let e' = Emitter e+ _res <- yaml_emitter_initialize e'+ -- FIXME check res+ bs <- withBuffer $ \(Buffer b) -> do+ let fun = buffer_append+ yaml_emitter_set_output e' buffer_append $ castPtr b+ f e'+ yaml_emitter_delete e'+ return bs++{#fun unsafe yaml_emitter_emit+ { id `Emitter'+ , id `EventRaw'+ } -> `Int' #}++{#fun unsafe print_emitter_error+ { id `Emitter'+ } -> `()' #}++emitEvents :: Emitter -> [Event] -> IO ()+emitEvents _ [] = return ()+emitEvents emitter (e:rest) = do+ res <- toEventRaw e $ yaml_emitter_emit emitter+ when (res == 0) $+ print_emitter_error emitter >> fail "yaml_emitter_emit failed"+ emitEvents emitter rest++{#fun unsafe yaml_stream_start_event_initialize+ { id `EventRaw'+ , `Int'+ } -> `Int' #}++{#fun unsafe yaml_stream_end_event_initialize+ { id `EventRaw'+ } -> `Int' #}++{#fun unsafe yaml_scalar_event_initialize+ { id `EventRaw'+ , id `Ptr CUChar' -- anchor+ , id `Ptr CUChar' -- tag+ , id `Ptr CUChar' -- value+ , `Int'+ , `Int'+ , `Int'+ , `Int'+ } -> `Int' #}++{#fun unsafe simple_document_start+ { id `EventRaw'+ } -> `Int' #}++{#fun unsafe yaml_document_end_event_initialize+ { id `EventRaw'+ , `Int'+ } -> `Int' #}++{#fun unsafe yaml_sequence_start_event_initialize+ { id `EventRaw'+ , id `Ptr CUChar'+ , id `Ptr CUChar'+ , `Int'+ , `Int'+ } -> `Int' #}++{#fun unsafe yaml_sequence_end_event_initialize+ { id `EventRaw'+ } -> `Int' #}++{#fun unsafe yaml_mapping_start_event_initialize+ { id `EventRaw'+ , id `Ptr CUChar'+ , id `Ptr CUChar'+ , `Int'+ , `Int'+ } -> `Int' #}++{#fun unsafe yaml_mapping_end_event_initialize+ { id `EventRaw'+ } -> `Int' #}++toEventRaw :: Event -> (EventRaw -> IO a) -> IO a+toEventRaw e f = withEventRaw $ \er -> do+ case e of+ EventStreamStart ->+ yaml_stream_start_event_initialize+ er+ 0 -- YAML_ANY_ENCODING+ EventStreamEnd ->+ yaml_stream_end_event_initialize er+ EventDocumentStart ->+ simple_document_start er+ EventDocumentEnd ->+ yaml_document_end_event_initialize er 1+ EventScalar bs -> do+ let (fvalue, offset, len) = B.toForeignPtr bs+ withForeignPtr fvalue $ \value -> do+ let value' = value `plusPtr` offset+ yaml_scalar_event_initialize+ er+ nullPtr+ nullPtr+ value'+ len+ 0+ 1+ 0 -- YAML_ANY_SCALAR_STYLE+ EventSequenceStart ->+ yaml_sequence_start_event_initialize+ er+ nullPtr+ nullPtr+ 1+ 0 -- YAML_ANY_SEQUENCE_STYLE+ EventSequenceEnd ->+ yaml_sequence_end_event_initialize er+ EventMappingStart ->+ yaml_mapping_start_event_initialize+ er+ nullPtr+ nullPtr+ 1+ 0 -- YAML_ANY_SEQUENCE_STYLE+ EventMappingEnd ->+ yaml_mapping_end_event_initialize er+ EventAlias -> error "toEventRaw: EventAlias not supported"+ EventNone -> error "toEventRaw: EventNone not supported"+ f er
+ Text/Yaml.hs view
@@ -0,0 +1,98 @@+---------------------------------------------------------+--+-- Module : Text.Yaml+-- Copyright : Michael Snoyman+-- License : BSD3+--+-- Maintainer : Michael Snoyman <michael@snoyman.com>+-- Stability : Stable+-- Portability : portable+--+-- Provides a user friendly interface for serializing Yaml data.+--+---------------------------------------------------------++module Text.Yaml+ ( module Data.Object+ , encode+ , encodeFile+ , decode+ , decodeFile+ ) where++import Prelude hiding (readList)+import Text.Libyaml+import qualified Data.ByteString as B+import Data.ByteString.Class+import Data.Object+import System.IO.Unsafe++encode :: (StrictByteString bs, ToObject o) => o -> bs+encode = unsafePerformIO . encode'++decode :: (Monad m, StrictByteString bs, FromObject o) => bs -> m o+decode = unsafePerformIO . decode'++encodeFile :: ToObject o => FilePath -> o -> IO ()+encodeFile path o = encode' o >>= B.writeFile path++decodeFile :: (Monad m, FromObject o) => FilePath -> IO (m o)+decodeFile path = do+ c <- B.readFile path+ decode' c++encode' :: (StrictByteString bs, ToObject o) => o -> IO bs+encode' o =+ let events = objectToEvents $ toObject o+ result = withEmitter $ flip emitEvents $ events+ in fromStrictByteString `fmap` result++decode' :: (Monad m, StrictByteString bs, FromObject o) => bs -> IO (m o)+decode' bs = do+ let bs' = toStrictByteString bs+ events = withParser bs' parserParse+ (fromObject . eventsToObject) `fmap` events++objectToEvents :: Object -> [Event]+objectToEvents y = concat+ [ [EventStreamStart, EventDocumentStart]+ , writeSingle y+ , [EventDocumentEnd, EventStreamEnd]] where+ writeSingle :: Object -> [Event]+ writeSingle (Scalar bs) = [EventScalar bs]+ writeSingle (Sequence ys) =+ (EventSequenceStart : concatMap writeSingle ys)+ ++ [EventSequenceEnd]+ writeSingle (Mapping pairs) =+ EventMappingStart : concatMap writePair pairs ++ [EventMappingEnd]+ writePair :: (B.ByteString, Object) -> [Event]+ writePair (k, v) = EventScalar k : writeSingle v++eventsToObject :: [Event] -> Object+eventsToObject = fst . readSingle . dropWhile isIgnored where+ isIgnored EventAlias = False+ isIgnored (EventScalar _) = False+ isIgnored EventSequenceStart = False+ isIgnored EventSequenceEnd = False+ isIgnored EventMappingStart = False+ isIgnored EventMappingEnd = False+ isIgnored _ = True+ readSingle :: [Event] -> (Object, [Event])+ readSingle [] = error "readSingle: no more events"+ readSingle (EventScalar bs:rest) = (Scalar bs, rest)+ readSingle (EventSequenceStart:rest) = readList [] rest+ readSingle (EventMappingStart:rest) = readMap [] rest+ readSingle (x:_) = error $ "readSingle: " ++ show x+ readList :: [Object] -> [Event] -> (Object, [Event])+ readList nodes (EventSequenceEnd:rest) =+ (Sequence $ reverse nodes, rest)+ readList nodes events =+ let (next, rest) = readSingle events+ in readList (next : nodes) rest+ readMap :: [(B.ByteString, Object)] -> [Event] -> (Object, [Event])+ readMap pairs (EventMappingEnd:rest) = (Mapping $ reverse pairs, rest)+ readMap pairs (EventScalar bs:events) =+ let (next, rest) = readSingle events+ in readMap ((fromStrictByteString bs, next) : pairs) rest+ readMap _ (e:_) = error $ "Unexpected event in readMap: " ++ show e+ readMap _ [] = error "Unexpected empty event list in readMap"
+ c/helper.c view
@@ -0,0 +1,55 @@+#include <stdlib.h>+#include <string.h>+#include <stdio.h>+#include "helper.h"++void buffer_init(buffer_t *buffer)+{+ buffer->buff = 0;+ buffer->size = buffer->used = 0;+}++int buffer_append(void *ext, unsigned char *str, size_t size)+{+ buffer_t *b = ext;+ int new_size, new_used;+ char *tmp;++ new_used = b->used + size;+ for (new_size = b->size || 8; new_size < new_used; new_size *= 2);++ if (new_size != b->size) {+ tmp = realloc(b->buff, new_size);+ if (!tmp) return 0;+ b->buff = tmp;+ b->size = new_size;+ }++ memcpy(b->buff + b->used, str, size);+ b->used = new_used;++ return 1;+}++void print_parser_error(yaml_parser_t *p)+{+ fprintf(stderr, "Problem: %s\nContext: %s\nOffset: %u\n",+ p->problem,+ p->context,+ (unsigned int) p->problem_offset);+}++void print_emitter_error(yaml_emitter_t *e)+{+ fprintf(stderr, "%s\n", e->problem);+}++int simple_document_start(yaml_event_t *e)+{+ return yaml_document_start_event_initialize+ (e,+ 0,+ 0,+ 0,+ 1);+}
+ yaml.cabal view
@@ -0,0 +1,26 @@+name: yaml+version: 0.0.0+license: BSD3+license-file: LICENSE+author: Michael Snoyman <michael@snoyman.com>+maintainer: Michael Snoyman <michael@snoyman.com>+synopsis: Support for serialising Haskell to and from Yaml.+description: Binds to the libyaml library+category: Web+stability: unstable+cabal-version: >= 1.2+build-type: Simple+homepage: http://github.com/snoyberg/yaml/tree/master++library+ build-depends: base >= 4 && < 5,+ bytestring-class,+ data-object,+ bytestring >= 0.9.1.4 && < 1,+ haskell98+ exposed-modules: Text.Yaml+ other-modules: Text.Libyaml,+ C2HS+ ghc-options: -Wall+ c-sources: c/helper.c+ extra-libraries: yaml