diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,11 @@
 # Revision history for Z-Data
 
+## 0.7.4.0  -- 2021-04-06
+
+* Add `emptyArr` to `Z.Data.Array`. 
+* Add `newCPtr'` to accommodate common cases.
+* Use `memchr` in `split/splitWith/lines` if possible.
+
 ## 0.7.3.0  -- 2021-03-30
 
 * Add more helpers to debug `Parser`: `currentChunk`, `failWithInput`, `unsafeLiftIO`.
diff --git a/Z-Data.cabal b/Z-Data.cabal
--- a/Z-Data.cabal
+++ b/Z-Data.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               Z-Data
-version:            0.7.3.0
+version:            0.7.4.0
 synopsis:           Array, vector and text
 description:        This package provides array, slice and text operations
 license:            BSD-3-Clause
diff --git a/Z/Data/Array.hs b/Z/Data/Array.hs
--- a/Z/Data/Array.hs
+++ b/Z/Data/Array.hs
@@ -28,7 +28,7 @@
 module Z.Data.Array (
   -- * Arr typeclass
     Arr(..)
-  , singletonArr, doubletonArr
+  , emptyArr, singletonArr, doubletonArr
   , modifyIndexArr, insertIndexArr, deleteIndexArr
   , RealWorld
   -- * Boxed array type
@@ -437,7 +437,7 @@
     {-# INLINE newArr #-}
     newArrWith n x = do
         marr <- newPrimArray n
-        setPrimArray marr 0 n x
+        when (n > 0) (setPrimArray marr 0 n x)
         return marr
     {-# INLINE newArrWith #-}
     readArr = readPrimArray
@@ -623,6 +623,11 @@
 castMutableArray = unsafeCoerce#
 
 --------------------------------------------------------------------------------
+
+emptyArr :: Arr arr a => arr a
+emptyArr = runST $ do
+    marr <- newArrWith 0 uninitialized
+    unsafeFreezeArr marr
 
 singletonArr :: Arr arr a => a -> arr a
 {-# INLINE singletonArr #-}
diff --git a/Z/Data/Array/Checked.hs b/Z/Data/Array/Checked.hs
--- a/Z/Data/Array/Checked.hs
+++ b/Z/Data/Array/Checked.hs
@@ -16,7 +16,7 @@
 module Z.Data.Array.Checked
   ( -- * Arr typeclass re-export
     Arr, MArr
-  , A.singletonArr, A.doubletonArr
+  , A.emptyArr, A.singletonArr, A.doubletonArr
   , modifyIndexArr, insertIndexArr, deleteIndexArr
   , RealWorld
   -- * Boxed array type
diff --git a/Z/Data/JSON.hs b/Z/Data/JSON.hs
--- a/Z/Data/JSON.hs
+++ b/Z/Data/JSON.hs
@@ -100,14 +100,18 @@
 -- >     deriving (Show, Generic)
 -- >     deriving anyclass (JSON.JSON)
 --
--- We can now encode & decode with 'T.Text' like so:
+-- We can now encode & decode JSON like this:
 --
+-- >>> JSON.toValue (Person{ name="Alice", age=16 })
+-- Object [("name",String "Alice"),("age",Number 16.0)]
+-- >>> JSON.encode (Person{ name="Alice", age=16 })
+-- [123,34,110,97,109,101,34,58,34,65,108,105,99,101,34,44,34,97,103,101,34,58,49,54,125]
 -- >>> JSON.encodeText (Person{ name="Alice", age=16 })
 -- "{\"age\":16,\"name\":\"Alice\"}"
 -- >>> JSON.decodeText' "{\"age\":16,\"name\":\"Alice\"}" :: Either JSON.DecodeError Person
 -- Right (Person {age = 16, name = "Alice"})
 --
--- The 'GHC.Generics.Generic' instances convert(encode) Haskell data with following rules:
+-- The 'GHC.Generics.Generic' based instances convert Haskell data with following rules:
 --
 --   * Constructors without payloads are encoded as JSON String, @data T = A | B@ are encoded as @\"A\"@ or @\"B\"@.
 --   * Single constructor are ingored if there're payloads, @data T = T ...@,  @T@ is ingored:
@@ -122,8 +126,7 @@
 --         @{\"B\":{\"k1\":...,\"k2\":...}}@ in @B .. ..@ case, or @\"A\"@ in @A@ case.
 --     * Plain product are similar to above, wrappered by an outer single-key object layer marking which constructor.
 --
--- These rules apply to user defined ADTs, but some built-in instances have
--- different behaviour, namely:
+-- These rules apply to user defined ADTs, but some built-in instances have different behaviours, namely:
 --
 --   * @Maybe a@ are encoded as JSON @null@ in 'Nothing' case, or directly encoded to its payload in 'Just' case.
 --   * @[a]@ are encoded to JSON array, @[Char]@ are encoded into JSON string.
@@ -140,13 +143,9 @@
 -- escaping pass. To use custom 'Settings' just write:
 --
 -- > data T = T {fooT :: Int, barT :: [Int]} deriving Generic
--- > instance JSON.ToValue T where
+-- > instance JSON.JSON T where
 -- >     -- You can omit following definition if you don't need to change settings
 -- >     toValue = JSON.gToValue JSON.defaultSettings{ JSON.fieldFmt = JSON.snakeCase } . from
--- >
--- > -- define this instances if you need fast JSON encoding(without convert to JSON.Value first)
--- > instance JSON.EncodeJSON T where
--- >     -- You can omit following definition if you don't need to change settings
 -- >     encodeJSON = JSON.gEncodeJSON JSON.defaultSettings{ JSON.fieldFmt = JSON.snakeCase } . from
 --
 -- >>> JSON.toValue (T 0 [1,2,3])
diff --git a/Z/Data/Vector/Base.hs b/Z/Data/Vector/Base.hs
--- a/Z/Data/Vector/Base.hs
+++ b/Z/Data/Vector/Base.hs
@@ -536,7 +536,7 @@
 type Bytes = PrimVector Word8
 
 -- | This instance use 'packASCII', which may silently chop bytes, use it with ASCII literals only.
-instance IsString Bytes where
+instance a ~ Word8 => IsString (PrimVector a) where
     {-# INLINE fromString #-}
     fromString = packASCII
 
@@ -697,8 +697,7 @@
 -- | /O(1)/. The empty vector.
 --
 empty :: Vec v a => v a
-{-# INLINE empty #-}
-empty = create 0 (\_ -> return ())
+empty = Vec emptyArr 0 0
 
 -- | /O(1)/. Single element vector.
 singleton :: Vec v a => a -> v a
diff --git a/Z/Data/Vector/Extra.hs b/Z/Data/Vector/Extra.hs
--- a/Z/Data/Vector/Extra.hs
+++ b/Z/Data/Vector/Extra.hs
@@ -465,13 +465,15 @@
 -- <https://github.com/haskell/bytestring/issues/56 #56>.
 splitWith :: Vec v a => (a -> Bool) -> v a -> [v a]
 {-# INLINE splitWith #-}
-splitWith f (Vec arr s l) = go s s
+splitWith f = go
   where
-    !end = s + l
-    go !p !q | q >= end  = let !v = Vec arr p (q-p) in [v]
-             | f x       = let !v = Vec arr p (q-p) in v:go (q+1) (q+1)
-             | otherwise = go p (q+1)
-        where (# x #) = indexArr' arr q
+    go v@(Vec _ _ l)
+        | l == 0    = [empty]
+        | otherwise =
+            let n = findIndex f v
+            in if n == l
+                then [v]
+                else unsafeTake n v : go (unsafeDrop (n+1) v)
 
 -- | /O(n)/ Breaks a 'Bytes' up into a list of words, delimited by ascii space.
 words ::  Bytes -> [Bytes]
@@ -491,18 +493,17 @@
                     let !v = fromArr arr s' (i-s') in v : go (i+1) (i+1)
               | otherwise = go s' (i+1)
 
--- | /O(n)/ Breaks a 'Bytes' up into a list of lines, delimited by ascii @\n@.
+-- | /O(n)/ Breaks a 'Bytes' up into a list of lines, delimited by ascii @\n@,
+-- The resulting strings do not contain newlines.
+--
+--  Note that it __does not__ regard CR (@'\\r'@) as a newline character.
 lines ::  Bytes -> [Bytes]
 {-# INLINE lines #-}
-lines (Vec arr s l) = go s s
-  where
-    !end = s + l
-    go :: Int -> Int -> [Bytes]
-    go !p !q | q >= end              = if p == q
-                                       then []
-                                       else let !v = Vec arr p (q-p) in [v]
-             | indexArr arr q == 10  = let !v = Vec arr p (q-p) in v:go (q+1) (q+1)
-             | otherwise             = go p (q+1)
+lines v
+    | null v = []
+    | otherwise = case elemIndex 10 v of
+         Nothing -> [v]
+         Just n  -> unsafeTake n v : lines (unsafeDrop (n+1) v)
 
 -- | /O(n)/ Joins words with ascii space.
 unwords :: [Bytes] -> Bytes
diff --git a/Z/Foreign/CPtr.hs b/Z/Foreign/CPtr.hs
--- a/Z/Foreign/CPtr.hs
+++ b/Z/Foreign/CPtr.hs
@@ -12,7 +12,7 @@
 
 module Z.Foreign.CPtr (
   -- * CPtr type
-    CPtr, newCPtrUnsafe, newCPtr, withCPtr
+    CPtr, newCPtr', newCPtrUnsafe, newCPtr, withCPtr
   -- * Ptr type
   , Ptr
   , nullPtr
@@ -43,6 +43,22 @@
 instance T.Print (CPtr a) where
     {-# INLINE toUTF8BuilderP #-}
     toUTF8BuilderP _ (CPtr mpa) = T.toUTF8BuilderP 0 (indexPrimArray mpa 0)
+
+-- | Initialize a 'CPtr' with initializer which return an allocated pointer.
+--
+newCPtr' :: IO (Ptr a) -- ^ initializer
+         -> FunPtr (Ptr a -> IO b) -- ^ finalizer
+         -> IO (CPtr a)
+newCPtr' ini (FunPtr fin#) = mask_ $ do
+    mpa <- newPrimArray 1
+    p@(Ptr addr#) <- ini
+    writePrimArray mpa 0 p
+    pa@(PrimArray ba#) <- unsafeFreezePrimArray mpa
+    primitive_ $ \ s0# ->
+        let !(# s1#, w# #) = mkWeakNoFinalizer# ba# () s0#
+            !(# s2#, _ #) = addCFinalizerToWeak# fin# addr# 0# addr# w# s1#
+        in s2#
+    return (CPtr pa)
 
 -- | Initialize a 'CPtr' with initializer(must be unsafe FFI) and finalizer.
 --
diff --git a/test/Z/Data/Vector/ExtraSpec.hs b/test/Z/Data/Vector/ExtraSpec.hs
--- a/test/Z/Data/Vector/ExtraSpec.hs
+++ b/test/Z/Data/Vector/ExtraSpec.hs
@@ -323,6 +323,14 @@
                 Just ys' = V.stripPrefix c $ V.pack ys
             in (a,b) === (xs', ys')
 
+    describe "vector split x [x] == [[],[]]"  $ do
+        prop "vector split x [x] == [[],[]]" $ \ x ->
+            V.split x (V.singleton @V.Vector @Integer x) == [V.empty, V.empty]
+        prop "vector split x [x] == [[],[]]" $ \ x ->
+            V.split x (V.singleton @V.PrimVector @Int x) == [V.empty, V.empty]
+        prop "vector split x [x] == [[],[]]" $ \ x ->
+            V.split x (V.singleton @V.PrimVector @Word8 x) == [V.empty, V.empty]
+
     describe "vector intercalate [x] . split x == id" $ do
         prop "vector intercalate [x] . split x == id" $ \ xs x ->
             (V.intercalate (V.singleton x) . V.split x . V.pack @V.Vector @Integer $ xs) ===
