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