packages feed

foundation 0.0.19 → 0.0.20

raw patch · 27 files changed

+542/−48 lines, 27 filesdep +template-haskelldep ~basedep ~basementdep ~gaugePVP ok

version bump matches the API change (PVP)

Dependencies added: template-haskell

Dependency ranges changed: base, basement, gauge

API changes (from Hackage documentation)

+ Foundation.Check: propertyCompareWith :: String -> (a -> a -> Bool) -> (a -> String) -> a -> a -> PropertyCheck
+ Foundation.Format.CSV: DoubleEscape :: Escaping
+ Foundation.Format.CSV: Escape :: Escaping
+ Foundation.Format.CSV: FieldDouble :: Double -> Field
+ Foundation.Format.CSV: FieldInteger :: Integer -> Field
+ Foundation.Format.CSV: FieldString :: String -> Escaping -> Field
+ Foundation.Format.CSV: NoEscape :: Escaping
+ Foundation.Format.CSV: class ToField a
+ Foundation.Format.CSV: class ToRow a
+ Foundation.Format.CSV: csvBlockBuilder :: CSV -> Builder
+ Foundation.Format.CSV: csvStringBuilder :: CSV -> Builder
+ Foundation.Format.CSV: data CSV
+ Foundation.Format.CSV: data Escaping
+ Foundation.Format.CSV: data Field
+ Foundation.Format.CSV: data Row
+ Foundation.Format.CSV: fieldBlockBuilder :: Field -> Builder
+ Foundation.Format.CSV: fieldStringBuilder :: Field -> Builder
+ Foundation.Format.CSV: float :: Double -> Field
+ Foundation.Format.CSV: instance (Foundation.Format.CSV.ToField a, Foundation.Format.CSV.ToField b) => Foundation.Format.CSV.ToRow (a, b)
+ Foundation.Format.CSV: instance (Foundation.Format.CSV.ToField a, Foundation.Format.CSV.ToField b, Foundation.Format.CSV.ToField c) => Foundation.Format.CSV.ToRow (a, b, c)
+ Foundation.Format.CSV: instance (Foundation.Format.CSV.ToField a, Foundation.Format.CSV.ToField b, Foundation.Format.CSV.ToField c, Foundation.Format.CSV.ToField d) => Foundation.Format.CSV.ToRow (a, b, c, d)
+ Foundation.Format.CSV: instance (Foundation.Format.CSV.ToField a, Foundation.Format.CSV.ToField b, Foundation.Format.CSV.ToField c, Foundation.Format.CSV.ToField d, Foundation.Format.CSV.ToField e) => Foundation.Format.CSV.ToRow (a, b, c, d, e)
+ Foundation.Format.CSV: instance (Foundation.Format.CSV.ToField a, Foundation.Format.CSV.ToField b, Foundation.Format.CSV.ToField c, Foundation.Format.CSV.ToField d, Foundation.Format.CSV.ToField e, Foundation.Format.CSV.ToField f) => Foundation.Format.CSV.ToRow (a, b, c, d, e, f)
+ Foundation.Format.CSV: instance Basement.NormalForm.NormalForm Foundation.Format.CSV.CSV
+ Foundation.Format.CSV: instance Basement.NormalForm.NormalForm Foundation.Format.CSV.Escaping
+ Foundation.Format.CSV: instance Basement.NormalForm.NormalForm Foundation.Format.CSV.Field
+ Foundation.Format.CSV: instance Basement.NormalForm.NormalForm Foundation.Format.CSV.Row
+ Foundation.Format.CSV: instance Data.Semigroup.Semigroup Foundation.Format.CSV.CSV
+ Foundation.Format.CSV: instance Data.Semigroup.Semigroup Foundation.Format.CSV.Row
+ Foundation.Format.CSV: instance Foundation.Check.Arbitrary.Arbitrary Foundation.Format.CSV.Field
+ Foundation.Format.CSV: instance Foundation.Collection.Collection.Collection Foundation.Format.CSV.CSV
+ Foundation.Format.CSV: instance Foundation.Collection.Collection.Collection Foundation.Format.CSV.Row
+ Foundation.Format.CSV: instance Foundation.Collection.Indexed.IndexedCollection Foundation.Format.CSV.CSV
+ Foundation.Format.CSV: instance Foundation.Collection.Indexed.IndexedCollection Foundation.Format.CSV.Row
+ Foundation.Format.CSV: instance Foundation.Collection.Sequential.Sequential Foundation.Format.CSV.CSV
+ Foundation.Format.CSV: instance Foundation.Collection.Sequential.Sequential Foundation.Format.CSV.Row
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField (Basement.Types.OffsetSize.CountOf a)
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField (Basement.Types.OffsetSize.Offset a)
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField Basement.Types.Word128.Word128
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField Basement.Types.Word256.Word256
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField Basement.UTF8.Base.String
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField Foundation.Format.CSV.Field
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Int.Int16
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Int.Int32
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Int.Int64
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Int.Int8
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Integer.Type.Integer
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Natural.Natural
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Types.Char
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Types.Double
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Types.Int
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Types.Word
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Word.Word16
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Word.Word32
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Word.Word64
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField GHC.Word.Word8
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField [GHC.Types.Char]
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToField a => Foundation.Format.CSV.ToField (GHC.Base.Maybe a)
+ Foundation.Format.CSV: instance Foundation.Format.CSV.ToRow Foundation.Format.CSV.Row
+ Foundation.Format.CSV: instance GHC.Base.Monoid Foundation.Format.CSV.CSV
+ Foundation.Format.CSV: instance GHC.Base.Monoid Foundation.Format.CSV.Row
+ Foundation.Format.CSV: instance GHC.Classes.Eq Foundation.Format.CSV.CSV
+ Foundation.Format.CSV: instance GHC.Classes.Eq Foundation.Format.CSV.Escaping
+ Foundation.Format.CSV: instance GHC.Classes.Eq Foundation.Format.CSV.Field
+ Foundation.Format.CSV: instance GHC.Classes.Eq Foundation.Format.CSV.Row
+ Foundation.Format.CSV: instance GHC.Classes.Ord Foundation.Format.CSV.Escaping
+ Foundation.Format.CSV: instance GHC.Enum.Bounded Foundation.Format.CSV.Escaping
+ Foundation.Format.CSV: instance GHC.Enum.Enum Foundation.Format.CSV.Escaping
+ Foundation.Format.CSV: instance GHC.Exts.IsList Foundation.Format.CSV.CSV
+ Foundation.Format.CSV: instance GHC.Exts.IsList Foundation.Format.CSV.Row
+ Foundation.Format.CSV: instance GHC.Show.Show Foundation.Format.CSV.CSV
+ Foundation.Format.CSV: instance GHC.Show.Show Foundation.Format.CSV.Escaping
+ Foundation.Format.CSV: instance GHC.Show.Show Foundation.Format.CSV.Field
+ Foundation.Format.CSV: instance GHC.Show.Show Foundation.Format.CSV.Row
+ Foundation.Format.CSV: integral :: Into Integer a => a -> Field
+ Foundation.Format.CSV: rowBlockBuilder :: Row -> Builder
+ Foundation.Format.CSV: rowC :: (ToRow row, Monad m) => Conduit row (Block Word8) m ()
+ Foundation.Format.CSV: rowStringBuilder :: Row -> Builder
+ Foundation.Format.CSV: string :: String -> Field
+ Foundation.Format.CSV: toField :: ToField a => a -> Field
+ Foundation.Format.CSV: toRow :: ToRow a => a -> Row

