44 #ifndef included_clib_string_h 45 #define included_clib_string_h 51 #ifdef CLIB_LINUX_KERNEL 52 #include <linux/string.h> 59 #ifdef CLIB_STANDALONE 60 #include <vppinfra/standalone_string.h> 64 #include <x86intrin.h> 77 #define clib_memcpy_fast_arch(a, b, c) clib_memcpy_fast_avx512 (a, b, c) 80 #define clib_memcpy_fast_arch(a, b, c) clib_memcpy_fast_avx2 (a, b, c) 83 #define clib_memcpy_fast_arch(a, b, c) clib_memcpy_fast_sse3 (a, b, c) 87 #ifndef clib_memcpy_fast_arch 88 #define clib_memcpy_fast_arch(a, b, c) memcpy (a, b, c) 95 "memcpy(src, dst, n) with src == NULL or dst == NULL is undefined " 100 #undef clib_memcpy_fast_arch 128 #define CLIB_STRING_MACRO_MAX 4096 160 bad = (dest == 0) + (src == 0) + (n > dmax) + (dest == src) + (n == 0);
178 low = (
uword) (src < dest ? src : dest);
179 hi = (
uword) (src < dest ? dest : src);
197 #define clib_memcpy(d,s,n) memcpy_s_inline(d,n,s,n) 206 bad = (s == 0) + (n > smax);
231 #define clib_memset(s,c,n) memset_s_inline(s,n,c,n) 236 #if defined (CLIB_HAVE_VEC256) 237 u8x32 s0, s1, d0, d1;
238 u8x32 mask = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
239 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
241 u8x32 lv = u8x32_splat (len);
242 u8x32 add = u8x32_splat (32);
244 s0 = u8x32_load_unaligned (src);
245 s1 = u8x32_load_unaligned (src + 32);
246 d0 = u8x32_load_unaligned (dst);
247 d1 = u8x32_load_unaligned (dst + 32);
250 u8x32_store_unaligned (d0, dst);
257 u8x32_store_unaligned (d1, dst + 32);
259 #elif defined (CLIB_HAVE_VEC128) 260 u8x16 s0, s1, s2, s3, d0, d1, d2, d3;
261 u8x16 mask = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
262 u8x16 lv = u8x16_splat (len);
263 u8x16 add = u8x16_splat (16);
265 s0 = u8x16_load_unaligned (src);
266 s1 = u8x16_load_unaligned (src + 16);
267 s2 = u8x16_load_unaligned (src + 32);
268 s3 = u8x16_load_unaligned (src + 48);
269 d0 = u8x16_load_unaligned (dst);
270 d1 = u8x16_load_unaligned (dst + 16);
271 d2 = u8x16_load_unaligned (dst + 32);
272 d3 = u8x16_load_unaligned (dst + 48);
275 u8x16_store_unaligned (d0, dst);
282 u8x16_store_unaligned (d1, dst + 16);
289 u8x16_store_unaligned (d2, dst + 32);
293 u8x16_store_unaligned (d3, dst + 48);
295 memmove (dst, src, len);
315 #if defined(CLIB_HAVE_VEC512) 316 u64x8 v512 = u64x8_splat (val);
319 u64x8_store_unaligned (v512, ptr);
326 #if defined(CLIB_HAVE_VEC256) 327 u64x4 v256 = u64x4_splat (val);
330 u64x4_store_unaligned (v256, ptr);
339 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
352 #if defined(CLIB_HAVE_VEC512) 353 u32x16 v512 = u32x16_splat (val);
356 u32x16_store_unaligned (v512, ptr);
363 #if defined(CLIB_HAVE_VEC256) 364 u32x8 v256 = u32x8_splat (val);
367 u32x8_store_unaligned (v256, ptr);
374 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) 375 u32x4 v128 = u32x4_splat (val);
378 u32x4_store_unaligned (v128, ptr);
385 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
398 #if defined(CLIB_HAVE_VEC512) 399 u16x32 v512 = u16x32_splat (val);
402 u16x32_store_unaligned (v512, ptr);
409 #if defined(CLIB_HAVE_VEC256) 410 u16x16 v256 = u16x16_splat (val);
413 u16x16_store_unaligned (v256, ptr);
420 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) 421 u16x8 v128 = u16x8_splat (val);
424 u16x8_store_unaligned (v128, ptr);
431 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
444 #if defined(CLIB_HAVE_VEC512) 445 u8x64 v512 = u8x64_splat (val);
448 u8x64_store_unaligned (v512, ptr);
455 #if defined(CLIB_HAVE_VEC256) 456 u8x32 v256 = u8x32_splat (val);
459 u8x32_store_unaligned (v256, ptr);
466 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) 467 u8x16 v128 = u8x16_splat (val);
470 u8x16_store_unaligned (v128, ptr);
477 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
494 if (data[0] != data[1])
500 #if defined(CLIB_HAVE_VEC256) 501 u64x4 splat = u64x4_splat (first);
502 while (count + 3 < max_count)
506 if (bmp != 0xffffffff)
518 while (count + 3 < max_count &&
519 ((data[0] ^ first) | (data[1] ^ first) |
520 (data[2] ^ first) | (data[3] ^ first)) == 0)
526 while (count < max_count && (data[0] == first))
542 if (data[0] != data[1])
548 #if defined(CLIB_HAVE_VEC256) 549 u32x8 splat = u32x8_splat (first);
550 while (count + 7 < max_count)
554 if (bmp != 0xffffffff)
563 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 564 u32x4 splat = u32x4_splat (first);
565 while (count + 3 < max_count)
581 while (count + 3 < max_count &&
582 ((data[0] ^ first) | (data[1] ^ first) |
583 (data[2] ^ first) | (data[3] ^ first)) == 0)
589 while (count < max_count && (data[0] == first))
605 if (data[0] != data[1])
611 #if defined(CLIB_HAVE_VEC256) 612 u16x16 splat = u16x16_splat (first);
613 while (count + 15 < max_count)
617 if (bmp != 0xffffffff)
626 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 627 u16x8 splat = u16x8_splat (first);
628 while (count + 7 < max_count)
644 while (count + 3 < max_count &&
645 ((data[0] ^ first) | (data[1] ^ first) |
646 (data[2] ^ first) | (data[3] ^ first)) == 0)
652 while (count < max_count && (data[0] == first))
668 if (data[0] != data[1])
674 #if defined(CLIB_HAVE_VEC256) 675 u8x32 splat = u8x32_splat (first);
676 while (count + 31 < max_count)
680 if (bmp != 0xffffffff)
686 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 687 u8x16 splat = u8x16_splat (first);
688 while (count + 15 < max_count)
704 while (count + 3 < max_count &&
705 ((data[0] ^ first) | (data[1] ^ first) |
706 (data[2] ^ first) | (data[3] ^ first)) == 0)
712 while (count < max_count && (data[0] == first))
734 #define clib_memcmp(s1,s2,m1) \ 736 memcmp_s_inline (s1, m1, s2, m1, &__diff); \ 749 bad = (s1 == 0) + (s2 == 0) + (diff == 0) + (s2max > s1max) + (s2max == 0) +
775 *diff = memcmp (s1, s2, s2max);
782 #define clib_strnlen(s,m) strnlen_s_inline(s,m) 784 size_t strnlen_s (
const char *s,
size_t maxsize);
791 bad = (s == 0) + (maxsize == 0);
800 return strnlen (s, maxsize);
823 #define clib_strcmp(s1,s2) \ 824 ({ int __indicator = 0; \ 825 strcmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, &__indicator); \ 838 bad = (indicator == 0) + (s1 == 0) + (s2 == 0) + (s1max == 0) +
843 if (indicator == NULL)
851 if (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0')
856 *indicator = strcmp (s1, s2);
877 #define clib_strncmp(s1,s2,n) \ 878 ({ int __indicator = 0; \ 879 strncmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, n, &__indicator); \ 891 u8 s1_greater_s1max = (s1 && s1max && n >
clib_strnlen (s1, s1max));
901 *indicator = strncmp (s1, s2, n);
905 bad = (s1 == 0) + (s2 == 0) + (indicator == 0) + (s1max == 0) +
906 (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0') + s1_greater_s1max;
910 if (indicator == NULL)
918 if (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0')
920 if (s1_greater_s1max)
925 *indicator = strncmp (s1, s2, n);
935 #define clib_strcpy(d,s) strcpy_s_inline(d,CLIB_STRING_MACRO_MAX,s) 938 const char *__restrict__
src);
942 const char *__restrict__
src)
948 bad = (dest == 0) + (dmax == 0) + (src == 0);
971 low = (
uword) (src < dest ? src : dest);
972 hi = (
uword) (src < dest ? dest : src);
992 #define clib_strncpy(d,s,n) strncpy_s_inline(d,CLIB_STRING_MACRO_MAX,s,n) 1007 bad = (dest == 0) + (dmax == 0) + (src == 0) + (n == 0);
1039 low = (
uword) (src < dest ? src : dest);
1040 hi = (
uword) (src < dest ? dest : src);
1051 if (low + (m - 1) >= hi)
1071 #define clib_strcat(d,s) strcat_s_inline(d,CLIB_STRING_MACRO_MAX,s) 1074 const char *__restrict__
src);
1078 const char *__restrict__
src)
1082 size_t m, n, dest_size;
1084 bad = (dest == 0) + (dmax == 0) + (src == 0);
1097 m = dmax - dest_size;
1110 low = (
uword) (src < dest ? src : dest);
1111 hi = (
uword) (src < dest ? dest : src);
1120 dest[dest_size + n] =
'\0';
1132 #define clib_strncat(d,s,n) strncat_s_inline(d,CLIB_STRING_MACRO_MAX,s,n) 1143 size_t m, dest_size, allowed_size;
1146 bad = (dest == 0) + (src == 0) + (dmax == 0) + (n == 0);
1162 low = (
uword) (src < dest ? src : dest);
1163 hi = (
uword) (src < dest ? dest : src);
1172 allowed_size = dmax - dest_size;
1188 if (m >= allowed_size)
1190 m = allowed_size - 1;
1198 dest[dest_size + m] =
'\0';
1211 #define clib_strtok(s1,s2,p) \ 1212 ({ rsize_t __s1max = CLIB_STRING_MACRO_MAX; \ 1213 strtok_s_inline (s1, &__s1max, s2, p); \ 1217 const char *__restrict__ s2,
char **__restrict__ ptr);
1221 const char *__restrict__ s2,
char **__restrict__ ptr)
1223 #define STRTOK_DELIM_MAX_LEN 16 1229 bad = (s1max == 0) + (s2 == 0) + (ptr == 0) +
1230 ((s1 == 0) && ptr && (*ptr == 0));
1240 if ((s1 == 0) && ptr && (*ptr == 0))
1253 while (*s1 !=
'\0' && !ptoken)
1363 #define clib_strstr(s1,s2) \ 1364 ({ char * __substring = 0; \ 1365 strstr_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, CLIB_STRING_MACRO_MAX, \ 1378 size_t s1_size, s2_size;
1381 (s1 == 0) + (s2 == 0) + (substring == 0) + (s1max == 0) + (s2max == 0) +
1382 (s1 && s1max && (s1[
clib_strnlen (s1, s1max)] !=
'\0')) +
1383 (s2 && s2max && (s2[
clib_strnlen (s2, s2max)] !=
'\0'));
1396 if (s1 && s1max && (s1[
clib_strnlen (s1, s1max)] !=
'\0'))
1398 if (s2 && s2max && (s2[
clib_strnlen (s2, s1max)] !=
'\0'))
1420 *substring = strstr (s1, s2);
1421 if (*substring == 0)
errno_t strcat_s(char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src)
append src string to dest string, including null
errno_t strcmp_s(const char *s1, rsize_t s1max, const char *s2, int *indicator)
compare string s2 to string s1, and their difference is returned in indicator
char * strtok_s(char *__restrict__ s1, rsize_t *__restrict__ s1max, const char *__restrict__ s2, char **__restrict__ ptr)
tokenize string s1 with delimiter specified in s2.
#define COMPILE_TIME_CONST(x)
static errno_t memcmp_s_inline(const void *s1, rsize_t s1max, const void *s2, rsize_t s2max, int *diff)
static errno_t strcmp_s_inline(const char *s1, rsize_t s1max, const char *s2, int *indicator)
Optimized string handling code, including c11-compliant "safe C library" variants.
#define clib_memcpy_fast_arch(a, b, c)
size_t strnlen_s(const char *s, size_t maxsize)
compute the length in s, no more than maxsize
static errno_t strcat_s_inline(char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src)
static errno_t strncpy_s_inline(char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src, rsize_t n)
static_always_inline u8x16 u8x16_blend(u8x16 v1, u8x16 v2, u8x16 mask)
static errno_t strstr_s_inline(char *s1, rsize_t s1max, const char *s2, rsize_t s2max, char **substring)
void clib_memswap(void *_a, void *_b, uword bytes)
#define count_trailing_zeros(x)
errno_t memcmp_s(const void *s1, rsize_t s1max, const void *s2, rsize_t s2max, int *diff)
compare memory until they differ, and their difference is returned in diff
void clib_c11_violation(const char *s)
#define static_always_inline
errno_t strcpy_s(char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src)
copy src string to dest string
static errno_t memcpy_s_inline(void *__restrict__ dest, rsize_t dmax, const void *__restrict__ src, rsize_t n)
static errno_t memset_s_inline(void *s, rsize_t smax, int c, rsize_t n)
errno_t strstr_s(char *s1, rsize_t s1max, const char *s2, rsize_t s2max, char **substring)
locate the first occurrence of the substring s2 in s1
static heap_elt_t * first(heap_header_t *h)
static errno_t strncat_s_inline(char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src, rsize_t n)
static_always_inline u16 u8x16_msb_mask(u8x16 v)
static_always_inline uword clib_count_equal_u64(u64 *data, uword max_count)
#define STRTOK_DELIM_MAX_LEN
static_always_inline uword clib_count_equal_u16(u16 *data, uword max_count)
errno_t strncpy_s(char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src, rsize_t n)
copy src string to dest string, no more than n characters
static_always_inline void clib_memcpy_le(u8 *dst, u8 *src, u8 len, u8 max_len)
errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n)
set n bytes starting at s to the specified c value
errno_t strncat_s(char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src, rsize_t n)
append src string to dest string, including null, no more than n characters
static_always_inline u8x32 u8x32_is_greater(u8x32 v1, u8x32 v2)
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
static errno_t strcpy_s_inline(char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src)
static_always_inline u8x16 u8x16_is_greater(u8x16 v1, u8x16 v2)
static_always_inline void clib_memset_u8(void *p, u8 val, uword count)
static char * strtok_s_inline(char *__restrict__ s1, rsize_t *__restrict__ s1max, const char *__restrict__ s2, char **__restrict__ ptr)
_mm256_packus_epi16 _mm256_packus_epi32 static_always_inline u32 u8x32_msb_mask(u8x32 v)
static_always_inline void clib_memset_u16(void *p, u16 val, uword count)
static_always_inline void clib_memcpy_le64(u8 *dst, u8 *src, u8 len)
static_always_inline uword clib_count_equal_u8(u8 *data, uword max_count)
static errno_t strncmp_s_inline(const char *s1, rsize_t s1max, const char *s2, rsize_t n, int *indicator)
static_always_inline void clib_memset_u64(void *p, u64 val, uword count)
errno_t memcpy_s(void *__restrict__ dest, rsize_t dmax, const void *__restrict__ src, rsize_t n)
copy src to dest, at most n bytes, up to dmax
#define clib_strnlen(s, m)
static_always_inline uword clib_count_equal_u32(u32 *data, uword max_count)
static size_t strnlen_s_inline(const char *s, size_t maxsize)
_mm256_packus_epi16 u16x16
errno_t strncmp_s(const char *s1, rsize_t s1max, const char *s2, rsize_t n, int *indicator)
compare string s2 to string s1, no more than n characters, and their difference is returned in indica...
static_always_inline u8x32 u8x32_blend(u8x32 v1, u8x32 v2, u8x32 mask)
_mm512_packus_epi16 u16x32
static_always_inline void clib_memcpy_le32(u8 *dst, u8 *src, u8 len)
static_always_inline void clib_memset_u32(void *p, u32 val, uword count)