]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Use size_t instead of uint64_t for len in all adler32 functions
authorCameron Cawley <ccawley2011@gmail.com>
Fri, 30 Sep 2022 15:54:16 +0000 (16:54 +0100)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Sat, 21 Jan 2023 23:58:12 +0000 (00:58 +0100)
16 files changed:
adler32.c
adler32_fold.c
adler32_fold.h
adler32_p.h
arch/arm/adler32_neon.c
arch/power/adler32_power8.c
arch/power/adler32_vmx.c
arch/x86/adler32_avx2_tpl.h
arch/x86/adler32_avx512_tpl.h
arch/x86/adler32_avx512_vnni.c
arch/x86/adler32_sse42.c
arch/x86/adler32_ssse3.c
cpu_features.h
functable.c
functable.h
test/benchmarks/benchmark_adler32_copy.cc

index c47f7645866f92465bd61056b4c052d2dde299e0..95ac13c3046b34b9f746a04364e01a03fa4cd04f 100644 (file)
--- a/adler32.c
+++ b/adler32.c
@@ -8,7 +8,7 @@
 #include "adler32_p.h"
 
 /* ========================================================================= */
-Z_INTERNAL uint32_t adler32_c(uint32_t adler, const uint8_t *buf, uint64_t len) {
+Z_INTERNAL uint32_t adler32_c(uint32_t adler, const uint8_t *buf, size_t len) {
     uint32_t sum2;
     unsigned n;
 
index adaabe021052b4b52ae9514ef92ec7fd6e7f59f1..e2f6f9ac7dd27b514ad1b4c82f3fd3cdbc1945df 100644 (file)
@@ -9,19 +9,8 @@
 
 #include <limits.h>
 
-Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) {
+Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) {
     adler = functable.adler32(adler, src, len);
-/* Test that we don't try to copy more than actually fits in available address space */
-#if INTPTR_MAX > SSIZE_MAX
-    while (len > SSIZE_MAX) {
-        memcpy(dst, src, SSIZE_MAX);
-        dst += SSIZE_MAX;
-        src += SSIZE_MAX;
-        len -= SSIZE_MAX;
-    }
-#endif
-    if (len) {
-        memcpy(dst, src, (size_t)len);
-    }
+    memcpy(dst, src, len);
     return adler;
 }
index bdaf2130fe4b346aa90bb1a71bb5778c64808417..20aa1c7400b76a5dd7b48f1a736cd0cceef9d3f1 100644 (file)
@@ -6,6 +6,6 @@
 #ifndef ADLER32_FOLD_H_
 #define ADLER32_FOLD_H_
 
-Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len);
+Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len);
 
 #endif
index 8fe41b1422c323d567bfc6cb0b1439930adc013a..38ba2ad721491a67c0bc7887beba429f30957010 100644 (file)
@@ -26,7 +26,7 @@ static inline uint32_t adler32_len_1(uint32_t adler, const uint8_t *buf, uint32_
     return adler | (sum2 << 16);
 }
 
