[FarGroup/FarManager] master: Refactoring, clean up tvar.*pp (4d877380b)

1 view
Skip to first unread message

farg...@farmanager.com

unread,
Sep 25, 2026, 2:15:56 PM (10 days ago) Sep 25
to farco...@googlegroups.com
Repository : https://github.com/FarGroup/FarManager
On branch : master
Link : https://github.com/FarGroup/FarManager/commit/4d877380bf1c068c964372ef245ee1e1e70cec92

>---------------------------------------------------------------

commit 4d877380bf1c068c964372ef245ee1e1e70cec92
Author: Alex Alabuzhev <alab...@gmail.com>
Date: Fri Sep 25 19:00:06 2026 +0100

Refactoring, clean up tvar.*pp


>---------------------------------------------------------------

4d877380bf1c068c964372ef245ee1e1e70cec92
far/changelog | 5 +
far/macroapi.cpp | 110 +++++------------
far/plugapi.cpp | 3 +
far/tvar.cpp | 364 ++++++++++---------------------------------------------
far/tvar.hpp | 21 ++--
far/vbuild.m4 | 2 +-
6 files changed, 114 insertions(+), 391 deletions(-)

diff --git a/far/changelog b/far/changelog
index f31543530..b5bd0b0a8 100644
--- a/far/changelog
+++ b/far/changelog
@@ -1,3 +1,8 @@
+--------------------------------------------------------------------------------
+drkns 2026-09-25 18:58:09+01:00 - build 6739
+
+1. Refactoring, clean up tvar.*pp.
+
--------------------------------------------------------------------------------
zeroes 2026-09-23 17:23:27+03:00 - build 6738

diff --git a/far/macroapi.cpp b/far/macroapi.cpp
index dae39b401..4c584e562 100644
--- a/far/macroapi.cpp
+++ b/far/macroapi.cpp
@@ -114,12 +114,8 @@ static TVar Convert2TVar(const FarMacroValue &val)
case FMVT_STRING: return TVar(val.String);
case FMVT_POINTER: return TVar(val.Pointer);
case FMVT_DIALOG: return TVar(static_cast<Dialog*>(val.Pointer));
- case FMVT_TABLE: {
- TVar tv(val.Integer);
- tv.SetType(TVar::Type::Table);
- return tv;
- }
- default: return TVar();
+ case FMVT_TABLE: return TVar(val.Integer, TVar::Type::Table);
+ default: return TVar();
}
}

@@ -1582,14 +1578,28 @@ void FarMacroApi::waitkeyFunc() const
void FarMacroApi::minFunc() const
{
const auto Params = parseParams(2);
- PushValue(std::min(Params[0], Params[1]));
+
+ PushValue(std::min(Params[0], Params[1], [](TVar const& a, TVar const& b)
+ {
+ if (a.isDouble() || b.isDouble())
+ return a.asDouble() < b.asDouble();
+
+ return a.asInteger() < b.asInteger();
+ }));
}

// n=max(n1,n2)
void FarMacroApi::maxFunc() const
{
const auto Params = parseParams(2);
- PushValue(std::max(Params[0], Params[1]));
+
+ PushValue(std::min(Params[0], Params[1], [](TVar const& a, TVar const& b)
+ {
+ if (a.isDouble() || b.isDouble())
+ return a.asDouble() > b.asDouble();
+
+ return a.asInteger() > b.asInteger();
+ }));
}

// n=mod(n1,n2)
@@ -1597,59 +1607,13 @@ void FarMacroApi::modFunc() const
{
const auto Params = parseParams(2);

- const auto NumeratorType = Params[0].ParseType();
- const auto DenominatorType = Params[1].ParseType();
-
- TVar Result;
-
- switch(DenominatorType)
+ if (Params[0].isDouble() || Params[1].isDouble())
{
- case TVar::Type::Unknown:
- case TVar::Type::Integer:
- if (const auto Denominator = Params[1].asInteger())
- {
- switch (NumeratorType)
- {
- case TVar::Type::Unknown:
- case TVar::Type::Integer:
- Result = Params[0].asInteger() % Denominator;
- break;
-
- case TVar::Type::Double:
- Result = std::fmod(Params[0].asDouble(), Denominator);
- break;
-
- default:
- break;
- }
- }
- break;
-
- case TVar::Type::Double:
- if (const auto Denominator = Params[1].asDouble())
- {
- switch (NumeratorType)
- {
- case TVar::Type::Unknown:
- case TVar::Type::Integer:
- Result = std::fmod(Params[0].asInteger(), Denominator);
- break;
-
- case TVar::Type::Double:
- Result = std::fmod(Params[0].asDouble(), Denominator);
- break;
-
- default:
- break;
- }
- }
- break;
-
- default:
- break;
+ PushValue(std::fmod(Params[0].asDouble(), Params[1].asDouble()));
+ return;
}

- PushValue(Result);
+ PushValue(Params[0].asInteger() % Params[1].asInteger());
}

