Line data Source code
1 : /*
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 :
41 : /**
42 : * @file
43 : * @brief String Handling routines, including a performant
44 : * implementation of many c-11 "safe" string functions.
45 : */
46 :
47 : /* Exchanges source and destination. */
48 : void
49 0 : clib_memswap (void *_a, void *_b, uword bytes)
50 : {
51 0 : uword pa = pointer_to_uword (_a);
52 0 : 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 : }
74 :
75 : if (BITS (uword) == BITS (u64))
76 0 : _(u64);
77 0 : _(u32);
78 0 : _(u16);
79 0 : _(u8);
80 :
81 : #undef _
82 :
83 0 : ASSERT (bytes < 2);
84 0 : if (bytes)
85 : {
86 0 : u8 *a = uword_to_pointer (pa, u8 *);
87 0 : u8 *b = uword_to_pointer (pb, u8 *);
88 0 : u8 a0 = a[0], b0 = b[0];
89 0 : a[0] = b0;
90 0 : b[0] = a0;
91 : }
92 0 : }
93 :
94 : __clib_export void
95 72 : clib_c11_violation (const char *s)
96 : {
97 72 : _clib_error (CLIB_ERROR_WARNING, (char *) __FUNCTION__, 0, (char *) s);
98 72 : }
99 :
100 : /**
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 : */
119 : __clib_export errno_t
120 25 : memcpy_s (void *__restrict__ dest, rsize_t dmax,
121 : const void *__restrict__ src, rsize_t n)
122 : {
123 25 : return memcpy_s_inline (dest, dmax, src, n);
124 : }
125 :
126 : /**
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 : */
144 : __clib_export errno_t
145 5 : memset_s (void *s, rsize_t smax, int c, rsize_t n)
146 : {
147 5 : return memset_s_inline (s, smax, c, n);
148 : }
149 :
150 : /**
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 : */
177 : __clib_export errno_t
178 5 : memcmp_s (const void *s1, rsize_t s1max, const void *s2, rsize_t s2max,
179 : int *diff)
180 : {
181 5 : 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 : */
212 : __clib_export errno_t
213 44 : strcmp_s (const char *s1, rsize_t s1max, const char *s2, int *indicator)
214 : {
215 44 : 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 : */
245 : __clib_export errno_t
246 8 : strncmp_s (const char *s1, rsize_t s1max, const char *s2, rsize_t n,
247 : int *indicator)
248 : {
249 8 : 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 : */
271 : __clib_export errno_t
272 17 : strcpy_s (char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src)
273 : {
274 17 : 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 : */
298 : __clib_export errno_t
299 1088960 : strncpy_s (char *__restrict__ dest, rsize_t dmax,
300 : const char *__restrict__ src, rsize_t n)
301 : {
302 1088960 : 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 : */
327 : __clib_export errno_t
328 5 : strcat_s (char *__restrict__ dest, rsize_t dmax, const char *__restrict__ src)
329 : {
330 5 : 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 : */
357 : __clib_export errno_t
358 9 : strncat_s (char *__restrict__ dest, rsize_t dmax,
359 : const char *__restrict__ src, rsize_t n)
360 : {
361 9 : 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 : *
388 : * Example:
389 : * 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 : */
409 : __clib_export char *
410 12 : strtok_s (char *__restrict__ s1, rsize_t * __restrict__ s1max,
411 : const char *__restrict__ s2, char **__restrict__ ptr)
412 : {
413 12 : 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 : */
432 : __clib_export size_t
433 6 : strnlen_s (const char *s, size_t maxsize)
434 : {
435 6 : 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 : *
460 : * Example:
461 : * 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 : */
469 : __clib_export errno_t
470 4 : strstr_s (char *s1, rsize_t s1max, const char *s2, rsize_t s2max,
471 : char **substring)
472 : {
473 4 : return strstr_s_inline (s1, s1max, s2, s2max, substring);
474 : }
475 :
476 : /*
477 : * fd.io coding-style-patch-verification: ON
478 : *
479 : * Local Variables:
480 : * eval: (c-set-style "gnu")
481 : * End:
482 : */
|