-static inline uint32_t adler32_len_16(uint32_t adler, const uint8_t *buf, uint64_t len, uint32_t sum2) {
+static inline uint32_t adler32_len_16(uint32_t adler, const uint8_t *buf, size_t len, uint32_t sum2) {
     while (len) {
         --len;
         adler += *buf++;
@@ -38,7 +38,7 @@ static inline uint32_t adler32_len_16(uint32_t adler, const uint8_t *buf, uint64
     return adler | (sum2 << 16);
 }
 
-static inline uint32_t adler32_copy_len_16(uint32_t adler, const uint8_t *buf, uint8_t *dst, uint64_t len, uint32_t sum2) {
+static inline uint32_t adler32_copy_len_16(uint32_t adler, const uint8_t *buf, uint8_t *dst, size_t len, uint32_t sum2) {
     while (len--) {
         *dst = *buf++;
         adler += *dst++;
@@ -50,7 +50,7 @@ static inline uint32_t adler32_copy_len_16(uint32_t adler, const uint8_t *buf, u
     return adler | (sum2 << 16);
 }
 
-static inline uint32_t adler32_len_64(uint32_t adler, const uint8_t *buf, uint64_t len, uint32_t sum2) {
+static inline uint32_t adler32_len_64(uint32_t adler, const uint8_t *buf, size_t len, uint32_t sum2) {
 #ifdef UNROLL_MORE
     while (len >= 16) {
         len -= 16;
index 9b9d65ddd47d4dd7632fff0b2ecde59a755926eb..c8871cc0cd1bf11a76803ce59e1f291c9088f942 100644 (file)
@@ -10,7 +10,7 @@
 #include "../../zbuild.h"
 #include "../../adler32_p.h"
 
-static void NEON_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) {
+static void NEON_accum32(uint32_t *s, const uint8_t *buf, size_t len) {
     static const uint16_t ALIGNED_(16) taps[64] = {
         64, 63, 62, 61, 60, 59, 58, 57,
         56, 55, 54, 53, 52, 51, 50, 49,
@@ -39,10 +39,10 @@ static void NEON_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) {
     uint16x8_t s2_4, s2_5, s2_6, s2_7;
     s2_4 = s2_5 = s2_6 = s2_7 = vdupq_n_u16(0);
 
-    uint64_t num_iter = len >> 2;
+    size_t num_iter = len >> 2;
     int rem = len & 3;
 
-    for (uint64_t i = 0; i < num_iter; ++i) {
+    for (size_t i = 0; i < num_iter; ++i) {
         uint8x16x4_t d0_d3 = vld1q_u8_x4(buf);
 
         /* Unfortunately it doesn't look like there's a direct sum 8 bit to 32
@@ -133,7 +133,7 @@ static void NEON_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) {
     s[1] = vget_lane_u32(as, 1);
 }
 
-static void NEON_handle_tail(uint32_t *pair, const uint8_t *buf, uint64_t len) {
+static void NEON_handle_tail(uint32_t *pair, const uint8_t *buf, size_t len) {
     unsigned int i;
     for (i = 0; i < len; ++i) {
         pair[0] += buf[i];
@@ -141,7 +141,7 @@ static void NEON_handle_tail(uint32_t *pair, const uint8_t *buf, uint64_t len) {
     }
 }
 
-uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, uint64_t len) {
+uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, size_t len) {
     /* split Adler-32 into component sums */
     uint32_t sum2 = (adler >> 16) & 0xffff;
     adler &= 0xffff;
index 0e8e0d162ccc72b78e49900c49e4ac4169b77919..497e2f92c8632914177b5474e19e109c3ff231ee 100644 (file)
@@ -52,7 +52,7 @@ static inline vector unsigned int vec_sumsu(vector unsigned int __a, vector unsi
     return __a;
 }
 
-uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, uint64_t len) {
+uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t len) {
     uint32_t s1 = adler & 0xffff;
     uint32_t s2 = (adler >> 16) & 0xffff;
 
index 2c8eb68270221aeaa82cf63fa1ad443125a428d6..1b648820d02e86f3486569901aaf749f7ef97cab 100644 (file)
@@ -12,7 +12,7 @@
 
 #define vmx_zero()  (vec_splat_u32(0))
 
-static inline void vmx_handle_head_or_tail(uint32_t *pair, const uint8_t *buf, uint64_t len) {
+static inline void vmx_handle_head_or_tail(uint32_t *pair, const uint8_t *buf, size_t len) {
     unsigned int i;
     for (i = 0; i < len; ++i) {
         pair[0] += buf[i];
@@ -20,7 +20,7 @@ static inline void vmx_handle_head_or_tail(uint32_t *pair, const uint8_t *buf, u
     }
 }
 
-static void vmx_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) {
+static void vmx_accum32(uint32_t *s, const uint8_t *buf, size_t len) {
     /* Different taps for the separable components of sums */
     const vector unsigned char t0 = {64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49};
     const vector unsigned char t1 = {48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33};
@@ -113,7 +113,7 @@ static void vmx_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) {
     vec_ste(s2acc, 0, s+1);
 }
 
-uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, uint64_t len) {
+uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, size_t len) {
     uint32_t sum2;
     uint32_t pair[16] ALIGNED_(16);
     memset(&pair[2], 0, 14);
index 4ff1838de02202ae5718795aa8bdda5e71a4cb8c..0b2e89be43a813a0abb6dd6875726bee6bed0a53 100644 (file)
@@ -11,8 +11,8 @@
 #include "adler32_avx2_p.h"
 
 #ifdef X86_SSE42_ADLER32
-extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len);
-extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, uint64_t len);
+extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len);
+extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, size_t len);
 
 #define copy_sub32(a, b, c, d) adler32_fold_copy_sse42(a, b, c, d)
 #define sub32(a, b, c) adler32_ssse3(a, b, c)
@@ -22,9 +22,9 @@ extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, uint64_t len);
 #endif
 
 #ifdef COPY
-Z_INTERNAL uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) {
+Z_INTERNAL uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) {
 #else
-Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, uint64_t len) {
+Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) {
 #endif
     if (src == NULL) return 1L;
     if (len == 0) return adler;
@@ -61,7 +61,7 @@ rem_peel:
        __m256i vs1_0 = vs1;
        __m256i vs3 = _mm256_setzero_si256();
 
-       uint64_t k = MIN(len, NMAX);
+       size_t k = MIN(len, NMAX);
        k -= k % 32;
        len -= k;
 
index 24198659883a47861b5be461ea562e28c6ec65a7..6ed39b45dfa5c4b5e7358a9ca2d1f172a344a401 100644 (file)
@@ -14,9 +14,9 @@
 #ifdef X86_AVX512_ADLER32
 
 #ifdef COPY
-Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) {
+Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) {
 #else
-Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, uint64_t len) {
+Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t len) {
 #endif
 
     if (src == NULL) return 1L;
@@ -52,7 +52,7 @@ rem_peel:
                                           56, 57, 58, 59, 60, 61, 62, 63, 64);
     const __m512i dot3v = _mm512_set1_epi16(1);
     const __m512i zero = _mm512_setzero_si512();
-    uint64_t k;
+    size_t k;
 
     while (len >= 64) {
         __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0));
index ecebdec733637aa43c77bb4f1e077d45fa4c96a2..42a166062fb4cbcd5aa64d68881e6b3e5aed39d6 100644 (file)
@@ -18,7 +18,7 @@
 #include "adler32_avx512_p.h"
 #include "adler32_avx2_p.h"
 
-Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, uint64_t len) {
+Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, size_t len) {
     if (src == NULL) return 1L;
     if (len == 0) return adler;
 
@@ -54,7 +54,7 @@ rem_peel:
     while (len >= 64) {
         vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0));
         vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler1));
-        uint64_t k = MIN(len, NMAX);
+        size_t k = MIN(len, NMAX);
         k -= k % 64;
         len -= k;
         __m512i vs1_0 = vs1;
@@ -120,7 +120,7 @@ rem_peel:
     return adler;
 }
 
-Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) {
+Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) {
     if (src == NULL) return 1L;
     if (len == 0) return adler;
 
@@ -151,7 +151,7 @@ rem_peel_copy:
     while (len >= 32) {
         vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler0));
         vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler1));
-        uint64_t k = MIN(len, NMAX);
+        size_t k = MIN(len, NMAX);
         k -= k % 32;
         len -= k;
         __m256i vs1_0 = vs1;
index 5e68e4c41e0c71ec74bf67121d47bf50d4aba610..ec0513409bb044b57e1f57b21f4361f404741b9d 100644 (file)
@@ -14,7 +14,7 @@
 
 #ifdef X86_SSE42_ADLER32
 
-Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) {
+Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) {
     uint32_t adler0, adler1;
     adler1 = (adler >> 16) & 0xffff;
     adler0 = adler & 0xffff;
@@ -31,7 +31,7 @@ rem_peel:
     const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17);
     const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
     const __m128i dot3v = _mm_set1_epi16(1);
