"Fossies" - the Fresh Open Source Software Archive

Member "AutoHotkey_L-1.1.33.09/source/util.h" (8 May 2021, 36907 Bytes) of package /windows/misc/AutoHotkey_L-1.1.33.09.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "util.h" see the Fossies "Dox" file reference documentation.

    1 /*
    2 AutoHotkey
    3 
    4 Copyright 2003-2009 Chris Mallett (support@autohotkey.com)
    5 
    6 This program is free software; you can redistribute it and/or
    7 modify it under the terms of the GNU General Public License
    8 as published by the Free Software Foundation; either version 2
    9 of the License, or (at your option) any later version.
   10 
   11 This program is distributed in the hope that it will be useful,
   12 but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 GNU General Public License for more details.
   15 */
   16 
   17 #ifndef util_h
   18 #define util_h
   19 
   20 #include "stdafx.h" // pre-compiled headers
   21 #include "defines.h"
   22 EXTERN_G;  // For ITOA() and related functions' use of g->FormatIntAsHex
   23 
   24 
   25 #ifdef _WIN64
   26 #define Exp32or64(a,b) (b)
   27 #else
   28 #define Exp32or64(a,b) (a)
   29 #endif
   30 
   31 
   32 #ifdef UNICODE
   33 #define tmemcpy         wmemcpy
   34 #define tmemmove        wmemmove
   35 #define tmemset         wmemset
   36 #define tmemcmp         wmemcmp
   37 #define tmalloc(c)      ((LPTSTR) malloc((c) << 1))
   38 #define trealloc(p, c)  ((LPTSTR) realloc((p), (c) << 1))
   39 #define talloca(c)      ((LPTSTR) _alloca((c) << 1))
   40 #else
   41 #define tmemcpy         (char*)memcpy
   42 #define tmemmove        memmove
   43 #define tmemset         memset
   44 #define tmemcmp         memcmp
   45 #define tmalloc(c)      ((LPTSTR) malloc(c))
   46 #define trealloc(p, c)  ((LPTSTR) realloc((p), (c)))
   47 #define talloca(c)      ((LPTSTR) _alloca(c))
   48 #endif
   49 
   50 #define IS_SPACE_OR_TAB(c) (c == ' ' || c == '\t')
   51 #ifndef UNICODE
   52 #define IS_SPACE_OR_TAB_OR_NBSP(c) (c == ' ' || c == '\t' || c == -96) // Use a negative to support signed chars.
   53 #else
   54 #define IS_SPACE_OR_TAB_OR_NBSP(c) IS_SPACE_OR_TAB(c) // wchar_t is unsigned
   55 #endif
   56 
   57 #ifdef UNICODE
   58 #define TRANS_CHAR_TO_INT(a) ((int)(USHORT)(a)) // Cast not actually necessary since wchar_t is usually unsigned.
   59 #define TRANS_CHAR_MAX 65535
   60 #else
   61 #define TRANS_CHAR_TO_INT(a) ((int)(UCHAR)(a)) // Cast to UCHAR so that chars above Asc(127) show as positive.
   62 #define TRANS_CHAR_MAX 255
   63 #endif
   64 
   65 // v1.0.43.04: The following are macros to avoid crash bugs caused by improper casting, namely a failure to cast
   66 // a signed char to UCHAR before promoting it to LPSTR, which crashes since CharLower/Upper would interpret
   67 // such a high unsigned value as an address rather than a single char.
   68 #define ltolower(ch) (TBYTE)(UINT_PTR)CharLower((LPTSTR)(TBYTE)(ch))  // "L" prefix stands for "locale", like lstrcpy.
   69 #define ltoupper(ch) (TBYTE)(UINT_PTR)CharUpper((LPTSTR)(TBYTE)(ch))  // For performance, some callers don't want return value cast to char.
   70 
   71 
   72 // Locale independent ctype (applied to the ASCII characters only)
   73 // isctype/iswctype affects the some non-ASCII characters.
   74 inline int cisctype(TBYTE c, int type)
   75 {
   76     return (c & (~0x7F)) ? 0 : _isctype(c, type);
   77 }
   78 
   79 #define cisalpha(c)     cisctype(c, _ALPHA)
   80 #define cisalnum(c)     cisctype(c, _ALPHA | _DIGIT)
   81 #define cisdigit(c)     cisctype(c, _DIGIT)
   82 #define cisxdigit(c)    cisctype(c, _HEX)
   83 #define cisupper(c)     cisctype(c, _UPPER)
   84 #define cislower(c)     cisctype(c, _LOWER)
   85 #define cisprint(c)     cisctype(c, _ALPHA | _BLANK | _DIGIT | _PUNCT)
   86 #define cisspace(c)     cisctype(c, _SPACE)
   87 
   88 // The results of toupper/tolower are implementations dependent (see below), though the test results are OK in VS2008's CRT.
   89 // MDSN: In order for toupper to give the expected results, __isascii and islower must both return nonzero.
   90 // Linux (man page): The value returned is that of the converted letter, or c if the conversion was not possible. (CONFORMING TO C89, C99, 4.3BSD.)
   91 inline TCHAR ctoupper(TBYTE c)
   92 {
   93     return cislower(c) ? (c & ~0x20) : c;
   94 }
   95 inline TCHAR ctolower(TBYTE c)
   96 {
   97     return cisupper(c) ? (c | 0x20) : c;
   98 }
   99 
  100 // Runtime setting dependent. "a" prefix stand for AutoHotkey.
  101 #define aisalpha(c) ((int)((::g->StringCaseSense == SCS_INSENSITIVE_LOCALE) ? IsCharAlpha(c) : cisalpha(c)))
  102 #define aisalnum(c) ((int)((::g->StringCaseSense == SCS_INSENSITIVE_LOCALE) ? IsCharAlphaNumeric(c) : cisalnum(c)))
  103 #define aisupper(c) ((int)((::g->StringCaseSense == SCS_INSENSITIVE_LOCALE) ? IsCharUpper(c) : cisupper(c)))
  104 #define aislower(c) ((int)((::g->StringCaseSense == SCS_INSENSITIVE_LOCALE) ? IsCharLower(c) : cislower(c)))
  105 
  106 #define atoupper(c) ((::g->StringCaseSense == SCS_INSENSITIVE_LOCALE) ? ltoupper(c) : ctoupper(c))
  107 #define atolower(c) ((::g->StringCaseSense == SCS_INSENSITIVE_LOCALE) ? ltolower(c) : ctolower(c))
  108 
  109 // NOTE: MOVING THINGS OUT OF THIS FILE AND INTO util.cpp can hurt benchmarks by 10% or more, so be careful
  110 // when doing so (even when the change seems inconsequential, it can impact benchmarks due to quirks of code
  111 // generation and caching).
  112 
  113 
  114 inline LPTSTR StrToTitleCase(LPTSTR aStr)
  115 // Inline functions like the following probably don't actually get put inline by the compiler (since it knows
  116 // it's not worth it).  However, changing this to be non-inline has a significant impact on benchmarks even
  117 // though the function is never called by those benchmarks, probably due to coincidences in how the generated
  118 // code gets cached in the CPU.  So it seems best not to mess with anything without making sure it doesn't
  119 // drop the benchmarks significantly.
  120 {
  121     if (!aStr) return aStr;
  122     LPTSTR aStr_orig = aStr;    
  123     for (bool convert_next_alpha_char_to_upper = true; *aStr; ++aStr)
  124     {
  125         if (IsCharAlpha(*aStr)) // Use this to better support chars from non-English languages.
  126         {
  127             if (convert_next_alpha_char_to_upper)
  128             {
  129                 *aStr = ltoupper(*aStr);
  130                 convert_next_alpha_char_to_upper = false;
  131             }
  132             else
  133                 *aStr = ltolower(*aStr);
  134         }
  135         else
  136             if (_istspace(*aStr))
  137                 convert_next_alpha_char_to_upper = true;
  138         // Otherwise, it's a digit, punctuation mark, etc. so nothing needs to be done.
  139     }
  140     return aStr_orig;
  141 }
  142 
  143 
  144 
  145 inline LPTSTR StrChrAny(LPTSTR aStr, LPTSTR aCharList)
  146 // Returns the position of the first char in aStr that is of any one of the characters listed in aCharList.
  147 // Returns NULL if not found.
  148 // Update: Yes, this seems identical to strpbrk().  However, since the corresponding code would
  149 // have to be added to the EXE regardless of which was used, there doesn't seem to be much
  150 // advantage to switching (especially since if the two differ in behavior at all, things might
  151 // get broken).  Another reason is the name "strpbrk()" is not as easy to remember.
  152 {
  153     if (aStr == NULL || aCharList == NULL) return NULL;
  154     if (!*aStr || !*aCharList) return NULL;
  155     // Don't use strchr() because that would just find the first occurrence
  156     // of the first search-char, which is not necessarily the first occurrence
  157     // of *any* search-char:
  158     LPTSTR look_for_this_char;
  159     TCHAR char_being_analyzed;
  160     for (; *aStr; ++aStr)
  161         // If *aStr is any of the search char's, we're done:
  162         for (char_being_analyzed = *aStr, look_for_this_char = aCharList; *look_for_this_char; ++look_for_this_char)
  163             if (char_being_analyzed == *look_for_this_char)
  164                 return aStr;  // Match found.
  165     return NULL; // No match.
  166 }
  167 
  168 
  169 
  170 inline LPCTSTR omit_leading_whitespace(LPCTSTR aBuf) // 10/17/2006: __forceinline didn't help significantly.
  171 // While aBuf points to a whitespace, moves to the right and returns the first non-whitespace
  172 // encountered.
  173 {
  174     for (; IS_SPACE_OR_TAB(*aBuf); ++aBuf);
  175     return aBuf;
  176 }
  177 inline LPTSTR omit_leading_whitespace(LPTSTR aBuf)
  178 {
  179     return (LPTSTR) omit_leading_whitespace((LPCTSTR) aBuf);
  180 }
  181 
  182 
  183 inline LPTSTR omit_leading_any(LPTSTR aBuf, LPTSTR aOmitList, size_t aLength)
  184 // Returns the address of the first character in aBuf that isn't a member of aOmitList.
  185 // But no more than aLength characters of aBuf will be considered.  If aBuf is composed
  186 // entirely of omitted characters, the address of the char after the last char in the
  187 // string will returned (that char will be the zero terminator unless aLength explicitly
  188 // caused only part of aBuf to be considered).
  189 {
  190     LPTSTR cp;
  191     for (size_t i = 0; i < aLength; ++i, ++aBuf)
  192     {
  193         // Check if the current char is a member of the omitted-char list:
  194         for (cp = aOmitList; *cp; ++cp)
  195             if (*aBuf == *cp) // Match found.
  196                 break;
  197         if (!*cp) // No match found, so this character is not omitted, thus we immediately return it's position.
  198             return aBuf;
  199     }
  200     // Since the above didn't return, aBuf is the position of the zero terminator or (if aLength
  201     // indicated only a substring) the position of the char after the last char in the substring.
  202     return aBuf;
  203 }
  204 
  205 
  206 
  207 inline LPTSTR omit_trailing_whitespace(LPTSTR aBuf, LPTSTR aBuf_marker)
  208 // aBuf_marker must be a position in aBuf (to the right of it).
  209 // Starts at aBuf_marker and keeps moving to the left until a non-whitespace
  210 // char is encountered.  Returns the position of that char.
  211 {
  212     for (; aBuf_marker > aBuf && IS_SPACE_OR_TAB(*aBuf_marker); --aBuf_marker);
  213     return aBuf_marker;  // Can equal aBuf.
  214 }
  215 
  216 
  217 
  218 inline size_t omit_trailing_any(LPTSTR aBuf, LPTSTR aOmitList, LPTSTR aBuf_marker)
  219 // aBuf_marker must be a position in aBuf (to the right of it).
  220 // Starts at aBuf_marker and keeps moving to the left until a char that isn't a member
  221 // of aOmitList is found.  The length of the remaining substring is returned.
  222 // That length will be zero if the string consists entirely of omitted characters.
  223 {
  224     LPTSTR cp;
  225     for (; aBuf_marker > aBuf; --aBuf_marker)
  226     {
  227         // Check if the current char is a member of the omitted-char list:
  228         for (cp = aOmitList; *cp; ++cp)
  229             if (*aBuf_marker == *cp) // Match found.
  230                 break;
  231         if (!*cp) // No match found, so this character is not omitted, thus we immediately return.
  232             return (aBuf_marker - aBuf) + 1; // The length of the string when trailing chars are omitted.
  233     }
  234     // Since the above didn't return, aBuf_marker is now equal to aBuf.  If this final character is itself
  235     // a member of the omitted-list, the length returned will be zero.  Otherwise it will be 1:
  236     for (cp = aOmitList; *cp; ++cp)
  237         if (*aBuf_marker == *cp) // Match found.
  238             return 0;
  239     return 1;
  240 }
  241 
  242 
  243 
  244 inline size_t ltrim(LPTSTR aStr, size_t aLength = -1)
  245 // Caller must ensure that aStr is not NULL.
  246 // v1.0.25: Returns the length if it was discovered as a result of the operation, or aLength otherwise.
  247 // This greatly improves the performance of PerformAssign().
  248 // NOTE: THIS VERSION trims only tabs and spaces.  It specifically avoids
  249 // trimming newlines because some callers want to retain those.
  250 {
  251     if (!*aStr) return 0;
  252     LPTSTR ptr;
  253     // Find the first non-whitespace char (which might be the terminator):
  254     for (ptr = aStr; IS_SPACE_OR_TAB(*ptr); ++ptr); // Self-contained loop.
  255     // v1.0.25: If no trimming needed, don't do the memmove.  This seems to make a big difference
  256     // in the performance of critical sections of the program such as PerformAssign():
  257     size_t offset;
  258     if (offset = ptr - aStr) // Assign.
  259     {
  260         if (aLength == -1)
  261             aLength = _tcslen(ptr); // Set aLength as new/trimmed length, for use below and also as the return value.
  262         else // v1.0.25.05 bug-fix: Must adjust the length provided by caller to reflect what we did here.
  263             aLength -= offset;
  264         tmemmove(aStr, ptr, aLength + 1); // +1 to include the '\0'.  memmove() permits source & dest to overlap.
  265     }
  266     return aLength; // This will return -1 if the block above didn't execute and caller didn't specify the length.
  267 }
  268 
  269 inline size_t rtrim(LPTSTR aStr, size_t aLength = -1)
  270 // Caller must ensure that aStr is not NULL.
  271 // To improve performance, caller may specify a length (e.g. when it is already known).
  272 // v1.0.25: Always returns the new length of the string.  This greatly improves the performance of
  273 // PerformAssign().
  274 // NOTE: THIS VERSION trims only tabs and spaces.  It specifically avoids trimming newlines because
  275 // some callers want to retain those.
  276 {
  277     if (!*aStr) return 0; // The below relies upon this check having been done.
  278     // It's done this way in case aStr just happens to be address 0x00 (probably not possible
  279     // on Intel & Intel-clone hardware) because otherwise --cp would decrement, causing an
  280     // underflow since pointers are probably considered unsigned values, which would
  281     // probably cause an infinite loop.  Extremely unlikely, but might as well try
  282     // to be thorough:
  283     if (aLength == -1)
  284         aLength = _tcslen(aStr); // Set aLength for use below and also as the return value.
  285     for (LPTSTR cp = aStr + aLength - 1; ; --cp, --aLength)
  286     {
  287         if (!IS_SPACE_OR_TAB(*cp))
  288         {
  289             cp[1] = '\0';
  290             return aLength;
  291         }
  292         // Otherwise, it is a space or tab...
  293         if (cp == aStr) // ... and we're now at the first character of the string...
  294         {
  295             if (IS_SPACE_OR_TAB(*cp)) // ... and that first character is also a space or tab...
  296             {
  297                 *cp = '\0'; // ... so the entire string is made empty...
  298                 return 0; // Fix for v1.0.39: Must return 0 not aLength in this case.
  299             }
  300             return aLength; // ... and we return in any case.
  301         }
  302         // else it's a space or tab, and there are still more characters to check.  Let the loop
  303         // do its decrements.
  304     }
  305 }
  306 
  307 inline void rtrim_literal(LPTSTR aStr, TCHAR aLiteralMap[])
  308 // Caller must ensure that aStr is not NULL.
  309 // NOTE: THIS VERSION trims only tabs and spaces which aren't marked as literal (so not "`t" or "` ").
  310 // It specifically avoids trimming newlines because some callers want to retain those.
  311 {
  312     if (!*aStr) return; // The below relies upon this check having been done.
  313     // It's done this way in case aStr just happens to be address 0x00 (probably not possible
  314     // on Intel & Intel-clone hardware) because otherwise --cp would decrement, causing an
  315     // underflow since pointers are probably considered unsigned values, which would
  316     // probably cause an infinite loop.  Extremely unlikely, but might as well try
  317     // to be thorough:
  318     for (size_t last = _tcslen(aStr) - 1; ; --last)
  319     {
  320         if (!IS_SPACE_OR_TAB(aStr[last]) || aLiteralMap[last]) // It's not a space or tab, or it's a literal one.
  321         {
  322             aStr[last + 1] = '\0';
  323             return;
  324         }
  325         // Otherwise, it is a space or tab...
  326         if (last == 0) // ... and we're now at the first character of the string...
  327         {
  328             if (IS_SPACE_OR_TAB(aStr[last])) // ... and that first character is also a space or tab...
  329                 *aStr = '\0'; // ... so the entire string is made empty.
  330             return; // ... and we return in any case.
  331         }
  332         // else it's a space or tab, and there are still more characters to check.  Let the loop
  333         // do its decrements.
  334     }
  335 }
  336 
  337 inline size_t rtrim_with_nbsp(LPTSTR aStr, size_t aLength = -1)
  338 // Returns the new length of the string.
  339 // Caller must ensure that aStr is not NULL.
  340 // To improve performance, caller may specify a length (e.g. when it is already known).
  341 // Same as rtrim but also gets rid of those annoying nbsp (non breaking space) chars that sometimes
  342 // wind up on the clipboard when copied from an HTML document, and thus get pasted into the text
  343 // editor as part of the code (such as the sample code in some of the examples).
  344 {
  345     if (!*aStr) return 0; // The below relies upon this check having been done.
  346     if (aLength == -1)
  347         aLength = _tcslen(aStr); // Set aLength for use below and also as the return value.
  348     for (LPTSTR cp = aStr + aLength - 1; ; --cp, --aLength)
  349     {
  350         if (!IS_SPACE_OR_TAB_OR_NBSP(*cp))
  351         {
  352             cp[1] = '\0';
  353             return aLength;
  354         }
  355         if (cp == aStr)
  356         {
  357             if (IS_SPACE_OR_TAB_OR_NBSP(*cp)) // ... and that first character is also a space or tab...
  358             {
  359                 *cp = '\0'; // ... so the entire string is made empty...
  360                 return 0; // Fix for v1.0.39: Must return 0 not aLength in this case.
  361             }
  362             return aLength; // ... and we return in any case.
  363         }
  364     }
  365 }
  366 
  367 inline size_t trim(LPTSTR aStr, size_t aLength = -1)
  368 // Caller must ensure that aStr is not NULL.
  369 // Returns new length of aStr.
  370 // To improve performance, caller may specify a length (e.g. when it is already known).
  371 // NOTE: THIS VERSION trims only tabs and spaces.  It specifically avoids
  372 // trimming newlines because some callers want to retain those.
  373 {
  374     aLength = ltrim(aStr, aLength);  // It may return -1 to indicate that it still doesn't know the length.
  375     return rtrim(aStr, aLength);
  376     // v1.0.25: rtrim() always returns the new length of the string.  This greatly improves the
  377     // performance of PerformAssign() and possibly other things.
  378 }
  379 
  380 inline size_t strip_trailing_backslash(LPTSTR aPath)
  381 // Removes any backslash (if there is one).
  382 // Returns length of the new string to allow some callers to avoid another strlen() call.
  383 {
  384     size_t length = _tcslen(aPath);
  385     if (!length) // Below relies on this check having been done to prevent underflow.
  386         return length;
  387     LPTSTR cp = aPath + length - 1;
  388     if (*cp == _T('\\'))
  389     {
  390         *cp = '\0';
  391         return length - 1;
  392     }
  393     // Otherwise there no slash to remove, so return the current length.
  394     return length;
  395 }
  396 
  397 
  398 
  399 #define IS_IDENTIFIER_CHAR(c) (cisalnum(c) || (c) == '_' || ((UINT)(c) > 0x7F))
  400 template<typename T> inline T find_identifier_end(T aBuf)
  401 // Locates the next character which is not valid in an identifier (var, func, or obj.key name).
  402 {
  403     while (IS_IDENTIFIER_CHAR(*aBuf)) ++aBuf;
  404     return aBuf;
  405 }
  406 
  407 
  408 
  409 
  410 // Transformation is the same in either direction because the end bytes are swapped
  411 // and the middle byte is left as-is:
  412 #define bgr_to_rgb(aBGR) rgb_to_bgr(aBGR)
  413 inline COLORREF rgb_to_bgr(DWORD aRGB)
  414 // Fancier methods seem prone to problems due to byte alignment or compiler issues.
  415 {
  416     return RGB(GetBValue(aRGB), GetGValue(aRGB), GetRValue(aRGB));
  417 }
  418 
  419 
  420 
  421 inline bool IsHex(LPCTSTR aBuf) // 10/17/2006: __forceinline worsens performance, but physically ordering it near ATOI64() [via /ORDER] boosts by 3.5%.
  422 // Note: AHK support for hex ints reduces performance by only 10% for decimal ints, even in the tightest
  423 // of math loops that have SetBatchLines set to -1.
  424 {
  425     // For whatever reason, omit_leading_whitespace() benches consistently faster (albeit slightly) than
  426     // the same code put inline (confirmed again on 10/17/2006, though the difference is hardly anything):
  427     //for (; IS_SPACE_OR_TAB(*aBuf); ++aBuf);
  428     aBuf = omit_leading_whitespace(aBuf); // i.e. caller doesn't have to have ltrimmed.
  429     if (!*aBuf)
  430         return false;
  431     if (*aBuf == '-' || *aBuf == '+')
  432         ++aBuf;
  433     // The "0x" prefix must be followed by at least one hex digit, otherwise it's not considered hex:
  434     #define IS_HEX(buf) (*buf == '0' && (*(buf + 1) == 'x' || *(buf + 1) == 'X') && isxdigit(*(buf + 2)))
  435     return IS_HEX(aBuf);
  436 }
  437 
  438 
  439 
  440 // As of v1.0.30, ATOI(), ITOA() and the other related functions below are no longer macros
  441 // because there are too many places where something like ATOI(++cp) is done, which would be a
  442 // bug if not caught since cp would be incremented more than once if the macro referred to that
  443 // arg more than once.  In addition, a non-comprehensive, simple benchmark shows that the
  444 // macros don't perform any better anyway, probably in part because there are many times when
  445 // something like ArgToInt(1) is called, which forces the ARG1 macro to be expanded two or more
  446 // times within ATOI (when it was a macro).  So for now, the below are declared as inline.
  447 // However, it seems that the compiler chooses not to make them truly inline, which as it
  448 // turns out is probably the right decision since a simple benchmark shows that even with
  449 // __forceinline in effect for all of them (which is confirmed to actually force inline),
  450 // the performance isn't any better.
  451 
  452 inline __int64 ATOI64(LPCTSTR buf)
  453 // The following comment only applies if the code is a macro or actually put inline by the compiler,
  454 // which is no longer true:
  455 // A more complex macro is used for ATOI64(), since it is more often called from places where
  456 // performance matters (e.g. ACT_ADD).  It adds about 500 bytes to the code size  in exchange for
  457 // a 8% faster math loops.  But it's probably about 8% slower when used with hex integers, but
  458 // those are so rare that the speed-up seems worth the extra code size:
  459 //#define ATOI64(buf) _strtoi64(buf, NULL, 0) // formerly used _atoi64()
  460 {
  461     return IsHex(buf) ? _tcstoi64(buf, NULL, 16) : _ttoi64(buf);  // _atoi64() has superior performance, so use it when possible.
  462 }
  463 
  464 inline unsigned __int64 ATOU64(LPCTSTR buf)
  465 {
  466     return _tcstoui64(buf, NULL, IsHex(buf) ? 16 : 10);
  467 }
  468 
  469 inline int ATOI(LPCTSTR buf)
  470 {
  471     // Below has been updated because values with leading zeros were being interpreted as
  472     // octal, which is undesirable.
  473     // Formerly: #define ATOI(buf) strtol(buf, NULL, 0) // Use zero as last param to support both hex & dec.
  474     return IsHex(buf) ? _tcstol(buf, NULL, 16) : _ttoi(buf); // atoi() has superior performance, so use it when possible.
  475 }
  476 
  477 // v1.0.38.01: Make ATOU a macro that refers to ATOI64() to improve performance (takes advantage of _atoi64()
  478 // being considerably faster than strtoul(), at least when the number is non-hex).  This relies on the fact
  479 // that ATOU() and (UINT)ATOI64() produce the same result due to the way casting works.  For example:
  480 // ATOU("-1") == (UINT)ATOI64("-1")
  481 // ATOU("-0xFFFFFFFF") == (UINT)ATOI64("-0xFFFFFFFF")
  482 #define ATOU(buf) (UINT)ATOI64(buf)
  483 //inline unsigned long ATOU(char *buf)
  484 //{
  485 //  // As a reminder, strtoul() also handles negative numbers.  For example, ATOU("-1") is
  486 //  // 4294967295 (0xFFFFFFFF) and ATOU("-2") is 4294967294.
  487 //  return strtoul(buf, NULL, IsHex(buf) ? 16 : 10);
  488 //}
  489 
  490 inline double ATOF(LPCTSTR buf)
  491 // Unlike some Unix versions of strtod(), the VC++ version does not seem to handle hex strings
  492 // such as "0xFF" automatically.  So this macro must check for hex because some callers rely on that.
  493 // Also, it uses _strtoi64() vs. strtol() so that more of a double's capacity can be utilized:
  494 {
  495     return IsHex(buf) ? (double)_tcstoi64(buf, NULL, 16) : _tstof(buf);
  496 }
  497 
  498 inline LPTSTR ITOA(int value, LPTSTR buf)
  499 {
  500     if (g->FormatInt == 'D')
  501     {
  502         return _itot(value, buf, 10);
  503     }
  504     // g->FormatInt == 'h' or 'H'
  505     LPTSTR our_buf_temp = buf;
  506     // Negative hex numbers need special handling, otherwise something like zero minus one would create
  507     // a huge 0xffffffffffffffff value, which would subsequently not be read back in correctly as
  508     // a negative number (but UTOA() doesn't need this since there can't be negatives in that case).
  509     if (value < 0)
  510     {
  511         *our_buf_temp++ = '-';
  512         value = -value;
  513     }
  514     *our_buf_temp++ = '0';
  515     *our_buf_temp++ = 'x';
  516     _itot(value, our_buf_temp, 16);
  517     // Must not return the result of the above because it's our_buf_temp and we want buf.
  518     if (g->FormatInt == 'H') // uppercase
  519         CharUpper(our_buf_temp);
  520     return buf;
  521 }
  522 
  523 inline LPTSTR ITOA64(__int64 value, LPTSTR buf)
  524 {
  525     if (g->FormatInt == 'D')
  526     {
  527         return _i64tot(value, buf, 10);
  528     }
  529     // g->FormatInt == 'h' or 'H'
  530     LPTSTR our_buf_temp = buf;
  531     if (value < 0)
  532     {
  533         *our_buf_temp++ = '-';
  534         value = -value;
  535     }
  536     *our_buf_temp++ = '0';
  537     *our_buf_temp++ = 'x';
  538     _i64tot(value, our_buf_temp, 16);
  539     // Must not return the result of the above because it's our_buf_temp and we want buf.
  540     if (g->FormatInt == 'H') // uppercase
  541         CharUpper(our_buf_temp);
  542     return buf;
  543 }
  544 
  545 inline LPTSTR UTOA(unsigned long value, LPTSTR buf)
  546 {
  547     if (g->FormatInt == 'D')
  548     {
  549         return _ultot(value, buf, 10);
  550     }
  551     // g->FormatInt == 'h' or 'H'
  552     *buf = '0';
  553     *(buf + 1) = 'x';
  554     _ultot(value, buf + 2, 16);
  555     // Must not return the result of the above because it's buf + 2 and we want buf.
  556     if (g->FormatInt == 'H') // uppercase
  557         CharUpper(buf + 2);
  558     return buf;
  559 }
  560 
  561 #ifdef _WIN64
  562 inline LPTSTR UTOA64(unsigned __int64 value, LPTSTR buf) 
  563 {
  564     if (g->FormatInt == 'D')
  565     {
  566         return _ui64tot(value, buf, 10);
  567     }
  568     // g->FormatInt == 'h' or 'H'
  569     *buf = '0';
  570     *(buf + 1) = 'x';
  571     _ui64tot(value, buf + 2, 16);
  572     // Must not return the result of the above because it's buf + 2 and we want buf.
  573     if (g->FormatInt == 'H') // uppercase
  574         CharUpper(buf + 2);
  575     return buf;
  576 }
  577 #endif
  578 
  579 
  580 inline LPTSTR HwndToString(HWND aHwnd, LPTSTR aBuf)
  581 {
  582     aBuf[0] = '0';
  583     aBuf[1] = 'x';
  584     // Use _ultot for performance on 32-bit systems and _ui64tot on 64-bit systems in case it's
  585     // possible for HWNDs to have non-zero upper 32-bits:
  586     Exp32or64(_ultot,_ui64tot)((size_t)aHwnd, aBuf + 2, 16);
  587     return aBuf;
  588 }
  589 
  590 
  591 //inline LPTSTR tcscatmove(LPTSTR aDst, LPCTSTR aSrc)
  592 //// Same as strcat() but allows aSrc and aDst to overlap.
  593 //// Unlike strcat(), it doesn't return aDst.  Instead, it returns the position
  594 //// in aDst where aSrc was appended.
  595 //{
  596 //  if (!aDst || !aSrc || !*aSrc) return aDst;
  597 //  LPTSTR aDst_end = aDst + _tcslen(aDst);
  598 //  return (LPTSTR)memmove(aDst_end, aSrc, (_tcslen(aSrc) + 1) * sizeof(TCHAR));  // Add 1 to include aSrc's terminator.
  599 //}
  600 
  601 
  602 
  603 // v1.0.43.03: The following macros support the new "StringCaseSense Locale" setting.  This setting performs
  604 // 1 to 10 times slower for most things, but has the benefit of seeing characters like ä and Ä as identical
  605 // when insensitive.  MSDN implies that lstrcmpi() is the same as:
  606 //     CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, ...)
  607 // Note that when MSDN talks about the "word sort" vs. "string sort", it does not mean that strings like
  608 // "co-op" and "co-op" are considered equal.  Instead, they are considered closer together than the traditional
  609 // string sort would see them, so that they wind up together in a sorted list.
  610 // And both of them benchmark the same, so lstrcmpi is now used here and in various other places throughout
  611 // the program when the new locale-case-insensitive mode is in effect.
  612 #define tcscmp2(str1, str2, string_case_sense) ((string_case_sense) == SCS_INSENSITIVE ? _tcsicmp(str1, str2) \
  613     : ((string_case_sense) == SCS_INSENSITIVE_LOCALE ? lstrcmpi(str1, str2) : _tcscmp(str1, str2)))
  614 #define g_tcscmp(str1, str2) tcscmp2(str1, str2, ::g->StringCaseSense)
  615 // The most common mode is listed first for performance:
  616 #define tcsstr2(haystack, needle, string_case_sense) ((string_case_sense) == SCS_INSENSITIVE ? tcscasestr(haystack, needle) \
  617     : ((string_case_sense) == SCS_INSENSITIVE_LOCALE ? lstrcasestr(haystack, needle) : _tcsstr(haystack, needle)))
  618 #define g_tcsstr(haystack, needle) tcsstr2(haystack, needle, ::g->StringCaseSense)
  619 // For the following, caller must ensure that len1 and len2 aren't beyond the terminated length of the string
  620 // because CompareString() might not stop at the terminator when a length is specified.  Also, CompareString()
  621 // returns 0 on failure, but failure occurs only when parameter/flag is invalid, which should never happen in
  622 // this case.
  623 #define lstrcmpni(str1, len1, str2, len2) (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, str1, (int)(len1), str2, (int)(len2)) - 2) // -2 for maintainability
  624 
  625 
  626 // The following macros simplify and make consistent the calls to MultiByteToWideChar().
  627 // MSDN implies that passing -1 for cbMultiByte is the most typical and secure usage because it ensures
  628 // that the output is null-terminated: "the resulting wide character string has a null terminator, and the
  629 // length returned by the function includes the terminating null character."
  630 //
  631 // I couldn't find any info on when MB_PRECOMPOSED is needed (if ever).  It's the default anyway,
  632 // which implies that passing zero (which is quite common in many examples I've seen) is essentially
  633 // the same as passing MB_PRECOMPOSED.  However, some modes such as CP_UTF8 should never use MB_PRECOMPOSED
  634 // or the function will fail.
  635 //
  636 // #1: FROM ANSI TO UNICODE (UTF-16).  dest_size_in_wchars includes the terminator.
  637 // From looking at the source to mbstowcs(), it might be faster when the "C" locale is in effect (which is
  638 // the default in the absence of setlocale()) than MultiByteToWideChar() depending on how the latter is
  639 // implemented. This is because mbstowcs() simply casts the characters to (wchar_t)(unsigned char) without
  640 // any other translation at all.  Although that behavior is probably identical to MultiByteToWideChar(CP_ACP...),
  641 // it's not completely certain -- so it seems best to stick with MultiByteToWideChar() for consistency
  642 // (also, avoiding mbstowcs slightly reduces code size).  If there's ever a case where performance is
  643 // important, create a simple casting loop (see mbstowcs.c for an example) that converts source to dest,
  644 // and test if it performs significantly better than MultiByteToWideChar(CP_ACP...).
  645 #define ToWideChar(source, dest, dest_size_in_wchars) MultiByteToWideChar(CP_ACP, 0, source, -1, dest, dest_size_in_wchars)
  646 //
  647 // #2: FROM UTF-8 TO UNICODE (UTF-16). dest_size_in_wchars includes the terminator.  MSDN: "For UTF-8, dwFlags must be set to either 0 or MB_ERR_INVALID_CHARS. Otherwise, the function fails with ERROR_INVALID_FLAGS."
  648 #define UTF8ToWideChar(source, dest, dest_size_in_wchars) MultiByteToWideChar(CP_UTF8, 0, source, -1, dest, dest_size_in_wchars)
  649 //
  650 // #3: FROM UNICODE (UTF-16) TO UTF-8. dest_size_in_bytes includes the terminator.
  651 #define WideCharToUTF8(source, dest, dest_size_in_bytes) WideCharToMultiByte(CP_UTF8, 0, source, -1, dest, dest_size_in_bytes, NULL, NULL)
  652 
  653 #define UTF8StrLen(str, cch) MultiByteToWideChar(CP_UTF8, 0, (str), (cch), NULL, 0)
  654 #define WideUTF8StrLen(str, cch) WideCharToMultiByte(CP_UTF8, 0, (str), (cch), NULL, 0, NULL, NULL)
  655 
  656 #ifdef UNICODE
  657 #define PosToUTF8Pos              WideUTF8StrLen
  658 #define LenToUTF8Len(str,pos,len) WideUTF8StrLen(LPCWSTR(str)+int(pos),len)
  659 #define UTF8PosToPos              UTF8StrLen
  660 #define UTF8LenToLen(str,pos,len) UTF8StrLen(LPCSTR(str)+int(pos),len)
  661 
  662 inline char* WideToUTF8(LPCWSTR str){
  663     int buf_len = WideCharToUTF8(str, NULL, 0);
  664     LPSTR buf = (LPSTR) malloc(buf_len);
  665     if (buf) WideCharToUTF8(str, buf, buf_len);
  666     return buf;
  667 }
  668 inline LPTSTR UTF8ToWide(LPCSTR str){
  669     int buf_len = UTF8ToWideChar(str, NULL, 0);
  670     LPTSTR buf = (LPTSTR) tmalloc(buf_len);
  671     if (buf) UTF8ToWideChar(str, buf, buf_len);
  672     return buf;
  673 }
  674 #endif
  675 
  676 #ifdef UNICODE
  677 #define UorA(u,a)      (u)
  678 #define RegExToUTF8(a) CStringUTF8FromTChar(a)
  679 #define TPosToUTF8Pos  PosToUTF8Pos
  680 #define TLenToUTF8Len  LenToUTF8Len
  681 #define UTF8PosToTPos  UTF8PosToPos
  682 #define UTF8LenToTLen  UTF8LenToLen
  683 #define ToUnicodeOrAsciiEx(wVirtKey, wScanCode, lpKeyState, pszBuff, wFlags, dwhkl) \
  684     ToUnicodeEx((wVirtKey), (wScanCode), (lpKeyState), (LPWSTR)(pszBuff), 2, (wFlags), (dwhkl))
  685 #else
  686 #define UorA(u,a)            (a)
  687 #define RegExToUTF8(a)       (a)
  688 #define TPosToUTF8Pos(a,b)   (b)
  689 #define TLenToUTF8Len(a,b,c) (c)
  690 #define UTF8PosToTPos(a,b)   (b)
  691 #define UTF8LenToTLen(a,b,c) (c)
  692 #define ToUnicodeOrAsciiEx(wVirtKey, wScanCode, lpKeyState, pszBuff, wFlags, dwhkl) \
  693     ToAsciiEx((wVirtKey), (wScanCode), (lpKeyState), (LPWORD)(pszBuff), (wFlags), (dwhkl))
  694 #endif
  695 
  696 // v1.0.44.03: Callers now use the following macro rather than the old approach.  However, this change
  697 // is meaningful only to people who use more than one keyboard layout.  In the case of hotstrings:
  698 // It seems that the vast majority of them would want the Hotstring monitoring to adhere to the active
  699 // window's current keyboard layout rather than the script's.  This change is somewhat less certain to
  700 // be desirable unconditionally for the Input command (especially invisible/non-V-option Inputs); but it 
  701 // seems best to use the same approach to avoid calling ToAsciiEx() more than once in cases where a
  702 // script has hotstrings and also uses the Input command. Calling ToAsciiEx() twice in such a case would
  703 // be likely to aggravate its side effects with dead keys as described at length in the hook/Input code).
  704 // v1.1.27.01: Retrieve the layout of the thread which owns the focused control, not the active window.
  705 // This fixes UWP apps such as Microsoft Edge, where the top-level window is owned by a different process.
  706 #define Get_active_window_keybd_layout \
  707     HKL active_window_keybd_layout = GetFocusedKeybdLayout();
  708 
  709 
  710 #define FONT_POINT(hdc, p) (-MulDiv(p, GetDeviceCaps(hdc, LOGPIXELSY), 72))
  711 #define DATE_FORMAT_LENGTH 14 // "YYYYMMDDHHMISS"
  712 #define IS_LEAP_YEAR(year) ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  713 
  714 int GetYDay(int aMon, int aDay, bool aIsLeapYear);
  715 int GetISOWeekNumber(LPTSTR aBuf, int aYear, int aYDay, int aWDay);
  716 ResultType YYYYMMDDToFileTime(LPTSTR aYYYYMMDD, FILETIME &aFileTime);
  717 DWORD YYYYMMDDToSystemTime2(LPTSTR aYYYYMMDD, SYSTEMTIME *aSystemTime);
  718 ResultType YYYYMMDDToSystemTime(LPTSTR aYYYYMMDD, SYSTEMTIME &aSystemTime, bool aDoValidate);
  719 LPTSTR FileTimeToYYYYMMDD(LPTSTR aBuf, FILETIME &aTime, bool aConvertToLocalTime = false);
  720 LPTSTR SystemTimeToYYYYMMDD(LPTSTR aBuf, SYSTEMTIME &aTime);
  721 __int64 YYYYMMDDSecondsUntil(LPTSTR aYYYYMMDDStart, LPTSTR aYYYYMMDDEnd, bool &aFailed);
  722 __int64 FileTimeSecondsUntil(FILETIME *pftStart, FILETIME *pftEnd);
  723 
  724 SymbolType IsPureNumeric(LPCTSTR aBuf, BOOL aAllowNegative = false // BOOL vs. bool might squeeze a little more performance out of this frequently-called function.
  725     , BOOL aAllowAllWhitespace = true, BOOL aAllowFloat = false, BOOL aAllowImpure = false);
  726 
  727 void strlcpy(LPSTR aDst, LPCSTR aSrc, size_t aDstSize);
  728 void wcslcpy(LPWSTR aDst, LPCWSTR aSrc, size_t aDstSize);
  729 #ifdef UNICODE
  730 #define tcslcpy wcslcpy
  731 #else
  732 #define tcslcpy strlcpy
  733 #endif
  734 int sntprintf(LPTSTR aBuf, int aBufSize, LPCTSTR aFormat, ...);
  735 int sntprintfcat(LPTSTR aBuf, int aBufSize, LPCTSTR aFormat, ...);
  736 // Not currently used by anything, so commented out to possibly reduce code size:
  737 //int tcslcmp (LPTSTR aBuf1, LPTSTR aBuf2, UINT aLength1 = UINT_MAX, UINT aLength2 = UINT_MAX);
  738 int tcslicmp(LPTSTR aBuf1, LPTSTR aBuf2, size_t aLength1 = -1, size_t aLength2 = -1);
  739 LPTSTR tcsrstr(LPTSTR aStr, size_t aStr_length, LPCTSTR aPattern, StringCaseSenseType aStringCaseSense, int aOccurrence = 1);
  740 LPTSTR ltcschr(LPCTSTR haystack, TCHAR ch);
  741 LPTSTR lstrcasestr(LPCTSTR phaystack, LPCTSTR pneedle);
  742 LPTSTR tcscasestr (LPCTSTR phaystack, LPCTSTR pneedle);
  743 UINT StrReplace(LPTSTR aHaystack, LPTSTR aOld, LPTSTR aNew, StringCaseSenseType aStringCaseSense
  744     , UINT aLimit = UINT_MAX, size_t aSizeLimit = -1, LPTSTR *aDest = NULL, size_t *aHaystackLength = NULL);
  745 size_t PredictReplacementSize(ptrdiff_t aLengthDelta, int aReplacementCount, int aLimit, size_t aHaystackLength
  746     , size_t aCurrentLength, size_t aEndOffsetOfCurrMatch);
  747 LPTSTR TranslateLFtoCRLF(LPTSTR aString);
  748 bool DoesFilePatternExist(LPTSTR aFilePattern, DWORD *aFileAttr = NULL);
  749 #ifdef _DEBUG
  750     ResultType FileAppend(LPTSTR aFilespec, LPTSTR aLine, bool aAppendNewline = true);
  751 #endif
  752 LPTSTR ConvertFilespecToCorrectCase(LPTSTR aFilespec, LPTSTR aBuf, size_t aBufSize, size_t &aBufLength);
  753 void ConvertFilespecToCorrectCase(LPTSTR aBuf, size_t aBufSize, size_t &aBufLength);
  754 LPTSTR FileAttribToStr(LPTSTR aBuf, DWORD aAttr);
  755 unsigned __int64 GetFileSize64(HANDLE aFileHandle);
  756 LPTSTR GetWin32ErrorText(LPTSTR aBuf, DWORD aBufSize, DWORD aError);
  757 void AssignColor(LPTSTR aColorName, COLORREF &aColor, HBRUSH &aBrush);
  758 COLORREF ColorNameToBGR(LPTSTR aColorName);
  759 HRESULT MySetWindowTheme(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
  760 HRESULT MyEnableThemeDialogTexture(HWND hwnd, DWORD dwFlags);
  761 BOOL MyIsAppThemed();
  762 LPTSTR ConvertEscapeSequences(LPTSTR aBuf, TCHAR aEscapeChar, bool aAllowEscapedSpace);
  763 int FindNextDelimiter(LPCTSTR aBuf, TCHAR aDelimiter = ',', int aStartIndex = 0, LPCTSTR aLiteralMap = NULL);
  764 int FindExprDelim(LPCTSTR aBuf, TCHAR aDelimiter = ',', int aStartIndex = 0, LPCTSTR aLiteralMap = NULL);
  765 POINT CenterWindow(int aWidth, int aHeight);
  766 bool FontExist(HDC aHdc, LPCTSTR aTypeface);
  767 void ScreenToWindow(POINT &aPoint, HWND aHwnd);
  768 void CoordToScreen(int &aX, int &aY, int aWhichMode);
  769 void CoordToScreen(POINT &aPoint, int aWhichMode);
  770 void GetVirtualDesktopRect(RECT &aRect);
  771 BOOL IsProcess64Bit(HANDLE aHandle);
  772 BOOL IsOS64Bit();
  773 LPVOID AllocInterProcMem(HANDLE &aHandle, DWORD aSize, HWND aHwnd, DWORD aExtraAccess = 0);
  774 void FreeInterProcMem(HANDLE aHandle, LPVOID aMem);
  775 
  776 DWORD GetEnvVarReliable(LPCTSTR aEnvVarName, LPTSTR aBuf);
  777 DWORD ReadRegString(HKEY aRootKey, LPTSTR aSubkey, LPTSTR aValueName, LPTSTR aBuf, DWORD aBufSize, DWORD aFlag = 0);
  778 
  779 HBITMAP LoadPicture(LPTSTR aFilespec, int aWidth, int aHeight, int &aImageType, int aIconNumber
  780     , bool aUseGDIPlusIfAvailable, bool *apNoDelete = NULL, HMODULE *apModule = NULL);
  781 HBITMAP IconToBitmap(HICON ahIcon, bool aDestroyIcon);
  782 HBITMAP IconToBitmap32(HICON aIcon, bool aDestroyIcon); // Lexikos: Used for menu icons on Vista+. Creates a 32-bit (ARGB) device-independent bitmap from an icon.
  783 int CALLBACK FontEnumProc(ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, DWORD FontType, LPARAM lParam);
  784 bool IsStringInList(LPTSTR aStr, LPTSTR aList, bool aFindExactMatch);
  785 LPTSTR InStrAny(LPTSTR aStr, LPTSTR aNeedle[], int aNeedleCount, size_t &aFoundLen);
  786 
  787 LPTSTR ResourceIndexToId(HMODULE aModule, LPCTSTR aType, int aIndex); // L17: Find integer ID of resource from index. i.e. IconNumber -> resource ID.
  788 HICON ExtractIconFromExecutable(LPTSTR aFilespec, int aIconNumber, int aWidth, int aHeight // L17: Extract icon of the appropriate size from an executable (or compatible) file.
  789     , HMODULE *apModule = NULL);
  790 
  791 int CompareVersion(LPCTSTR a, LPCTSTR b);
  792 
  793 // This is used due to the popcnt instruction not being supported on old CPUs.
  794 // Source: https://www.autohotkey.com/boards/viewtopic.php?f=14&p=384978
  795 inline int popcount8(unsigned char c)
  796 {
  797     c = (c & 0x55u) + ((c >> 1) & 0x55u);
  798     c = (c & 0x33u) + ((c >> 2) & 0x33u);
  799     c = (c & 0x0fu) + ((c >> 4) & 0x0fu);
  800     return c;
  801 }
  802 
  803 #if defined(_MSC_VER) && defined(_DEBUG)
  804 void OutputDebugStringFormat(LPCTSTR fmt, ...); // put debug message to the "Output" panel of Visual Studio.
  805 #endif
  806 
  807 #endif