blob: ea9480875a5c0b63ed0728d91a6877dd436d5c72 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 Copyright (c) 2006 Eliot Dresselhaus
17
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
25
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
28
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36*/
37
38#include <vppinfra/string.h>
39#include <vppinfra/error.h>
40
Stevenb0598492018-10-24 21:15:45 -070041/**
42 * @file
43 * @brief String Handling routines, including a performant
44 * implementation of many c-11 "safe" string functions.
45 */
46
Ed Warnickecb9cada2015-12-08 15:45:58 -070047/* Exchanges source and destination. */
Dave Barachc3799992016-08-15 11:12:27 -040048void
49clib_memswap (void *_a, void *_b, uword bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -070050{
51 uword pa = pointer_to_uword (_a);
52 uword pb = pointer_to_uword (_b);
53
54#define _(TYPE) \
55 if (0 == ((pa | pb) & (sizeof (TYPE) - 1))) \
56 { \
57 TYPE * a = uword_to_pointer (pa, TYPE *); \
58 TYPE * b = uword_to_pointer (pb, TYPE *); \
59 \
60 while (bytes >= 2*sizeof (TYPE)) \
61 { \
62 TYPE a0, a1, b0, b1; \
63 bytes -= 2*sizeof (TYPE); \
64 a += 2; \
65 b += 2; \
66 a0 = a[-2]; a1 = a[-1]; \
67 b0 = b[-2]; b1 = b[-1]; \
68 a[-2] = b0; a[-1] = b1; \
69 b[-2] = a0; b[-1] = a1; \
70 } \
71 pa = pointer_to_uword (a); \
72 pb = pointer_to_uword (b); \
73 }
Dave Barachc3799992016-08-15 11:12:27 -040074
Ed Warnickecb9cada2015-12-08 15:45:58 -070075 if (BITS (uword) == BITS (u64))
Dave Barachc3799992016-08-15 11:12:27 -040076 _(u64);
77 _(u32);
78 _(u16);
79 _(u8);
Ed Warnickecb9cada2015-12-08 15:45:58 -070080
81#undef _
82
83 ASSERT (bytes < 2);
84 if (bytes)
85 {
Dave Barachc3799992016-08-15 11:12:27 -040086 u8 *a = uword_to_pointer (pa, u8 *);
87 u8 *b = uword_to_pointer (pb, u8 *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070088 u8 a0 = a[0], b0 = b[0];
Dave Barachc3799992016-08-15 11:12:27 -040089 a[0] = b0;
90 b[0] = a0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070091 }
92}
Dave Barachc3799992016-08-15 11:12:27 -040093
Damjan Mariondae1c7e2020-10-17 13:32:25 +020094__clib_export void
Dave Barachb7b92992018-10-17 10:38:51 -040095clib_c11_violation (const char *s)
96{
97 _clib_error (CLIB_ERROR_WARNING, (char *) __FUNCTION__, 0, (char *) s);
98}
99
Stevenb0598492018-10-24 21:15:45 -0700100/**
101 * @brief copy src to dest, at most n bytes, up to dmax
102 *
103 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
104 * Annex K; Bounds-checking interfaces
105 *
106 * @param *dest pointer to memory to copy to
107 * @param dmax maximum length of resulting dest
108 * @param *src pointer to memory to copy from
109 * @param n maximum number of characters to copy from src
110 *
111 * @constraints No null pointers
112 * n shall not be greater than dmax
113 * no memory overlap between src and dest
114 *
115 * @return EOK success
116 * EINVAL runtime constraint error
117 *
118 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200119__clib_export errno_t
Dave Barachb7b92992018-10-17 10:38:51 -0400120memcpy_s (void *__restrict__ dest, rsize_t dmax,
121 const void *__restrict__ src, rsize_t n)
122{
123 return memcpy_s_inline (dest, dmax, src, n);
124}
125
Stevenb0598492018-10-24 21:15:45 -0700126/**
127 * @brief set n bytes starting at s to the specified c value
128 *
129 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
130 * Annex K; Bounds-checking interfaces
131 *
132 * @param *s pointer to memory to set the c value
133 * @param smax maximum length of resulting s
134 * @param c byte value
135 * @param n maximum number of characters to set in s
136 *
137 * @constraints No null pointers
138 * n shall not be greater than smax
139 *
140 * @return EOK success
141 * EINVAL runtime constraint error
142 *
143 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200144__clib_export errno_t
Dave Barachb7b92992018-10-17 10:38:51 -0400145memset_s (void *s, rsize_t smax, int c, rsize_t n)
146{
147 return memset_s_inline (s, smax, c, n);
148}
149
Stevenb0598492018-10-24 21:15:45 -0700150/**
151 * @brief compare memory until they differ, and their difference is returned in
152 * diff
153 *
154 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
155 * Annex K; Bounds-checking interfaces
156 *
157 * @param *s1 pointer to memory to compare against
158 * @param s1max maximum length of s1
159 * @param *s2 pointer to memory to compare with s1
160 * @param s2max length of s2
161 * @param *diff pointer to the diff which is an integer greater than, equal to,
162 * or less than zero according to s1 is greater than, equal to,
163 * or less than s2.
164 *
165 * @constraints No null pointers
166 * s1max and s2max shall not be zero
167 * s2max shall not be greater than s1max
168 *
169 * @return EOK success
170 * diff when the return code is EOK
171 * >0 s1 greater s2
172 * 0 s1 == s2
173 * <0 s1 < s2
174 * EINVAL runtime constraint error
175 *
176 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200177__clib_export errno_t
Stevenb0598492018-10-24 21:15:45 -0700178memcmp_s (const void *s1, rsize_t s1max, const void *s2, rsize_t s2max,
179 int *diff)
180{
181 return memcmp_s_inline (s1, s1max, s2, s2max, diff);
182}
183
184/**
185 * @brief compare string s2 to string s1, and their difference is returned in
186 * indicator
187 *
188 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
189 * Annex K; Bounds-checking interfaces
190 *
191 * @param *s1 pointer to string to compare against
192 * @param s1max maximum length of s1, excluding null
193 * @param *s2 pointer to string to compare with s1
194 * @param *indicator pointer to the comparison result, which is an integer
195 * greater than, equal to, or less than zero according to
196 * s1 is greater than, equal to, or less than s2.
197 *
198 * @constraints No null pointers
199 * s1max shall not be zero
200 * s1 shall be null terminated
201 * n shall not be greater than the smaller of s1max and strlen
202 * of s1
203 *
204 * @return EOK success
205 * indicator when the return code is EOK
206 * >0 s1 greater s2
207 * 0 s1 == s2
208 * <0 s1 < s2
209 * EINVAL runtime constraint error
210 *
211 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200212__clib_export errno_t
Stevenb0598492018-10-24 21:15:45 -0700213strcmp_s (const char *s1, rsize_t s1max, const char *s2, int *indicator)
214{
215 return strcmp_s_inline (s1, s1max, s2, indicator);
216}
217
218/**
219 * @brief compare string s2 to string s1, no more than n characters, and their
220 * difference is returned in indicator
221 *
222 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
223 * Annex K; Bounds-checking interfaces
224 *
225 * @param *s1 pointer to string to compare against
226 * @param s1max maximum length of s1, excluding null
227 * @param *s2 pointer to string to compare with s1
228 * @param n maximum number of characters to compare
229 * @param *indicator pointer to the comparison result, which is an integer
230 * greater than, equal to, or less than zero according to
231 * s1 is greater than, equal to, or less than s2.
232 *
233 * @constraints No null pointers
234 * s1max shall not be zero
235 * s1 shall be null terminated
236 *
237 * @return EOK success
238 * indicator when the return code is EOK
239 * >0 s1 greater s2
240 * 0 s1 == s2
241 * <0 s1 < s2
242 * EINVAL runtime constraint error
243 *
244 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200245__clib_export errno_t
Stevenb0598492018-10-24 21:15:45 -0700246strncmp_s (const char *s1, rsize_t s1max, const char *s2, rsize_t n,
247 int *indicator)
248{
249 return strncmp_s_inline (s1, s1max, s2, n, indicator);
250}
251
252/**
253 * @brief copy src string to dest string
254 *
255 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
256 * Annex K; Bounds-checking interfaces
257 *
258 * @param *dest pointer to string to copy to
259 * @param dmax maximum length of resulting dest string, including null
260 * @param *src pointer to string to copy from
261 *
262 * @constraints No null pointers
263 * dmax shall not be zero
264 * dmax shall be greater than string length of src
265 * no memory overlap between src and dest
266 *
267 * @return EOK success
268 * EINVAL runtime constraint error
269 *
270 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200271__clib_export errno_t
Stevenb0598492018-10-24 21:15:45 -0700272strcpy_s (char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src)
273{
274 return strcpy_s_inline (dest, dmax, src);
275}
276
277/**
278 * @brief copy src string to dest string, no more than n characters
279 *
280 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
281 * Annex K; Bounds-checking interfaces
282 *
283 * @param *dest pointer to string to copy to
284 * @param dmax maximum length of resulting dest string, including null
285 * @param *src pointer to string to copy from
286 * @param n maximum number of characters to copy from src, excluding null
287 *
288 * @constraints No null pointers
289 * dmax shall not be zero
290 * no memory overlap between src and dest
291 *
292 * @return EOK success
293 * EINVAL runtime constraint error
294 * EOVERFLOW truncated operation. dmax - 1 characters were copied.
295 * dest is null terminated.
296 *
297 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200298__clib_export errno_t
Stevenb0598492018-10-24 21:15:45 -0700299strncpy_s (char *__restrict__ dest, rsize_t dmax,
300 const char *__restrict__ src, rsize_t n)
301{
302 return strncpy_s_inline (dest, dmax, src, n);
303}
304
305/**
306 * @brief append src string to dest string, including null
307 *
308 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
309 * Annex K; Bounds-checking interfaces
310 *
311 * @param *dest pointer to string to append to
312 * @param dmax maximum length of resulting dest string, including null
313 * @param *src pointer to string to append from
314 *
315 * @constraints No null pointers
316 * dmax shall not be zero
317 * dest shall be null terminated
318 * given m = dmax - strnlen (dest, dmax)
319 * n = strnlen (src, m)
320 * n shall not be >= m
321 * no memory overlap between src and dest
322 *
323 * @return EOK success
324 * EINVAL runtime constraint error
325 *
326 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200327__clib_export errno_t
Stevenb0598492018-10-24 21:15:45 -0700328strcat_s (char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src)
329{
330 return strcat_s_inline (dest, dmax, src);
331}
332
333/**
334 * @brief append src string to dest string, including null, no more than n
335 * characters
336 *
337 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
338 * Annex K; Bounds-checking interfaces
339 *
340 * @param *dest pointer to string to append to
341 * @param dmax maximum length of resulting dest string, including null
342 * @param *src pointer to string to append from
343 * @param n maximum characters to append (excluding null)
344 *
345 * @constraints No null pointers
346 * dmax shall not be zero
347 * dest shall be null terminated
348 * dmax - strnlen (dest, dmax) shall not be zero
349 * no memory overlap between src and dest
350 *
351 * @return EOK success
352 * EINVAL runtime constraint error
353 * EOVERFLOW truncated operation. dmax - 1 characters were appended.
354 * dest is null terminated.
355 *
356 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200357__clib_export errno_t
Stevenb0598492018-10-24 21:15:45 -0700358strncat_s (char *__restrict__ dest, rsize_t dmax,
359 const char *__restrict__ src, rsize_t n)
360{
361 return strncat_s_inline (dest, dmax, src, n);
362}
363
364/**
365 * @brief tokenize string s1 with delimiter specified in s2. This is a stateful
366 * API when it is iterately called, it returns the next token from s1
367 * which is delimited by s2. s1max and ptr maintain the stateful
368 * information for the same caller and must not be altered by the
369 * caller during the iteration for the correct result
370 *
371 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
372 * Annex K; Bounds-checking interfaces
373 *
374 * @param *s1 pointer to string to be searched for substring
375 * @param *s1max restricted maximum length of s1
376 * @param *s2 pointer to substring to search (16 characters max,
377 * including null)
378 * @param **ptr in/out pointer which maintains the stateful information
379 *
380 * @constraints s2, s1max, and ptr shall not be null
381 * if s1 is null, contents of ptr shall not be null
382 * s1 and s2 shall be null terminated
383 *
384 * @return non-null pointer to the first character of a token
385 * s1max and ptr are modified to contain the state
386 * null runtime constraint error or token is not found
387 *
Andrew Yourtchenko5e0c5ff2019-01-21 16:01:41 +0100388 * Example:
Stevenb0598492018-10-24 21:15:45 -0700389 * char *str2 = " ";
390 * char str1[100];
391 * uword len;
392 * char *p2str = 0;
393 * char *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7;
394 *
395 * strncpy (str1, "brevity is the soul of wit", sizeof (str1));
396 * len = strlen (str1);
397 * tok1 = strtok_s (str1, &len, str2, &p2str);
398 * tok2 = strtok_s (0, &len, str2, &p2str);
399 * tok3 = strtok_s (0, &len, str2, &p2str);
400 * tok4 = strtok_s (0, &len, str2, &p2str);
401 * tok5 = strtok_s (0, &len, str2, &p2str);
402 * tok6 = strtok_s (0, &len, str2, &p2str);
403 * tok7 = strtok_s (0, &len, str2, &p2str);
404 *
405 * After the above series of calls,
406 * tok1 = "brevity", tok2 = "is", tok3 = "the", tok4 = "soul", tok5 = "of",
407 * tok6 = "wit", tok7 = null
408 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200409__clib_export char *
Stevenb0598492018-10-24 21:15:45 -0700410strtok_s (char *__restrict__ s1, rsize_t * __restrict__ s1max,
411 const char *__restrict__ s2, char **__restrict__ ptr)
412{
413 return strtok_s_inline (s1, s1max, s2, ptr);
414}
415
416/**
417 * @brief compute the length in s, no more than maxsize
418 *
419 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
420 * Annex K; Bounds-checking interfaces
421 *
422 * @param *s pointer to string
423 * @param maxsize restricted maximum length
424 *
425 * @constraints No null pointers
426 * maxsize shall not be zero
427 *
428 * @return size_t the string length in s, excluding null character, and no
429 * more than maxsize or 0 if there is a constraint error
430 *
431 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200432__clib_export size_t
Stevenb0598492018-10-24 21:15:45 -0700433strnlen_s (const char *s, size_t maxsize)
434{
435 return strnlen_s_inline (s, maxsize);
436}
437
438/**
439 * @brief locate the first occurrence of the substring s2 in s1
440 *
441 * ISO/IEC 9899:2017(C11), Porgramming languages -- C
442 * Annex K; Bounds-checking interfaces
443 *
444 * @param *s1 pointer to string to be searched for substring
445 * @param s1max restricted maximum length of s1
446 * @param *s2 pointer to substring to search
447 * @param s2max restricted maximum length of s2
448 * @param **substring pointer to pointer substring to be returned
449 *
450 * @constraints No null pointers
451 * s1max and s2max shall not be zero
452 * s1 and s2 shall be null terminated
453 *
454 * @return EOK success
455 * substring when the return code is EOK, it contains the pointer which
456 * points to s1 that matches s2
457 * EINVAL runtime constraint error
458 * ESRCH no match
459 *
Andrew Yourtchenko5e0c5ff2019-01-21 16:01:41 +0100460 * Example:
Stevenb0598492018-10-24 21:15:45 -0700461 * char *sub = 0;
462 * char *s1 = "success is not final, failure is not fatal.";
463 *
464 * strstr_s (s1, strlen (s1), "failure", strlen ("failure"), &sub);
465 *
466 * After the above call,
467 * sub = "failure is not fatal."
468 */
Damjan Mariondae1c7e2020-10-17 13:32:25 +0200469__clib_export errno_t
Stevenb0598492018-10-24 21:15:45 -0700470strstr_s (char *s1, rsize_t s1max, const char *s2, rsize_t s2max,
471 char **substring)
472{
473 return strstr_s_inline (s1, s1max, s2, s2max, substring);
474}
475
Dave Barachc3799992016-08-15 11:12:27 -0400476/*
477 * fd.io coding-style-patch-verification: ON
478 *
479 * Local Variables:
480 * eval: (c-set-style "gnu")
481 * End:
482 */