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_HxAVE_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) && !defined (__aarch64__) 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);
488 bmp =
u8x32_msb_mask ((u8x32) (u64x4_load_unaligned (data) == splat));
489 if (bmp != 0xffffffff)
498 if (count >= max_count)
504 while (count + 3 < max_count &&
505 ((data[0] ^ first) | (data[1] ^ first) |
506 (data[2] ^ first) | (data[3] ^ first)) == 0)
511 while (count < max_count && (data[0] == first))
527 if (data[0] != data[1])
533 #if defined(CLIB_HAVE_VEC256) 534 u32x8 splat = u32x8_splat (first);
538 bmp =
u8x32_msb_mask ((u8x32) (u32x8_load_unaligned (data) == splat));
539 if (bmp != 0xffffffff)
548 if (count >= max_count)
551 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 552 u32x4 splat = u32x4_splat (first);
556 bmp =
u8x16_msb_mask ((u8x16) (u32x4_load_unaligned (data) == splat));
566 if (count >= max_count)
572 while (count + 3 < max_count &&
573 ((data[0] ^ first) | (data[1] ^ first) |
574 (data[2] ^ first) | (data[3] ^ first)) == 0)
579 while (count < max_count && (data[0] == first))
595 if (data[0] != data[1])
601 #if defined(CLIB_HAVE_VEC256) 602 u16x16 splat = u16x16_splat (first);
606 bmp =
u8x32_msb_mask ((u8x32) (u16x16_load_unaligned (data) == splat));
607 if (bmp != 0xffffffff)
616 if (count >= max_count)
619 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 620 u16x8 splat = u16x8_splat (first);
624 bmp =
u8x16_msb_mask ((u8x16) (u16x8_load_unaligned (data) == splat));
634 if (count >= max_count)
640 while (count + 3 < max_count &&
641 ((data[0] ^ first) | (data[1] ^ first) |
642 (data[2] ^ first) | (data[3] ^ first)) == 0)
647 while (count < max_count && (data[0] == first))
663 if (data[0] != data[1])
669 #if defined(CLIB_HAVE_VEC256) 670 u8x32 splat = u8x32_splat (first);
674 bmp =
u8x32_msb_mask ((u8x32) (u8x32_load_unaligned (data) == splat));
675 if (bmp != 0xffffffff)
684 if (count >= max_count)
687 #elif defined(CLIB_HAVE_VEC128) && defined(CLIB_HAVE_VEC128_MSB_MASK) 688 u8x16 splat = u8x16_splat (first);
692 bmp =
u8x16_msb_mask ((u8x16) (u8x16_load_unaligned (data) == splat));
702 if (count >= max_count)
708 while (count + 3 < max_count &&
709 ((data[0] ^ first) | (data[1] ^ first) |
710 (data[2] ^ first) | (data[3] ^ first)) == 0)
715 while (count < max_count && (data[0] == first))
737 #define clib_memcmp(s1,s2,m1) \ 739 memcmp_s_inline (s1, m1, s2, m1, &__diff); \ 752 bad = (s1 == 0) + (s2 == 0) + (diff == 0) + (s2max > s1max) + (s2max == 0) +
778 *diff = memcmp (s1, s2, s2max);
785 #define clib_strnlen(s,m) strnlen_s_inline(s,m) 787 size_t strnlen_s (
const char *s,
size_t maxsize);
794 bad = (s == 0) + (maxsize == 0);
803 return strnlen (s, maxsize);
826 #define clib_strcmp(s1,s2) \ 827 ({ int __indicator = 0; \ 828 strcmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, &__indicator); \ 841 bad = (indicator == 0) + (s1 == 0) + (s2 == 0) + (s1max == 0) +
846 if (indicator ==
NULL)
854 if (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0')
859 *indicator = strcmp (s1, s2);
880 #define clib_strncmp(s1,s2,n) \ 881 ({ int __indicator = 0; \ 882 strncmp_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, n, &__indicator); \ 894 u8 s1_greater_s1max = (s1 && s1max && n >
clib_strnlen (s1, s1max));
904 *indicator = strncmp (s1, s2, n);
908 bad = (s1 == 0) + (s2 == 0) + (indicator == 0) + (s1max == 0) +
909 (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0') + s1_greater_s1max;
913 if (indicator ==
NULL)
921 if (s1 && s1max && s1[
clib_strnlen (s1, s1max)] !=
'\0')
923 if (s1_greater_s1max)
928 *indicator = strncmp (s1, s2, n);
938 #define clib_strcpy(d,s) strcpy_s_inline(d,CLIB_STRING_MACRO_MAX,s) 941 const char *__restrict__
src);
945 const char *__restrict__
src)
951 bad = (dest == 0) + (dmax == 0) + (src == 0);
974 low = (
uword) (src < dest ? src : dest);
975 hi = (
uword) (src < dest ? dest : src);
995 #define clib_strncpy(d,s,n) strncpy_s_inline(d,CLIB_STRING_MACRO_MAX,s,n) 1010 bad = (dest == 0) + (dmax == 0) + (src == 0) + (n == 0);
1042 low = (
uword) (src < dest ? src : dest);
1043 hi = (
uword) (src < dest ? dest : src);
1054 if (low + (m - 1) >= hi)
1074 #define clib_strcat(d,s) strcat_s_inline(d,CLIB_STRING_MACRO_MAX,s) 1077 const char *__restrict__
src);
1081 const char *__restrict__
src)
1085 size_t m, n, dest_size;
1087 bad = (dest == 0) + (dmax == 0) + (src == 0);
1100 m = dmax - dest_size;
1113 low = (
uword) (src < dest ? src : dest);
1114 hi = (
uword) (src < dest ? dest : src);
1123 dest[dest_size + n] =
'\0';
1135 #define clib_strncat(d,s,n) strncat_s_inline(d,CLIB_STRING_MACRO_MAX,s,n) 1146 size_t m, dest_size, allowed_size;
1149 bad = (dest == 0) + (src == 0) + (dmax == 0) + (n == 0);
1165 low = (
uword) (src < dest ? src : dest);
1166 hi = (
uword) (src < dest ? dest : src);
1175 allowed_size = dmax - dest_size;
1191 if (m >= allowed_size)
1193 m = allowed_size - 1;
1201 dest[dest_size + m] =
'\0';
1214 #define clib_strtok(s1,s2,p) \ 1215 ({ rsize_t __s1max = CLIB_STRING_MACRO_MAX; \ 1216 strtok_s_inline (s1, &__s1max, s2, p); \ 1220 const char *__restrict__ s2,
char **__restrict__ ptr);
1224 const char *__restrict__ s2,
char **__restrict__ ptr)
1226 #define STRTOK_DELIM_MAX_LEN 16 1232 bad = (s1max == 0) + (s2 == 0) + (ptr == 0) +
1233 ((s1 == 0) && ptr && (*ptr == 0));
1243 if ((s1 == 0) && ptr && (*ptr == 0))
1256 while (*s1 !=
'\0' && !ptoken)
1366 #define clib_strstr(s1,s2) \ 1367 ({ char * __substring = 0; \ 1368 strstr_s_inline (s1, CLIB_STRING_MACRO_MAX, s2, CLIB_STRING_MACRO_MAX, \ 1381 size_t s1_size, s2_size;
1384 (s1 == 0) + (s2 == 0) + (substring == 0) + (s1max == 0) + (s2max == 0) +
1385 (s1 && s1max && (s1[
clib_strnlen (s1, s1max)] !=
'\0')) +
1386 (s2 && s2max && (s2[
clib_strnlen (s2, s2max)] !=
'\0'));
1399 if (s1 && s1max && (s1[
clib_strnlen (s1, s1max)] !=
'\0'))
1401 if (s2 && s2max && (s2[
clib_strnlen (s2, s1max)] !=
'\0'))
1423 *substring = strstr (s1, s2);
1424 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)