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

Function IsNumeric

source/util.cpp:317–419  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

315
316
317SymbolType IsNumeric(LPCTSTR aBuf, BOOL aAllowNegative, BOOL aAllowAllWhitespace
318 , BOOL aAllowFloat, BOOL aAllowImpure) // BOOL vs. bool might squeeze a little more performance out of this frequently-called function.
319// String can contain whitespace.
320// If aBuf doesn't contain something purely numeric, PURE_NOT_NUMERIC is returned. The same happens if
321// aBuf contains a float but aAllowFloat is false. (The aAllowFloat parameter isn't strictly necessary
322// because the caller could just check whether the return value is/isn't PURE_FLOAT to get the same effect.
323// However, supporting aAllowFloat seems to greatly improve maintainability because it saves many callers
324// from having to compare the return value to PURE_INTEGER [they can just interpret the return value as BOOL].
325// It also improves readability due to the "Is" part of the function name. So it seems worth keeping.)
326// Otherwise, PURE_INTEGER or PURE_FLOAT is returned.
327// If aAllowAllWhitespace==true and the string is blank or all whitespace, PURE_INTEGER is returned.
328// Obsolete comment: Making this non-inline reduces the size of the compressed EXE by only 2K. Since this
329// function is called so often, it seems preferable to keep it inline for performance.
330{
331 aBuf = omit_leading_whitespace(aBuf); // i.e. caller doesn't have to have ltrimmed, only rtrimmed.
332 if (!*aBuf) // The string is empty or consists entirely of whitespace.
333 return aAllowAllWhitespace ? PURE_INTEGER : PURE_NOT_NUMERIC;
334
335 if (*aBuf == '-')
336 {
337 if (aAllowNegative)
338 ++aBuf;
339 else
340 return PURE_NOT_NUMERIC;
341 }
342 else if (*aBuf == '+')
343 ++aBuf;
344
345 // Relies on short circuit boolean order to prevent reading beyond the end of the string:
346 BOOL is_hex = IS_HEX(aBuf); // BOOL vs. bool might squeeze a little more performance out this frequently-called function.
347 if (is_hex)
348 aBuf += 2; // Skip over the 0x prefix.
349
350 // Set defaults:
351 BOOL has_decimal_point = false;
352 BOOL has_exponent = false;
353 BOOL has_at_least_one_digit = false; // i.e. a string consisting of only "+", "-" or "." is not considered numeric.
354 int c; // int vs. char might squeeze a little more performance out of it (it does reduce code size by 5 bytes). Probably must stay signed vs. unsigned for some of the uses below.
355
356 for (;; ++aBuf)
357 {
358 c = *aBuf;
359 if (IS_SPACE_OR_TAB(c))
360 {
361 if (*omit_leading_whitespace(aBuf)) // But that space or tab is followed by something other than whitespace.
362 if (!aAllowImpure) // e.g. "123 456" is not a valid pure number.
363 return PURE_NOT_NUMERIC;
364 // else fall through to the bottom logic.
365 // else since just whitespace at the end, the number qualifies as pure, so fall through to the bottom
366 // logic (it would already have returned in the loop if it was impure)
367 break;
368 }
369 if (!c) // End of string was encountered.
370 break; // The number qualifies as pure, so fall through to the logic at the bottom. (It would already have returned elsewhere in the loop if the number is impure).
371 if (c == '.')
372 {
373 if (!aAllowFloat || has_decimal_point || is_hex) // If aAllowFloat==false, a decimal point at the very end of the number is considered non-numeric even if aAllowImpure==true. Some callers might rely on this.
374 // i.e. if aBuf contains 2 decimal points, it can't be a valid number.

Callers 15

ControlSetChoiceMethod · 0.85
ParseOptionsMethod · 0.85
ControlParseOptionsMethod · 0.85
FindControlMethod · 0.85
FindOrCreateFontMethod · 0.85
ProcessExistFunction · 0.85
DefineFuncMethod · 0.85
PreparseCommandsMethod · 0.85
ExecUntilMethod · 0.85
UnhandledExceptionMethod · 0.85
ParseClickOptionsFunction · 0.85
IsNumericMethod · 0.85

Calls 2

omit_leading_whitespaceFunction · 0.85
ctoupperFunction · 0.85

Tested by

no test coverage detected