Files

CHANGELOG.md view
@@ -1,3 +1,14 @@+## 0.0.20++* Reduce algorithm duplication between native and foreign backend+* Improve Unicode cases algorithm and increase testing+* Add CSV Builder+* Add a BitOps & FiniteBitOps classes to have better types than the Data.Bits.Bits class+* Improve BlockN operations+* Improve ListN operations+* Allow compilation with gauge 0.1+* Add support for [haskell-ci](https://github.com/vincenthz/haskell-ci)+ ## 0.0.19  * Add Block, UArray, String Builder
Foundation/Array/Bitmap.hs view
@@ -39,6 +39,7 @@ import           Basement.Compat.Base import           Basement.Types.OffsetSize import           Basement.Monad+ import qualified Foundation.Collection as C import           Foundation.Numerical import           Data.Bits@@ -146,6 +147,8 @@     mutUnsafeRead = unsafeRead     mutWrite = write     mutRead = read++  bitmapIndex :: Offset Bool -> (Offset Word32, Int) bitmapIndex (Offset !i) = (Offset (i .>>. shiftPerTy), i .&. maskPerTy)
Foundation/Check.hs view
@@ -26,6 +26,7 @@     , IsProperty(..)     , (===)     , propertyCompare+    , propertyCompareWith     , propertyAnd     , propertyFail     , forAll
Foundation/Check/Main.hs view
@@ -34,7 +34,6 @@ import           Foundation.Random import           Foundation.Monad import           Foundation.Monad.State-import           Control.Monad (when) import           Data.Maybe (catMaybes)  nbFail :: TestResult -> HasFailures@@ -273,8 +272,10 @@         then return (GroupResult name 0 (planValidations st) [])         else do             displayCurrent name-            forM_ fails $ \f ->-                liftIO $ putStrLn $ show f+            forM_ fails $ \(PropertyResult name' nb r) ->+                case r of+                    PropertySuccess  -> whenVerbose $ displayPropertySucceed (name <> ": " <> name') nb+                    PropertyFailed w -> whenErrorOnly $ displayPropertyFailed (name <> ": " <> name') nb w             return (GroupResult name (length fails) (planValidations st) fails)  testProperty :: String -> Property -> CheckMain TestResult
Foundation/Check/Property.hs view
@@ -12,6 +12,7 @@     , forAll     , (===)     , propertyCompare+    , propertyCompareWith     , propertyAnd     , propertyFail     ) where@@ -92,9 +93,22 @@                 -> a                -- ^ value left of the operator                 -> a                -- ^ value right of the operator                 -> PropertyCheck-propertyCompare name op a b =-    let sa = pretty a Proxy-        sb = pretty b Proxy+propertyCompare name op = propertyCompareWith name op (flip pretty Proxy)++-- | A property that check for a specific comparaison of its 2 members.+--+-- This is equivalent to `===` but with `compare` and a given method to+-- pretty print the values.+--+propertyCompareWith :: String           -- ^ name of the function used for comparaison, e.g. (<)+                    -> (a -> a -> Bool) -- ^ function used for value comparaison+                    -> (a -> String)    -- ^ function used to pretty print the values+                    -> a                -- ^ value left of the operator+                    -> a                -- ^ value right of the operator+                    -> PropertyCheck+propertyCompareWith name op display a b =+    let sa = display a+        sb = display b      in PropertyBinaryOp (a `op` b) name sa sb  -- | A conjuctive property composed of 2 properties that need to pass
Foundation/Collection/Copy.hs view
@@ -1,14 +1,24 @@+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE CPP #-}+ module Foundation.Collection.Copy     ( Copy(..)     ) where  import           GHC.ST (runST) import           Basement.Compat.Base ((>>=))+import           Basement.Nat+import           Basement.Types.OffsetSize import qualified Basement.Block as BLK import qualified Basement.UArray as UA import qualified Basement.BoxedArray as BA import qualified Basement.String as S +#if MIN_VERSION_base(4,9,0)+import qualified Basement.Sized.Block as BLKN+import qualified Basement.Sized.List  as LN+#endif+ class Copy a where     copy :: a -> a instance Copy [ty] where@@ -21,3 +31,10 @@     copy = BA.copy instance Copy S.String where     copy = S.copy++#if MIN_VERSION_base(4,9,0)+instance Copy (LN.ListN n ty) where+    copy a = a+instance (Countable ty n, UA.PrimType ty, KnownNat n) => Copy (BLKN.BlockN n ty) where+    copy blk = runST (BLKN.thaw blk >>= BLKN.freeze)+#endif
Foundation/Collection/Element.hs view
@@ -5,6 +5,9 @@ -- Stability   : experimental -- Portability : portable --++{-# LANGUAGE CPP #-}+ module Foundation.Collection.Element     ( Element     ) where@@ -18,6 +21,11 @@ import Basement.Types.Char7 (Char7) import Basement.NonEmpty +#if MIN_VERSION_base(4,9,0)+import Basement.Sized.Block (BlockN)+import Basement.Sized.List  (ListN)+#endif+ -- | Element type of a collection type family Element container type instance Element [a] = a@@ -27,3 +35,8 @@ type instance Element String = Char type instance Element AsciiString = Char7 type instance Element (NonEmpty a) = Element a++#if MIN_VERSION_base(4,9,0)+type instance Element (BlockN n ty) = ty+type instance Element (ListN n a) = a+#endif
Foundation/Collection/Foldable.hs view
@@ -7,6 +7,14 @@ -- -- A mono-morphic re-thinking of the Foldable class --++{-# LANGUAGE CPP                   #-}++#if MIN_VERSION_base(4,9,0)+{-# LANGUAGE DataKinds     #-}+{-# LANGUAGE TypeOperators #-}+#endif+ module Foundation.Collection.Foldable     ( Foldable(..)     , Fold1able(..)@@ -15,11 +23,17 @@ import           Basement.Compat.Base import           Foundation.Collection.Element import           Basement.NonEmpty+import           Basement.Nat import qualified Data.List import qualified Basement.UArray as UV import qualified Basement.Block as BLK import qualified Basement.BoxedArray as BA +#if MIN_VERSION_base(4,9,0)+import qualified Basement.Sized.List as LN+import qualified Basement.Sized.Block as BLKN+#endif+ -- | Give the ability to fold a collection on itself class Foldable collection where     -- | Left-associative fold of a structure.@@ -74,12 +88,22 @@     foldr = BLK.foldr     foldl' = BLK.foldl' +#if MIN_VERSION_base(4,9,0)+instance Foldable (LN.ListN n a) where+    foldr = LN.foldr+    foldl' = LN.foldl'+instance UV.PrimType ty => Foldable (BLKN.BlockN n ty) where+    foldr = BLKN.foldr+    foldl' = BLKN.foldl'+#endif+ ---------------------------- -- Fold1able instances ----------------------------+ instance Fold1able [a] where-  foldr1 f  = Data.List.foldr1 f . getNonEmpty-  foldl1' f = Data.List.foldl1' f . getNonEmpty+    foldr1  f = Data.List.foldr1  f . getNonEmpty+    foldl1' f = Data.List.foldl1' f . getNonEmpty  instance UV.PrimType ty => Fold1able (UV.UArray ty) where     foldr1 = UV.foldr1@@ -90,3 +114,9 @@ instance UV.PrimType ty => Fold1able (BLK.Block ty) where     foldr1  = BLK.foldr1     foldl1' = BLK.foldl1'++#if MIN_VERSION_base(4,9,0)+instance (1 <= n) => Fold1able (LN.ListN n a) where+    foldr1  f = LN.foldr1  f . getNonEmpty+    foldl1' f = LN.foldl1' f . getNonEmpty+#endif
Foundation/Collection/Indexed.hs view
@@ -5,12 +5,20 @@ -- Stability   : experimental -- Portability : portable ---{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE CPP                   #-}++#if MIN_VERSION_base(4,9,0)+{-# LANGUAGE TypeApplications      #-}+{-# LANGUAGE UndecidableInstances  #-}+#endif+ module Foundation.Collection.Indexed     ( IndexedCollection(..)     ) where  import           Basement.Compat.Base+import           Basement.Numerical.Additive ((+)) import           Basement.Types.OffsetSize import           Foundation.Collection.Element import qualified Data.List@@ -20,6 +28,12 @@ import qualified Basement.Exception as A import qualified Basement.String as S +#if MIN_VERSION_base(4,9,0)+import qualified Basement.Sized.Block as BLKN+import qualified Basement.Sized.List  as LN+import           Basement.Nat+#endif+ -- | Collection of elements that can indexed by int class IndexedCollection c where     (!) :: c -> Offset (Element c) -> Maybe (Element c)@@ -36,14 +50,14 @@ instance UV.PrimType ty => IndexedCollection (BLK.Block ty) where     (!) l n         | A.isOutOfBound n (BLK.length l) = Nothing-        | otherwise                           = Just $ BLK.index l n+        | otherwise                       = Just $ BLK.index l n     findIndex predicate c = loop 0       where         !len = BLK.length c         loop i             | i .==# len                      = Nothing             | predicate (BLK.unsafeIndex c i) = Just i-            | otherwise                       = Nothing+            | otherwise                       = loop (i + 1)  instance UV.PrimType ty => IndexedCollection (UV.UArray ty) where     (!) l n@@ -72,3 +86,29 @@ instance IndexedCollection S.String where     (!) = S.index     findIndex = S.findIndex++#if MIN_VERSION_base(4,9,0)+instance (NatWithinBound Int n, KnownNat n) => IndexedCollection (LN.ListN n a) where+    (!) c off+        | A.isOutOfBound off (LN.length c) = Nothing+        | otherwise                        = Just $ LN.index c off+    findIndex predicate c = loop 0+      where+        !len = LN.length c+        loop i+            | i .==# len               = Nothing+            | predicate (LN.index c i) = Just i+            | otherwise                = loop (i + 1)++instance (NatWithinBound (CountOf ty) n, KnownNat n, UV.PrimType ty) => IndexedCollection (BLKN.BlockN n ty) where+    (!) c off+        | A.isOutOfBound off (BLKN.length c) = Nothing+        | otherwise                          = Just $ BLKN.index c off+    findIndex predicate c = loop 0+      where+        !len = BLKN.length c+        loop i+            | i .==# len                 = Nothing+            | predicate (BLKN.index c i) = Just i+            | otherwise                  = loop (i + 1)+#endif
Foundation/Collection/Sequential.hs view
@@ -76,11 +76,11 @@     break :: (Element c -> Bool) -> c -> (c,c)     break predicate = span (not . predicate) -    -- | Split a collection when the predicate return true+    -- | Split a collection when the predicate return true starting from the end of the collection     breakEnd :: (Element c -> Bool) -> c -> (c,c)     breakEnd predicate = spanEnd (not . predicate) -    -- | Split a collection when the predicate return true starting from the end of the collection+    -- | Split a collection at the given element     breakElem :: Eq (Element c) => Element c -> c -> (c,c)     breakElem c = break (== c) @@ -116,7 +116,7 @@     -- | Filter all the elements that satisfy the predicate     filter :: (Element c -> Bool) -> c -> c -    -- | Partition the elements thtat satisfy the predicate and those that don't+    -- | Partition the elements that satisfy the predicate and those that don't     partition :: (Element c -> Bool) -> c -> (c,c)     partition predicate c = (filter predicate c, filter (not . predicate) c) 
+ Foundation/Format/CSV.hs view
@@ -0,0 +1,232 @@+-- |+-- Module      : Foundation.Format.CSV+-- License     : BSD-style+-- Maintainer  : Foundation+-- Stability   : experimental+-- Portability : portable+--+-- Provies the support for Comma Separated Value++{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings          #-}+{-# LANGUAGE FlexibleInstances          #-}++module Foundation.Format.CSV+    (-- * CSV+      CSV++    -- ** Builder+    -- ** String Bulider+    , csvStringBuilder+    , rowStringBuilder+    , fieldStringBuilder+    -- ** Block Builder+    , csvBlockBuilder+    , rowBlockBuilder+    , fieldBlockBuilder+    -- ** Conduit+    , rowC+    -- * Row+    , Row+    , ToRow(..)+    -- * Field+    , Field(..)+    , Escaping(..)+    , ToField(..)+    -- ** helpers+    , integral+    , float+    , string+    ) where++import           Basement.Imports -- hiding (throw)+import           Basement.BoxedArray              (Array)+import           Basement.NormalForm              (NormalForm(..))+import           Basement.From                    (Into, into)+import           Basement.String                  (String, replace, any, elem)+import qualified Basement.String        as String (singleton)+import           Basement.Types.Word128           (Word128)+import           Basement.Types.Word256           (Word256)+import           Basement.Types.OffsetSize        (Offset, CountOf)+import           Foundation.Collection.Element    (Element)+import           Foundation.Collection.Collection (Collection, nonEmpty_)+import           Foundation.Collection.Sequential (Sequential(intersperse))+import           Foundation.Collection.Indexed    (IndexedCollection)+import           Foundation.Check.Arbitrary       (Arbitrary(..), frequency)+import           Foundation.Conduit.Internal++import qualified Foundation.String.Builder as String+import           Basement.Block              (Block)+import qualified Basement.Block.Builder    as Block++import           GHC.ST (runST)++-- | CSV field+data Field+    = FieldInteger Integer+    | FieldDouble  Double+    | FieldString  String  Escaping+  deriving (Eq, Show, Typeable)+instance NormalForm Field where+    toNormalForm (FieldInteger i) = toNormalForm i+    toNormalForm (FieldDouble  d) = toNormalForm d+    toNormalForm (FieldString  s e) = toNormalForm s `seq` toNormalForm e+instance Arbitrary Field where+    arbitrary = frequency $ nonEmpty_ [ (1, FieldInteger <$> arbitrary)+                                      , (1, FieldDouble <$> arbitrary)+                                      , (3, string <$> arbitrary)+                                      ]++data Escaping = NoEscape | Escape | DoubleEscape+  deriving (Eq, Ord, Enum, Bounded, Show, Typeable)+instance NormalForm Escaping where+    toNormalForm !_ = ()++class ToField a where+    toField :: a -> Field+instance ToField Field where+    toField = id+instance ToField a => ToField (Maybe a) where+    toField Nothing  = FieldString mempty NoEscape+    toField (Just a) = toField a++instance ToField Int8 where+    toField = FieldInteger . into+instance ToField Int16 where+    toField = FieldInteger . into+instance ToField Int32 where+    toField = FieldInteger . into+instance ToField Int64 where+    toField = FieldInteger . into+instance ToField Int where+    toField = FieldInteger . into++instance ToField Word8 where+    toField = FieldInteger . into+instance ToField Word16 where+    toField = FieldInteger . into+instance ToField Word32 where+    toField = FieldInteger . into+instance ToField Word64 where+    toField = FieldInteger . into+instance ToField Word where+    toField = FieldInteger . into+instance ToField Word128 where+    toField = FieldInteger . into+instance ToField Word256 where+    toField = FieldInteger . into++instance ToField Integer where+    toField = FieldInteger+instance ToField Natural where+    toField = FieldInteger . into++instance ToField Double where+    toField = FieldDouble++instance ToField Char where+    toField = string . String.singleton++instance ToField (Offset a) where+    toField = FieldInteger . into+instance ToField (CountOf a) where+    toField = FieldInteger . into++instance ToField [Char] where+    toField = string . fromString+instance ToField String where+    toField = string++-- | helper function to create a `FieldInteger`+--+integral :: Into Integer a => a -> Field+integral = FieldInteger . into++float :: Double -> Field+float = FieldDouble++-- | heler function to create a FieldString.+--+-- This function will findout automatically if an escaping is needed.+-- if you wish to perform the escaping manually, do not used this function+--+string :: String -> Field+string s = FieldString s encoding+  where+    encoding+        | any g s   = DoubleEscape+        | any f s   = Escape+        | otherwise = NoEscape+    f c = c == '\"'+    g c = c `elem` ",\r\n"++-- | CSV Row+--+newtype Row = Row { unRow :: Array Field }+  deriving (Eq, Show, Typeable, Semigroup, Monoid, Collection, NormalForm, Sequential, IndexedCollection)++type instance Element Row = Field+instance IsList Row where+    type Item Row = Field+    toList = toList . unRow+    fromList = Row . fromList++class ToRow a where+    toRow :: a -> Row+instance ToRow Row where+    toRow = id+instance (ToField a, ToField b) => ToRow (a,b) where+    toRow (a,b) = fromList [toField a, toField b]+instance (ToField a, ToField b, ToField c) => ToRow (a,b,c) where+    toRow (a,b,c) = fromList [toField a, toField b, toField c]+instance (ToField a, ToField b, ToField c, ToField d) => ToRow (a,b,c,d) where+    toRow (a,b,c,d) = fromList [toField a, toField b, toField c, toField d]+instance (ToField a, ToField b, ToField c, ToField d, ToField e) => ToRow (a,b,c,d,e) where+    toRow (a,b,c,d,e) = fromList [toField a, toField b, toField c, toField d, toField e]+instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f) => ToRow (a,b,c,d,e,f) where+    toRow (a,b,c,d,e,f) = fromList [toField a, toField b, toField c, toField d, toField e, toField f]++-- | CSV Type+newtype CSV = CSV { unCSV :: Array Row }+  deriving (Eq, Show, Typeable, Semigroup, Monoid, Collection, NormalForm, Sequential, IndexedCollection)++type instance Element CSV = Row++instance IsList CSV where+    type Item CSV = Row+    toList = toList . unCSV+    fromList = CSV . fromList++-- | serialise the CSV document into a UTF8 string+csvStringBuilder :: CSV -> String.Builder+csvStringBuilder = String.unsafeStringBuilder . csvBlockBuilder++rowStringBuilder :: Row -> String.Builder+rowStringBuilder = String.unsafeStringBuilder . rowBlockBuilder++fieldStringBuilder :: Field -> String.Builder+fieldStringBuilder = String.unsafeStringBuilder . fieldBlockBuilder++-- | serialise the CSV document into a UTF8 encoded (Block Word8)+csvBlockBuilder :: CSV -> Block.Builder+csvBlockBuilder = mconcat . intersperse (Block.emitString "\r\n") . fmap rowBlockBuilder . toList . unCSV++rowBlockBuilder :: Row -> Block.Builder+rowBlockBuilder = mconcat . intersperse (Block.emitUTF8Char ',') . fmap fieldBlockBuilder . toList . unRow++fieldBlockBuilder :: Field -> Block.Builder+fieldBlockBuilder (FieldInteger i) = Block.emitString $ show i+fieldBlockBuilder (FieldDouble  d) = Block.emitString $ show d+fieldBlockBuilder (FieldString  s e) = case e of+    NoEscape     -> Block.emitString s+    Escape       -> Block.emitUTF8Char '"' <> Block.emitString s <> Block.emitUTF8Char '"'+    DoubleEscape -> Block.emitUTF8Char '"' <> Block.emitString (replace "\"" "\"\"" s) <> Block.emitUTF8Char '"'++rowC :: (ToRow row, Monad m) => Conduit row (Block Word8) m ()+rowC = await >>= go+  where+    go Nothing  = pure ()+    go (Just r) =+      let bytes = runST (Block.run $ rowBlockBuilder (toRow r) <> Block.emitString "\r\n")+         in yield bytes >> await >>= go
Foundation/Hashing/FNV.hs view
@@ -21,6 +21,7 @@     , FNV1a_64     ) where +import           Basement.Block (Block(..)) import           Basement.Compat.Base import qualified Basement.UArray as A import           Basement.Types.OffsetSize@@ -119,8 +120,8 @@     ba :: A.UArray Word8     ba = A.unsafeRecast baA -    goVec :: ByteArray# -> Offset Word8 -> FNV1_32-    goVec !ma !start = loop start initialState+    goVec :: Block Word8 -> Offset Word8 -> FNV1_32+    goVec (Block !ma) !start = loop start initialState       where         !len = start `offsetPlusE` A.length ba         loop !idx !acc@@ -144,8 +145,8 @@     ba :: A.UArray Word8     ba = A.unsafeRecast baA -    goVec :: ByteArray# -> Offset Word8 -> FNV1a_32-    goVec !ma !start = loop start initialState+    goVec :: Block Word8 -> Offset Word8 -> FNV1a_32+    goVec (Block !ma) !start = loop start initialState       where         !len = start `offsetPlusE` A.length ba         loop !idx !acc@@ -169,8 +170,8 @@     ba :: A.UArray Word8     ba = A.unsafeRecast baA -    goVec :: ByteArray# -> Offset Word8 -> FNV1_64-    goVec !ma !start = loop start initialState+    goVec :: Block Word8 -> Offset Word8 -> FNV1_64+    goVec (Block !ma) !start = loop start initialState       where         !len = start `offsetPlusE` A.length ba         loop !idx !acc@@ -194,8 +195,8 @@     ba :: A.UArray Word8     ba = A.unsafeRecast baA -    goVec :: ByteArray# -> Offset Word8 -> FNV1a_64-    goVec !ma !start = loop start initialState+    goVec :: Block Word8 -> Offset Word8 -> FNV1a_64+    goVec (Block !ma) !start = loop start initialState       where         !len = start `offsetPlusE` A.length ba         loop !idx !acc
Foundation/Hashing/SipHash.hs view
@@ -24,6 +24,7 @@ import           Basement.Cast (cast) import           Basement.IntegralConv import           Foundation.Hashing.Hasher+import           Basement.Block (Block(..)) import qualified Basement.UArray as A import           Foundation.Array import           Foundation.Numerical@@ -186,8 +187,8 @@     totalLen = A.length array8     array8 = A.unsafeRecast array -    goVec :: ByteArray# -> Offset Word8 -> Sip-    goVec ba start = loop8 initSt initIncr start totalLen+    goVec :: Block Word8 -> Offset Word8 -> Sip+    goVec (Block ba) start = loop8 initSt initIncr start totalLen       where         loop8 !st !incr            _     0 = Sip st incr (currentLen + totalLen)         loop8 !st SipIncremental0 !ofs !l = case l - 8 of
Foundation/Network/IPv6.hs view
@@ -25,7 +25,6 @@ import qualified Text.Printf as Base import Data.Char (isHexDigit, isDigit) import Numeric (readHex)-import Control.Monad (when)  import Foundation.Class.Storable import Foundation.Hashing.Hashable
Foundation/Timing/Main.hs view
@@ -14,7 +14,6 @@ import           Basement.Imports import           Foundation.IO.Terminal import           Foundation.Collection-import           Control.Monad (when)  data MainConfig = MainConfig     { mainHelp       :: Bool
Foundation/UUID.hs view
@@ -9,7 +9,6 @@     , uuidParser     ) where -import Control.Monad (unless) import Data.Maybe (fromMaybe)  import           Basement.Compat.Base
benchs/BenchUtil/Common.hs view
@@ -12,8 +12,8 @@     , nf     ) where -import           Gauge hiding (bgroup, bench)-import qualified Gauge as C+import           Gauge.Main hiding (bgroup, bench)+import qualified Gauge.Main as C import           Foundation  fbench = bench "foundation"
benchs/BenchUtil/RefData.hs view
@@ -7,6 +7,9 @@     , rdFoundationZh     , rdFoundationJap     , rdFoundationHun+    , rdFoundationLower+    , rdFoundationUpper+    , rdSpecialCasing     -- byte array     , rdBytes20     , rdBytes200@@ -26,6 +29,12 @@ rdFoundationEn :: [Char] rdFoundationEn = "Set in the year 0 F.E. (\"Foundation Era\"), The Psychohistorians opens on Trantor, the capital of the 12,000-year-old Galactic Empire. Though the empire appears stable and powerful, it is slowly decaying in ways that parallel the decline of the Western Roman Empire. Hari Seldon, a mathematician and psychologist, has developed psychohistory, a new field of science and psychology that equates all possibilities in large societies to mathematics, allowing for the prediction of future events." +rdFoundationLower :: [Char]+rdFoundationLower = "set in the year 0 f.e. (\"foundation era\"), the psychohistorians opens on trantor, the capital of the 12,000-year-old galactic empire. though the empire appears stable and powerful, it is slowly decaying in ways that parallel the decline of the western roman empire. hari seldon, a mathematician and psychologist, has developed psychohistory, a new field of science and psychology that equates all possibilities in large societies to mathematics, allowing for the prediction of future events."++rdFoundationUpper :: [Char]+rdFoundationUpper = "SET IN THE YEAR 0 F.E. (\"FOUNDATION ERA\"), THE PSYCHOHISTORIANS OPENS ON TRANTOR, THE CAPITAL OF THE 12,000-YEAR-OLD GALACTIC EMPIRE. THOUGH THE EMPIRE APPEARS STABLE AND POWERFUL, IT IS SLOWLY DECAYING IN WAYS THAT PARALLEL THE DECLINE OF THE WESTERN ROMAN EMPIRE. HARI SELDON, A MATHEMATICIAN AND PSYCHOLOGIST, HAS DEVELOPED PSYCHOHISTORY, A NEW FIELD OF SCIENCE AND PSYCHOLOGY THAT EQUATES ALL POSSIBILITIES IN LARGE SOCIETIES TO MATHEMATICS, ALLOWING FOR THE PREDICTION OF FUTURE EVENTS."+ rdFoundationZh :: [Char] rdFoundationZh = "故事發生在〈心理史學家〉五十年後,端點星面臨首度的「謝頓危機」(Seldon Crisis)銀河帝國邊緣的星群紛紛獨立起來,端點星處於四個王國之間,備受威脅。此時,謝頓早前錄下影像突然播放,告知他的後人端點星「銀河百科全書第一號基地」的真正目的──在千年後建立一個新的銀河帝國。同時,在這一千年間,基地會遇到各種不同的危機,令基地可以急速成長。端點星市長塞佛·哈定(Salvor Hardin)趁機發動政變,從心神未定的百科全書理事會手中奪權,以他靈活的手腕帶領端點星走出危機。" @@ -34,6 +43,9 @@  rdFoundationJap :: [Char] rdFoundationJap = "数学者ハリ・セルダンは、膨大な集団の行動を予測する心理歴史学を作りあげ発展させることで、銀河帝国が近いうちに崩壊することを予言する[1]。セルダンは、帝国崩壊後に3万年続くはずの暗黒時代を、あらゆる知識を保存することで千年に縮めようとし、知識の集大成となる銀河百科事典 (Encyclopedia Galactica) を編纂するグループ「ファウンデーション」をつくったが、帝国崩壊を公言し平和を乱したという罪で裁判にかけられ、グループは銀河系辺縁部にある資源の乏しい無人惑星ターミナスへ追放されることになった。しかし、この追放劇すらもセルダンの計画に予定されていた事柄であった。病で死期をさとっていたセルダンは、己の仕事が終わったことを確信する。"++rdSpecialCasing :: [Char]+rdSpecialCasing = "fflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflfflffl"  rdBytes20 ::[Word8] rdBytes20 = take 20 $ cycle [1..255]
benchs/Fake/Text.hs view
@@ -11,6 +11,8 @@     , decimal     , double     , decodeUtf8+    , toLower+    , toUpper     ) where  import Prelude (undefined, Either(..), Char)@@ -27,6 +29,8 @@ reverse     = undefined any         = undefined decodeUtf8  = undefined+toLower     = undefined+toUpper     = undefined  decimal :: Text -> Either a (b, c) decimal = undefined
benchs/Main.hs view
@@ -43,6 +43,8 @@     , benchFilter     , benchRead     , benchFromUTF8Bytes+    , benchUpper+    , benchLower     ]   where     diffTextString :: (String -> a)@@ -132,6 +134,14 @@     benchFilter = bgroup "Filter" $         fmap (\(n, dat) -> bgroup n $ diffTextString (filter (> 'b')) (Just $ filter (> 'b')) (Text.filter (> 'b')) dat)             allDat++    benchUpper = bgroup "Upper" $+        fmap (\(n, dat) -> bgroup n $ diffTextString upper Nothing Text.toUpper dat)+            (("special casing", rdSpecialCasing) : ("ascii already upper", rdFoundationUpper) : allDat)++    benchLower = bgroup "Lower" $+        fmap (\(n, dat) -> bgroup n $ diffTextString lower Nothing Text.toLower dat)+            (("special casing", rdSpecialCasing) : ("ascii already lower", rdFoundationLower) : allDat)      benchRead = bgroup "Read"         [ bgroup "Integer"
foundation.cabal view
@@ -1,5 +1,5 @@ name:                foundation-version:             0.0.19+version:             0.0.20 synopsis:            Alternative prelude with batteries and no dependencies description:     A custom prelude with no dependencies apart from base.@@ -59,10 +59,15 @@   manual:            True  flag doctest-  description:       Add extra friendly boundary check for unsafe array operations+  description:       Build doctest on demand only   default:           False   manual:            True +flag linktest+  description:       Run linking test+  default:           False+  manual:            True+ library   exposed-modules:   Foundation                      Foundation.Numerical@@ -74,6 +79,7 @@                      Foundation.Conduit                      Foundation.Conduit.Textual                      Foundation.Exception+                     Foundation.Format.CSV                      Foundation.String                      Foundation.String.Read                      Foundation.String.Builder@@ -110,7 +116,7 @@                      Foundation.UUID                      Foundation.System.Entropy                      Foundation.System.Bindings-  other-modules:     +  other-modules:                      Foundation.Tuple                      Foundation.Hashing.FNV                      Foundation.Hashing.SipHash@@ -191,7 +197,7 @@                       BangPatterns                       DeriveDataTypeable   build-depends:     base >= 4.7 && < 5-                   , basement == 0.0.6+                   , basement == 0.0.7                    , ghc-prim   -- FIXME add suport for armel mipsel   --  CPP-options: -DARCH_IS_LITTLE_ENDIAN@@ -228,6 +234,8 @@                      Test.Data.List                      Test.Foundation.Network.IPv4                      Test.Foundation.Network.IPv6+                     Test.Foundation.Format+                     Test.Foundation.Format.CSV   default-extensions: NoImplicitPrelude                       RebindableSyntax                       OverloadedStrings@@ -239,6 +247,21 @@   if impl(ghc >= 8.0)     ghc-options:     -Wno-redundant-constraints +test-suite foundation-link+  type:              exitcode-stdio-1.0+  hs-source-dirs:    tests+  default-language:  Haskell2010+  main-is:           Scripts/Link.hs+  default-extensions: NoImplicitPrelude+                      RebindableSyntax+  if flag(linktest)+    build-depends:     base+                     , foundation+                     , template-haskell+    buildable:     True+  else+    buildable:     False+ test-suite doctest   type:              exitcode-stdio-1.0   hs-source-dirs:    tests@@ -273,7 +296,7 @@   if flag(minimal-deps) || impl(ghc < 7.10)     buildable: False   else-    build-depends:     base >= 4, gauge >= 0.2.0, basement, foundation+    build-depends:     base >= 4, gauge, basement, foundation     if flag(bench-all)       cpp-options:     -DBENCH_ALL       build-depends:   text, attoparsec, vector, bytestring
tests/Checks.hs view
@@ -28,6 +28,7 @@ import Test.Foundation.Network.IPv6 import Test.Foundation.String.Base64 import Test.Checks.Property.Collection+import Test.Foundation.Format import qualified Test.Foundation.Bits as Bits  #if MIN_VERSION_base(4,9,0)@@ -197,11 +198,11 @@     , testNetworkIPv6     , testBase64Refs     , testHexadecimal-    , testTime     , testUUID     , testRandom     , testConduit #if MIN_VERSION_base(4,9,0)     , testBlockN #endif+    , testFormat     ]
+ tests/Scripts/Link.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE TemplateHaskell   #-}++-- | This module is to test issue+-- https://github.com/haskell-foundation/foundation/issues/326+--+-- this test has been originaly proposed by https://github.com/RyanGlScott+-- in comment of the issue 326:+-- https://github.com/haskell-foundation/foundation/issues/326#issuecomment-309219955++module Main (main) where++import Foundation as F+import Language.Haskell.TH++main :: IO ()+main = $(do runIO $ F.putStrLn (F.fromString "Hello")+            [| return () |])
+ tests/Test/Foundation/Format.hs view
@@ -0,0 +1,14 @@+{-# LANGUAGE OverloadedStrings #-}+module Test.Foundation.Format+    ( testFormat+    ) where++import Foundation+import Foundation.Check+import Test.Foundation.Format.CSV+++testFormat :: Test+testFormat = Group "Format"+  [ testFormatCSV+  ]
+ tests/Test/Foundation/Format/CSV.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE OverloadedStrings #-}+module Test.Foundation.Format.CSV+    ( testFormatCSV+    ) where++import Foundation+import Foundation.Format.CSV+import Foundation.Check+import Foundation.String.Builder (toString)++testFormatCSV :: Test+testFormatCSV = Group "CSV"+    [ Group "field unit tests" $ testFieldEncoding <$> fieldUnitTests+    , Group "row unit tests" $ testRowEncoding <$> rowUnitTests+    ]++  where+    testFieldEncoding (f,r) = Property (show f) $+      let str = toString (fieldStringBuilder f)+       in r === str+    testRowEncoding (row,result) = Property (show row) $+      let str = toString (rowStringBuilder row)+       in result === str++fieldUnitTests :: [(Field, String)]+fieldUnitTests =+    [ (FieldInteger 42, "42")+    , (FieldDouble  1, "1.0")+    , (FieldDouble  0.000001, "1.0e-6")+    , (FieldString  "String" NoEscape, "String")+    , (string "String", "String")+    , (string "with comma,string", "\"with comma,string\"")+    , (FieldString  "multiline\nstring" Escape, "\"multiline\nstring\"")+    , (FieldString  "piece of 12\" by 23\""  DoubleEscape, "\"piece of 12\"\" by 23\"\"\"")+    , (string "supported sizes are: 12\", 13\" and 14\"", "\"supported sizes are: 12\"\", 13\"\" and 14\"\"\"")+    ]++rowUnitTests :: [(Row, String)]+rowUnitTests =+    [ (fromList [toField (42 :: Int), toField ("some string" :: String)], "42,some string")+    , (toRow (42 :: Int, "some string" :: String), "42,some string")+    , ( toRow ( 42 :: Int+              , "some string" :: String+              , "supported sizes are: 12\", 13\" and 14\"" :: String+              )+      , "42,some string,\"supported sizes are: 12\"\", 13\"\" and 14\"\"\""+      )+    , ( toRow ( 42 :: Int+              , "some string" :: String+              , "supported sizes are: 12\", 13\" and 14\"" :: String+              , Just 0.000001 :: Maybe Double+              )+      , "42,some string,\"supported sizes are: 12\"\", 13\"\" and 14\"\"\",1.0e-6"+      )+    , ( toRow ( 42 :: Int+              , "some string" :: String+              , "supported sizes are: 12\", 13\" and 14\"" :: String+              , Just 0.000001 :: Maybe Double+              , Nothing       :: Maybe Char+              )+      , "42,some string,\"supported sizes are: 12\"\", 13\"\" and 14\"\"\",1.0e-6,"+      )+    ]
tests/Test/Foundation/Misc.hs view
@@ -1,8 +1,6 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-} module Test.Foundation.Misc     ( testHexadecimal-    , testTime     , testUUID     ) where @@ -33,16 +31,6 @@ testHexadecimal = Group "hexadecimal"     [ Property  "UArray(W8)" $ \l ->         toList (toHexadecimal (fromListP (Proxy :: Proxy (UArray Word8)) l)) == hex l-    ]--testTime = Group "Time"-    [ Property "foundation_time_clock_gettime links properly" $-        $(let s :: String-              s = fromString "Hello"--              b :: Bool-              b = s == s-           in [| b |])     ]  testUUID = Group "UUID"
tests/Test/Foundation/String.hs view
@@ -68,7 +68,7 @@          , CheckPlan "B should not capitalize" $ validate "B" $ upper "B" == "B"          , CheckPlan "é should capitalize to É" $ validate "é" $ upper "é" == "É"          , CheckPlan "ß should capitalize to SS" $ validate "ß" $ upper "ß" == "SS"-         , CheckPlan "ffl should capitalize to FFL" $ validate "ffl" $ upper "ffl" == "FFL"+         , CheckPlan "ffl should capitalize to FFL" $ validate "ffl" $ upper "fflfflfflfflfflfflfflfflfflffl" == "FFLFFLFFLFFLFFLFFLFFLFFLFFLFFL"          , CheckPlan "0a should capitalize to 0A" $ validate "0a" $ upper "\0a" == "\0A"          , CheckPlan "0a should capitalize to 0A" $ validate "0a" $ upper "a\0a" == "A\0A"          , CheckPlan "0a should capitalize to 0A" $ validate "0a" $ upper "\0\0" == "\0\0"