| 1063 | |
| 1064 | |
| 1065 | UINT StrReplace(LPTSTR aHaystack, LPTSTR aOld, LPTSTR aNew, StringCaseSenseType aStringCaseSense |
| 1066 | , UINT aLimit, size_t aSizeLimit, LPTSTR *aDest, size_t *aHaystackLength) |
| 1067 | // Replaces all (or aLimit) occurrences of aOld with aNew in aHaystack. |
| 1068 | // On success, it returns the number of replacements done (0 if none). On failure (out of memory), it returns 0 |
| 1069 | // (and if aDest isn't NULL, it also sets *aDest to NULL on failure). |
| 1070 | // |
| 1071 | // PARAMETERS: |
| 1072 | // - aLimit: Specify UINT_MAX to have no restriction on the number of replacements. Otherwise, specify a number >=0. |
| 1073 | // - aSizeLimit: Specify -1 to assume that aHaystack has enough capacity for any mode #1 replacement. Otherwise, |
| 1074 | // specify the size limit (in either mode 1 or 2), but it must be >= length of aHaystack (simplifies the code). |
| 1075 | // - aDest: If NULL, the function will operate in mode #1. Otherwise, it uses mode #2 (see further below). |
| 1076 | // - aHaystackLength: If it isn't NULL, *aHaystackLength must be the length of aHaystack. HOWEVER, *aHaystackLength |
| 1077 | // is then changed here to be the length of the result string so that caller can use it to improve performance. |
| 1078 | // |
| 1079 | // MODE 1 (when aDest==NULL): aHaystack is used as both the source and the destination (sometimes temporary memory |
| 1080 | // is used for performance, but it's freed afterward and so transparent to the caller). |
| 1081 | // When it passes in -1 for aSizeLimit (the default), caller must ensure that aHaystack has enough capacity to hold |
| 1082 | // the new/replaced result. When non-NULL, aSizeLimit will be enforced by limiting the number of replacements to |
| 1083 | // the available memory (i.e. any remaining replacements are simply not done and that part of haystack is unaltered). |
| 1084 | // |
| 1085 | // MODE 2 (when aDest!=NULL): If zero replacements are needed, we set *aDest to be aHaystack to indicate that no |
| 1086 | // new memory was allocated. Otherwise, we store in *aDest the address of the new memory that holds the result. |
| 1087 | // - The caller is responsible for any new memory in *aDest (freeing it, etc.) |
| 1088 | // - The initial value of *aDest doesn't matter. |
| 1089 | // - The contents of aHaystack isn't altered, not even if aOld_length==aNew_length (some callers rely on this). |
| 1090 | // |
| 1091 | // v1.0.45: This function was heavily revised to improve performance and flexibility. It has also made |
| 1092 | // two other/related StrReplace() functions obsolete. Also, the code has been simplified to avoid doing |
| 1093 | // a first pass through haystack to find out exactly how many replacements there are because that step |
| 1094 | // nearly doubles the time required for the entire operation (in most cases). Its benefit was mainly in |
| 1095 | // memory savings and avoidance of any reallocs since the initial alloc was always exactly right; however, |
| 1096 | // testing shows that one or two reallocs are generally much quicker than doing the size-calculation phase |
| 1097 | // because extra alloc'ing & memcpy'ing is much faster than an extra search through haystack for all the matches. |
| 1098 | // Furthermore, the new approach minimizes reallocs by using smart prediction. Furthermore, the caller shrinks |
| 1099 | // the result memory via _expand() to avoid having too much extra/overhang. These optimizations seem to make |
| 1100 | // the new approach better than the old one in every way, but especially performance. |
| 1101 | { |
| 1102 | #define REPLACEMENT_MODE2 aDest // For readability. |
| 1103 | |
| 1104 | // THINGS TO SET NOW IN CASE OF EARLY RETURN OR GOTO: |
| 1105 | // Set up the input/output lengths: |
| 1106 | size_t haystack_length = aHaystackLength ? *aHaystackLength : _tcslen(aHaystack); // For performance, use caller's length if it was provided. |
| 1107 | size_t length_temp; // Just a placeholder/memory location used by the alias below. |
| 1108 | size_t &result_length = aHaystackLength ? *aHaystackLength : length_temp; // Make an alias for convenience and maintainability (if this is an output parameter for our caller, this step takes care that in advance). |
| 1109 | // Set up the output buffer: |
| 1110 | LPTSTR result_temp; // In mode #1, holds temporary memory that is freed before we return. |
| 1111 | LPTSTR &result = aDest ? *aDest : result_temp; // Make an alias for convenience and maintainability (if aDest is non-NULL, it's an output parameter for our caller, and this step takes care that in advance). |
| 1112 | result = NULL; // It's allocated only upon first use to avoid a potentially massive allocation that might |
| 1113 | result_length = 0; // be wasted and cause swapping (not to mention that we'll have better ability to estimate the correct total size after the first replacement is discovered). |
| 1114 | size_t result_size = 0; |
| 1115 | // Variables used by both replacement methods. |
| 1116 | LPTSTR src, match_pos; |
| 1117 | // END OF INITIAL SETUP. |
| 1118 | |
| 1119 | // From now on, result_length and result should be kept up-to-date because they may have been set up |
| 1120 | // as output parameters above. |
| 1121 | |
| 1122 | if (!(*aHaystack && *aOld)) |
no test coverage detected