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) 219 #if defined (CLIB_HAVE_VEC256) 220 u8x32 s0, s1, d0, d1;
221 u8x32
mask = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
222 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
224 u8x32 lv = u8x32_splat (len);
225 u8x32 add = u8x32_splat (32);
227 s0 = u8x32_load_unaligned (src);
228 s1 = u8x32_load_unaligned (src + 32);
229 d0 = u8x32_load_unaligned (dst);
230 d1 = u8x32_load_unaligned (dst + 32);
233 u8x32_store_unaligned (d0, dst);
240 u8x32_store_unaligned (d1, dst + 32);
242 #elif defined (CLIB_HAVE_VEC128) 243 u8x16 s0, s1, s2, s3, d0, d1, d2, d3;
244 u8x16 mask = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
245 u8x16 lv = u8x16_splat (len);
246 u8x16 add = u8x16_splat (16);
248 s0 = u8x16_load_unaligned (src);
249 s1 = u8x16_load_unaligned (src + 16);
250 s2 = u8x16_load_unaligned (src + 32);
251 s3 = u8x16_load_unaligned (src + 48);
252 d0 = u8x16_load_unaligned (dst);
253 d1 = u8x16_load_unaligned (dst + 16);
254 d2 = u8x16_load_unaligned (dst + 32);
255 d3 = u8x16_load_unaligned (dst + 48);
258 u8x16_store_unaligned (d0, dst);
265 u8x16_store_unaligned (d1, dst + 16);
272 u8x16_store_unaligned (d2, dst + 32);
276 u8x16_store_unaligned (d3, dst + 48);
278 memmove (dst, src, len);
298 #if defined(CLIB_HAVE_VEC512) 299 u64x8 v512 = u64x8_splat (val);
302 u64x8_store_unaligned (v512, ptr);
309 #if defined(CLIB_HAVE_VEC256) 310 u64x4 v256 = u64x4_splat (val);
313 u64x4_store_unaligned (v256, ptr);
322 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
335 #if defined(CLIB_HAVE_VEC512) 336 u32x16 v512 = u32x16_splat (val);
339 u32x16_store_unaligned (v512, ptr);
346 #if defined(CLIB_HAVE_VEC256) 347 u32x8 v256 = u32x8_splat (val);
350 u32x8_store_unaligned (v256, ptr);
357 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) 358 u32x4 v128 = u32x4_splat (val);
361 u32x4_store_unaligned (v128, ptr);
368 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
381 #if defined(CLIB_HAVE_VEC512) 382 u16x32 v512 = u16x32_splat (val);
385 u16x32_store_unaligned (v512, ptr);
392 #if defined(CLIB_HAVE_VEC256) 393 u16x16 v256 = u16x16_splat (val);
396 u16x16_store_unaligned (v256, ptr);
403 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) 404 u16x8 v128 = u16x8_splat (val);
407 u16x8_store_unaligned (v128, ptr);
414 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
427 #if defined(CLIB_HAVE_VEC512) 428 u8x64 v512 = u8x64_splat (val);
431 u8x64_store_unaligned (v512, ptr);
438 #if defined(CLIB_HAVE_VEC256) 439 u8x32 v256 = u8x32_splat (val);
442 u8x32_store_unaligned (v256, ptr);
449 #if defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_UNALIGNED_LOAD_STORE) 450 u8x16 v128 = u8x16_splat (val);
453 u8x16_store_unaligned (v128, ptr);
460 ptr[0] = ptr[1] = ptr[2] = ptr[3] = val;
477 if (data[0] != data[1])
483 #if defined(CLIB_HAVE_VEC256) 484 u64x4 splat = u64x4_splat (first);
485 while (count + 3 < max_count)
488 bmp =
u8x32_msb_mask ((u8x32) (u64x4_load_unaligned (data) == splat));
489 if (bmp != 0xffffffff)
501 while (count + 3 < max_count &&
502 ((data[0] ^ first) | (data[1] ^ first) |
503 (data[2] ^ first) | (data[3] ^ first)) == 0)
509 while (count < max_count && (data[0] == first))
525 if (data[0] != data[1])
531 #if defined(CLIB_HAVE_VEC256) 532 u32x8 splat = u32x8_splat (first);
533 while (count + 7 < max_count)
536 bmp =
u8x32_msb_mask ((u8x32) (u32x8_load_unaligned (data) == splat));
537 if (bmp != 0xffffffff)
546 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 547 u32x4 splat = u32x4_splat (first);
548 while (count + 3 < max_count)
551 bmp =
u8x16_msb_mask ((u8x16) (u32x4_load_unaligned (data) == splat));
564 while (count + 3 < max_count &&
565 ((data[0] ^ first) | (data[1] ^ first) |
566 (data[2] ^ first) | (data[3] ^ first)) == 0)
572 while (count < max_count && (data[0] == first))
588 if (data[0] != data[1])
594 #if defined(CLIB_HAVE_VEC256) 595 u16x16 splat = u16x16_splat (first);
596 while (count + 15 < max_count)
599 bmp =
u8x32_msb_mask ((u8x32) (u16x16_load_unaligned (data) == splat));
600 if (bmp != 0xffffffff)
609 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 610 u16x8 splat = u16x8_splat (first);
611 while (count + 7 < max_count)
614 bmp =
u8x16_msb_mask ((u8x16) (u16x8_load_unaligned (data) == splat));
627 while (count + 3 < max_count &&
628 ((data[0] ^ first) | (data[1] ^ first) |
629 (data[2] ^ first) | (data[3] ^ first)) == 0)
635 while (count < max_count && (data[0] == first))
651 if (data[0] != data[1])
657 #if defined(CLIB_HAVE_VEC256) 658 u8x32 splat = u8x32_splat (first);
659 while (count + 31 < max_count)
662 bmp =
u8x32_msb_mask ((u8x32) (u8x32_load_unaligned (data) == splat));
663 if (bmp != 0xffffffff)
672 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 673 u8x16 splat = u8x16_splat (first);
674 while (count + 15 < max_count)
677 bmp =
u8x16_msb_mask ((u8x16) (u8x16_load_unaligned (data) == splat));
690 while (count + 3 < max_count &&
691 ((data[0] ^ first) | (data[1] ^ first) |
692 (data[2] ^ first) | (data[3] ^ first)) == 0)
698 while (count < max_count && (data[0] == first))
720 #define clib_memcmp(s1,s2,m1) \ 722 memcmp_s_inline (s1, m1, s2, m1, &__diff); \ 735 bad = (s1 == 0) + (s2 == 0) + (diff == 0) + (s2max > s1max) + (s2max == 0) +
761 *diff = memcmp (s1, s2, s2max);
768 #define clib_strnlen(s,m) strnlen_s_inline(s,m) 770 size_t strnlen_s (
const char *s,
size_t maxsize);
777 bad = (s == 0) + (maxsize == 0);
786 return strnlen (s, maxsize);
809 #define clib_strcmp(s1,s2) \ 810 ({ int __indicator = 0; \ 811 strcmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, &__indicator); \ 824 bad = (indicator == 0) + (s1 == 0) + (s2 == 0) + (s1max == 0) +
829 if (indicator == NULL)
837 if (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0')
842 *indicator = strcmp (s1, s2);
863 #define clib_strncmp(s1,s2,n) \ 864 ({ int __indicator = 0; \ 865 strncmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, n, &__indicator); \ 877 u8 s1_greater_s1max = (s1 && s1max && n >
clib_strnlen (s1, s1max));
887 *indicator = strncmp (s1, s2, n);
891 bad = (s1 == 0) + (s2 == 0) + (indicator == 0) + (s1max == 0) +
892 (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0') + s1_greater_s1max;
896 if (indicator == NULL)
904 if (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0')
906 if (s1_greater_s1max)
911 *indicator = strncmp (s1, s2, n);
921 #define clib_strcpy(d,s) strcpy_s_inline(d,CLIB_STRING_MACRO_MAX,s) 924 const char *__restrict__
src);
928 const char *__restrict__
src)
934 bad = (dest == 0) + (dmax == 0) + (src == 0);
957 low = (
uword) (src < dest ? src : dest);
958 hi = (
uword) (src < dest ? dest : src);
978 #define clib_strncpy(d,s,n) strncpy_s_inline(d,CLIB_STRING_MACRO_MAX,s,n) 993 bad = (dest == 0) + (dmax == 0) + (src == 0) + (n == 0);
1025 low = (
uword) (src < dest ? src : dest);
1026 hi = (
uword) (src < dest ? dest : src);
1037 if (low + (m - 1) >= hi)
1057 #define clib_strcat(d,s) strcat_s_inline(d,CLIB_STRING_MACRO_MAX,s) 1060 const char *__restrict__
src);
1064 const char *__restrict__
src)
1068 size_t m, n, dest_size;
1070 bad = (dest == 0) + (dmax == 0) + (src == 0);
1083 m = dmax - dest_size;
1096 low = (
uword) (src < dest ? src : dest);
1097 hi = (
uword) (src < dest ? dest : src);
1106 dest[dest_size + n] =
'\0';
1118 #define clib_strncat(d,s,n) strncat_s_inline(d,CLIB_STRING_MACRO_MAX,s,n) 1129 size_t m, dest_size, allowed_size;
1132 bad = (dest == 0) + (src == 0) + (dmax == 0) + (n == 0);
1148 low = (
uword) (src < dest ? src : dest);
1149 hi = (
uword) (src < dest ? dest : src);
1158 allowed_size = dmax - dest_size;
1174 if (m >= allowed_size)
1176 m = allowed_size - 1;
1184 dest[dest_size + m] =
'\0';
1197 #define clib_strtok(s1,s2,p) \ 1198 ({ rsize_t __s1max = CLIB_STRING_MACRO_MAX; \ 1199 strtok_s_inline (s1, &__s1max, s2, p); \ 1203 const char *__restrict__ s2,
char **__restrict__ ptr);
1207 const char *__restrict__ s2,
char **__restrict__ ptr)
1209 #define STRTOK_DELIM_MAX_LEN 16 1215 bad = (s1max == 0) + (s2 == 0) + (ptr == 0) +
1216 ((s1 == 0) && ptr && (*ptr == 0));
1226 if ((s1 == 0) && ptr && (*ptr == 0))
1239 while (*s1 !=
'\0' && !ptoken)
1349 #define clib_strstr(s1,s2) \ 1350 ({ char * __substring = 0; \ 1351 strstr_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, CLIB_STRING_MACRO_MAX, \ 1364 size_t s1_size, s2_size;
1367 (s1 == 0) + (s2 == 0) + (substring == 0) + (s1max == 0) + (s2max == 0) +
1368 (s1 && s1max && (s1[
clib_strnlen (s1, s1max)] !=
'\0')) +
1369 (s2 && s2max && (s2[
clib_strnlen (s2, s2max)] !=
'\0'));
1382 if (s1 && s1max && (s1[
clib_strnlen (s1, s1max)] !=
'\0'))
1384 if (s2 && s2max && (s2[
clib_strnlen (s2, s1max)] !=
'\0'))
1406 *substring = strstr (s1, s2);
1407 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_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 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)
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)
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)
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)