MCPcopy Create free account
hub / github.com/AutoHotkey/AutoHotkey / StrReplace

Function StrReplace

source/util.cpp:1065–1292  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1063
1064
1065UINT 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))

Callers 4

ControlGetEditMethod · 0.85
GetLineContinuationMethod · 0.85
BIF_DECLFunction · 0.85
script2.cppFile · 0.85

Calls 1

PredictReplacementSizeFunction · 0.85

Tested by

no test coverage detected