-    uint64_t k;
+    size_t k;
 
     while (len >= 16) {
 
index 45fddd42afefb59c1b19993f129d5d0ad89290b2..1f4abba507807133637fc4b97e7b9f57c167bc04 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <immintrin.h>
 
-Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, uint64_t len) {
+Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, size_t len) {
     uint32_t sum2;
 
      /* split Adler-32 into component sums */
@@ -46,10 +46,10 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, uint64_t l
      * additions worthwhile or if it's worth it to just eat the cost of an unaligned
      * load. This is a pretty simple test, just test if 16 - the remainder + len is
      * < 16 */
-    uint64_t max_iters = NMAX;
-    uint64_t rem = (uintptr_t)buf & 15;
-    uint64_t align_offset = 16 - rem;
-    uint64_t k = 0;
+    size_t max_iters = NMAX;
+    size_t rem = (uintptr_t)buf & 15;
+    size_t align_offset = 16 - rem;
+    size_t k = 0;
     if (rem) {
         if (len < 16 + align_offset) {
             /* Let's eat the cost of this one unaligned load so that
index 9d10ce7df00d966f67f68f1e30c971892b15e56d..72e40a16523671200143625c00a3a484a9dbb542 100644 (file)
 extern void cpu_check_features(void);
 
 /* adler32 */
-typedef uint32_t (*adler32_func)(uint32_t adler, const uint8_t *buf, uint64_t len);
+typedef uint32_t (*adler32_func)(uint32_t adler, const uint8_t *buf, size_t len);
 
-extern uint32_t adler32_c(uint32_t adler, const uint8_t *buf, uint64_t len);
+extern uint32_t adler32_c(uint32_t adler, const uint8_t *buf, size_t len);
 #ifdef ARM_NEON_ADLER32
-extern uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, uint64_t len);
+extern uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, size_t len);
 #endif
 #ifdef PPC_VMX_ADLER32
-extern uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, uint64_t len);
+extern uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, size_t len);
 #endif
 #ifdef X86_SSSE3_ADLER32
-extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, uint64_t len);
+extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, size_t len);
 #endif
 #ifdef X86_AVX2_ADLER32
-extern uint32_t adler32_avx2(uint32_t adler, const uint8_t *buf, uint64_t len);
+extern uint32_t adler32_avx2(uint32_t adler, const uint8_t *buf, size_t len);
 #endif
 #ifdef X86_AVX512_ADLER32
-extern uint32_t adler32_avx512(uint32_t adler, const uint8_t *buf, uint64_t len);
+extern uint32_t adler32_avx512(uint32_t adler, const uint8_t *buf, size_t len);
 #endif
 #ifdef X86_AVX512VNNI_ADLER32
-extern uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *buf, uint64_t len);
+extern uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *buf, size_t len);
 #endif
 #ifdef POWER8_VSX_ADLER32
-extern uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, uint64_t len);
+extern uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t len);
 #endif
 
 /* adler32 folding */
 #ifdef X86_SSE42_ADLER32
-extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len);
+extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len);
 #endif
 #ifdef X86_AVX2_ADLER32
-extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len);
+extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len);
 #endif
 #ifdef X86_AVX512_ADLER32
-extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len);
+extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len);
 #endif
 #ifdef X86_AVX512VNNI_ADLER32
-extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len);
+extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len);
 #endif
 
 /* CRC32 folding */
index 5dd5e54d4ce07684135f6c77418dbba271475829..260d52f2f358ec122976548297e896b392b48e41 100644 (file)
@@ -162,7 +162,7 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc
     return functable.longest_match_slow(s, cur_match);
 }
 
-Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const uint8_t *buf, uint64_t len) {
+Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const uint8_t *buf, size_t len) {
     // Initialize default
     functable.adler32 = &adler32_c;
     cpu_check_features();
@@ -202,7 +202,7 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const uint8_t *buf, uint64_t le
     return functable.adler32(adler, buf, len);
 }
 
-Z_INTERNAL uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) {
+Z_INTERNAL uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) {
     functable.adler32_fold_copy = &adler32_fold_copy_c;
 #if (defined X86_SSE42_ADLER32)
     if (x86_cpu_has_sse42)
index 9b6ec3b542436d26f5a534a9f07580b9e5b1220d..531f3a1cef86b5059142619b84d6030e3ccd99a4 100644 (file)
@@ -11,8 +11,8 @@
 #include "adler32_fold.h"
 
 struct functable_s {
-    uint32_t (* adler32)            (uint32_t adler, const uint8_t *buf, uint64_t len);
-    uint32_t (* adler32_fold_copy)  (uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len);
+    uint32_t (* adler32)            (uint32_t adler, const uint8_t *buf, size_t len);
+    uint32_t (* adler32_fold_copy)  (uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len);
     uint32_t (* crc32)              (uint32_t crc, const uint8_t *buf, size_t len);
     uint32_t (* crc32_fold_reset)   (struct crc32_fold_s *crc);
     void     (* crc32_fold_copy)    (struct crc32_fold_s *crc, uint8_t *dst, const uint8_t *src, size_t len);
index 71ac72f295107d5e99f3049785334b8b4edea4c4..f89659a7f12530f0c05f082466dcfbb4c8bf2013 100644 (file)
@@ -18,7 +18,7 @@ extern "C" {
 #define MAX_RANDOM_INTS (1024 * 1024)
 #define MAX_RANDOM_INTS_SIZE (MAX_RANDOM_INTS * sizeof(uint32_t))
 
-typedef uint32_t (*adler32_cpy_func)(uint32_t adler, unsigned char *dst, const uint8_t *buf, uint64_t len);
+typedef uint32_t (*adler32_cpy_func)(uint32_t adler, unsigned char *dst, const uint8_t *buf, size_t len);
 
 class adler32_copy: public benchmark::Fixture {
 private:
@@ -76,7 +76,7 @@ public:
             state.SkipWithError("CPU does not support " #name); \
         } \
         Bench(state, [](uint32_t init_sum, unsigned char *dst, \
-                        const uint8_t *buf, uint64_t len) -> uint32_t { \
+                        const uint8_t *buf, size_t len) -> uint32_t { \
             memcpy(dst, buf, (size_t)len); \
             return fptr(init_sum, buf, len); \
         }); \