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: PETSC_EXTERN PetscErrorCode PetscStrcat(char[], const char[]);
35: PETSC_EXTERN PetscErrorCode PetscStrcpy(char[], const char[]);
37: #define PetscAssertPointer_Private(ptr, arg) PetscAssert((ptr), PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null Pointer: Parameter '" PetscStringize(ptr) "' # " PetscStringize(arg))
39: /*@C
40: PetscStrtolower - Converts string to lower case
42: Not Collective, No Fortran Support
44: Input Parameter:
45: . a - pointer to string
47: Level: intermediate
49: .seealso: `PetscStrtoupper()`
50: @*/
51: static inline PetscErrorCode PetscStrtolower(char a[])
52: {
53: PetscFunctionBegin;
54: PetscAssertPointer_Private(a, 1);
55: while (*a) {
56: if (*a >= 'A' && *a <= 'Z') *a += 'a' - 'A';
57: a++;
58: }
59: PetscFunctionReturn(PETSC_SUCCESS);
60: }
62: /*@C
63: PetscStrtoupper - Converts string to upper case
65: Not Collective, No Fortran Support
67: Input Parameter:
68: . a - pointer to string
70: Level: intermediate
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: }
85: /*@C
86: PetscStrlen - Gets length of a string
88: Not Collective, No Fortran Support
90: Input Parameter:
91: . s - pointer to string
93: Output Parameter:
94: . len - length in bytes
96: Level: intermediate
98: Notes:
99: This routine is analogous to `strlen()`. `NULL` string returns a length of zero.
101: .seealso: `PetscStrallocpy()`
102: @*/
103: static inline PetscErrorCode PetscStrlen(const char s[], size_t *len)
104: {
105: PetscFunctionBegin;
106: PetscAssertPointer_Private(len, 2);
107: if (s) {
108: #if PetscHasBuiltin(__builtin_strlen)
109: *len = __builtin_strlen(s);
110: #else
111: *len = strlen(s);
112: #endif
113: } else {
114: *len = 0;
115: }
116: PetscFunctionReturn(PETSC_SUCCESS);
117: }
119: /*@C
120: PetscStrallocpy - Allocates space to hold a copy of a string then copies the string in the new space
122: Not Collective, No Fortran Support
124: Input Parameter:
125: . s - pointer to string
127: Output Parameter:
128: . t - the copied string
130: Level: intermediate
132: Notes:
133: `NULL` string returns a new `NULL` string.
135: If `t` has previously been allocated then that memory is lost, you may need to `PetscFree()`
136: the array before calling this routine.
138: .seealso: `PetscStrArrayallocpy()`, `PetscStrNArrayallocpy()`
139: @*/
140: static inline PetscErrorCode PetscStrallocpy(const char s[], char *t[])
141: {
142: PetscFunctionBegin;
143: PetscAssertPointer_Private(t, 2);
144: *t = PETSC_NULLPTR;
145: if (s) {
146: size_t len;
147: char *tmp;
149: PetscAssertPointer_Private(s, 1);
150: PetscCall(PetscStrlen(s, &len));
151: PetscCall(PetscMalloc1(len + 1, &tmp));
152: #if PetscHasBuiltin(__builtin_memcpy)
153: __builtin_memcpy(tmp, s, len);
154: #else
155: memcpy(tmp, s, len);
156: #endif
157: tmp[len] = '\0';
158: *t = tmp;
159: }
160: PetscFunctionReturn(PETSC_SUCCESS);
161: }
163: static inline void PetscStrcmpNoError(const char a[], const char b[], PetscBool *flg)
164: {
165: if (!a && !b) {
166: *flg = PETSC_TRUE;
167: } else if (!a || !b) {
168: *flg = PETSC_FALSE;
169: } else {
170: #if PetscHasBuiltin(__builtin_strcmp)
171: *flg = __builtin_strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
172: #else
173: *flg = strcmp(a, b) ? PETSC_FALSE : PETSC_TRUE;
174: #endif
175: }
176: }
178: /*@C
179: PetscStrcmp - Compares two strings,
181: Not Collective, No Fortran Support
183: Input Parameters:
184: + a - pointer to string first string
185: - b - pointer to second string
187: Output Parameter:
188: . flg - `PETSC_TRUE` if the two strings are equal
190: Level: intermediate
192: .seealso: `PetscStrgrt()`, `PetscStrncmp()`, `PetscStrcasecmp()`
193: @*/
194: static inline PetscErrorCode PetscStrcmp(const char a[], const char b[], PetscBool *flg)
195: {
196: PetscFunctionBegin;
197: PetscAssertPointer_Private(flg, 3);
198: PetscStrcmpNoError(a, b, flg);
199: PetscFunctionReturn(PETSC_SUCCESS);
200: }
202: #if defined(__GNUC__) && !defined(__clang__)
203: #if __GNUC__ >= 8
204: #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN \
205: do { \
206: _Pragma("GCC diagnostic push"); \
207: _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\""); \
208: } while (0)
209: #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END _Pragma("GCC diagnostic pop")
210: #endif
211: #endif
213: #ifndef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
214: #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN (void)0
215: #define PETSC_SILENCE_WSTRINGOP_TRUNCATION_END (void)0
216: #endif
218: /*@C
219: PetscStrncpy - Copies a string up to a certain length
221: Not Collective
223: Input Parameters:
224: + t - pointer to string
225: - n - the length to copy
227: Output Parameter:
228: . s - the copied string
230: Level: intermediate
232: Notes:
233: `NULL` string returns a string starting with zero.
235: If the string that is being copied is of length `n` or larger, then the entire string is not
236: copied and the final location of `s` is set to `NULL`. This is different then the behavior of
237: `strncpy()` which leaves `s` non-terminated if there is not room for the entire string.
239: Developers Notes:
240: Should this be `PetscStrlcpy()` to reflect its behavior which is like `strlcpy()` not
241: `strncpy()`?
243: .seealso: `PetscStrlcat()`, `PetscStrallocpy()`
244: @*/
245: static inline PetscErrorCode PetscStrncpy(char s[], const char t[], size_t n)
246: {
247: PetscFunctionBegin;
248: 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");
249: if (t) {
250: PetscAssertPointer_Private(s, 1);
251: PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN;
252: #if PetscHasBuiltin(__builtin_strncpy)
253: __builtin_strncpy(s, t, n);
254: #else
255: strncpy(s, t, n);
256: #endif
257: PETSC_SILENCE_WSTRINGOP_TRUNCATION_END;
258: s[n - 1] = '\0';
259: } else if (s) {
260: s[0] = '\0';
261: }
262: PetscFunctionReturn(PETSC_SUCCESS);
263: }
265: /*@C
266: PetscStrlcat - Concatenates a string onto a given string, up to a given length
268: Not Collective, No Fortran Support
270: Input Parameters:
271: + s - pointer to string to be added to at end
272: . t - string to be added
273: - n - length of the original allocated string
275: Level: intermediate
277: Notes:
278: Unlike the system call `strncat()`, the length passed in is the length of the
279: original allocated space, not the length of the left-over space. This is
280: similar to the BSD system call `strlcat()`.
282: .seealso: `PetscStrncpy()`
283: @*/
284: static inline PetscErrorCode PetscStrlcat(char s[], const char t[], size_t n)
285: {
286: size_t len;
288: PetscFunctionBegin;
289: if (!t) PetscFunctionReturn(PETSC_SUCCESS);
290: PetscAssert(n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "String buffer length must be positive");
291: PetscCall(PetscStrlen(s, &len));
292: PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN;
293: #if PetscHasBuiltin(__builtin_strncat)
294: __builtin_strncat(s, t, n - len);
295: #else
296: strncat(s, t, n - len);
297: #endif
298: PETSC_SILENCE_WSTRINGOP_TRUNCATION_END;
299: s[n - 1] = '\0';
300: PetscFunctionReturn(PETSC_SUCCESS);
301: }
303: #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_BEGIN
304: #undef PETSC_SILENCE_WSTRINGOP_TRUNCATION_END
306: /*@C
307: PetscStrncmp - Compares two strings, up to a certain length
309: Not Collective, No Fortran Support
311: Input Parameters:
312: + a - pointer to first string
313: . b - pointer to second string
314: - n - length to compare up to
316: Output Parameter:
317: . t - `PETSC_TRUE` if the two strings are equal, `PETSC_FALSE` otherwise
319: Level: intermediate
321: Notes:
322: If `n` is `0`, `t` is set to `PETSC_FALSE`. `a` and/or `b` may be `NULL` in this case.
324: .seealso: `PetscStrgrt()`, `PetscStrcmp()`, `PetscStrcasecmp()`
325: @*/
326: static inline PetscErrorCode PetscStrncmp(const char a[], const char b[], size_t n, PetscBool *t)
327: {
328: PetscFunctionBegin;
329: PetscAssertPointer_Private(t, 4);
330: *t = PETSC_FALSE;
331: if (n) {
332: PetscAssertPointer_Private(a, 1);
333: PetscAssertPointer_Private(b, 2);
334: }
335: #if PetscHasBuiltin(__builtin_strncmp)
336: *t = __builtin_strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
337: #else
338: *t = strncmp(a, b, n) ? PETSC_FALSE : PETSC_TRUE;
339: #endif
340: PetscFunctionReturn(PETSC_SUCCESS);
341: }
343: /*@C
344: PetscStrrstr - Locates last occurrence of string in another string
346: Not Collective, No Fortran Support
348: Input Parameters:
349: + a - pointer to string
350: - b - string to find
352: Output Parameter:
353: . tmp - location of occurrence
355: Level: intermediate
357: .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
358: `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
359: `PetscStrcmp()`
360: @*/
361: static inline PetscErrorCode PetscStrrstr(const char a[], const char b[], char *tmp[])
362: {
363: const char *ltmp = PETSC_NULLPTR;
365: PetscFunctionBegin;
366: PetscAssertPointer_Private(a, 1);
367: PetscAssertPointer_Private(b, 2);
368: PetscAssertPointer_Private(tmp, 3);
369: while (a) {
370: #if PetscHasBuiltin(__builtin_strstr)
371: a = (char *)__builtin_strstr(a, b);
372: #else
373: a = (char *)strstr(a, b);
374: #endif
375: if (a) ltmp = a++;
376: }
377: *tmp = (char *)ltmp;
378: PetscFunctionReturn(PETSC_SUCCESS);
379: }
381: /*@C
382: PetscStrstr - Locates first occurrence of string in another string
384: Not Collective, No Fortran Support
386: Input Parameters:
387: + haystack - string to search
388: - needle - string to find
390: Output Parameter:
391: . tmp - location of `needle` within `haystack`, `NULL` if `needle` is not found
393: Level: intermediate
395: .seealso: `PetscStrbeginswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
396: `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
397: `PetscStrcmp()`
398: @*/
399: static inline PetscErrorCode PetscStrstr(const char haystack[], const char needle[], char *tmp[])
400: {
401: PetscFunctionBegin;
402: PetscAssertPointer_Private(haystack, 1);
403: PetscAssertPointer_Private(needle, 2);
404: PetscAssertPointer_Private(tmp, 3);
405: #if PetscHasBuiltin(__builtin_strstr)
406: *tmp = (char *)__builtin_strstr(haystack, needle);
407: #else
408: *tmp = (char *)strstr(haystack, needle);
409: #endif
410: PetscFunctionReturn(PETSC_SUCCESS);
411: }
413: /*@C
414: PetscStrgrt - If first string is greater than the second
416: Not Collective, No Fortran Support
418: Input Parameters:
419: + a - pointer to first string
420: - b - pointer to second string
422: Output Parameter:
423: . flg - `PETSC_TRUE` if `a` is strictly greater than `b`, `PETSC_FALSE` otherwise
425: Level: intermediate
427: Notes:
428: `NULL` arguments are OK, a `NULL` string is considered smaller than all others. If both `a`
429: and `b` are `NULL` then `t` is set to `PETSC_FALSE`.
431: .seealso: `PetscStrcmp()`, `PetscStrncmp()`, `PetscStrcasecmp()`
432: @*/
433: static inline PetscErrorCode PetscStrgrt(const char a[], const char b[], PetscBool *t)
434: {
435: PetscFunctionBegin;
436: PetscAssertPointer_Private(t, 3);
437: if (!a && !b) {
438: *t = PETSC_FALSE;
439: } else if (a && !b) {
440: *t = PETSC_TRUE;
441: } else if (!a && b) {
442: *t = PETSC_FALSE;
443: } else {
444: #if PetscHasBuiltin(__builtin_strcmp)
445: *t = __builtin_strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
446: #else
447: *t = strcmp(a, b) > 0 ? PETSC_TRUE : PETSC_FALSE;
448: #endif
449: }
450: PetscFunctionReturn(PETSC_SUCCESS);
451: }
453: /*@C
454: PetscStrchr - Locates first occurrence of a character in a string
456: Not Collective, No Fortran Support
458: Input Parameters:
459: + a - pointer to string
460: - b - character
462: Output Parameter:
463: . c - location of occurrence, `NULL` if not found
465: Level: intermediate
467: .seealso: `PetscStrrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
468: @*/
469: static inline PetscErrorCode PetscStrchr(const char a[], char b, char *c[])
470: {
471: PetscFunctionBegin;
472: PetscAssertPointer_Private(a, 1);
473: PetscAssertPointer_Private(c, 3);
474: #if PetscHasBuiltin(__builtin_strchr)
475: *c = (char *)__builtin_strchr(a, b);
476: #else
477: *c = (char *)strchr(a, b);
478: #endif
479: PetscFunctionReturn(PETSC_SUCCESS);
480: }
482: /*@C
483: PetscStrrchr - Locates one location past the last occurrence of a character in a string, if
484: the character is not found then returns entire string
486: Not Collective, No Fortran Support
488: Input Parameters:
489: + a - pointer to string
490: - b - character
492: Output Parameter:
493: . c - one past location of `b` in `a`, or `a` if `b` was not found
495: Level: intermediate
497: .seealso: `PetscStrchr()`, `PetscTokenCreate()`, `PetscStrendswith()`, `PetscStrbeginsswith()`
498: @*/
499: static inline PetscErrorCode PetscStrrchr(const char a[], char b, char *c[])
500: {
501: PetscFunctionBegin;
502: PetscAssertPointer_Private(a, 1);
503: PetscAssertPointer_Private(c, 3);
504: #if PetscHasBuiltin(__builtin_strrchr)
505: *c = (char *)__builtin_strrchr(a, b);
506: #else
507: *c = (char *)strrchr(a, b);
508: #endif
509: if (!*c) *c = (char *)a;
510: else *c = *c + 1;
511: PetscFunctionReturn(PETSC_SUCCESS);
512: }
514: /*@C
515: PetscStrendswith - Determines if a string ends with a certain string
517: Not Collective, No Fortran Support
519: Input Parameters:
520: + a - string to search
521: - b - string to end with
523: Output Parameter:
524: . flg - `PETSC_TRUE` if `a` ends with `b`, `PETSC_FALSE` otherwise
526: Level: intermediate
528: Notes:
529: Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) bot not either.
531: .seealso: `PetscStrendswithwhich()`, `PetscStrbeginswith()`, `PetscStrtoupper`,
532: `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
533: `PetscStrcmp()`
534: @*/
535: static inline PetscErrorCode PetscStrendswith(const char a[], const char b[], PetscBool *flg)
536: {
537: size_t na = 0, nb = 0;
539: PetscFunctionBegin;
540: PetscAssertPointer_Private(flg, 3);
541: // do this here to silence stupid "may be used uninitialized"" warnings
542: *flg = PETSC_FALSE;
543: PetscCall(PetscStrlen(a, &na));
544: PetscCall(PetscStrlen(b, &nb));
545: if (na >= nb) {
546: #if PetscHasBuiltin(__builtin_memcmp)
547: *flg = __builtin_memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE;
548: #else
549: *flg = memcmp(b, a + (na - nb), nb) == 0 ? PETSC_TRUE : PETSC_FALSE;
550: #endif
551: }
552: PetscFunctionReturn(PETSC_SUCCESS);
553: }
555: /*@C
556: PetscStrbeginswith - Determines if a string begins with a certain string
558: Not Collective, No Fortran Support
560: Input Parameters:
561: + a - string to search
562: - b - string to begin with
564: Output Parameter:
565: . flg - `PETSC_TRUE` if `a` begins with `b`, `PETSC_FALSE` otherwise
567: Level: intermediate
569: Notes:
570: Both `a` and `b` may be `NULL` (in which case `flg` is set to `PETSC_FALSE`) but not
571: either. Both `a` and `b` may point to the same string.
573: .seealso: `PetscStrendswithwhich()`, `PetscStrendswith()`, `PetscStrtoupper`,
574: `PetscStrtolower()`, `PetscStrrchr()`, `PetscStrchr()`, `PetscStrncmp()`, `PetscStrlen()`,
575: `PetscStrcmp()`
576: @*/
577: static inline PetscErrorCode PetscStrbeginswith(const char a[], const char b[], PetscBool *flg)
578: {
579: size_t len = 0;
581: PetscFunctionBegin;
582: PetscAssertPointer_Private(flg, 3);
583: // do this here to silence stupid "may be used uninitialized"" warnings
584: *flg = PETSC_FALSE;
585: PetscCall(PetscStrlen(b, &len));
586: PetscCall(PetscStrncmp(a, b, len, flg));
587: PetscFunctionReturn(PETSC_SUCCESS);
588: }
590: #undef PetscAssertPointer_Private
592: /*@C
593: PetscMemmove - Copies n bytes, beginning at location b, to the space
594: beginning at location a. Copying between regions that overlap will
595: take place correctly. Use `PetscMemcpy()` if the locations do not overlap
597: Not Collective
599: Input Parameters:
600: + b - pointer to initial memory space
601: . a - pointer to copy space
602: - n - length (in bytes) of space to copy
604: Level: intermediate
606: Notes:
607: `PetscArraymove()` is preferred
609: This routine is analogous to `memmove()`.
611: Developers Notes:
612: This is inlined for performance
614: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscStrallocpy()`,
615: `PetscArraymove()`
616: @*/
617: static inline PetscErrorCode PetscMemmove(void *a, const void *b, size_t n)
618: {
619: PetscFunctionBegin;
620: if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
621: PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to null pointer (Argument #1)", n);
622: PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
623: #if PetscDefined(HAVE_MEMMOVE)
624: memmove((char *)a, (const char *)b, n);
625: #else
626: if (a < b) {
627: if ((char *)a <= (char *)b - n) {
628: memcpy(a, b, n);
629: } else {
630: const size_t ptr_diff = (size_t)((char *)b - (char *)a);
632: memcpy(a, b, ptr_diff);
633: PetscCall(PetscMemmove((void *)b, (char *)b + ptr_diff, n - ptr_diff));
634: }
635: } else {
636: if ((char *)b <= (char *)a - n) {
637: memcpy(a, b, n);
638: } else {
639: const size_t ptr_diff = (size_t)((char *)a - (char *)b);
641: memcpy((void *)((char *)b + n), (char *)b + (n - ptr_diff), ptr_diff);
642: PetscCall(PetscMemmove(a, b, n - ptr_diff));
643: }
644: }
645: #endif
646: PetscFunctionReturn(PETSC_SUCCESS);
647: }
649: /*@C
650: PetscMemcpy - Copies n bytes, beginning at location b, to the space
651: beginning at location a. The two memory regions CANNOT overlap, use
652: `PetscMemmove()` in that case.
654: Not Collective
656: Input Parameters:
657: + b - pointer to initial memory space
658: - n - length (in bytes) of space to copy
660: Output Parameter:
661: . a - pointer to copy space
663: Level: intermediate
665: Compile Option:
666: `PETSC_PREFER_DCOPY_FOR_MEMCPY` will cause the BLAS dcopy() routine to be used
667: for memory copies on double precision values.
668: `PETSC_PREFER_COPY_FOR_MEMCPY` will cause C code to be used
669: for memory copies on double precision values.
670: `PETSC_PREFER_FORTRAN_FORMEMCPY` will cause Fortran code to be used
671: for memory copies on double precision values.
673: Notes:
674: Prefer `PetscArraycpy()`
676: This routine is analogous to `memcpy()`.
678: Developer Notes:
679: This is inlined for fastest performance
681: .seealso: `PetscMemzero()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
682: @*/
683: static inline PetscErrorCode PetscMemcpy(void *a, const void *b, size_t n)
684: {
685: const PETSC_UINTPTR_T al = (PETSC_UINTPTR_T)a;
686: const PETSC_UINTPTR_T bl = (PETSC_UINTPTR_T)b;
688: PetscFunctionBegin;
689: if (PetscUnlikely((n == 0) || (a == b))) PetscFunctionReturn(PETSC_SUCCESS);
690: PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes to a null pointer (Argument #1)", n);
691: PetscAssert(b, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to copy %zu bytes from a null pointer (Argument #2)", n);
692: 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);
693: if (PetscDefined(PREFER_DCOPY_FOR_MEMCPY) || PetscDefined(PREFER_COPY_FOR_MEMCPY) || PetscDefined(PREFER_FORTRAN_FORMEMCPY)) {
694: if (!(al % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
695: const size_t scalar_len = n / sizeof(PetscScalar);
696: const PetscScalar *x = (PetscScalar *)b;
697: PetscScalar *y = (PetscScalar *)a;
699: #if PetscDefined(PREFER_DCOPY_FOR_MEMCPY)
700: {
701: const PetscBLASInt one = 1;
702: PetscBLASInt blen;
704: PetscCall(PetscBLASIntCast(scalar_len, &blen));
705: PetscCallBLAS("BLAScopy", BLAScopy_(&blen, x, &one, y, &one));
706: }
707: #elif PetscDefined(PREFER_FORTRAN_FORMEMCPY)
708: fortrancopy_(&scalar_len, x, y);
709: #else
710: for (size_t i = 0; i < scalar_len; i++) y[i] = x[i];
711: #endif
712: PetscFunctionReturn(PETSC_SUCCESS);
713: }
714: }
715: memcpy(a, b, n);
716: PetscFunctionReturn(PETSC_SUCCESS);
717: }
719: /*@C
720: PetscMemzero - Zeros the specified memory.
722: Not Collective
724: Input Parameters:
725: + a - pointer to beginning memory location
726: - n - length (in bytes) of memory to initialize
728: Level: intermediate
730: Compile Option:
731: `PETSC_PREFER_BZERO` - on certain machines (the IBM RS6000) the bzero() routine happens
732: to be faster than the memset() routine. This flag causes the bzero() routine to be used.
734: Notes:
735: Prefer `PetscArrayzero()`
737: Developer Notes:
738: This is inlined for fastest performance
740: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`
741: @*/
742: static inline PetscErrorCode PetscMemzero(void *a, size_t n)
743: {
744: PetscFunctionBegin;
745: if (PetscUnlikely(n == 0)) PetscFunctionReturn(PETSC_SUCCESS);
746: PetscAssert(a, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Trying to zero %zu bytes at a null pointer", n);
747: if (PetscDefined(PREFER_ZERO_FOR_MEMZERO) || PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)) {
748: if (!(((PETSC_UINTPTR_T)a) % sizeof(PetscScalar)) && !(n % sizeof(PetscScalar))) {
749: const size_t scalar_len = n / sizeof(PetscScalar);
750: PetscScalar *x = (PetscScalar *)a;
752: if (PetscDefined(PREFER_ZERO_FOR_MEMZERO)) {
753: for (size_t i = 0; i < scalar_len; ++i) x[i] = 0;
754: } else {
755: #if PetscDefined(PREFER_FORTRAN_FOR_MEMZERO)
756: fortranzero_(&scalar_len, x);
757: #else
758: (void)scalar_len;
759: (void)x;
760: #endif
761: }
762: PetscFunctionReturn(PETSC_SUCCESS);
763: }
764: }
765: #if PetscDefined(PREFER_BZERO)
766: bzero(a, n);
767: #else
768: memset(a, 0, n);
769: #endif
770: PetscFunctionReturn(PETSC_SUCCESS);
771: }
773: /*MC
774: PetscArraycmp - Compares two arrays in memory.
776: Synopsis:
777: #include <petscstring.h>
778: PetscErrorCode PetscArraycmp(const anytype *str1,const anytype *str2,size_t cnt,PetscBool *e)
780: Not Collective
782: Input Parameters:
783: + str1 - First array
784: . str2 - Second array
785: - cnt - Count of the array, not in bytes, but number of entries in the arrays
787: Output Parameter:
788: . e - `PETSC_TRUE` if equal else `PETSC_FALSE`.
790: Level: intermediate
792: Notes:
793: This routine is a preferred replacement to `PetscMemcmp()`
795: The arrays must be of the same type
797: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`,
798: `PetscArraymove()`
799: M*/
800: #define PetscArraycmp(str1, str2, cnt, e) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcmp((str1), (str2), (size_t)(cnt) * sizeof(*(str1)), (e)) : PETSC_ERR_ARG_SIZ)
802: /*MC
803: PetscArraymove - Copies from one array in memory to another, the arrays may overlap. Use `PetscArraycpy()` when the arrays
804: do not overlap
806: Synopsis:
807: #include <petscstring.h>
808: PetscErrorCode PetscArraymove(anytype *str1,const anytype *str2,size_t cnt)
810: Not Collective
812: Input Parameters:
813: + str1 - First array
814: . str2 - Second array
815: - cnt - Count of the array, not in bytes, but number of entries in the arrays
817: Level: intermediate
819: Notes:
820: This routine is a preferred replacement to `PetscMemmove()`
822: The arrays must be of the same type
824: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()`
825: M*/
826: #define PetscArraymove(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemmove((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ)
828: /*MC
829: PetscArraycpy - Copies from one array in memory to another
831: Synopsis:
832: #include <petscstring.h>
833: PetscErrorCode PetscArraycpy(anytype *str1,const anytype *str2,size_t cnt)
835: Not Collective
837: Input Parameters:
838: + str1 - First array (destination)
839: . str2 - Second array (source)
840: - cnt - Count of the array, not in bytes, but number of entries in the arrays
842: Level: intermediate
844: Notes:
845: This routine is a preferred replacement to `PetscMemcpy()`
847: The arrays must be of the same type
849: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscArrayzero()`, `PetscMemzero()`, `PetscArraymove()`, `PetscMemmove()`, `PetscArraycmp()`, `PetscStrallocpy()`
850: M*/
851: #define PetscArraycpy(str1, str2, cnt) ((sizeof(*(str1)) == sizeof(*(str2))) ? PetscMemcpy((str1), (str2), (size_t)(cnt) * sizeof(*(str1))) : PETSC_ERR_ARG_SIZ)
853: /*MC
854: PetscArrayzero - Zeros an array in memory.
856: Synopsis:
857: #include <petscstring.h>
858: PetscErrorCode PetscArrayzero(anytype *str1,size_t cnt)
860: Not Collective
862: Input Parameters:
863: + str1 - array
864: - cnt - Count of the array, not in bytes, but number of entries in the array
866: Level: intermediate
868: Notes:
869: This routine is a preferred replacement to `PetscMemzero()`
871: .seealso: `PetscMemcpy()`, `PetscMemcmp()`, `PetscMemzero()`, `PetscArraycmp()`, `PetscArraycpy()`, `PetscMemmove()`, `PetscStrallocpy()`, `PetscArraymove()`
872: M*/
873: #define PetscArrayzero(str1, cnt) PetscMemzero((str1), (size_t)(cnt) * sizeof(*(str1)))
875: #endif // PETSC_STRING_H