- Here are some potential AHK functions written in C++.
- Once inserted into the source code, and compiled, they work just like any other built-in functions.
- I would welcome people to post better more efficient versions of the functions.
C++: AHK source code: potential functions
C++: AHK source code: potential functions
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: C++: AHK source code: potential functions
Code: Select all
==================================================
for AHK v1: function names and parameters:
ATan2(NumY, NumX)
Between(Num, Lim1, Lim2)
[FloorCeil] Ceil(Num, DP:=0)
[FloorCeil] Floor(Num, DP:=0)
IsNum(Num)
Log(Num, Base:=10)
NoOp(Params*)
Num(Num)
Pow(Num, Power)
Sign(Num)
StrCount(Haystack, Needle, CaseSen:="", StartPos:=1)
StrJoin(Sep, Params*)
StrRept(Text, Num)
- note: BIF_FloorCeil would be amended
- note: BIF_Log would be used for Log, instead of BIF_SqrtLogLn
- note: I wouldn't mind if StrCount's StartPos parameter was removed for now
- note: For StrCount, a decision would be needed on how to handle a negative StartPos (I would recommend the AHK v2 behaviour for AHK v1 and AHK v2)
- note: StrJoin takes a string 'Sep', however, perhaps functionality for passing a linear array could be added, for alternating separators
- IsNum:
- Float/Integer/numeric-looking string return 1, else 0.
- Num:
- Float/Integer unchanged, numeric-looking string to Float/Integer, else error.
- I've since thought of adding a second parameter: Default.
- If present, instead of an error, the Default would be returned e.g. 0, or "".
==================================================
[script.h]
BIF_DECL(BIF_ATan2);
BIF_DECL(BIF_Between);
BIF_DECL(BIF_FloorCeil);
BIF_DECL(BIF_IsNum);
BIF_DECL(BIF_Log);
BIF_DECL(BIF_NoOp);
BIF_DECL(BIF_Num);
BIF_DECL(BIF_Pow);
BIF_DECL(BIF_Sign);
BIF_DECL(BIF_StrCount);
BIF_DECL(BIF_StrJoin);
BIF_DECL(BIF_StrRept);
==================================================
[script.cpp]
else if (!_tcsicmp(func_name, _T("ATan2")))
{
bif = BIF_ATan2;
min_params = 2;
max_params = 2;
}
else if (!_tcsicmp(func_name, _T("Between")))
{
bif = BIF_Between;
min_params = 3;
max_params = 3;
}
else if (!_tcsicmp(func_name, _T("Floor")) || !_tcsicmp(func_name, _T("Ceil")))
{
bif = BIF_FloorCeil;
max_params = 2;
}
else if (!_tcsicmp(func_name, _T("IsNum")))
{
bif = BIF_IsNum;
}
else if (!_tcsicmp(func_name, _T("Log")))
{
bif = BIF_Log;
max_params = 2;
}
else if (!_tcsicmp(func_name, _T("NoOp")))
{
bif = BIF_NoOp;
min_params = 0;
max_params = 10000; // An arbitrarily high limit that will never realistically be reached.
}
else if (!_tcsicmp(func_name, _T("Num")))
{
bif = BIF_Num;
}
else if (!_tcsicmp(func_name, _T("Pow")))
{
bif = BIF_Pow;
min_params = 2;
max_params = 2;
}
else if (!_tcsicmp(func_name, _T("Sign")))
{
bif = BIF_Sign;
}
else if (!_tcsicmp(func_name, _T("StrCount")))
{
bif = BIF_StrCount;
min_params = 2;
max_params = 4;
}
else if (!_tcsicmp(func_name, _T("StrJoin")))
{
bif = BIF_StrJoin;
min_params = 2;
max_params = 10000; // An arbitrarily high limit that will never realistically be reached.
}
else if (!_tcsicmp(func_name, _T("StrRept")))
{
bif = BIF_StrRept;
min_params = 2;
max_params = 2;
}
==================================================
[script2.cpp]
BIF_DECL(BIF_ATan2)
{
// For simplicity and backward compatibility, a numeric result is always returned (even if the input
// is non-numeric or an empty string).
aResultToken.symbol = SYM_FLOAT;
aResultToken.value_double = qmathAtan2(ParamIndexToDouble(0), ParamIndexToDouble(1));
}
BIF_DECL(BIF_Between)
{
if (!TokenToDoubleOrInt64(*aParam[0], aResultToken)) // "Cast" token to Int64/Double depending on whether it has a decimal point.
return;
if (!TokenToDoubleOrInt64(*aParam[1], aResultToken)) // "Cast" token to Int64/Double depending on whether it has a decimal point.
return;
if (!TokenToDoubleOrInt64(*aParam[2], aResultToken)) // "Cast" token to Int64/Double depending on whether it has a decimal point.
return;
double value = ParamIndexToDouble(0);
double min = ParamIndexToDouble(1);
double max = ParamIndexToDouble(2);
aResultToken.symbol = SYM_INTEGER;
if (min <= value && value <= max)
aResultToken.value_int64 = 1;
else
aResultToken.value_int64 = 0;
}
BIF_DECL(BIF_FloorCeil)
{
LPTSTR buf = aResultToken.buf; // Must be saved early since below overwrites the union (better maintainability too).
int param2;
double multiplier;
if (aParamCount > 1)
{
param2 = ParamIndexToInt(1);
multiplier = qmathPow(10, param2);
}
else // Omitting the parameter is the same as explicitly specifying 0 for it.
{
param2 = 0;
multiplier = 1;
}
double value = ParamIndexToDouble(0);
aResultToken.value_double = ((ctoupper(aResultToken.marker[0]) == 'F') ? qmathFloor(value * multiplier)
: qmathCeil(value * multiplier)) / multiplier;
if (param2 > 0) // aResultToken.value_double already contains the result.
{
_stprintf(buf, _T("%0.*f"), param2, aResultToken.value_double); // %f can handle doubles in MSVC++.
aResultToken.marker = buf;
aResultToken.symbol = SYM_STRING;
}
else
aResultToken.value_int64 = (__int64)(aResultToken.value_double + (aResultToken.value_double > 0 ? 0.2 : -0.2));
}
BIF_DECL(BIF_IsNum)
{
if (!TokenToDoubleOrInt64(*aParam[0], aResultToken)) // "Cast" token to Int64/Double depending on whether it has a decimal point.
{
aResultToken.symbol = SYM_INTEGER;
aResultToken.value_int64 = 0;
}
else
{
aResultToken.symbol = SYM_INTEGER;
aResultToken.value_int64 = 1;
}
}
BIF_DECL(BIF_Log)
{
double value = ParamIndexToDouble(0);
double base = ParamIndexIsOmitted(1) ? 10 : ParamIndexToDouble(1);
if (value < 0 || base < 0) // Result is undefined in these cases, so make blank to indicate.
{
aResultToken.symbol = SYM_STRING;
aResultToken.marker = _T("");
}
else if (base == 10)
{
aResultToken.symbol = SYM_FLOAT;
aResultToken.value_double = qmathLog10(value);
}
else
{
aResultToken.symbol = SYM_FLOAT;
aResultToken.value_double = qmathLog10(value)/qmathLog10(base);
//aResultToken.value_double = qmathLog(value)/qmathLog(base);
}
}
BIF_DECL(BIF_NoOp)
{
aResultToken.symbol = SYM_STRING;
aResultToken.marker = _T("");
}
BIF_DECL(BIF_Num)
{
if (!TokenToDoubleOrInt64(*aParam[0], aResultToken)) // "Cast" token to Int64/Double depending on whether it has a decimal point.
{
aResultToken.symbol = SYM_STRING;
aResultToken.marker = _T("");
}
}
BIF_DECL(BIF_Pow)
{
double value_double1 = ParamIndexToDouble(0);
double value_double2 = ParamIndexToDouble(1);
bool value1_was_negative = (value_double1 < 0);
if (value_double1 == 0.0 && value_double2 < 0 // In essence, this is divide-by-zero.
|| value1_was_negative && qmathFmod(value_double2, 1.0) != 0.0) // Negative base but exponent isn't close enough to being an integer: unsupported (to simplify code).
{
aResultToken.symbol = SYM_STRING;
aResultToken.marker = _T("");
return;
}
// Otherwise:
if (value1_was_negative)
value_double1 = -value_double1; // Force a positive due to the limitations of qmathPow().
double result_double = qmathPow(value_double1, value_double2);
if (value1_was_negative && qmathFabs(qmathFmod(value_double2, 2.0)) == 1.0) // Negative base and exactly-odd exponent (otherwise, it can only be zero or even because if not it would have returned higher above).
result_double = -result_double;
if (qmathFloor(result_double) == result_double)
{
aResultToken.symbol = SYM_INTEGER;
aResultToken.value_int64 = (__int64)result_double;
}
else
{
aResultToken.symbol = SYM_FLOAT;
aResultToken.value_double = result_double;
}
}
BIF_DECL(BIF_Sign)
{
if (!TokenToDoubleOrInt64(*aParam[0], aResultToken)) // "Cast" token to Int64/Double depending on whether it has a decimal point.
return;
double value = ParamIndexToDouble(0);
aResultToken.symbol = SYM_INTEGER;
if (value > 0)
aResultToken.value_int64 = 1;
else if (value < 0)
aResultToken.value_int64 = -1;
else
aResultToken.value_int64 = 0;
}
BIF_DECL(BIF_StrCount)
{
TCHAR old_buf[MAX_NUMBER_SIZE], new_buf[MAX_NUMBER_SIZE];
// Must use aResultToken.buf for source in case StrReplace() performs no replacements:
LPTSTR source = ParamIndexToString(0, aResultToken.buf); // Parameter #1: Haystack
size_t length = ParamIndexLength(0, source);
LPTSTR oldstr = ParamIndexToString(1, old_buf); // Parameter #2: SearchText
//LPTSTR newstr = ParamIndexToOptionalString(2, new_buf); // Parameter #3: ReplaceText
LPTSTR newstr = new_buf;
//UINT replacement_limit = (UINT)ParamIndexToOptionalInt64(4, UINT_MAX); // Parameter #5: Limit
UINT replacement_limit = (UINT)-1; // Parameter #5: Limit
int start_pos = ParamIndexIsOmitted(3) ? 0 : ParamIndexToInt(3)-1;
LPTSTR dest;
UINT found_count;
if (ParamIndexIsOmitted(2))
found_count = StrReplace(source+start_pos, oldstr, newstr, (StringCaseSenseType)g->StringCaseSense
, replacement_limit, -1, &dest, &length);
else
{
int case_sen = ParamIndexToInt(2);
if (case_sen == 1 || case_sen == 0)
found_count = StrReplace(source+start_pos, oldstr, newstr, (StringCaseSenseType)case_sen
, replacement_limit, -1, &dest, &length);
}
if (!dest) // Failure due to out of memory.
{
aResult = g_script.ScriptError(ERR_OUTOFMEM);
return;
}
//aResultToken.symbol = SYM_STRING;
//aResultToken.marker = dest;
//if (dest != source) // StrReplace() allocated new memory rather than returning "source" to us unaltered.
//{
// aResultToken.mem_to_free = dest; // Let caller know it needs to be freed.
// aResultToken.marker_length = length; // Must always be set if using mem_to_free.
//}
aResultToken.symbol = SYM_INTEGER;
aResultToken.value_int64 = (__int64)found_count;
}
BIF_DECL(BIF_StrJoin)
{
aResultToken.symbol = SYM_STRING;
if (aParamCount < 2)
{
aResultToken.marker = _T("");
return;
}
int len_sep = (int)_tcslen(ParamIndexToString(0));
TCHAR *sep = new TCHAR[len_sep+1];
tmemcpy(sep, ParamIndexToString(0), len_sep+1);
int len = 0;
for (int i = 1; i < aParamCount; ++i)
len += (int)_tcslen(ParamIndexToString(i));
int len_out = len+len_sep*(aParamCount-2)+1;
TCHAR *output = new TCHAR[len_out];
len = 0;
int len_temp;
for (int i = 1; i < aParamCount-1; ++i)
{
len_temp = _tcslen(ParamIndexToString(i));
tmemcpy(output+len, ParamIndexToString(i), len_temp);
tmemcpy(output+len+len_temp, sep, len_sep);
len += len_temp+len_sep;
}
len_temp = _tcslen(ParamIndexToString(aParamCount-1));
tmemcpy(output+len, ParamIndexToString(aParamCount-1), len_temp);
*(output+len_out-1) = '\0';
aResultToken.marker = output;
}
BIF_DECL(BIF_StrRept)
{
aResultToken.symbol = SYM_STRING;
int len = (int)_tcslen(ParamIndexToString(0));
int count = (int)ParamIndexToInt64(1);
if (count < 1)
{
aResultToken.marker = _T("");
return;
}
int size = len*count+1;
TCHAR *output = new TCHAR[size];
for (int i = 0; i <= count-1; i++)
tmemcpy(output+i*len, ParamIndexToString(0), len);
*(output+size-1) = '\0';
aResultToken.marker = output;
}
==================================================
C++: AHK source code: FloorMod - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=75&t=64692
C++: AHK source code: StrJoin (alternating pad string) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=75&t=64693
C++: AHK source code: Base64Get/Base64Put and HexGet/HexPut - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=75&t=64694
C++: AHK source code: VarIsInit - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=75&t=65308
And:
[Sum function]
C++: AHK source code: demo functions - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=75&t=54386
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Who is online
Users browsing this forum: No registered users and 0 guests