Line data Source code
1 : #pragma once
2 :
3 : #include <petscsystypes.h>
4 : #include <petscerror.h>
5 : #include <petscmacros.h>
6 : #include <petscsys.h>
7 :
8 : /* SUBMANSEC = Sys */
9 :
10 : #include <stddef.h> /* size_t */
11 : #include <string.h> /* for memcpy, memset */
12 :
13 : PETSC_EXTERN PetscErrorCode PetscMemcmp(const void *, const void *, size_t, PetscBool *);
14 : PETSC_EXTERN PetscErrorCode PetscStrToArray(const char[], char, int *, char ***);
15 : PETSC_EXTERN PetscErrorCode PetscStrToArrayDestroy(int, char **);
16 : PETSC_EXTERN PetscErrorCode PetscStrcasecmp(const char[], const char[], PetscBool *);
17 : PETSC_EXTERN PetscErrorCode PetscStrendswithwhich(const char[], const char *const *, PetscInt *);
18 : PETSC_EXTERN PetscErrorCode PetscStrArrayallocpy(const char *const *, char ***);
19 : PETSC_EXTERN PetscErrorCode PetscStrArrayDestroy(char ***);
20 : PETSC_EXTERN PetscErrorCode PetscStrNArrayallocpy(PetscInt, const char *const *, char ***);
21 : PETSC_EXTERN PetscErrorCode PetscStrNArrayDestroy(PetscInt, char ***);
22 : PETSC_EXTERN PetscErrorCode PetscStrreplace(MPI_Comm, const char[], char[], size_t);
23 : PETSC_EXTERN PetscErrorCode PetscStrcmpAny(const char[], PetscBool *, const char[], ...);
24 :
25 : PETSC_EXTERN PetscErrorCode PetscTokenCreate(const char[], char, PetscToken *);
26 : PETSC_EXTERN PetscErrorCode PetscTokenFind(PetscToken, char *[]);
27 : PETSC_EXTERN PetscErrorCode PetscTokenDestroy(PetscToken *);
28 :
29 : PETSC_EXTERN PetscErrorCode PetscStrInList(const char[], const char[], char, PetscBool *);
30 : PETSC_EXTERN const char *PetscBasename(const char[]);
31 : PETSC_EXTERN PetscErrorCode PetscEListFind(PetscInt, const char *const *, const char *, PetscInt *, PetscBool *);
32 : PETSC_EXTERN PetscErrorCode PetscEnumFind(const char *const *, const char *, PetscEnum *, PetscBool *);
33 :
34 : PETSC_EXTERN PetscErrorCode PetscStrcat(char[], const char[]);
35 : PETSC_EXTERN PetscErrorCode PetscStrcpy(char[], const char[]);
36 :
37 : #define PetscAssertPointer_Private(ptr, arg) PetscAssert((ptr), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter '" PetscStringize(ptr) "' # " PetscStringize(arg))
38 :
39 : /*@C
40 : PetscStrtolower - Converts a string to lower case
41 :
42 : Not Collective, No Fortran Support
43 :
44 : Input Parameter:
45 : . a - pointer to string
46 :
47 : Level: intermediate
48 :
49 : .seealso: `PetscStrtoupper()`
50 : @*/
51 2 : static inline PetscErrorCode PetscStrtolower(char a[])
52 : {
53 2 : PetscFunctionBegin;
54 2 : PetscAssertPointer_Private(a, 1);
55 18 : while (*a) {
56 16 : if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
57 16 : a++;
58 : }
59 2 : PetscFunctionReturn(PETSC_SUCCESS);
60 : }
61 :
62 : /*@C
63 : PetscStrtoupper - Converts a string to upper case
64 :
65 : Not Collective, No Fortran Support
66 :
67 : Input Parameter:
68 : . a - pointer to string
69 :
70 : Level: intermediate
71 :
72 : .seealso: `PetscStrtolower()`
73 : @*/
74 : static inline PetscErrorCode PetscStrtoupper(char a[])
75 : {
76 : PetscFunctionBegin;
77 : PetscAssertPointer_Private(a, 1);
78 : while (*a) {
79 : if (*a >= 'a' && *a <= 'z') *a += 'A' - 'a';
80 : a++;
81 : }
82 : PetscFunctionReturn(PETSC_SUCCESS);
83 : }
84 :
85 : /*@C
86 : PetscStrlen - Gets the length of a string
87 :
88 : Not Collective, No Fortran Support
89 :
90 : Input Parameter:
91 : . s - pointer to string
92 :
93 : Output Parameter:
94 : . len - length in bytes
95 :
96 : Level: intermediate
97 :
98 : Note:
99 : This routine is analogous to `strlen()`. `NULL` string returns a length of zero.
100 :
101 : .seealso: `PetscStrallocpy()`
102 : @*/
103 46637 : static inline PetscErrorCode PetscStrlen(const char s[], size_t *len)
104 : {
105 46637 : PetscFunctionBegin;
106 46637 : PetscAssertPointer_Private(len, 2);
107 46637 : if (s) {
108 : #if PetscHasBuiltin(__builtin_strlen)
109 46637 : *len = __builtin_strlen(s);
110 : #else
111 : *len = strlen(s);
112 : #endif
113 : } else {
114 0 : *len = 0;
115 : }
116 46637 : PetscFunctionReturn(PETSC_SUCCESS);
117 : }
118 :
119 : /*@C
120 : PetscStrallocpy - Allocates space to hold a copy of a string then copies the string into the new space
121 :
122 : Not Collective, No Fortran Support
123 :
124 : Input Parameter:
125 : . s - pointer to string
126 :
127 : Output Parameter:
128 : . t - the copied string
129 :
130 : Level: intermediate
131 :
132 : Notes:
133 : `NULL` string returns a new `NULL` string.
134 :
135 : Use `PetscFree()` to release the data when it is no longer needed.
136 :
137 : If `t` has previously been allocated then that memory is lost, you may need to `PetscFree()`
138 : the array before calling this routine.
139 :
140 : .seealso: `PetscStrArrayallocpy()`, `PetscStrNArrayallocpy()`
141 : @*/
142 14806 : static inline PetscErrorCode PetscStrallocpy(const char s[], char *t[])
143 : {
144 14806 : PetscFunctionBegin;
145 14806 : PetscAssertPointer_Private(t, 2);
146 14806 : *t = PETSC_NULLPTR;
147 14806 : if (s) {
148 14806 : size_t len;
149 14806 : char *tmp;
150 :
151 0 : PetscAssertPointer_Private(s, 1);
152 14806 : PetscCall(PetscStrlen(s, &len));
153 14806 : PetscCall(PetscMalloc1(len + 1, &tmp));
154 : #if PetscHasBuiltin(__builtin_memcpy)
155 14806 : __builtin_memcpy(tmp, s, len);
156 : #else
157 : memcpy(tmp, s, len);
158 : #endif
159 14806 : tmp[len] = '\0';
160 14806 : *t = tmp;
161 : }
162 14806 : PetscFunctionReturn(PETSC_SUCCESS);
163 : }
164 :
165 43262 : static inline void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg)
166 : {
167 43262 : if (!a && !b) {
168 0 : *flg = PETSC_TRUE;
169 43262 : } else if (!a || !b) {
170 0 : *flg = PETSC_FALSE;
171 : } else {
172 : #if PetscHasBuiltin(__builtin_strcmp)
173 43262 : *flg = __builtin_strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
174 : #else
175 : *flg = strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
176 : #endif
177 : }
178 43262 : }
179 :
180 : /*@C
181 : PetscStrcmp - Compares two strings
182 :
183 : Not Collective, No Fortran Support
184 :
185 : Input Parameters:
186 : + a - pointer to string first string
187 : - b - pointer to second string
188 :
189 : Output Parameter:
190 : . flg - `PETSC_TRUE` if the two strings are equal
191 :
192 : Level: intermediate
193 :
194 : .seealso: `PetscStrcmpAny()`, `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`
195 : @*/
196 43262 : static inline PetscErrorCode PetscStrcmp(const char a[], const char b[], PetscBool *flg)
197 : {
198 43262 : PetscFunctionBegin;
199 43262 : PetscAssertPointer_Private(flg, 3);
200 43262 : PetscStrcmpNoError(a, b, flg);
201 43262 : PetscFunctionReturn(PETSC_SUCCESS);
202 : }
203 :
204 : #if defined(__GNUC__) && !defined(__clang__)
205 : #if __GNUC__ >= 8
206 : #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN \
207 : do { \
208 : _Pragma("GCC diagnostic push"); \
209 : _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\""); \
210 : } while (0)
211 : #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END _Pragma("GCC diagnostic pop")
212 : #endif
213 : #endif
214 :
215 : #ifndef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
216 : #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN (void)0
217 : #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END (void)0
218 : #endif
219 :
220 : /*@C
221 : PetscStrncpy - Copies a string up to a certain length
222 :
223 : Not Collective
224 :
225 : Input Parameters:
226 : + t - pointer to string
227 : - n - the length to copy
228 :
229 : Output Parameter:
230 : . s - the copied string
231 :
232 : Level: intermediate
233 :
234 : Notes:
235 : `NULL` string returns a string starting with zero.
236 :
237 : If the string that is being copied is of length `n` or larger, then the entire string is not
238 : copied and the final location of `s` is set to `NULL`. This is different then the behavior of
239 : `strncpy()` which leaves `s` non-terminated if there is not room for the entire string.
240 :
241 : Developer Note:
242 : Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not
243 : `strncpy()`?
244 :
245 : .seealso: `PetscStrlcat()`, `PetscStrallocpy()`
246 : @*/
247 7377 : static inline PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n)
248 : {
249 7377 : PetscFunctionBegin;
250 7377 : if (s) PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Requires an output string of length at least 1 to hold the termination character");
251 7377 : if (t) {
252 7377 : PetscAssertPointer_Private(s, 1);
253 7377 : PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN;
254 : #if PetscHasBuiltin(__builtin_strncpy)
255 7377 : __builtin_strncpy(s, t, n);
256 : #else
257 : strncpy(s, t, n);
258 : #endif
259 7377 : PETSC_SILENCE_WSTRINGOP_TRUNCATION_END;
260 7377 : s[n - 1] = '\0';
261 0 : } else if (s) {
262 0 : s[0] = '\0';
263 : }
264 7377 : PetscFunctionReturn(PETSC_SUCCESS);
265 : }
266 :
267 : /*@C
268 : PetscStrlcat - Concatenates a string onto a given string, up to a given length
269 :
270 : Not Collective, No Fortran Support
271 :
272 : Input Parameters:
273 : + s - pointer to string to be added to at end
274 : . t - string to be added
275 : - n - length of the original allocated string
276 :
277 : Level: intermediate
278 :
279 : Note:
280 : Unlike the system call `strncat()`, the length passed in is the length of the
281 : original allocated space, not the length of the left-over space. This is
282 : similar to the BSD system call `strlcat()`.
283 :
284 : .seealso: `PetscStrncpy()`
285 : @*/
286 28308 : static inline PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n)
287 : {
288 28308 : size_t len;
289 :
290 28308 : PetscFunctionBegin;
291 28308 : if (!t) PetscFunctionReturn(PETSC_SUCCESS);
292 28308 : PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "String buffer length must be positive");
293 28308 : PetscCall(PetscStrlen(s, &len));
294 28308 : PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN;
295 : #if PetscHasBuiltin(__builtin_strncat)
296 28308 : __builtin_strncat(s, t, n - len);
297 : #else
298 : strncat(s, t, n - len);
299 : #endif
300 28308 : PETSC_SILENCE_WSTRINGOP_TRUNCATION_END;
301 28308 : s[n - 1] = '\0';
302 28308 : PetscFunctionReturn(PETSC_SUCCESS);
303 : }
304 :
305 : #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
306 : #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_END
307 :
308 : /*@C
309 : PetscStrncmp - Compares two strings, up to a certain length
310 :
311 : Not Collective, No Fortran Support
312 :
313 : Input Parameters:
314 : + a - pointer to first string
315 : . b - pointer to second string
316 : - n - length to compare up to
317 :
318 : Output Parameter:
319 : . t - `PETSC_TRUE` if the two strings are equal, `PETSC_FALSE` otherwise
320 :
321 : Level: intermediate
322 :
323 : Note:
324 : If `n` is `0`, `t` is set to `PETSC_FALSE`. `a` and/or `b` may be `NULL` in this case.
325 :
326 : .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()`
327 : @*/
328 : static inline PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t)
329 : {
330 : PetscFunctionBegin;
331 : PetscAssertPointer_Private(t, 4);
332 : *t = PETSC_FALSE;
333 : if (n) {
334 : PetscAssertPointer_Private(a, 1);
335 : PetscAssertPointer_Private(b, 2);
336 : }
337 : #if PetscHasBuiltin(__builtin_strncmp)
338 : *t = __builtin_strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
339 : #else
340 : *t = strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
341 : #endif
342 : PetscFunctionReturn(PETSC_SUCCESS);
343 : }
344 :
345 : /*@C
346 : PetscStrrstr - Locates last occurrence of string in another string
347 :
348 : Not Collective, No Fortran Support
349 :
350 : Input Parameters:
351 : + a - pointer to string
352 : - b - string to find
353 :
354 : Output Parameter:
355 : . tmp - location of occurrence
356 :
357 : Level: intermediate
358 :
359 : .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
360 : `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
361 : `PetscStrcmp()`
362 : @*/
363 : static inline PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[])
364 : {
365 : const char *ltmp = PETSC_NULLPTR;
366 :
367 : PetscFunctionBegin;
368 : PetscAssertPointer_Private(a, 1);
369 : PetscAssertPointer_Private(b, 2);
370 : PetscAssertPointer_Private(tmp, 3);
371 : while (a) {
372 : #if PetscHasBuiltin(__builtin_strstr)
373 : a = (char *)__builtin_strstr(a, b);
374 : #else
375 : a = (char *)strstr(a, b);
376 : #endif
377 : if (a) ltmp = a++;
378 : }
379 : *tmp = (char *)ltmp;
380 : PetscFunctionReturn(PETSC_SUCCESS);
381 : }
382 :
383 : /*@C
384 : PetscStrstr - Locates first occurrence of string in another string
385 :
386 : Not Collective, No Fortran Support
387 :
388 : Input Parameters:
389 : + haystack - string to search
390 : - needle - string to find
391 :
392 : Output Parameter:
393 : . tmp - location of `needle` within `haystack`, `NULL` if `needle` is not found
394 :
395 : Level: intermediate
396 :
397 : .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
398 : `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
399 : `PetscStrcmp()`
400 : @*/
401 2 : static inline PetscErrorCode PetscStrstr(const char haystack[], const char needle[], char *tmp[])
402 : {
403 2 : PetscFunctionBegin;
404 2 : PetscAssertPointer_Private(haystack, 1);
405 2 : PetscAssertPointer_Private(needle, 2);
406 2 : PetscAssertPointer_Private(tmp, 3);
407 : #if PetscHasBuiltin(__builtin_strstr)
408 2 : *tmp = (char *)__builtin_strstr(haystack, needle);
409 : #else
410 : *tmp = (char *)strstr(haystack, needle);
411 : #endif
412 2 : PetscFunctionReturn(PETSC_SUCCESS);
413 : }
414 :
415 : /*@C
416 : PetscStrgrt - If first string is greater than the second
417 :
418 : Not Collective, No Fortran Support
419 :
420 : Input Parameters:
421 : + a - pointer to first string
422 : - b - pointer to second string
423 :
424 : Output Parameter:
425 : . flg - `PETSC_TRUE` if `a` is strictly greater than `b`, `PETSC_FALSE` otherwise
426 :
427 : Level: intermediate
428 :
429 : Note:
430 : `NULL` arguments are OK, a `NULL` string is considered smaller than all others. If both `a`
431 : and `b` are `NULL` then `t` is set to `PETSC_FALSE`.
432 :
433 : .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()`
434 : @*/
435 : static inline PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t)
436 : {
437 : PetscFunctionBegin;
438 : PetscAssertPointer_Private(t, 3);
439 : if (!a && !b) {
440 : *t = PETSC_FALSE;
441 : } else if (a && !b) {
442 : *t = PETSC_TRUE;
443 : } else if (!a && b) {
444 : *t = PETSC_FALSE;
445 : } else {
446 : #if PetscHasBuiltin(__builtin_strcmp)
447 : *t = __builtin_strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
448 : #else
449 : *t = strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
450 : #endif
451 : }
452 : PetscFunctionReturn(PETSC_SUCCESS);
453 : }
454 :
455 : /*@C
456 : PetscStrchr - Locates first occurrence of a character in a string
457 :
458 : Not Collective, No Fortran Support
459 :
460 : Input Parameters:
461 : + a - pointer to string
462 : - b - character
463 :
464 : Output Parameter:
465 : . c - location of occurrence, `NULL` if not found
466 :
467 : Level: intermediate
468 :
469 : .seealso: `PetscStrrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
470 : @*/
471 : static inline PetscErrorCode PetscStrchr(const char a[], char b, char *c[])
472 : {
473 : PetscFunctionBegin;
474 : PetscAssertPointer_Private(a, 1);
475 : PetscAssertPointer_Private(c, 3);
476 : #if PetscHasBuiltin(__builtin_strchr)
477 : *c = (char *)__builtin_strchr(a, b);
478 : #else
479 : *c = (char *)strchr(a, b);
480 : #endif
481 : PetscFunctionReturn(PETSC_SUCCESS);
482 : }
483 :
484 : /*@C
485 : PetscStrrchr - Locates one location past the last occurrence of a character in a string, if
486 : the character is not found then returns entire string
487 :
488 : Not Collective, No Fortran Support
489 :
490 : Input Parameters:
491 : + a - pointer to string
492 : - b - character
493 :
494 : Output Parameter:
495 : . c - one past location of `b` in `a`, or `a` if `b` was not found
496 :
497 : Level: intermediate
498 :
499 : .seealso: `PetscStrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
500 : @*/
501 : static inline PetscErrorCode PetscStrrchr(const char a[], char b, char *c[])
502 : {
503 : PetscFunctionBegin;
504 : PetscAssertPointer_Private(a, 1);
505 : PetscAssertPointer_Private(c, 3);
506 : #if PetscHasBuiltin(__builtin_strrchr)
507 : *c = (char *)__builtin_strrchr(a, b);
508 : #else
509 : *c = (char *)strrchr(a, b);
510 : #endif
511 : if (!*c) *c = (char *)a;
512 : else *c = *c + 1;
513 : PetscFunctionReturn(PETSC_SUCCESS);
514 : }
515 :
516 : /*@C
517 : PetscStrendswith - Determines if a string ends with a certain string
518 :
519 : Not Collective, No Fortran Support
520 :
521 : Input Parameters:
522 : + a - string to search
523 : - b - string to end with
524 :
525 : Output Parameter:
526 : . flg - `PETSC_TRUE` if `a` ends with `b`, `PETSC_FALSE` otherwise
527 :
528 : Level: intermediate
529 :
530 : Note:
531 : Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) bot not either.
532 :
533 : .seealso: `PetscStrendswithwhich()`, `PetscStrbeginswith()`, `PetscStrtoupper`,
534 : `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
535 : `PetscStrcmp()`
536 : @*/
537 3 : static inline PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg)
538 : {
539 3 : size_t na = 0, nb = 0;
540 :
541 3 : PetscFunctionBegin;
542 3 : PetscAssertPointer_Private(flg, 3);
543 : // do this here to silence stupid "may be used uninitialized"" warnings
544 3 : *flg = PETSC_FALSE;
545 3 : PetscCall(PetscStrlen(a, &na));
546 3 : PetscCall(PetscStrlen(b, &nb));
547 3 : if (na >= nb) {
548 : #if PetscHasBuiltin(__builtin_memcmp)
549 3 : *flg = __builtin_memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE;
550 : #else
551 : *flg = memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE;
552 : #endif
553 : }
554 3 : PetscFunctionReturn(PETSC_SUCCESS);
555 : }
556 :
557 : /*@C
558 : PetscStrbeginswith - Determines if a string begins with a certain string
559 :
560 : Not Collective, No Fortran Support
561 :
562 : Input Parameters:
563 : + a - string to search
564 : - b - string to begin with
565 :
566 : Output Parameter:
567 : . flg - `PETSC_TRUE` if `a` begins with `b`, `PETSC_FALSE` otherwise
568 :
569 : Level: intermediate
570 :
571 : Notes:
572 : Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) but not
573 : either.
574 :
575 : `a` and `b` may point to the same string.
576 :
577 : .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
578 : `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
579 : `PetscStrcmp()`
580 : @*/
581 : static inline PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg)
582 : {
583 : size_t len = 0;
584 :
585 : PetscFunctionBegin;
586 : PetscAssertPointer_Private(flg, 3);
587 : // do this here to silence stupid "may be used uninitialized"" warnings
588 : *flg = PETSC_FALSE;
589 : PetscCall(PetscStrlen(b, &len));
590 : PetscCall(PetscStrncmp(a, b, len, flg));
591 : PetscFunctionReturn(PETSC_SUCCESS);
592 : }
593 :
594 : #undef PetscAssertPointer_Private
595 :
596 : /*@C
597 : PetscMemmove - Copies `n` bytes, beginning at location `b`, to the space
598 : beginning at location `a`. Copying between regions that overlap will
599 : take place correctly. Use `PetscMemcpy()` if the locations do not overlap
600 :
601 : Not Collective, No Fortran Support
602 :
603 : Input Parameters:
604 : + b - pointer to initial memory space
605 : . a - pointer to copy space
606 : - n - length (in bytes) of space to copy
607 :
608 : Level: intermediate
609 :
610 : Notes:
611 : `PetscArraymove()` is preferred
612 :
613 : This routine is analogous to `memmove()`.
614 :
615 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscStrallocpy()`,
616 : `PetscArraymove()`
617 : @*/
618 : static inline PetscErrorCode PetscMemmove(void *a, const void *b, size_t n)
619 : {
620 : PetscFunctionBegin;
621 : if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
622 : PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to null pointer (Argument #1)", n);
623 : PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
624 : #if PetscDefined(HAVE_MEMMOVE)
625 : memmove((char *)a, (const char *)b, n);
626 : #else
627 : if (a < b) {
628 : if ((char *)a <= (char *)b - n) {
629 : memcpy(a, b, n);
630 : } else {
631 : const size_t ptr_diff = (size_t)((char *)b - (char *)a);
632 :
633 : memcpy(a, b, ptr_diff);
634 : PetscCall(PetscMemmove((void *)b, (char *)b + ptr_diff, n - ptr_diff));
635 : }
636 : } else {
637 : if ((char *)b <= (char *)a - n) {
638 : memcpy(a, b, n);
639 : } else {
640 : const size_t ptr_diff = (size_t)((char *)a - (char *)b);
641 :
642 : memcpy((void *)((char *)b + n), (char *)b + (n - ptr_diff), ptr_diff);
643 : PetscCall(PetscMemmove(a, b, n - ptr_diff));
644 : }
645 : }
646 : #endif
647 : PetscFunctionReturn(PETSC_SUCCESS);
648 : }
649 :
650 : /*@C
651 : PetscMemcpy - Copies `n` bytes, beginning at location `b`, to the space
652 : beginning at location `a`. The two memory regions CANNOT overlap, use
653 : `PetscMemmove()` in that case.
654 :
655 : Not Collective, No Fortran Support
656 :
657 : Input Parameters:
658 : + b - pointer to initial memory space
659 : - n - length (in bytes) of space to copy
660 :
661 : Output Parameter:
662 : . a - pointer to copy space
663 :
664 : Level: intermediate
665 :
666 : Compile Options\:
667 : + `PETSC_PREFER_DCOPY_FOR_MEMCPY` - cause the BLAS `dcopy()` routine to be used for memory copies on double precision values.
668 : . `PETSC_PREFER_COPY_FOR_MEMCPY` - cause C code to be used for memory copies on double precision values.
669 : - `PETSC_PREFER_FORTRAN_FORMEMCPY` - cause Fortran code to be used for memory copies on double precision values.
670 :
671 : Notes:
672 : Prefer `PetscArraycpy()`
673 :
674 : This routine is analogous to `memcpy()`.
675 :
676 : .seealso: `PetscMemzero()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
677 : @*/
678 2115568 : static inline PetscErrorCode PetscMemcpy(void *a, const void *b, size_t n)
679 : {
680 2115568 : const PETSC_UINTPTR_T al = (PETSC_UINTPTR_T)a;
681 2115568 : const PETSC_UINTPTR_T bl = (PETSC_UINTPTR_T)b;
682 :
683 2115568 : PetscFunctionBegin;
684 2115568 : if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
685 2110623 : PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to a null pointer (Argument #1)", n);
686 2110623 : PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
687 2110623 : PetscAssert(!(((al > bl) && (al - bl) < n) || (bl - al) < n), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Memory regions overlap: either use PetscMemmove(), or make sure your copy regions and lengths are correct. Length (bytes) %zu first address %" PRIxPTR " second address %" PRIxPTR, n, al, bl);
688 2110623 : if (PetscDefined(PREFER_DCOPY_FOR_MEMCPY) || PetscDefined(PREFER_COPY_FOR_MEMCPY) || PetscDefined(PREFER_FORTRAN_FORMEMCPY)) {
689 : if (!(al % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
690 : const size_t scalar_len = n / sizeof(PetscScalar);
691 : const PetscScalar *x = (PetscScalar *)b;
692 : PetscScalar *y = (PetscScalar *)a;
693 :
694 : #if PetscDefined(PREFER_DCOPY_FOR_MEMCPY)
695 : {
696 : const PetscBLASInt one = 1;
697 : PetscBLASInt blen;
698 :
699 : PetscCall(PetscBLASIntCast(scalar_len, &blen));
700 : PetscCallBLAS("BLAScopy", BLAScopy_(&blen, x, &one, y, &one));
701 : }
702 : #elif PetscDefined(PREFER_FORTRAN_FORMEMCPY)
703 : fortrancopy_(&scalar_len, x, y);
704 : #else
705 : for (size_t i = 0; i < scalar_len; i++) y[i] = x[i];
706 : #endif
707 2110623 : PetscFunctionReturn(PETSC_SUCCESS);
708 : }
709 : }
710 2110623 : memcpy(a, b, n);
711 2110623 : PetscFunctionReturn(PETSC_SUCCESS);
712 : }
713 :
714 : /*@C
715 : PetscMemzero - Zeros the specified memory.
716 :
717 : Not Collective, No Fortran Support
718 :
719 : Input Parameters:
720 : + a - pointer to beginning memory location
721 : - n - length (in bytes) of memory to initialize
722 :
723 : Level: intermediate
724 :
725 : Compile Option:
726 : `PETSC_PREFER_BZERO` - on certain machines (the IBM RS6000) the bzero() routine happens
727 : to be faster than the memset() routine. This flag causes the bzero() routine to be used.
728 :
729 : Note:
730 : Prefer `PetscArrayzero()`
731 :
732 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
733 : @*/
734 547302 : static inline PetscErrorCode PetscMemzero(void *a, size_t n)
735 : {
736 547302 : PetscFunctionBegin;
737 547302 : if (PetscUnlikely(n == 0)) PetscFunctionReturn(PETSC_SUCCESS);
738 547299 : PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to zero %zu bytes at a null pointer", n);
739 547299 : if (PetscDefined(PREFER_ZERO_FOR_MEMZERO) || PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)) {
740 : if (!(((PETSC_UINTPTR_T)a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
741 : const size_t scalar_len = n / sizeof(PetscScalar);
742 : PetscScalar *x = (PetscScalar *)a;
743 :
744 : if (PetscDefined(PREFER_ZERO_FOR_MEMZERO)) {
745 : for (size_t i = 0; i < scalar_len; ++i) x[i] = 0;
746 : } else {
747 : #if PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)
748 : fortranzero_(&scalar_len, x);
749 : #else
750 : (void)scalar_len;
751 : (void)x;
752 : #endif
753 : }
754 547299 : PetscFunctionReturn(PETSC_SUCCESS);
755 : }
756 : }
757 : #if PetscDefined(PREFER_BZERO)
758 : bzero(a, n);
759 : #else
760 547299 : memset(a, 0, n);
761 : #endif
762 547299 : PetscFunctionReturn(PETSC_SUCCESS);
763 : }
764 :
765 : /*MC
766 : PetscArraycmp - Compares two arrays in memory.
767 :
768 : Synopsis:
769 : #include <petscstring.h>
770 : PetscErrorCode PetscArraycmp(const anytype *str1, const anytype *str2, size_t cnt, PetscBool *e)
771 :
772 : Not Collective
773 :
774 : Input Parameters:
775 : + str1 - First array
776 : . str2 - Second array
777 : - cnt - Count of the array, not in bytes, but number of entries in the arrays
778 :
779 : Output Parameter:
780 : . e - `PETSC_TRUE` if equal else `PETSC_FALSE`.
781 :
782 : Level: intermediate
783 :
784 : Notes:
785 : This routine is a preferred replacement to `PetscMemcmp()`
786 :
787 : The arrays must be of the same type
788 :
789 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`,
790 : `PetscArraymove()`
791 : M*/
792 : #define PetscArraycmp(str1, str2, cnt, e) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcmp((str1), (str2), (size_t)(cnt) * sizeof(*(str1)), (e)) : PETSC_ERR_ARG_SIZ)
793 :
794 : /*MC
795 : PetscArraymove - Copies from one array in memory to another, the arrays may overlap. Use `PetscArraycpy()` when the arrays
796 : do not overlap
797 :
798 : Synopsis:
799 : #include <petscstring.h>
800 : PetscErrorCode PetscArraymove(anytype *str1, const anytype *str2, size_t cnt)
801 :
802 : Not Collective
803 :
804 : Input Parameters:
805 : + str1 - First array
806 : . str2 - Second array
807 : - cnt - Count of the array, not in bytes, but number of entries in the arrays
808 :
809 : Level: intermediate
810 :
811 : Notes:
812 : This routine is a preferred replacement to `PetscMemmove()`
813 :
814 : The arrays must be of the same type
815 :
816 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()`
817 : M*/
818 : #define PetscArraymove(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemmove((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ)
819 :
820 : /*MC
821 : PetscArraycpy - Copies from one array in memory to another
822 :
823 : Synopsis:
824 : #include <petscstring.h>
825 : PetscErrorCode PetscArraycpy(anytype *str1, const anytype *str2, size_t cnt)
826 :
827 : Not Collective
828 :
829 : Input Parameters:
830 : + str1 - First array (destination)
831 : . str2 - Second array (source)
832 : - cnt - Count of the array, not in bytes, but number of entries in the arrays
833 :
834 : Level: intermediate
835 :
836 : Notes:
837 : This routine is a preferred replacement to `PetscMemcpy()`
838 :
839 : The arrays must be of the same type
840 :
841 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraymove()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()`
842 : M*/
843 : #define PetscArraycpy(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcpy((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ)
844 :
845 : /*MC
846 : PetscArrayzero - Zeros an array in memory.
847 :
848 : Synopsis:
849 : #include <petscstring.h>
850 : PetscErrorCode PetscArrayzero(anytype *str1, size_t cnt)
851 :
852 : Not Collective
853 :
854 : Input Parameters:
855 : + str1 - array
856 : - cnt - Count of the array, not in bytes, but number of entries in the array
857 :
858 : Level: intermediate
859 :
860 : Note:
861 : This routine is a preferred replacement to `PetscMemzero()`
862 :
863 : .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`, `PetscArraymove()`
864 : M*/
865 : #define PetscArrayzero(str1, cnt) PetscMemzero((str1), ((size_t)(cnt)) * sizeof(*(str1)))
|