|
21 | 21 | #include <drmaa_utils/exception.h> |
22 | 22 | #include <slurm_drmaa/util.h> |
23 | 23 | #include <string.h> |
| 24 | +#include <stdlib.h> |
| 25 | +#include <stddef.h> |
24 | 26 |
|
25 | 27 | #include <time.h> |
26 | 28 | #include <drmaa_utils/datetime.h> |
@@ -723,3 +725,87 @@ slurmdrmaa_set_cluster(const char * value) |
723 | 725 |
|
724 | 726 | fsd_log_return(( "" )); |
725 | 727 | } |
| 728 | + |
| 729 | +// https://creativeandcritical.net/str-replace-c |
| 730 | +char *repl_str(const char *str, const char *from, const char *to) { |
| 731 | + |
| 732 | + /* Adjust each of the below values to suit your needs. */ |
| 733 | + |
| 734 | + /* Increment positions cache size initially by this number. */ |
| 735 | + size_t cache_sz_inc = 16; |
| 736 | + /* Thereafter, each time capacity needs to be increased, |
| 737 | + * multiply the increment by this factor. */ |
| 738 | + const size_t cache_sz_inc_factor = 3; |
| 739 | + /* But never increment capacity by more than this number. */ |
| 740 | + const size_t cache_sz_inc_max = 1048576; |
| 741 | + |
| 742 | + char *pret, *ret = NULL; |
| 743 | + const char *pstr2, *pstr = str; |
| 744 | + size_t i, count = 0; |
| 745 | + #if (__STDC_VERSION__ >= 199901L) |
| 746 | + uintptr_t *pos_cache_tmp, *pos_cache = NULL; |
| 747 | + #else |
| 748 | + ptrdiff_t *pos_cache_tmp, *pos_cache = NULL; |
| 749 | + #endif |
| 750 | + size_t cache_sz = 0; |
| 751 | + size_t cpylen, orglen, retlen, tolen, fromlen = strlen(from); |
| 752 | + |
| 753 | + /* Find all matches and cache their positions. */ |
| 754 | + while ((pstr2 = strstr(pstr, from)) != NULL) { |
| 755 | + count++; |
| 756 | + |
| 757 | + /* Increase the cache size when necessary. */ |
| 758 | + if (cache_sz < count) { |
| 759 | + cache_sz += cache_sz_inc; |
| 760 | + pos_cache_tmp = realloc(pos_cache, sizeof(*pos_cache) * cache_sz); |
| 761 | + if (pos_cache_tmp == NULL) { |
| 762 | + goto end_repl_str; |
| 763 | + } else pos_cache = pos_cache_tmp; |
| 764 | + cache_sz_inc *= cache_sz_inc_factor; |
| 765 | + if (cache_sz_inc > cache_sz_inc_max) { |
| 766 | + cache_sz_inc = cache_sz_inc_max; |
| 767 | + } |
| 768 | + } |
| 769 | + |
| 770 | + pos_cache[count-1] = pstr2 - str; |
| 771 | + pstr = pstr2 + fromlen; |
| 772 | + } |
| 773 | + |
| 774 | + orglen = pstr - str + strlen(pstr); |
| 775 | + |
| 776 | + /* Allocate memory for the post-replacement string. */ |
| 777 | + if (count > 0) { |
| 778 | + tolen = strlen(to); |
| 779 | + retlen = orglen + (tolen - fromlen) * count; |
| 780 | + } else retlen = orglen; |
| 781 | + ret = malloc(retlen + 1); |
| 782 | + if (ret == NULL) { |
| 783 | + goto end_repl_str; |
| 784 | + } |
| 785 | + |
| 786 | + if (count == 0) { |
| 787 | + /* If no matches, then just duplicate the string. */ |
| 788 | + strcpy(ret, str); |
| 789 | + } else { |
| 790 | + /* Otherwise, duplicate the string whilst performing |
| 791 | + * the replacements using the position cache. */ |
| 792 | + pret = ret; |
| 793 | + memcpy(pret, str, pos_cache[0]); |
| 794 | + pret += pos_cache[0]; |
| 795 | + for (i = 0; i < count; i++) { |
| 796 | + memcpy(pret, to, tolen); |
| 797 | + pret += tolen; |
| 798 | + pstr = str + pos_cache[i] + fromlen; |
| 799 | + cpylen = (i == count-1 ? orglen : pos_cache[i+1]) - pos_cache[i] - fromlen; |
| 800 | + memcpy(pret, pstr, cpylen); |
| 801 | + pret += cpylen; |
| 802 | + } |
| 803 | + ret[retlen] = '\0'; |
| 804 | + } |
| 805 | + |
| 806 | +end_repl_str: |
| 807 | + /* Free the cache and return the post-replacement string, |
| 808 | + * which will be NULL in the event of an error. */ |
| 809 | + free(pos_cache); |
| 810 | + return ret; |
| 811 | +} |
0 commit comments