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

Function get_compiled_regex

source/script2.cpp:12033–12333  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

12031}
12032
12033pcret *get_compiled_regex(LPTSTR aRegEx, pcret_extra *&aExtra, int *aOptionsLength, ResultToken *aResultToken)
12034// Returns the compiled RegEx, or NULL on failure.
12035// This function is called by things other than built-in functions so it should be kept general-purpose.
12036// Upon failure, if aResultToken!=NULL:
12037// - An exception is thrown with a descriptive message on failure.
12038// - *aResultToken is set up to contain an empty string.
12039// Upon success, the following output parameters are set based on the options that were specified:
12040// aGetPositionsNotSubstrings
12041// aExtra
12042// L14: aOptionsLength is used by callouts to adjust cb->pattern_position to be relative to beginning of actual user-specified NeedleRegEx instead of string seen by PCRE.
12043{
12044 if (!pcret_callout)
12045 { // Ensure this is initialized, even for ::RegExMatch() (to allow (?C) in window title regexes).
12046 pcret_callout = &RegExCallout;
12047 }
12048
12049 // While reading from or writing to the cache, don't allow another thread entry. This is because
12050 // that thread (or this one) might write to the cache while the other one is reading/writing, which
12051 // could cause loss of data integrity (the hook thread can enter here via #HotIf WinActive/Exist & SetTitleMatchMode RegEx).
12052 // Together, Enter/LeaveCriticalSection reduce performance by only 1.4% in the tightest possible script
12053 // loop that hits the first cache entry every time. So that's the worst case except when there's an actual
12054 // collision, in which case performance suffers more because internally, EnterCriticalSection() does a
12055 // wait/semaphore operation, which is more costly.
12056 // Finally, the code size of all critical-section features together is less than 512 bytes (uncompressed),
12057 // so like performance, that's not a concern either.
12058 EnterCriticalSection(&g_CriticalRegExCache); // Request ownership of the critical section. If another thread already owns it, this thread will block until the other thread finishes.
12059
12060 // SET UP THE CACHE.
12061 // This is a very crude cache for linear search. Of course, hashing would be better in the sense that it
12062 // would allow the cache to get much larger while still being fast (I believe PHP caches up to 4096 items).
12063 // Binary search might not be such a good idea in this case due to the time required to find the right spot
12064 // to insert a new cache item (however, items aren't inserted often, so it might perform quite well until
12065 // the cache contained thousands of RegEx's, which is unlikely to ever happen in most scripts).
12066 struct pcre_cache_entry
12067 {
12068 // For simplicity (and thus performance), the entire RegEx pattern including its options is cached
12069 // is stored in re_raw and that entire string becomes the RegEx's unique identifier for the purpose
12070 // of finding an entry in the cache. Technically, this isn't optimal because some options like Study
12071 // and aGetPositionsNotSubstrings don't alter the nature of the compiled RegEx. However, the CPU time
12072 // required to strip off some options prior to doing a cache search seems likely to offset much of the
12073 // cache's benefit. So for this reason, as well as rarity and code size issues, this policy seems best.
12074 LPTSTR re_raw; // The RegEx's literal string pattern such as "abc.*123".
12075 pcret *re_compiled; // The RegEx in compiled form.
12076 pcret_extra *extra; // NULL unless a study() was done (and NULL even then if study() didn't find anything).
12077 // int pcre_options; // Not currently needed in the cache since options are implicitly inside re_compiled.
12078 int options_length; // Lexikos: See aOptionsLength comment at beginning of this function.
12079 };
12080
12081 #define PCRE_CACHE_SIZE 100 // Going too high would be counterproductive due to the slowness of linear search (and also the memory utilization of so many compiled RegEx's).
12082 static pcre_cache_entry sCache[PCRE_CACHE_SIZE] = {{0}};
12083 static int sLastInsert, sLastFound = -1; // -1 indicates "cache empty".
12084 int insert_pos; // v1.0.45.03: This is used to avoid updating sLastInsert until an insert actually occurs (it might not occur if a compile error occurs in the regex, or something else stops it early).
12085
12086 // CHECK IF THIS REGEX IS ALREADY IN THE CACHE.
12087 if (sLastFound == -1) // Cache is empty, so insert this RegEx at the first position.
12088 insert_pos = 0; // A section further below will change sLastFound to be 0.
12089 else
12090 {

Callers 2

RegExMatchFunction · 0.85
BIF_DECLFunction · 0.85

Calls 2

sntprintfFunction · 0.85
ErrorMethod · 0.80

Tested by

no test coverage detected