packages feed

Z-Data 0.8.7.0 → 0.8.8.0

raw patch · 27 files changed

+638/−187 lines, 27 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Z.Data.Vector: replicateMVec :: (Applicative f, Vec v a) => Int -> f a -> f (v a)
+ Z.Data.Vector.Base: replicateMVec :: (Applicative f, Vec v a) => Int -> f a -> f (v a)
+ Z.Foreign.CPtr: addCPtrDep :: CPtr a -> b -> IO ()
+ Z.Foreign.CPtr: withCPtrForever :: CPtr a -> (Ptr a -> IO b) -> IO b

Files

ChangeLog.md view
@@ -1,5 +1,11 @@ # Revision history for Z-Data +## 0.8.8.0  -- 2021-06-13++* Add `withCPtrForever` and `addCPtrDep` to `Z.Foreign.CPtr` module.+* Add `replicateMVec` to `Z.Data.Vector`.+* Fix AVX512 text validate header building with C11.+ ## 0.8.7.0  -- 2021-06-12  * Add `use-avx2` and `use-avx512` flags(default to False) to enable avx2 or avx512 base64 codec, UTF8 validator, etc.
README.md view
@@ -19,7 +19,14 @@  ## Requirements -* A working haskell compiler system, GHC(>=8.6), cabal-install(>=2.4), hsc2hs.+* A working haskell compiler system, GHC(>=8.6), cabal-install(>=2.4), here're some options:+    * Mac users can get them via [homebew](//brew.sh/): `brew install ghc cabal-install`.+    * Windows users can get them via [chocolatey](//chocolatey.org): `choco install ghc cabal`.+    * Ubuntu users are recommended to use this [ppa](//launchpad.net/~hvr/+archive/ubuntu/ghc).+* A working C/C++ compiler support C++11, here're some options:+    * Mac users can use the `clang` comes with the [XCode Command Line Tools](https://developer.apple.com/downloads).+    * Windows users can use the mingw's one comes with GHC, you can use it by adding `your_path_to_ghc\mingw\bin` to your `PATH`.+    * Ubuntu users can install `gcc/g++` by running `sudo apt install build-essential`. * Tests need [hspec-discover](https://hackage.haskell.org/package/hspec-discover).  ## Example usage
Z-Data.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               Z-Data-version:            0.8.7.0+version:            0.8.8.0 synopsis:           Array, vector and text description:        This package provides array, slice and text operations license:            BSD-3-Clause@@ -23,6 +23,8 @@   README.md   third_party/fastvalidate-utf-8/include/simdasciicheck.h   third_party/fastvalidate-utf-8/include/simdutf8check.h+  third_party/fastvalidate-utf-8/include/simdasciicheck_avx512.h+  third_party/fastvalidate-utf-8/include/simdutf8check_avx512.h   third_party/fastbase64/include/chromiumbase64.h   third_party/fastbase64/include/fastavxbase64.h   third_party/fastbase64/src/fastavxbase64.c@@ -119,7 +121,7 @@  flag use-avx512   description:-    Use AVX512 instructions(utf8 validation, base64 codec, etc).+    Use AVX512(AVX512F, AVX512VL, AVX512BW, AVX512VBMI) instructions(utf8 validation, base64 codec, etc).    default:     False   manual:      True@@ -202,21 +204,24 @@     third_party/re2    includes:-    simdasciicheck.h-    simdutf8check.h     utf8rewind.h     chromiumbase64.h -  if flag(use-avx2)-      includes:-        fastavxbase64.h+  if arch(x86_64)+    includes:+      simdasciicheck.h+      simdutf8check.h -  if flag(use-avx512)-      includes:-        simdasciicheck_avx512.h-        simdutf8check_avx512.h-        fastavx512bwbase64.h+    if flag(use-avx2)+        includes:+          fastavxbase64.h +    if flag(use-avx512)+        includes:+          simdasciicheck_avx512.h+          simdutf8check_avx512.h+          fastavx512bwbase64.h+   c-sources:     cbits/bytes.c     cbits/dtoa.c@@ -233,13 +238,14 @@     third_party/utf8rewind/source/unicodedatabase.c     third_party/utf8rewind/source/utf8rewind.c -  if flag(use-avx2)-      c-sources:-        third_party/fastbase64/src/fastavxbase64.c+  if arch(x86_64)+    if flag(use-avx2)+        c-sources:+          third_party/fastbase64/src/fastavxbase64.c -  if flag(use-avx512)-      c-sources:-        third_party/fastbase64/src/fastavx512bwbase64.c+    if flag(use-avx512)+        c-sources:+          third_party/fastbase64/src/fastavx512bwbase64.c    cxx-sources:     cbits/regex.cc@@ -269,22 +275,25 @@   default-language:   Haskell2010   build-tool-depends: hsc2hs:hsc2hs -any -  cc-options:         -std=c11 -Wno-sign-compare+  cc-options:         -std=c11 -Wall -Wno-pointer-to-int-cast+  cxx-options:        -std=c++11 -  if flag(use-avx512)-    cc-options:       -march=cannonlake -DZ_USE_AVX512-  else-    if flag(use-avx2)-      cc-options:     -mavx2 -DZ_USE_AVX2+  if arch(x86_64)+    if flag(use-avx512)+      cc-options:       -march=cannonlake+      cxx-options:      -march=cannonlake     else-      cc-options:     -msse4.2--  cxx-options:        -std=c++11+      if flag(use-avx2)+        cc-options:     -mavx2+        cxx-options:    -mavx2+      else+        cc-options:     -msse4.2+        cxx-options:    -msse4.2    if os(windows)     extra-libraries: stdc++     cc-options:      -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600-    cxx-options:      -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600+    cxx-options:     -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600   else     if os(osx)       extra-libraries:@@ -306,7 +315,7 @@   -- we work around this issue using Setup.hs    ghc-options:-    -Wall -Wno-unticked-promoted-constructors -Wno-incomplete-patterns+    -Wall -Wno-unticked-promoted-constructors  -Wno-incomplete-patterns    default-extensions:     BangPatterns
Z/Data/Builder/Numeric.hs view
@@ -516,7 +516,7 @@             let !i = fromIntegral v .&. 0xFF; !j = i + i             writePrimArray marr off $ indexOffPtr hexDigitTable j             writePrimArray marr (off + 1) $ indexOffPtr hexDigitTable (j+1)-        | d < 0  = do         -- for FiniteBits instances which has extra bits+        | otherwise = do         -- for FiniteBits instances which has extra bits             let !i = fromIntegral v .&. 0x0F :: Int             writePrimArray marr off $ i2wHex i @@ -538,7 +538,7 @@             let !i = fromIntegral v .&. 0xFF; !j = i + i             writePrimArray marr off $ indexOffPtr hexDigitTableUpper j             writePrimArray marr (off + 1) $ indexOffPtr hexDigitTableUpper (j+1)-        | d < 0  = do         -- for FiniteBits instances which has extra bits+        | otherwise = do         -- for FiniteBits instances which has extra bits             let !i = fromIntegral v .&. 0x0F :: Int             writePrimArray marr off $ i2wHexUpper i 
Z/Data/CBytes.hs view
@@ -355,6 +355,7 @@                 let i' = i + l                 writePrimArray mba i' w8                 copy bs (i'+1) mba+    copy _ _ _ = error "Z.Data.CBytes.intercalateElem: impossible"  instance IsString CBytes where     {-# INLINE fromString #-}
Z/Data/Parser/Numeric.hs view
@@ -108,8 +108,7 @@ w2iHex w     | w <= 57   = fromIntegral w - 48     | w <= 70   = fromIntegral w - 55-    | w <= 102  = fromIntegral w - 87-+    | otherwise = fromIntegral w - 87  -- | Same with 'uint', but sliently cast in case of overflow. uint_ :: forall a. (Integral a, Bounded a) => Parser a
Z/Data/Vector.hs view
@@ -96,6 +96,7 @@   , mapAccumR   -- ** Generating and unfolding vector   , replicate+  , replicateMVec   , cycleN   , unfoldr   , unfoldrN
Z/Data/Vector/Base.hs view
@@ -56,6 +56,7 @@   , mapAccumR   -- ** Generating and unfolding vector   , replicate+  , replicateMVec   , cycleN   , unfoldr   , unfoldrN@@ -85,6 +86,7 @@ import           Control.Exception import           Control.Monad import           Control.Monad.ST+import           Control.Monad.Primitive import           Data.Bits import           Data.Char                      (ord) import qualified Data.Foldable                  as F@@ -338,51 +340,33 @@             | i >= end  = salt             | otherwise = go (h salt (indexArr arr i)) (i+1) --- | Traverse vector and gather result in another vector,+-- | Traverse vector and gather result in another vector.+--+-- There're rules to optimize the intermedia list away when @f@ is an instance of 'PrimMoand',+-- such as 'IO', 'ST' or 'Z.Data.Parser.Parser'. traverseVec :: (Vec v a, Vec u b, Applicative f) => (a -> f b) -> v a -> f (u b) {-# INLINE [1] traverseVec #-}-{-# RULES "traverseVec/ST" forall f. traverseVec f = traverseWithIndexST (const f) #-}-{-# RULES "traverseVec/IO" forall f. traverseVec f = traverseWithIndexIO (const f) #-}+{-# RULES "traverseVec/PrimMonad" forall (f :: PrimMonad m => a -> m b). traverseVec f = traverseWithIndexPM (const f) #-} traverseVec f v = packN (length v) <$> T.traverse f (unpack v) --- | Traverse vector and gather result in another vector,+-- | Traverse vector and gather result in another vector. traverseWithIndex :: (Vec v a, Vec u b, Applicative f) => (Int -> a -> f b) -> v a -> f (u b) {-# INLINE [1] traverseWithIndex #-}-{-# RULES "traverseWithIndex/ST" traverseWithIndex = traverseWithIndexST #-}-{-# RULES "traverseWithIndex/IO" traverseWithIndex = traverseWithIndexIO #-}+{-# RULES "traverseWithIndex/PrimMonad" forall (f :: PrimMonad m => Int -> a -> m b). traverseWithIndex f = traverseWithIndexPM f #-} traverseWithIndex f v = packN (length v) <$> zipWithM f [0..] (unpack v) -traverseWithIndexST :: forall v u a b s. (Vec v a, Vec u b) => (Int -> a -> ST s b) -> v a -> ST s (u b)-{-# INLINE traverseWithIndexST #-}-traverseWithIndexST f (Vec arr s l)-    | l == 0    = return empty-    | otherwise = do-        marr <- newArr l-        go marr 0-        ba <- unsafeFreezeArr marr-        return $! fromArr ba 0 l-  where-    go :: MArr (IArray u) s b -> Int -> ST s ()-    go !marr !i-        | i >= l = return ()-        | otherwise = do-            x <- indexArrM arr (i+s)-            writeArr marr i =<< f i x-            go marr (i+1)--traverseWithIndexIO :: forall v u a b. (Vec v a, Vec u b) => (Int -> a -> IO b) -> v a -> IO (u b)-{-# INLINE traverseWithIndexIO #-}-traverseWithIndexIO f (Vec arr s l)+traverseWithIndexPM :: forall m v u a b. (PrimMonad m, Vec v a, Vec u b) => (Int -> a -> m b) -> v a -> m (u b)+{-# INLINE traverseWithIndexPM #-}+traverseWithIndexPM f (Vec arr s l)     | l == 0    = return empty     | otherwise = do         marr <- newArr l-        go marr 0-        ba <- unsafeFreezeArr marr+        ba <- go marr 0         return $! fromArr ba 0 l   where-    go :: MArr (IArray u) RealWorld b -> Int -> IO ()+    go :: MArr (IArray u) (PrimState m) b -> Int -> m (IArray u b)     go !marr !i-        | i >= l = return ()+        | i >= l = unsafeFreezeArr marr         | otherwise = do             x <- indexArrM arr (i+s)             writeArr marr i =<< f i x@@ -563,9 +547,7 @@ -- | /O(n)/, pack an ASCII 'String', multi-bytes char WILL BE CHOPPED! packASCII :: String -> Bytes {-# INLINE CONLIKE [0] packASCII #-}-{-# RULES-    "packASCII/packASCIIAddr" forall addr . packASCII (unpackCString# addr) = packASCIIAddr addr-  #-}+{-# RULES "packASCII/packASCIIAddr" forall addr . packASCII (unpackCString# addr) = packASCIIAddr addr #-} packASCII = pack . fmap (fromIntegral . ord)  packASCIIAddr :: Addr# -> Bytes@@ -735,7 +717,7 @@ -- This function is a /good consumer/ in the sense of build/foldr fusion. -- packN :: forall v a. Vec v a => Int -> [a] -> v a-{-# INLINE packN #-}+{-# INLINE [1] packN #-} packN n0 = \ ws0 -> runST (do let n = max 4 n0                               marr <- newArr n                               (IPair i marr') <- foldM go (IPair 0 marr) ws0@@ -755,6 +737,31 @@                 !marr' <- resizeMutableArr marr n'                 writeArr marr' i x                 return (IPair (i+1) marr')+++-- | A version of 'replicateM' which works on 'Vec', with specialized rules under 'PrimMonad'.+--+-- There're rules to optimize the intermedia list away when m is an instance of 'PrimMoand',+-- such as 'IO', 'ST' or 'Z.Data.Parser.Parser'.+replicateMVec :: (Applicative f, Vec v a) => Int -> f a -> f (v a)+{-# INLINE [1] replicateMVec #-}+{-# RULES "replicateMVec/PrimMonad" forall n (x :: IO a). replicateMVec n x = replicatePMVec n x #-}+replicateMVec n f = packN n <$> replicateM n f++-- | A version of 'replicateM' which works on 'PrimMonad' and 'Vec'.+replicatePMVec :: (PrimMonad m, Vec v a) => Int -> m a -> m (v a)+{-# INLINE replicatePMVec #-}+replicatePMVec n f = do+    marr <- newArr n+    ba <- go marr 0+    (return $! fromArr ba 0 n)+  where+    go marr i+        | i >= n = unsafeFreezeArr marr+        | otherwise = do+            x <- f+            writeArr marr i x+            go marr (i+1)  -- | /O(n)/ Convert a list into a vector with given size. --
Z/Data/Vector/Hex.hs view
@@ -34,7 +34,6 @@ import           GHC.Stack import           System.IO.Unsafe import qualified Z.Data.Vector.Base         as V-import qualified Z.Data.Vector.Extra        as V import qualified Z.Data.Builder.Base        as B import qualified Z.Data.Text.Base           as T import qualified Z.Data.Text.Print          as T@@ -74,7 +73,6 @@             if upper             then hs_hex_encode_upper buf# 0 parr s l             else hs_hex_encode buf# 0 parr s l-  -- | 'B.Builder' version of 'hexEncode'. hexEncodeBuilder :: Bool -- ^ uppercase?
Z/Foreign/CPtr.hs view
@@ -12,7 +12,9 @@  module Z.Foreign.CPtr (   -- * CPtr type-    CPtr, newCPtr', newCPtrUnsafe, newCPtr, withCPtr, withCPtrsUnsafe, withCPtrs+    CPtr, newCPtr', newCPtrUnsafe, newCPtr+  , withCPtr, withCPtrsUnsafe, withCPtrForever, withCPtrs+  , addCPtrDep   -- * Ptr type   , Ptr   , nullPtr@@ -21,11 +23,11 @@  import Control.Monad import Control.Monad.Primitive-import Control.Exception                    (mask_) import Data.Primitive.PrimArray import qualified Z.Data.Text                as T import GHC.Ptr import GHC.Exts+import GHC.IO import Z.Data.Array import Z.Foreign @@ -52,6 +54,7 @@ newCPtr' :: IO (Ptr a) -- ^ initializer          -> FunPtr (Ptr a -> IO b) -- ^ finalizer          -> IO (CPtr a)+{-# INLINABLE newCPtr' #-} newCPtr' ini (FunPtr fin#) = mask_ $ do     mpa <- newPrimArray 1     p@(Ptr addr#) <- ini@@ -70,6 +73,7 @@ newCPtrUnsafe :: (MutableByteArray# RealWorld -> IO r) -- ^ initializer               -> FunPtr (Ptr a -> IO b) -- ^ finalizer               -> IO (CPtr a, r)+{-# INLINABLE newCPtrUnsafe #-} newCPtrUnsafe ini (FunPtr fin#) = mask_ $ do     mpa@(MutablePrimArray mba#) <- newPrimArray 1     r <- ini mba#@@ -88,6 +92,7 @@ newCPtr :: (Ptr (Ptr a) -> IO r) -- ^ initializer         -> FunPtr (Ptr a -> IO b) -- ^ finalizer         -> IO (CPtr a, r)+{-# INLINABLE newCPtr #-} newCPtr ini (FunPtr fin#) = mask_ $ do     mpa <- newPinnedPrimArray 1     r <- ini (mutablePrimArrayContents mpa)@@ -99,15 +104,36 @@         in s2#     return (CPtr pa, r) --- | The only way to use 'CPtr' as a 'Ptr' in FFI is to use 'withCPtr'.+-- | Use 'CPtr' as a 'Ptr' in FFI. withCPtr :: CPtr a -> (Ptr a -> IO b) -> IO b+{-# INLINABLE withCPtr #-} withCPtr (CPtr pa@(PrimArray ba#)) f = do     r <- f (indexPrimArray pa 0)     primitive_ (touch# ba#)     return r +-- | Use 'CPtr' as a 'Ptr' in FFI(potentially running forever).+--+-- When you pass a forever loop to 'withCPtr', GHC's simplifier may think the 'touch#'(which keep the 'CPtr' alive) after the loop are unreachable,+-- so it may be optimized away, 'withCPtrForever' solves that.+--+withCPtrForever :: CPtr a -> (Ptr a -> IO b) -> IO b+#if MIN_VERSION_base(4,15,0)+{-# INLINABLE withCPtrForever #-}+withCPtrForever (CPtr pa@(PrimArray ba#)) f = IO $ \ s ->+    case f (indexPrimArray pa 0) of+        IO action# -> keepAlive# ba# s action#+#else+{-# NOINLINE withCPtrForever #-}+withCPtrForever (CPtr pa@(PrimArray ba#)) f = do+    r <- f (indexPrimArray pa 0)+    primitive_ (touch# ba#)+    return r+#endif+ -- | Pass a list of 'CPtr Foo' as @foo**@. USE THIS FUNCTION WITH UNSAFE FFI ONLY! withCPtrsUnsafe :: forall a b. [CPtr a] -> (BA# (Ptr a) -> Int -> IO b) -> IO b+{-# INLINABLE withCPtrsUnsafe #-} withCPtrsUnsafe cptrs f = do     mpa <- newPrimArray @IO @(Ptr a) len     foldM_ (\ !i (CPtr pa) ->@@ -120,6 +146,7 @@  -- | Pass a list of 'CPtr Foo' as @foo**@. withCPtrs :: forall a b. [CPtr a] -> (Ptr (Ptr a) -> Int -> IO b) -> IO b+{-# INLINABLE withCPtrs #-} withCPtrs cptrs f = do     mpa <- newPinnedPrimArray @IO @(Ptr a) len     foldM_ (\ !i (CPtr pa) ->@@ -128,3 +155,19 @@     primitive_ (touch# cptrs)     return r   where len = length cptrs++-- | @addCPtrDep a b@ make @b@\'s life depends on @a@\'s, so that @b@ is guaranteed to outlive @a@.+--+-- This function is useful when you want to create life dependency among 'CPtr's,+-- be careful about the cost of collecting weak pointers though, see+-- <http://blog.ezyang.com/2014/05/the-cost-of-weak-pointers-and-finalizers-in-ghc/>.+-- e.g. If three 'CPtr's form a dependency chain, the dead weak list may get traversed three times.+-- So instead of adding dependencies in a chain or one by one, you should add them in a single call+-- with a tuple like @addCPtrDep root (fieldA, fieldB, ...)@.+--+addCPtrDep :: CPtr a -> b -> IO ()+{-# INLINABLE addCPtrDep #-}+addCPtrDep (CPtr (PrimArray ba#)) b =+    primitive_ $ \ s0# ->+        let !(# s1#, _ #) = mkWeakNoFinalizer# ba# b s0#+        in s1#
cbits/bytes.c view
@@ -36,9 +36,9 @@ #if defined(__x86_64__) #include <x86intrin.h> #endif-#if defined(Z_USE_AVX512)+#if defined(__AVX512BW__) #include <fastavx512bwbase64.h>-#elif defined(Z_USE_AVX2)+#elif defined(__AVX2__) #include <fastavxbase64.h> #endif @@ -142,12 +142,12 @@         mask = mask << 16 | mask;         for (i = 32; i < LBLOCKSIZE * 8; i <<= 1)             mask = (mask << i) | mask;-            while (length >= LBLOCKSIZE) {-                if (DETECTCHAR (*asrc, mask))-                    break;-                length -= LBLOCKSIZE;-                asrc--;-            }+        while (length >= LBLOCKSIZE) {+            if (DETECTCHAR (*asrc, mask))+                break;+            length -= LBLOCKSIZE;+            asrc--;+        }         /* If there are fewer than LBLOCKSIZE characters left,          then we resort to the bytewise loop.  */         src = (unsigned char *) asrc + LBLOCKSIZE - 1;@@ -293,9 +293,9 @@ // Base64 codec  void hs_base64_encode(char* output, HsInt output_off, const char* input, HsInt off, HsInt len){-#if defined(Z_USE_AVX512)+#if defined(__AVX512BW__)     fast_avx512bw_base64_encode(output+output_off, input+off, len);-#elif defined(Z_USE_AVX2)+#elif defined(__AVX2__)     fast_avx2_base64_encode(output+output_off, input+off, len); #else     chromium_base64_encode(output+output_off, input+off, len);@@ -303,9 +303,9 @@ }  HsInt hs_base64_decode(char* output, const char* input, HsInt off, HsInt len){-#if defined(Z_USE_AVX512)+#if defined(__AVX512BW__)     size_t r = fast_avx512bw_base64_decode(output, input+off, len);-#elif defined(Z_USE_AVX2)+#elif defined(__AVX2__)     size_t r = fast_avx2_base64_decode(output, input+off, len); #else     size_t r = chromium_base64_decode(output, input+off, len);@@ -352,7 +352,7 @@  // this function should be called with large enough len, otherwise underflow will happen. size_t hs_count_simd(unsigned char *str, size_t len, unsigned char w) {-#if defined(Z_USE_AVX2) +#if defined(__AVX2__)      __m256i pat = _mm256_set1_epi8(w);     size_t prefix = 0, res = 0;     size_t i = 0;@@ -457,7 +457,7 @@ }  HsInt hs_count_ba(unsigned char *str, HsInt off, HsInt len, unsigned char w) {-#if defined(__SSE4_2__) || defined(Z_USE_AVX2) || defined(Z_USE_AVX512)+#if defined(__SSE4_2__) || defined(__AVX2__)     if (len >= 1024) return (HsInt)hs_count_simd(str+off, len, w);     else { #endif@@ -466,7 +466,7 @@         for (res = 0; len-- != 0; ++str)             res += *str == w;         return res;-#if defined(__SSE4_2__) || defined(Z_USE_AVX2) || defined(Z_USE_AVX512)+#if defined(__SSE4_2__) || defined(__AVX2__)     } #endif }
cbits/dtoa.c view
@@ -32,6 +32,7 @@ #include <stdint.h> // uint64_t etc. #include <assert.h> // assert #include <math.h> // ceil+#include <string.h> // memcpy  #ifdef _MSC_VER #pragma warning(disable : 4204) // nonstandard extension used : non-constant aggregate initializer@@ -54,8 +55,6 @@ #define MIN_TARGET_EXP   -60 #define MASK32           0xFFFFFFFFULL -#define CAST_U64(d) (*(uint64_t*)&d)-#define CAST_U32(d) (*(uint32_t*)&d) #define MIN(x,y) ((x) <= (y) ? (x) : (y)) #define MAX(x,y) ((x) >= (y) ? (x) : (y)) @@ -207,7 +206,8 @@ static diy_fp double2diy_fp(double d) {     diy_fp fp;-    uint64_t u64 = CAST_U64(d);+    uint64_t u64;+    memcpy(&u64, &d, sizeof(double));     if (!(u64 & D64_EXP_MASK)) {         fp.f = u64 & D64_FRACT_MASK;         fp.e = 1 - D64_EXP_BIAS;@@ -222,7 +222,8 @@ static diy_fp float2diy_fp(float d) {     diy_fp fp;-    uint32_t u32 = CAST_U32(d);+    uint32_t u32;+    memcpy(&u32, &d, sizeof(float));     if (!(u32 & D32_EXP_MASK)) {         fp.f = (uint64_t)u32 & D32_FRACT_MASK;          fp.e = 1 - D32_EXP_BIAS; @@ -315,7 +316,8 @@     diy_fp b_plus = normalize_diy_fp(t);     diy_fp b_minus;     diy_fp c_mk; // Cached power of ten: 10^-k-    uint64_t u64 = CAST_U64(v);+    uint64_t u64;+    memcpy(&u64, &v, sizeof(double));     assert(v > 0 && v <= 1.7976931348623157e308); // Grisu only handles strictly positive finite numbers.     if (!(u64 & D64_FRACT_MASK) && (u64 & D64_EXP_MASK) != 0) {          b_minus.f = (dfp.f << 2) - 1; b_minus.e =  dfp.e - 2;@@ -346,7 +348,8 @@     diy_fp b_plus = normalize_diy_fp(t);     diy_fp b_minus;     diy_fp c_mk; // Cached power of ten: 10^-k-    uint64_t u32 = CAST_U32(v);+    uint64_t u32;+    memcpy(&u32, &v, sizeof(float));     assert(v > 0 && v <= 3.4028235e38); // Grisu only handles strictly positive finite numbers.     if (!(u32 & D32_FRACT_MASK) && (u32 & D32_EXP_MASK) != 0) {         b_minus.f = (dfp.f << 2) - 1; b_minus.e =  dfp.e - 2;
cbits/text.c view
@@ -30,21 +30,21 @@ #include <utf8rewind.h> #include <codepoint.h> -#if defined(Z_USE_AVX512)+#if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512VBMI__) #include <simdasciicheck_avx512.h> #include <simdutf8check_avx512.h>-#else+#elif defined(__SSSE3__)  #include <simdasciicheck.h> #include <simdutf8check.h> #endif  HsInt ascii_validate(const char* p, HsInt off, HsInt len){     const char* q = p + off;-#if defined(Z_USE_AVX512)+#if defined(AVX512_IMPLEMENTATION)     return (HsInt)validate_ascii_fast_avx512(q, (size_t)len);-#elif defined(Z_USE_AVX2)+#elif defined(__AVX2__)     return (HsInt)validate_ascii_fast_avx(q, (size_t)len);-#elif defined(__SSE2__)+#elif defined(__SSSE3__)      return (HsInt)validate_ascii_fast(q, (size_t)len); #else     return (HsInt)ascii_u64(q, (size_t)len);@@ -53,11 +53,11 @@ // for some reason unknown, on windows we have to supply a seperated version of ascii_validate // otherwise we got segfault if we import the same FFI with different type (Addr# vs ByteArray#) HsInt ascii_validate_addr(const char* p, HsInt len){-#if defined(Z_USE_AVX512)+#if defined(AVX512_IMPLEMENTATION)     return (HsInt)validate_ascii_fast_avx512(p, (size_t)len);-#elif defined(Z_USE_AVX2)+#elif defined(__AVX2__)     return (HsInt)validate_ascii_fast_avx(p, (size_t)len);-#elif defined(__SSE2__)+#elif defined(__SSSE3__)      return (HsInt)validate_ascii_fast(p, (size_t)len); #else     return (HsInt)ascii_u64(p, (size_t)len);@@ -66,11 +66,11 @@  HsInt utf8_validate(const char* p, HsInt off, HsInt len){     const char* q = p + off;-#if defined(Z_USE_AVX512)+#if defined(AVX512_IMPLEMENTATION)     return (HsInt)validate_utf8_fast_avx512(q, (size_t)len);-#elif defined(Z_USE_AVX2)+#elif defined(__AVX2__)     return (HsInt)validate_utf8_fast_avx(q, (size_t)len);-#elif defined(__SSE2__)+#elif defined(__SSSE3__)      return (HsInt)validate_utf8_fast(q, (size_t)len); #else     return utf8_validate_slow(q, (size_t)len);@@ -79,11 +79,11 @@ // for some reason unknown, on windows we have to supply a seperated version of utf8_validate // otherwise we got segfault if we import the same FFI with different type (Addr# vs ByteArray#) HsInt utf8_validate_addr(const char* p, HsInt len){-#if defined(Z_USE_AVX512)+#if defined(AVX512_IMPLEMENTATION)     return (HsInt)validate_utf8_fast_avx512(p, (size_t)len);-#elif defined(Z_USE_AVX2)+#elif defined(__AVX2__)     return (HsInt)validate_utf8_fast_avx(p, (size_t)len);-#elif defined(__SSE2__)+#elif defined(__SSSE3__)      return (HsInt)validate_utf8_fast(p, (size_t)len); #else     return utf8_validate_slow(p, (size_t)len);
+ third_party/fastvalidate-utf-8/include/simdasciicheck_avx512.h view
@@ -0,0 +1,29 @@+#ifndef SIMDASCIICHECK_AXV512_H+#define SIMDASCIICHECK_AXV512_H++#ifdef __AVX512F__+#include <stdbool.h>   // c99 bool+#include <stddef.h>    // size_t+#include <x86intrin.h>+// The function returns true (1) if all chars passed in src are+// 7-bit values (0x00..0x7F). Otherwise, it returns false (0).+static bool validate_ascii_fast_avx512(const char *src, size_t len) {+  size_t i = 0;+  __m512i has_error = _mm512_setzero_si512();+  if (len >= 64) {+    for (; i <= len - 64; i += 64) {+      __m512i current_bytes = _mm512_loadu_si512((const __m512i *)(src + i));+      has_error = _mm512_or_si512(has_error, current_bytes);+    }+  }+  int reduced = _mm512_reduce_or_epi32(has_error);++  for (; i < len; i++) {+    reduced |= src[i];+  }++  return !(reduced & 0x80808080);+}+#endif++#endif
+ third_party/fastvalidate-utf-8/include/simdutf8check_avx512.h view
@@ -0,0 +1,297 @@+#ifndef SIMDUTF8CHECK_AXV512_H+#define SIMDUTF8CHECK_AXV512_H++#include <stdbool.h>+#include <stddef.h>+#include <stdint.h>+#include <string.h>+#include <x86intrin.h>+/*+ * legal utf-8 byte sequence+ * http://www.unicode.org/versions/Unicode6.0.0/ch03.pdf - page 94+ *+ *  Code Points        1st       2s       3s       4s+ * U+0000..U+007F     00..7F+ * U+0080..U+07FF     C2..DF   80..BF+ * U+0800..U+0FFF     E0       A0..BF   80..BF+ * U+1000..U+CFFF     E1..EC   80..BF   80..BF+ * U+D000..U+D7FF     ED       80..9F   80..BF+ * U+E000..U+FFFF     EE..EF   80..BF   80..BF+ * U+10000..U+3FFFF   F0       90..BF   80..BF   80..BF+ * U+40000..U+FFFFF   F1..F3   80..BF   80..BF   80..BF+ * U+100000..U+10FFFF F4       80..8F   80..BF   80..BF+ *+ */++#if defined(__AVX512F__) && defined(__AVX512VL__) && defined(__AVX512VBMI__)+#define AVX512_IMPLEMENTATION+#endif++#ifdef AVX512_IMPLEMENTATION++/*****************************/+static inline __m512i avx512_push_last_byte_of_a_to_b(__m512i a, __m512i b) {+  __m512i indexes = _mm512_set_epi64(0x3E3D3C3B3A393837, 0x363534333231302F,+                                     0x2E2D2C2B2A292827, 0x262524232221201F,+                                     0x1E1D1C1B1A191817, 0x161514131211100F,+                                     0x0E0D0C0B0A090807, 0x060504030201007F);+  return _mm512_permutex2var_epi8(b, indexes, a);+}++static inline __m512i avx512_push_last_2bytes_of_a_to_b(__m512i a, __m512i b) {+  __m512i indexes = _mm512_set_epi64(0x3D3C3B3A39383736, 0x3534333231302F2E,+                                     0x2D2C2B2A29282726, 0x2524232221201F1E,+                                     0x1D1C1B1A19181716, 0x1514131211100F0E,+                                     0x0D0C0B0A09080706, 0x0504030201007F7E);+  return _mm512_permutex2var_epi8(b, indexes, a);+}++// all byte values must be no larger than 0xF4+static inline void avx512_checkSmallerThan0xF4(__m512i current_bytes,+                                               __mmask64 *has_error) {+  *has_error =+      _kor_mask64(*has_error, _mm512_cmpgt_epu8_mask(current_bytes,+                                                     _mm512_set1_epi8(0xF4)));+}++static inline __m512i avx512_continuationLengths(__m512i high_nibbles) {+  return _mm512_shuffle_epi8(+      _mm512_setr4_epi32(0x01010101, 0x01010101, 0x00000000,+                         0x04030202), // see avx2 version for clarity+      high_nibbles);+}++static inline __m512i avx512_carryContinuations(__m512i initial_lengths,+                                                __m512i previous_carries) {++  __m512i right1 = _mm512_subs_epu8(+      avx512_push_last_byte_of_a_to_b(previous_carries, initial_lengths),+      _mm512_set1_epi8(1));+  __m512i sum = _mm512_add_epi8(initial_lengths, right1);++  __m512i right2 =+      _mm512_subs_epu8(avx512_push_last_2bytes_of_a_to_b(previous_carries, sum),+                       _mm512_set1_epi8(2));+  return _mm512_add_epi8(sum, right2);+}++static inline void avx512_checkContinuations(__m512i initial_lengths,+                                             __m512i carries,+                                             __mmask64 *has_error) {+  // overlap || underlap+  // carry > length && length > 0 || !(carry > length) && !(length > 0)+  // (carries > length) == (lengths > 0)+  *has_error = _kor_mask64(+      *has_error,+      _kxnor_mask64(+          _mm512_cmpgt_epi8_mask(carries, initial_lengths),+          _mm512_cmpgt_epi8_mask(initial_lengths, _mm512_setzero_si512())));+}++// when 0xED is found, next byte must be no larger than 0x9F+// when 0xF4 is found, next byte must be no larger than 0x8F+// next byte must be continuation, ie sign bit is set, so signed < is ok+static inline void avx512_checkFirstContinuationMax(__m512i current_bytes,+                                                    __m512i off1_current_bytes,+                                                    __mmask64 *has_error) {+  __mmask64 maskED =+      _mm512_cmpeq_epi8_mask(off1_current_bytes, _mm512_set1_epi8(0xED));+  __mmask64 maskF4 =+      _mm512_cmpeq_epi8_mask(off1_current_bytes, _mm512_set1_epi8(0xF4));+  __mmask64 badfollowED = _kand_mask64(+      _mm512_cmpgt_epi8_mask(current_bytes, _mm512_set1_epi8(0x9F)), maskED);+  __mmask64 badfollowF4 = _kand_mask64(+      _mm512_cmpgt_epi8_mask(current_bytes, _mm512_set1_epi8(0x8F)), maskF4);++  *has_error = _kor_mask64(*has_error, _kor_mask64(badfollowED, badfollowF4));+}++// map off1_hibits => error condition+// hibits     off1    cur+// C       => < C2 && true+// E       => < E1 && < A0+// F       => < F1 && < 90+// else      false && false+static inline void avx512_checkOverlong(__m512i current_bytes,+                                        __m512i off1_current_bytes,+                                        __m512i hibits, __m512i previous_hibits,+                                        __mmask64 *has_error) {+  __m512i off1_hibits =+      avx512_push_last_byte_of_a_to_b(previous_hibits, hibits);+  __m512i initial_mins = _mm512_shuffle_epi8(+      _mm512_setr4_epi32(0x80808080, 0x80808080, 0x80808080,+                         0xF1E180C2), // see avx2 version for clarity+      off1_hibits);++  __mmask64 initial_under =+      _mm512_cmpgt_epi8_mask(initial_mins, off1_current_bytes);++  __m512i second_mins = _mm512_shuffle_epi8(+      _mm512_setr4_epi32(0x80808080, 0x80808080, 0x80808080,+                         0x90A07F7F), // see avx2 version for clarity+      off1_hibits);+  __mmask64 second_under = _mm512_cmpgt_epi8_mask(second_mins, current_bytes);+  *has_error =+      _kor_mask64(*has_error, _kand_mask64(initial_under, second_under));+}++struct avx512_processed_utf_bytes {+  __m512i rawbytes;+  __m512i high_nibbles;+  __m512i carried_continuations;+};++static inline void+avx512_count_nibbles(__m512i bytes, struct avx512_processed_utf_bytes *answer) {+  answer->rawbytes = bytes;+  answer->high_nibbles =+      _mm512_and_si512(_mm512_srli_epi16(bytes, 4), _mm512_set1_epi8(0x0F));+}++// check whether the current bytes are valid UTF-8+// at the end of the function, previous gets updated+static struct avx512_processed_utf_bytes+avx512_checkUTF8Bytes(__m512i current_bytes,+                      struct avx512_processed_utf_bytes *previous,+                      __mmask64 *has_error) {+  struct avx512_processed_utf_bytes pb;+  avx512_count_nibbles(current_bytes, &pb);++  avx512_checkSmallerThan0xF4(current_bytes, has_error);++  __m512i initial_lengths = avx512_continuationLengths(pb.high_nibbles);++  pb.carried_continuations = avx512_carryContinuations(+      initial_lengths, previous->carried_continuations);++  avx512_checkContinuations(initial_lengths, pb.carried_continuations,+                            has_error);++  __m512i off1_current_bytes =+      avx512_push_last_byte_of_a_to_b(previous->rawbytes, pb.rawbytes);+  avx512_checkFirstContinuationMax(current_bytes, off1_current_bytes,+                                   has_error);++  avx512_checkOverlong(current_bytes, off1_current_bytes, pb.high_nibbles,+                       previous->high_nibbles, has_error);+  return pb;+}++// check whether the current bytes are valid UTF-8+// at the end of the function, previous gets updated+static struct avx512_processed_utf_bytes+avx512_checkUTF8Bytes_asciipath(__m512i current_bytes,+                                struct avx512_processed_utf_bytes *previous,+                                __mmask64 *has_error) {+  if (!_mm512_cmpge_epu8_mask(current_bytes,+                              _mm512_set1_epi8(0x80))) { // fast ascii path+    *has_error = _kor_mask64(+        *has_error,+        _mm512_cmpgt_epi8_mask(+            previous->carried_continuations,+            _mm512_setr_epi32(0x09090909, 0x09090909, 0x09090909, 0x09090909,+                              0x09090909, 0x09090909, 0x09090909, 0x09090909,+                              0x09090909, 0x09090909, 0x09090909, 0x09090909,+                              0x09090909, 0x09090909, 0x09090909, 0x01090909)));+    return *previous;+  }++  struct avx512_processed_utf_bytes pb;+  avx512_count_nibbles(current_bytes, &pb);++  avx512_checkSmallerThan0xF4(current_bytes, has_error);++  __m512i initial_lengths = avx512_continuationLengths(pb.high_nibbles);++  pb.carried_continuations = avx512_carryContinuations(+      initial_lengths, previous->carried_continuations);++  avx512_checkContinuations(initial_lengths, pb.carried_continuations,+                            has_error);++  __m512i off1_current_bytes =+      avx512_push_last_byte_of_a_to_b(previous->rawbytes, pb.rawbytes);+  avx512_checkFirstContinuationMax(current_bytes, off1_current_bytes,+                                   has_error);++  avx512_checkOverlong(current_bytes, off1_current_bytes, pb.high_nibbles,+                       previous->high_nibbles, has_error);+  return pb;+}++static bool validate_utf8_fast_avx512_asciipath(const char *src, size_t len) {+  size_t i = 0;+  __mmask64 has_error = 0;+  struct avx512_processed_utf_bytes previous = {+    .rawbytes = _mm512_setzero_si512(),+    .high_nibbles = _mm512_setzero_si512(),+    .carried_continuations = _mm512_setzero_si512()+  };+  if (len >= 64) {+    for (; i <= len - 64; i += 64) {+      __m512i current_bytes = _mm512_loadu_si512((const __m512i *)(src + i));+      previous =+          avx512_checkUTF8Bytes_asciipath(current_bytes, &previous, &has_error);+    }+  }++  // last part+  if (i < len) {+    char buffer[64];+    memset(buffer, 0, 64);+    memcpy(buffer, src + i, len - i);+    __m512i current_bytes = _mm512_loadu_si512((const __m512i *)(buffer));+    previous = avx512_checkUTF8Bytes(current_bytes, &previous, &has_error);+  } else {+    has_error = _kor_mask64(+        has_error,+        _mm512_cmpgt_epi8_mask(+            previous.carried_continuations,+            _mm512_setr_epi32(0x09090909, 0x09090909, 0x09090909, 0x09090909,+                              0x09090909, 0x09090909, 0x09090909, 0x09090909,+                              0x09090909, 0x09090909, 0x09090909, 0x09090909,+                              0x09090909, 0x09090909, 0x09090909, 0x01090909)));+  }++  return !has_error;+}++static bool validate_utf8_fast_avx512(const char *src, size_t len) {+  size_t i = 0;+  __mmask64 has_error = 0;+  struct avx512_processed_utf_bytes previous = {+    .rawbytes = _mm512_setzero_si512(),+    .high_nibbles = _mm512_setzero_si512(),+    .carried_continuations = _mm512_setzero_si512()+  };+  if (len >= 64) {+    for (; i <= len - 64; i += 64) {+      __m512i current_bytes = _mm512_loadu_si512((const __m512i *)(src + i));+      previous = avx512_checkUTF8Bytes(current_bytes, &previous, &has_error);+    }+  }++  // last part+  if (i < len) {+    char buffer[64];+    memset(buffer, 0, 64);+    memcpy(buffer, src + i, len - i);+    __m512i current_bytes = _mm512_loadu_si512((const __m512i *)(buffer));+    previous = avx512_checkUTF8Bytes(current_bytes, &previous, &has_error);+  } else {+    has_error = _kor_mask64(+        has_error,+        _mm512_cmpgt_epi8_mask(+            previous.carried_continuations,+            _mm512_setr_epi32(0x09090909, 0x09090909, 0x09090909, 0x09090909,+                              0x09090909, 0x09090909, 0x09090909, 0x09090909,+                              0x09090909, 0x09090909, 0x09090909, 0x09090909,+                              0x09090909, 0x09090909, 0x09090909, 0x01090909)));+  }++  return !has_error;+}++#endif // AVX512_IMPLEMENTATION++#endif // SIMDUTF8CHECK_AXV512_H
third_party/re2/re2/compile.cc view
@@ -79,9 +79,11 @@ struct Frag {   uint32_t begin;   PatchList end;+  bool nullable; -  Frag() : begin(0) { end.head = 0; }  // needed so Frag can go in vector-  Frag(uint32_t begin, PatchList end) : begin(begin), end(end) {}+  Frag() : begin(0), end(kNullPatchList), nullable(false) {}+  Frag(uint32_t begin, PatchList end, bool nullable)+      : begin(begin), end(end), nullable(nullable) {} };  // Input encodings.@@ -264,7 +266,7 @@  // Returns an unmatchable fragment. Frag Compiler::NoMatch() {-  return Frag(0, kNullPatchList);+  return Frag(); }  // Is a an unmatchable fragment?@@ -290,11 +292,11 @@   // To run backward over string, reverse all concatenations.   if (reversed_) {     PatchList::Patch(inst_.data(), b.end, a.begin);-    return Frag(b.begin, a.end);+    return Frag(b.begin, a.end, b.nullable && a.nullable);   }    PatchList::Patch(inst_.data(), a.end, b.begin);-  return Frag(a.begin, b.end);+  return Frag(a.begin, b.end, a.nullable && b.nullable); }  // Given fragments for a and b, returns fragment for a|b.@@ -310,7 +312,8 @@     return NoMatch();    inst_[id].InitAlt(a.begin, b.begin);-  return Frag(id, PatchList::Append(inst_.data(), a.end, b.end));+  return Frag(id, PatchList::Append(inst_.data(), a.end, b.end),+              a.nullable || b.nullable); }  // When capturing submatches in like-Perl mode, a kOpAlt Inst@@ -320,27 +323,44 @@ // then the operator is greedy.  If out1_ is the repetition // (and out_ moves forward), then the operator is non-greedy. -// Given a fragment a, returns a fragment for a* or a*? (if nongreedy)-Frag Compiler::Star(Frag a, bool nongreedy) {+// Given a fragment for a, returns a fragment for a+ or a+? (if nongreedy)+Frag Compiler::Plus(Frag a, bool nongreedy) {   int id = AllocInst(1);   if (id < 0)     return NoMatch();-  inst_[id].InitAlt(0, 0);-  PatchList::Patch(inst_.data(), a.end, id);+  PatchList pl;   if (nongreedy) {-    inst_[id].out1_ = a.begin;-    return Frag(id, PatchList::Mk(id << 1));+    inst_[id].InitAlt(0, a.begin);+    pl = PatchList::Mk(id << 1);   } else {-    inst_[id].set_out(a.begin);-    return Frag(id, PatchList::Mk((id << 1) | 1));+    inst_[id].InitAlt(a.begin, 0);+    pl = PatchList::Mk((id << 1) | 1);   }+  PatchList::Patch(inst_.data(), a.end, id);+  return Frag(a.begin, pl, a.nullable); } -// Given a fragment for a, returns a fragment for a+ or a+? (if nongreedy)-Frag Compiler::Plus(Frag a, bool nongreedy) {-  // a+ is just a* with a different entry point.-  Frag f = Star(a, nongreedy);-  return Frag(a.begin, f.end);+// Given a fragment for a, returns a fragment for a* or a*? (if nongreedy)+Frag Compiler::Star(Frag a, bool nongreedy) {+  // When the subexpression is nullable, one Alt isn't enough to guarantee+  // correct priority ordering within the transitive closure. The simplest+  // solution is to handle it as (a+)? instead, which adds the second Alt.+  if (a.nullable)+    return Quest(Plus(a, nongreedy), nongreedy);++  int id = AllocInst(1);+  if (id < 0)+    return NoMatch();+  PatchList pl;+  if (nongreedy) {+    inst_[id].InitAlt(0, a.begin);+    pl = PatchList::Mk(id << 1);+  } else {+    inst_[id].InitAlt(a.begin, 0);+    pl = PatchList::Mk((id << 1) | 1);+  }+  PatchList::Patch(inst_.data(), a.end, id);+  return Frag(id, pl, true); }  // Given a fragment for a, returns a fragment for a? or a?? (if nongreedy)@@ -358,7 +378,7 @@     inst_[id].InitAlt(a.begin, 0);     pl = PatchList::Mk((id << 1) | 1);   }-  return Frag(id, PatchList::Append(inst_.data(), pl, a.end));+  return Frag(id, PatchList::Append(inst_.data(), pl, a.end), true); }  // Returns a fragment for the byte range lo-hi.@@ -367,7 +387,7 @@   if (id < 0)     return NoMatch();   inst_[id].InitByteRange(lo, hi, foldcase, 0);-  return Frag(id, PatchList::Mk(id << 1));+  return Frag(id, PatchList::Mk(id << 1), false); }  // Returns a no-op fragment.  Sometimes unavoidable.@@ -376,7 +396,7 @@   if (id < 0)     return NoMatch();   inst_[id].InitNop(0);-  return Frag(id, PatchList::Mk(id << 1));+  return Frag(id, PatchList::Mk(id << 1), true); }  // Returns a fragment that signals a match.@@ -385,7 +405,7 @@   if (id < 0)     return NoMatch();   inst_[id].InitMatch(match_id);-  return Frag(id, kNullPatchList);+  return Frag(id, kNullPatchList, false); }  // Returns a fragment matching a particular empty-width op (like ^ or $)@@ -394,7 +414,7 @@   if (id < 0)     return NoMatch();   inst_[id].InitEmptyWidth(empty, 0);-  return Frag(id, PatchList::Mk(id << 1));+  return Frag(id, PatchList::Mk(id << 1), true); }  // Given a fragment a, returns a fragment with capturing parens around a.@@ -408,7 +428,7 @@   inst_[id+1].InitCapture(2*n+1, 0);   PatchList::Patch(inst_.data(), a.end, id+1); -  return Frag(id, PatchList::Mk((id+1) << 1));+  return Frag(id, PatchList::Mk((id+1) << 1), a.nullable); }  // A Rune is a name for a Unicode code point.@@ -567,7 +587,7 @@ Frag Compiler::FindByteRange(int root, int id) {   if (inst_[root].opcode() == kInstByteRange) {     if (ByteRangeEqual(root, id))-      return Frag(root, kNullPatchList);+      return Frag(root, kNullPatchList, false);     else       return NoMatch();   }@@ -575,7 +595,7 @@   while (inst_[root].opcode() == kInstAlt) {     int out1 = inst_[root].out1();     if (ByteRangeEqual(out1, id))-      return Frag(root, PatchList::Mk((root << 1) | 1));+      return Frag(root, PatchList::Mk((root << 1) | 1), false);      // CharClass is a sorted list of ranges, so if out1 of the root Alt wasn't     // what we're looking for, then we can stop immediately. Unfortunately, we@@ -587,7 +607,7 @@     if (inst_[out].opcode() == kInstAlt)       root = out;     else if (ByteRangeEqual(out, id))-      return Frag(root, PatchList::Mk(root << 1));+      return Frag(root, PatchList::Mk(root << 1), false);     else       return NoMatch();   }
third_party/re2/re2/dfa.cc view
@@ -167,6 +167,9 @@   typedef std::unordered_set<State*, StateHash, StateEqual> StateSet;   private:+  // Make it easier to swap in a scalable reader-writer mutex.+  using CacheMutex = Mutex;+   enum {     // Indices into start_ for unanchored searches.     // Add kStartAnchored for anchored searches.@@ -331,7 +334,7 @@   // while holding cache_mutex_ for writing, to avoid interrupting other   // readers.  Any State* pointers are only valid while cache_mutex_   // is held.-  Mutex cache_mutex_;+  CacheMutex cache_mutex_;   int64_t mem_budget_;     // Total memory budget for all States.   int64_t state_budget_;   // Amount of memory remaining for new States.   StateSet state_cache_;   // All States computed so far.@@ -1106,7 +1109,7 @@  class DFA::RWLocker {  public:-  explicit RWLocker(Mutex* mu);+  explicit RWLocker(CacheMutex* mu);   ~RWLocker();    // If the lock is only held for reading right now,@@ -1116,14 +1119,14 @@   void LockForWriting();   private:-  Mutex* mu_;+  CacheMutex* mu_;   bool writing_;    RWLocker(const RWLocker&) = delete;   RWLocker& operator=(const RWLocker&) = delete; }; -DFA::RWLocker::RWLocker(Mutex* mu) : mu_(mu), writing_(false) {+DFA::RWLocker::RWLocker(CacheMutex* mu) : mu_(mu), writing_(false) {   mu_->ReaderLock(); } 
third_party/re2/re2/nfa.cc view
@@ -600,7 +600,7 @@     // by simply not continuing the loop.     // This complements the special case in NFA::Step().     if (p == NULL) {-      (void)Step(runq, nextq, p < etext_ ? p[0] & 0xFF : -1, context, p);+      (void) Step(runq, nextq, -1, context, p);       DCHECK_EQ(runq->size(), 0);       using std::swap;       swap(nextq, runq);
third_party/re2/re2/perl_groups.cc view
@@ -20,12 +20,12 @@ 	{ 0x61, 0x7a }, }; const UGroup perl_groups[] = {-	{ "\\d", +1, code1, 1 },-	{ "\\D", -1, code1, 1 },-	{ "\\s", +1, code2, 3 },-	{ "\\S", -1, code2, 3 },-	{ "\\w", +1, code3, 4 },-	{ "\\W", -1, code3, 4 },+	{ "\\d", +1, code1, 1, 0, 0 },+	{ "\\D", -1, code1, 1, 0, 0 },+	{ "\\s", +1, code2, 3, 0, 0 },+	{ "\\S", -1, code2, 3, 0, 0 },+	{ "\\w", +1, code3, 4, 0, 0 },+	{ "\\W", -1, code3, 4, 0, 0 }, }; const int num_perl_groups = 6; static const URange16 code4[] = {  /* [:alnum:] */@@ -85,34 +85,34 @@ 	{ 0x61, 0x66 }, }; const UGroup posix_groups[] = {-	{ "[:alnum:]", +1, code4, 3 },-	{ "[:^alnum:]", -1, code4, 3 },-	{ "[:alpha:]", +1, code5, 2 },-	{ "[:^alpha:]", -1, code5, 2 },-	{ "[:ascii:]", +1, code6, 1 },-	{ "[:^ascii:]", -1, code6, 1 },-	{ "[:blank:]", +1, code7, 2 },-	{ "[:^blank:]", -1, code7, 2 },-	{ "[:cntrl:]", +1, code8, 2 },-	{ "[:^cntrl:]", -1, code8, 2 },-	{ "[:digit:]", +1, code9, 1 },-	{ "[:^digit:]", -1, code9, 1 },-	{ "[:graph:]", +1, code10, 1 },-	{ "[:^graph:]", -1, code10, 1 },-	{ "[:lower:]", +1, code11, 1 },-	{ "[:^lower:]", -1, code11, 1 },-	{ "[:print:]", +1, code12, 1 },-	{ "[:^print:]", -1, code12, 1 },-	{ "[:punct:]", +1, code13, 4 },-	{ "[:^punct:]", -1, code13, 4 },-	{ "[:space:]", +1, code14, 2 },-	{ "[:^space:]", -1, code14, 2 },-	{ "[:upper:]", +1, code15, 1 },-	{ "[:^upper:]", -1, code15, 1 },-	{ "[:word:]", +1, code16, 4 },-	{ "[:^word:]", -1, code16, 4 },-	{ "[:xdigit:]", +1, code17, 3 },-	{ "[:^xdigit:]", -1, code17, 3 },+	{ "[:alnum:]", +1, code4, 3, 0, 0 },+	{ "[:^alnum:]", -1, code4, 3, 0, 0 },+	{ "[:alpha:]", +1, code5, 2, 0, 0 },+	{ "[:^alpha:]", -1, code5, 2, 0, 0 },+	{ "[:ascii:]", +1, code6, 1, 0, 0 },+	{ "[:^ascii:]", -1, code6, 1, 0, 0 },+	{ "[:blank:]", +1, code7, 2, 0, 0 },+	{ "[:^blank:]", -1, code7, 2, 0, 0 },+	{ "[:cntrl:]", +1, code8, 2, 0, 0 },+	{ "[:^cntrl:]", -1, code8, 2, 0, 0 },+	{ "[:digit:]", +1, code9, 1, 0, 0 },+	{ "[:^digit:]", -1, code9, 1, 0, 0 },+	{ "[:graph:]", +1, code10, 1, 0, 0 },+	{ "[:^graph:]", -1, code10, 1, 0, 0 },+	{ "[:lower:]", +1, code11, 1, 0, 0 },+	{ "[:^lower:]", -1, code11, 1, 0, 0 },+	{ "[:print:]", +1, code12, 1, 0, 0 },+	{ "[:^print:]", -1, code12, 1, 0, 0 },+	{ "[:punct:]", +1, code13, 4, 0, 0 },+	{ "[:^punct:]", -1, code13, 4, 0, 0 },+	{ "[:space:]", +1, code14, 2, 0, 0 },+	{ "[:^space:]", -1, code14, 2, 0, 0 },+	{ "[:upper:]", +1, code15, 1, 0, 0 },+	{ "[:^upper:]", -1, code15, 1, 0, 0 },+	{ "[:word:]", +1, code16, 4, 0, 0 },+	{ "[:^word:]", -1, code16, 4, 0, 0 },+	{ "[:xdigit:]", +1, code17, 3, 0, 0 },+	{ "[:^xdigit:]", -1, code17, 3, 0, 0 }, }; const int num_posix_groups = 28; 
third_party/re2/re2/re2.h view
@@ -830,8 +830,9 @@ #if !defined(_MSC_VER)   template <typename T>   using CanParseFrom = typename std::enable_if<-      std::is_member_function_pointer<decltype(-          (bool (T::*)(const char*, size_t))&T::ParseFrom)>::value,+      std::is_member_function_pointer<+          decltype(static_cast<bool (T::*)(const char*, size_t)>(+              &T::ParseFrom))>::value,       int>::type; #endif 
third_party/re2/re2/regexp.cc view
@@ -722,8 +722,14 @@   *foldcase = false;    // No need for a walker: the regexp must either begin with or be-  // a literal char or string.+  // a literal char or string. We "see through" capturing groups,+  // but make no effort to glue multiple prefix fragments together.   Regexp* re = op_ == kRegexpConcat && nsub_ > 0 ? sub()[0] : this;+  while (re->op_ == kRegexpCapture) {+    re = re->sub()[0];+    if (re->op_ == kRegexpConcat && re->nsub_ > 0)+      re = re->sub()[0];+  }   if (re->op_ != kRegexpLiteral &&       re->op_ != kRegexpLiteralString)     return false;@@ -913,7 +919,7 @@ // The ranges are allocated in the same block as the header, // necessitating a special allocator and Delete method. -CharClass* CharClass::New(int maxranges) {+CharClass* CharClass::New(size_t maxranges) {   CharClass* cc;   uint8_t* data = new uint8_t[sizeof *cc + maxranges*sizeof cc->ranges_[0]];   cc = reinterpret_cast<CharClass*>(data);@@ -930,7 +936,7 @@ }  CharClass* CharClass::Negate() {-  CharClass* cc = CharClass::New(nranges_+1);+  CharClass* cc = CharClass::New(static_cast<size_t>(nranges_+1));   cc->folds_ascii_ = folds_ascii_;   cc->nrunes_ = Runemax + 1 - nrunes_;   int n = 0;@@ -967,7 +973,7 @@ }  CharClass* CharClassBuilder::GetCharClass() {-  CharClass* cc = CharClass::New(static_cast<int>(ranges_.size()));+  CharClass* cc = CharClass::New(ranges_.size());   int n = 0;   for (iterator it = begin(); it != end(); ++it)     cc->ranges_[n++] = *it;
third_party/re2/re2/regexp.h view
@@ -86,6 +86,7 @@ // form accessible to clients, so that client code can analyze the // parsed regular expressions. +#include <stddef.h> #include <stdint.h> #include <map> #include <set>@@ -259,7 +260,7 @@  private:   CharClass();  // not implemented   ~CharClass();  // not implemented-  static CharClass* New(int maxranges);+  static CharClass* New(size_t maxranges);    friend class CharClassBuilder; 
third_party/re2/re2/set.cc view
@@ -133,6 +133,9 @@       error_info->kind = kNotCompiled;     return false;   }+#ifdef RE2_HAVE_THREAD_LOCAL+  hooks::context = NULL;+#endif   bool dfa_failed = false;   std::unique_ptr<SparseSet> matches;   if (v != NULL) {
third_party/re2/re2/tostring.cc view
@@ -291,7 +291,7 @@       // There's no syntax accepted by the parser to generate       // this node (it is generated by RE2::Set) so make something       // up that is readable but won't compile.-      t_->append("(?HaveMatch:%d)", re->match_id());+      t_->append(StringPrintf("(?HaveMatch:%d)", re->match_id()));       break;   } 
third_party/re2/util/mutex.h view
@@ -12,6 +12,7 @@  #ifdef _WIN32 // Requires Windows Vista or Windows Server 2008 at minimum.+#include <windows.h> #if defined(WINVER) && WINVER >= 0x0600 #define MUTEX_IS_WIN32_SRWLOCK #endif@@ -26,7 +27,6 @@ #endif  #if defined(MUTEX_IS_WIN32_SRWLOCK)-#include <windows.h> typedef SRWLOCK MutexType; #elif defined(MUTEX_IS_PTHREAD_RWLOCK) #include <pthread.h>
third_party/utf8rewind/include/utf8rewind/utf8rewind.h view
@@ -62,6 +62,7 @@ 	Custom type definitions used throughout the library.
 */
 
+#include <ctype.h>
 #include <locale.h>
 #include <stddef.h>
 #include <stdio.h>
third_party/utf8rewind/source/utf8rewind.c view
@@ -549,6 +549,22 @@ 	}
 }
 
+// internal helper to avoid the use of non-standard strncasecmp
+int __strncasecmp(const char* s1, const char* s2, size_t n) {
+  if (n == 0)
+    return 0;
+
+  do {
+    if (tolower((unsigned char) *s1) != tolower((unsigned char) *s2++))
+      return (int)tolower((unsigned char)*s1) -
+	(int) tolower((unsigned char) *--s2);
+    if (*s1++ == 0)
+      break;
+  } while (--n != 0);
+
+  return 0;
+}
+
 UTF8_API size_t utf8envlocale()
 {
 	/*
@@ -562,7 +578,7 @@ 	*/
 
 #define UTF8_LOCALE_CHECK(_name) \
-	!strncasecmp(locale, _name, 5)
+	!__strncasecmp(locale, _name, 5)
 
 #if WIN32 || _WINDOWS
     WCHAR localeW[LOCALE_NAME_MAX_LENGTH];
@@ -1376,4 +1392,4 @@ 	}
 
 	return src - input;
-}+}