// N=index(S1,S2[,Mode])
@@ -3500,33 +3464,19 @@ void FarMacroApi::absFunc() const
{
const auto Params = parseParams(1);

- TVar Result;
-
- switch(Params[0].ParseType())
+ if (Params[0].isInteger())
{
- case TVar::Type::Integer:
- {
- if (const auto i = Params[0].asInteger(); i < 0)
- Result = -i;
- else
- Result = Params[0];
- }
- break;
+ if (const auto i = Params[0].asInteger(); i < 0)
+ return PushValue(-i);
+ }

- case TVar::Type::Double:
- {
+ if (Params[0].isDouble())
+ {
if (const auto d = Params[0].asDouble(); d < 0)
- Result = -d;
- else
- Result = Params[0];
- }
- break;
-
- default:
- break;
+ return PushValue(-d);
}

- PushValue(Result);
+ PushValue(Params[0]);
}

void FarMacroApi::ascFunc() const
diff --git a/far/plugapi.cpp b/far/plugapi.cpp
index a3c9fdf07..1c80af0a4 100644
--- a/far/plugapi.cpp
+++ b/far/plugapi.cpp
@@ -1222,6 +1222,9 @@ intptr_t WINAPI apiMessageFn(const UUID* PluginId, const UUID* Id, unsigned long
TrailingNewLine = true;
}

+ const auto LinesCount = std::ranges::count(StrItems, L'\n') + 1;
+ Strings.reserve(LinesCount == 1 && TrailingNewLine? 2 : LinesCount);
+
for (const auto& i: enum_tokens(StrItems, L"\n"sv))
Strings.emplace_back(i);

diff --git a/far/tvar.cpp b/far/tvar.cpp
index 95a7b7fb1..ccc33ee5d 100644
--- a/far/tvar.cpp
+++ b/far/tvar.cpp
@@ -57,197 +57,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// If not, I don't know who wrote it.
//---------------------------------------------------------------

