44 #ifndef included_clib_string_h 45 #define included_clib_string_h 50 #ifdef CLIB_LINUX_KERNEL 51 #include <linux/string.h> 58 #ifdef CLIB_STANDALONE 59 #include <vppinfra/standalone_string.h> 63 #include <x86intrin.h> 81 #define clib_memcpy_fast(a,b,c) memcpy(a,b,c) 84 #define clib_memcpy_fast(a,b,c) memcpy(a,b,c) 111 #define CLIB_STRING_MACRO_MAX 4096 131 if (__builtin_constant_p (n))
143 bad = (dest == 0) + (src == 0) + (n > dmax) + (dest == src) + (n == 0);
161 low = (
uword) (src < dest ? src : dest);
162 hi = (
uword) (src < dest ? dest : src);
180 #define clib_memcpy(d,s,n) memcpy_s_inline(d,n,s,n) 189 bad = (s == 0) + (n > smax);
214 #define clib_memset(s,c,n) memset_s_inline(s,n,c,n) 226 #if defined (__AVX512F__) 227 __m512i r0 = _mm512_loadu_si512 (s);
229 _mm512_storeu_si512 (d0, r0);
230 _mm512_storeu_si512 (d1, r0);
231 _mm512_storeu_si512 (d2, r0);
232 _mm512_storeu_si512 (d3, r0);
234 #elif defined (__AVX2__) 235 __m256i r0 = _mm256_loadu_si256 ((__m256i *) (s + 0 * 32));
236 __m256i r1 = _mm256_loadu_si256 ((__m256i *) (s + 1 * 32));
238 _mm256_storeu_si256 ((__m256i *) (d0 + 0 * 32), r0);
239 _mm256_storeu_si256 ((__m256i *) (d0 + 1 * 32), r1);
241 _mm256_storeu_si256 ((__m256i *) (d1 + 0 * 32), r0);
242 _mm256_storeu_si256 ((__m256i *) (d1 + 1 * 32), r1);
244 _mm256_storeu_si256 ((__m256i *) (d2 + 0 * 32), r0);
245 _mm256_storeu_si256 ((__m256i *) (d2 + 1 * 32), r1);
247 _mm256_storeu_si256 ((__m256i *) (d3 + 0 * 32), r0);
248 _mm256_storeu_si256 ((__m256i *) (d3 + 1 * 32), r1);
250 #elif defined (__SSSE3__) 251 __m128i r0 = _mm_loadu_si128 ((__m128i *) (s + 0 * 16));
252 __m128i r1 = _mm_loadu_si128 ((__m128i *) (s + 1 * 16));
253 __m128i r2 = _mm_loadu_si128 ((__m128i *) (s + 2 * 16));
254 __m128i r3 = _mm_loadu_si128 ((__m128i *) (s + 3 * 16));
256 _mm_storeu_si128 ((__m128i *) (d0 + 0 * 16), r0);
257 _mm_storeu_si128 ((__m128i *) (d0 + 1 * 16), r1);
258 _mm_storeu_si128 ((__m128i *) (d0 + 2 * 16), r2);
259 _mm_storeu_si128 ((__m128i *) (d0 + 3 * 16), r3);
261 _mm_storeu_si128 ((__m128i *) (d1 + 0 * 16), r0);
262 _mm_storeu_si128 ((__m128i *) (d1 + 1 * 16), r1);
263 _mm_storeu_si128 ((__m128i *) (d1 + 2 * 16), r2);
264 _mm_storeu_si128 ((__m128i *) (d1 + 3 * 16), r3);
266 _mm_storeu_si128 ((__m128i *) (d2 + 0 * 16), r0);
267 _mm_storeu_si128 ((__m128i *) (d2 + 1 * 16), r1);
268 _mm_storeu_si128 ((__m128i *) (d2 + 2 * 16), r2);
269 _mm_storeu_si128 ((__m128i *) (d2 + 3 * 16), r3);
271 _mm_storeu_si128 ((__m128i *) (d3 + 0 * 16), r0);
272 _mm_storeu_si128 ((__m128i *) (d3 + 1 * 16), r1);
273 _mm_storeu_si128 ((__m128i *) (d3 + 2 * 16), r2);
274 _mm_storeu_si128 ((__m128i *) (d3 + 3 * 16), r3);
288 #if defined(CLIB_HAVE_VEC512) 289 u64x8 v512 = u64x8_splat (val);
292 u64x8_store_unaligned (v512, ptr);
299 #if defined(CLIB_HAVE_VEC256) 300 u64x4 v256 = u64x4_splat (val);
303 u64x4_store_unaligned (v256, ptr);
312 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
325 #if defined(CLIB_HAVE_VEC512) 326 u32x16 v512 = u32x16_splat (val);
329 u32x16_store_unaligned (v512, ptr);
336 #if defined(CLIB_HAVE_VEC256) 337 u32x8 v256 = u32x8_splat (val);
340 u32x8_store_unaligned (v256, ptr);
347 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) 348 u32x4 v128 = u32x4_splat (val);
351 u32x4_store_unaligned (v128, ptr);
358 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
371 #if defined(CLIB_HAVE_VEC512) 372 u16x32 v512 = u16x32_splat (val);
375 u16x32_store_unaligned (v512, ptr);
382 #if defined(CLIB_HAVE_VEC256) 383 u16x16 v256 = u16x16_splat (val);
386 u16x16_store_unaligned (v256, ptr);
393 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) 394 u16x8 v128 = u16x8_splat (val);
397 u16x8_store_unaligned (v128, ptr);
404 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
417 #if defined(CLIB_HAVE_VEC512) 418 u8x64 v512 = u8x64_splat (val);
421 u8x64_store_unaligned (v512, ptr);
428 #if defined(CLIB_HAVE_VEC256) 429 u8x32 v256 = u8x32_splat (val);
432 u8x32_store_unaligned (v256, ptr);
439 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) 440 u8x16 v128 = u8x16_splat (val);
443 u8x16_store_unaligned (v128, ptr);
450 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
467 if (data[0] != data[1])
473 #if defined(CLIB_HAVE_VEC256) 474 u64x4 splat = u64x4_splat (first);
478 bmp =
u8x32_msb_mask ((u8x32) (u64x4_load_unaligned (data) == splat));
479 if (bmp != 0xffffffff)
488 if (count >= max_count)
494 while (count + 3 < max_count &&
495 ((data[0] ^ first) | (data[1] ^ first) |
496 (data[2] ^ first) | (data[3] ^ first)) == 0)
501 while (count < max_count && (data[0] == first))
517 if (data[0] != data[1])
523 #if defined(CLIB_HAVE_VEC256) 524 u32x8 splat = u32x8_splat (first);
528 bmp =
u8x32_msb_mask ((u8x32) (u32x8_load_unaligned (data) == splat));
529 if (bmp != 0xffffffff)
538 if (count >= max_count)
541 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 542 u32x4 splat = u32x4_splat (first);
546 bmp =
u8x16_msb_mask ((u8x16) (u32x4_load_unaligned (data) == splat));
556 if (count >= max_count)
562 while (count + 3 < max_count &&
563 ((data[0] ^ first) | (data[1] ^ first) |
564 (data[2] ^ first) | (data[3] ^ first)) == 0)
569 while (count < max_count && (data[0] == first))
585 if (data[0] != data[1])
591 #if defined(CLIB_HAVE_VEC256) 592 u16x16 splat = u16x16_splat (first);
596 bmp =
u8x32_msb_mask ((u8x32) (u16x16_load_unaligned (data) == splat));
597 if (bmp != 0xffffffff)
606 if (count >= max_count)
609 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 610 u16x8 splat = u16x8_splat (first);
614 bmp =
u8x16_msb_mask ((u8x16) (u16x8_load_unaligned (data) == splat));
624 if (count >= max_count)
630 while (count + 3 < max_count &&
631 ((data[0] ^ first) | (data[1] ^ first) |
632 (data[2] ^ first) | (data[3] ^ first)) == 0)
637 while (count < max_count && (data[0] == first))
653 if (data[0] != data[1])
659 #if defined(CLIB_HAVE_VEC256) 660 u8x32 splat = u8x32_splat (first);
664 bmp =
u8x32_msb_mask ((u8x32) (u8x32_load_unaligned (data) == splat));
665 if (bmp != 0xffffffff)
674 if (count >= max_count)
677 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 678 u8x16 splat = u8x16_splat (first);
682 bmp =
u8x16_msb_mask ((u8x16) (u8x16_load_unaligned (data) == splat));
692 if (count >= max_count)
698 while (count + 3 < max_count &&
699 ((data[0] ^ first) | (data[1] ^ first) |
700 (data[2] ^ first) | (data[3] ^ first)) == 0)
705 while (count < max_count && (data[0] == first))
727 #define clib_memcmp(s1,s2,m1) \ 729 memcmp_s_inline (s1, m1, s2, m1, &__diff); \ 742 bad = (s1 == 0) + (s2 == 0) + (diff == 0) + (s2max > s1max) + (s2max == 0) +
768 *diff = memcmp (s1, s2, s2max);
775 #define clib_strnlen(s,m) strnlen_s_inline(s,m) 777 size_t strnlen_s (
const char *s,
size_t maxsize);
784 bad = (s == 0) + (maxsize == 0);
793 return strnlen (s, maxsize);
816 #define clib_strcmp(s1,s2) \ 817 ({ int __indicator = 0; \ 818 strcmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, &__indicator); \ 831 bad = (indicator == 0) + (s1 == 0) + (s2 == 0) + (s1max == 0) +
836 if (indicator ==
NULL)
844 if (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0')
849 *indicator = strcmp (s1, s2);
870 #define clib_strncmp(s1,s2,n) \ 871 ({ int __indicator = 0; \ 872 strncmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, n, &__indicator); \ 884 u8 s1_greater_s1max = (s1 && s1max && n >
clib_strnlen (s1, s1max));
894 *indicator = strncmp (s1, s2, n);
898 bad = (s1 == 0) + (s2 == 0) + (indicator == 0) + (s1max == 0) +
899 (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0') + s1_greater_s1max;
903 if (indicator ==
NULL)
911 if (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0')
913 if (s1_greater_s1max)
918 *indicator = strncmp (s1, s2, n);
928 #define clib_strcpy(d,s) strcpy_s_inline(d,CLIB_STRING_MACRO_MAX,s) 931 const char *__restrict__
src);
935 const char *__restrict__
src)
941 bad = (dest == 0) + (dmax == 0) + (src == 0);
964 low = (
uword) (src < dest ? src : dest);
965 hi = (
uword) (src < dest ? dest : src);
985 #define clib_strncpy(d,s,n) strncpy_s_inline(d,CLIB_STRING_MACRO_MAX,s,n) 1000 bad = (dest == 0) + (dmax == 0) + (src == 0) + (n == 0);
1032 low = (
uword) (src < dest ? src : dest);
1033 hi = (
uword) (src < dest ? dest : src);
1044 if (low + (m - 1) >= hi)
1064 #define clib_strcat(d,s) strcat_s_inline(d,CLIB_STRING_MACRO_MAX,s) 1067 const char *__restrict__
src);
1071 const char *__restrict__
src)
1075 size_t m, n, dest_size;
1077 bad = (dest == 0) + (dmax == 0) + (src == 0);
1090 m = dmax - dest_size;
1103 low = (
uword) (src < dest ? src : dest);
1104 hi = (
uword) (src < dest ? dest : src);
1113 dest[dest_size + n] =
'\0';
1125 #define clib_strncat(d,s,n) strncat_s_inline(d,CLIB_STRING_MACRO_MAX,s,n) 1136 size_t m, dest_size, allowed_size;
1139 bad = (dest == 0) + (src == 0) + (dmax == 0) + (n == 0);
1155 low = (
uword) (src < dest ? src : dest);
1156 hi = (
uword) (src < dest ? dest : src);
1165 allowed_size = dmax - dest_size;
1181 if (m >= allowed_size)
1183 m = allowed_size - 1;
1191 dest[dest_size + m] =
'\0';
1204 #define clib_strtok(s1,s2,p) \ 1205 ({ rsize_t __s1max = CLIB_STRING_MACRO_MAX; \ 1206 strtok_s_inline (s1, &__s1max, s2, p); \ 1210 const char *__restrict__ s2,
char **__restrict__ ptr);
1214 const char *__restrict__ s2,
char **__restrict__ ptr)
1216 #define STRTOK_DELIM_MAX_LEN 16 1222 bad = (s1max == 0) + (s2 == 0) + (ptr == 0) +
1223 ((s1 == 0) && ptr && (*ptr == 0));
1233 if ((s1 == 0) && ptr && (*ptr == 0))
1246 while (*s1 !=
'\0' && !ptoken)
1356 #define clib_strstr(s1,s2) \ 1357 ({ char * __substring = 0; \ 1358 strstr_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, CLIB_STRING_MACRO_MAX, \ 1371 size_t s1_size, s2_size;
1374 (s1 == 0) + (s2 == 0) + (substring == 0) + (s1max == 0) + (s2max == 0) +
1375 (s1 && s1max && (s1[
clib_strnlen (s1, s1max)] !=
'\0')) +
1376 (s2 && s2max && (s2[
clib_strnlen (s2, s2max)] !=
'\0'));
1389 if (s1 && s1max && (s1[
clib_strnlen (s1, s1max)] !=
'\0'))
1391 if (s2 && s2max && (s2[
clib_strnlen (s2, s1max)] !=
'\0'))
1413 *substring = strstr (s1, s2);
1414 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.
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.
u16x16 u64x4 static_always_inline u32 u8x32_msb_mask(u8x32 v)
#define clib_memcpy_fast(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 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_memcpy64_x4(void *d0, void *d1, void *d2, void *d3, void *s)
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 errno_t strcpy_s_inline(char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src)
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)
static_always_inline void clib_memset_u16(void *p, u16 val, uword count)
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)
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 void clib_memset_u32(void *p, u32 val, uword count)