-enum TypeString
-{
- tsStr,
- tsInt,
- tsFloat,
-};
-
-static TypeString checkTypeString(const string& TestStr)
-{
- TypeString typeTestStr=tsStr;
-
- if (!TestStr.empty())
- {
- auto ptrTestStr = TestStr.c_str();
- wchar_t ch, ch2;
- bool isNum = true;
- //bool isDec = false;
- bool isBegDec = false;
- //bool isHex = false;
- bool isBegHex = false;
- //bool isOct = false;
- bool isBegOct = false;
- //bool isE = false;
- bool isExp = false;
- bool isPoint = false;
- bool isSign = false;
- bool isExpSign = false;
-
- if (*ptrTestStr == L'-' || *ptrTestStr == L'+')
- {
- isSign=true;
- ptrTestStr++;
- }
-
- if (*ptrTestStr == L'.' && std::iswdigit(ptrTestStr[1]))
- {
- isPoint=true;
- ptrTestStr++;
- }
-
- if (*ptrTestStr >= L'1' && *ptrTestStr <=L'9')
- isBegDec=true;
- else if (*ptrTestStr == L'0')
- {
- if ((ptrTestStr[1] == L'x' || ptrTestStr[1] == L'X') && std::iswxdigit(ptrTestStr[2]))
- {
- isBegHex=true;
- ptrTestStr+=2;
- }
- else
- {
- if (std::iswdigit(ptrTestStr[1]) || ptrTestStr[1] == L'.')
- isBegDec=true;
- else if (!ptrTestStr[1])
- return tsInt;
- else
- isBegOct=true;
- }
- }
-
- while ((ch=*ptrTestStr++) != 0)
- {
- switch (ch)
- {
- case L'-':
- case L'+':
-
- if (ptrTestStr == TestStr.c_str() + 1)
- isSign=true;
- else if (isSign)
- {
- isNum=false;
- break;
- }
-
- if (isExp)
- {
- if (isExpSign)
- {
- isNum=false;
- break;
- }
-
- isExpSign=true;
- }
-
- break;
- case L'.':
-
- if (isPoint)
- {
- isNum=false;
- break;
- }
-
- isPoint=true;
-
- if (!(std::iswdigit(ptrTestStr[1]) || ptrTestStr[1] == L'e' || ptrTestStr[1] == L'E' || !ptrTestStr[1]))
- {
- isNum=false;
- break;
- }
-
- break;
- case L'e':
- case L'E':
- //isHex=true;
- //isE=true;
- ch2=*ptrTestStr++;
-
- if (ch2 == L'-' || ch2 == L'+') // E+D
- {
- if (isBegHex || isExpSign) // начало hex или уже был знак у порядка?
- {
- isNum=false;
- break;
- }
-
- isExpSign=true;
- const auto ch3 = *ptrTestStr++;
-
- if (!std::iswdigit(ch3)) // за знаком идет число?
- {
- isNum=false;
- break;
- }
- else
- {
- isExp=true;
- }
- }
- else if (!std::iswdigit(ch2)) // ED
- {
- if (isBegDec)
- {
- isNum=false;
- break;
- }
-
- ptrTestStr--;
- }
- else
- {
- isExp=true;
- ptrTestStr--;
- }
-
- break;
- case L'a': case L'A': case L'b': case L'B': case L'c': case L'C': case L'd': case L'D': case L'f': case L'F':
-
- if (isBegDec || isExp)
- {
- isNum=false;
- break;
- }
-
- //isHex=true;
- break;
- case L'0': case L'1': case L'2': case L'3': case L'4': case L'5': case L'6': case L'7':
- //isOct=true;
- case L'8': case L'9':
-
- if (isBegOct && (ch == L'8' || ch == L'9'))
- {
- isNum=false;
- break;
- }
-
- //isDec=true;
- break;
- default:
- isNum=false;
- }
-
- if (!isNum)
- break;
- }
-
- if (isNum)
- {
- if (isBegDec && (isExp || isPoint))
- typeTestStr=tsFloat;
-
- if ((isBegDec || isBegHex || isBegOct) && !(isExp || isPoint))
- typeTestStr=tsInt;
- }
- }
-
- return typeTestStr;
-}
-
TVar::TVar():
vType(Type::Unknown)
{
@@ -259,6 +68,12 @@ TVar::TVar(long long v):
{
}

+TVar::TVar(long long const v, Type const t):
+ inum(v),
+ vType(t)
+{
+}
+
TVar::TVar(int v):
TVar(static_cast<long long>(v))
{
@@ -317,14 +132,28 @@ double TVar::toDouble()

const string& TVar::asString() const
{
- if (!isString())
+ switch (vType)
{
+ case Type::String:
+ break;
+
+ case Type::Integer:
+ str = ::str(inum);
+ break;
+
+ case Type::Double:
// str() is implemented in terms of fmt::to_wstring().
// For doubles fmt::to_wstring adds ".0" even if there's no fractional part
// (e.g. 1234.0 to "1234.0"), and it's a feature (see issue #1153).
// For historical reasons we prefer the shortest possible representation, hence "g".
- str = isInteger()? ::str(inum) : far::format(L"{:.14g}"sv, dnum);
+ str = far::format(L"{:.14g}"sv, dnum);
+ break;
+
+ default:
+ str.clear();
+ break;
}
+
return str;
}

@@ -334,7 +163,6 @@ long long TVar::asInteger() const
{
case Type::Integer:
case Type::Table:
- case Type::Unknown:
return inum;

case Type::Double:
@@ -357,7 +185,6 @@ double TVar::asDouble() const
{
case Type::Integer:
case Type::Table:
- case Type::Unknown:
return inum;

case Type::Double:
@@ -402,116 +229,57 @@ bool TVar::isNumber() const
{
switch (type())
{
- case Type::Unknown:
- case Type::Integer:
- case Type::Double:
- case Type::Table:
- return true;
-
- case Type::String:
- switch (checkTypeString(str))
- {
- case tsInt:
- case tsFloat:
- return true;
- default:
- return false;
- }
- case Type::Pointer:
- case Type::Dialog:
- return false;
- }
-
- return false;
-}
-
-TVar::Type TVar::ParseType() const
-{
- if (vType != Type::String)
- return vType;
-
- switch(checkTypeString(str))
- {
- case tsInt:
- return Type::Integer;
-
- case tsFloat:
- return Type::Double;
+ case Type::Integer:
+ case Type::Double:
+ case Type::Table:
+ return true;

default:
- return Type::String;
+ return false;
}
}

-bool TVar::operator<(const TVar& rhs) const
-{
- switch (type())
- {
- case Type::Unknown:
- case Type::Integer:
- case Type::Table:
- switch (rhs.type())
- {
- case Type::Unknown:
- case Type::Integer:
- case Type::Table:
- return asInteger() < rhs.asInteger();
-
- case Type::Double:
- return asDouble() < rhs.asDouble();
-
- case Type::String:
- switch (checkTypeString(rhs.asString()))
- {
- case tsStr:
- return string_sort::less(asString(), rhs.asString());
-
- case tsInt:
- return asInteger() < rhs.asInteger();
-
- case tsFloat:
- return asDouble() < rhs.asDouble();
- }
- break;
- case Type::Pointer:
- case Type::Dialog:
- break;
- }
- break;
+#ifdef ENABLE_TESTS

- case Type::Double:
- switch (rhs.type())
- {
- case Type::Unknown:
- case Type::Integer:
- case Type::Table:
- case Type::Double:
- return asDouble() < rhs.asDouble();
-
- case Type::String:
- switch (checkTypeString(rhs.asString()))
- {
- case tsStr:
- return string_sort::less(asString(), rhs.asString());
-
- case tsInt:
- case tsFloat:
- return asDouble() < rhs.asDouble();
- }
- break;
- case Type::Pointer:
- case Type::Dialog:
- break;
- }
- break;
+#include "testing.hpp"

- case Type::String:
- return string_sort::less(asString(), rhs.asString());
+TEST_CASE("TVar")
+{
+ const auto
+ IntMin = std::numeric_limits<int64_t>::min(),
+ IntMax = std::numeric_limits<int64_t>::max();

- case Type::Pointer:
- case Type::Dialog:
- break;
+ static const struct tests
+ {
+ TVar t;
+ TVar::Type Type;
+ bool IsNumber;
+ string_view sValue;
+ long long iValue;
+ double dValue;
+ }
+ Tests[]
+ {
+ { TVar{}, TVar::Type::Unknown, false, {}, {}, {} },
+ { TVar{ 0 }, TVar::Type::Integer, true, L"0"sv, {}, {} },
+ { TVar{ IntMin }, TVar::Type::Integer, true, L"-9223372036854775808"sv, IntMin, static_cast<double>(IntMin) },
+ { TVar{ IntMax }, TVar::Type::Integer, true, L"9223372036854775807"sv, IntMax, static_cast<double>(IntMax) },
+ { TVar{ 42.0 }, TVar::Type::Double, true, L"42"sv, 42, 42.0 },
+ { TVar{ 42.123 }, TVar::Type::Double, true, L"42.123"sv, 42, 42.123 },
+ { TVar{ L"banana"sv }, TVar::Type::String, false, L"banana"sv, {}, {} },
+ { TVar{ L"Bamboléo" }, TVar::Type::String, false, L"Bamboléo"sv, {}, {} },
+ { TVar{ std::bit_cast<void*>(intptr_t{42}) }, TVar::Type::Pointer, false, L""sv, {}, {} },
+ };
+
+ for (const auto& i: Tests)
+ {
+ REQUIRE(i.t.type() == i.Type);
+ REQUIRE(i.t.isNumber() == i.IsNumber);
+ REQUIRE(i.t.asString() == i.sValue);
+ REQUIRE(i.t.asInteger() == i.iValue);
+ REQUIRE(i.t.asDouble() == i.dValue);
}
-
- return false;
}
+
+#endif
+
diff --git a/far/tvar.hpp b/far/tvar.hpp
index 0c43306a9..570708d4a 100644
--- a/far/tvar.hpp
+++ b/far/tvar.hpp
@@ -72,13 +72,14 @@ public:
MOVABLE(TVar);

explicit TVar();
- explicit TVar(int);
- explicit TVar(long long);
- explicit TVar(string_view);
- explicit TVar(const wchar_t*);
- explicit TVar(double);
- explicit TVar(void*);
- explicit TVar(Dialog*);
+ explicit TVar(int v);
+ explicit TVar(long long v);
+ explicit TVar(long long v, Type t);
+ explicit TVar(string_view v);
+ explicit TVar(const wchar_t* v);
+ explicit TVar(double v);
+ explicit TVar(void* v);
+ explicit TVar(Dialog* v);

COPY_AND_MOVE(TVar, long long)
COPY_AND_MOVE(TVar, string_view)
@@ -88,14 +89,10 @@ public:
COPY_AND_MOVE(TVar, void*)
COPY_AND_MOVE(TVar, Dialog*)

- bool operator<(const TVar&) const;
-
Type type() const { return vType; }
- Type ParseType() const;
- void SetType(Type newType) {vType=newType;}

bool isString() const { return vType == Type::String; }
- bool isInteger() const { return vType == Type::Integer || vType == Type::Unknown; }
+ bool isInteger() const { return vType == Type::Integer; }
bool isDouble() const { return vType == Type::Double; }
bool isPointer() const { return vType == Type::Pointer; }
bool isDialog() const { return vType == Type::Dialog; }
diff --git a/far/vbuild.m4 b/far/vbuild.m4
index cde8e1fc6..021d784d3 100644
--- a/far/vbuild.m4
+++ b/far/vbuild.m4
@@ -1 +1 @@
-6738
+6739


Reply all
Reply to author
Forward
0 new messages