diff --git a/doc/xml/release/2024/2.51.xml b/doc/xml/release/2024/2.51.xml
index 222f22f30..ced19c88e 100644
--- a/doc/xml/release/2024/2.51.xml
+++ b/doc/xml/release/2024/2.51.xml
@@ -53,6 +53,19 @@
Add detailed backtrace to autoconf/make build.
+
+
+
+
+
+
+
+
+
+
+ Improve sort comparators.
+
+
diff --git a/src/command/archive/common.c b/src/command/archive/common.c
index e18be6160..4fc1d6c5f 100644
--- a/src/command/archive/common.c
+++ b/src/command/archive/common.c
@@ -15,6 +15,7 @@ Archive Common
#include "common/log.h"
#include "common/memContext.h"
#include "common/regExp.h"
+#include "common/type/convert.h"
#include "common/wait.h"
#include "config/config.h"
#include "postgres/interface.h"
@@ -293,14 +294,15 @@ archiveAsyncExec(ArchiveMode archiveMode, const StringList *commandExec)
/**********************************************************************************************************************************/
FN_EXTERN int
-archiveIdComparator(const void *item1, const void *item2)
+archiveIdComparator(const void *const archiveId1, const void *const archiveId2)
{
- StringList *archiveSort1 = strLstNewSplitZ(*(String **)item1, "-");
- StringList *archiveSort2 = strLstNewSplitZ(*(String **)item2, "-");
- int int1 = atoi(strZ(strLstGet(archiveSort1, 1)));
- int int2 = atoi(strZ(strLstGet(archiveSort2, 1)));
+ ASSERT(strstr(strZ(*(String **)archiveId1), "-") != NULL);
+ ASSERT(strstr(strZ(*(String **)archiveId2), "-") != NULL);
- return int1 - int2;
+ const int id1 = cvtZToInt(strstr(strZ(*(String **)archiveId1), "-") + 1);
+ const int id2 = cvtZToInt(strstr(strZ(*(String **)archiveId2), "-") + 1);
+
+ return LST_COMPARATOR_CMP(id1, id2);
}
/**********************************************************************************************************************************/
diff --git a/src/command/backup/blockMap.c b/src/command/backup/blockMap.c
index 24761e5da..4a5fd737d 100644
--- a/src/command/backup/blockMap.c
+++ b/src/command/backup/blockMap.c
@@ -76,12 +76,10 @@ lstComparatorBlockMapReference(const void *const blockMapRef1, const void *const
ASSERT(blockMapRef1 != NULL);
ASSERT(blockMapRef2 != NULL);
- if (((BlockMapReference *)blockMapRef1)->reference < ((BlockMapReference *)blockMapRef2)->reference)
- FUNCTION_TEST_RETURN(INT, -1);
- else if (((BlockMapReference *)blockMapRef1)->reference > ((BlockMapReference *)blockMapRef2)->reference)
- FUNCTION_TEST_RETURN(INT, 1);
+ const unsigned int reference1 = ((BlockMapReference *)blockMapRef1)->reference;
+ const unsigned int reference2 = ((BlockMapReference *)blockMapRef2)->reference;
- FUNCTION_TEST_RETURN(INT, 0);
+ FUNCTION_TEST_RETURN(INT, LST_COMPARATOR_CMP(reference1, reference2));
}
FN_EXTERN BlockMap *
diff --git a/src/common/type/list.c b/src/common/type/list.c
index f4c0241b5..035c86905 100644
--- a/src/common/type/list.c
+++ b/src/common/type/list.c
@@ -89,23 +89,20 @@ lstComparatorStr(const void *item1, const void *item2)
/**********************************************************************************************************************************/
FN_EXTERN int
-lstComparatorUInt(const void *const item1, const void *const item2)
+lstComparatorUInt(const void *const uintPtr1, const void *const uintPtr2)
{
FUNCTION_TEST_BEGIN();
- FUNCTION_TEST_PARAM_P(VOID, item1);
- FUNCTION_TEST_PARAM_P(VOID, item2);
+ FUNCTION_TEST_PARAM_P(VOID, uintPtr1);
+ FUNCTION_TEST_PARAM_P(VOID, uintPtr2);
FUNCTION_TEST_END();
- ASSERT(item1 != NULL);
- ASSERT(item2 != NULL);
+ ASSERT(uintPtr1 != NULL);
+ ASSERT(uintPtr2 != NULL);
- if (*(unsigned int *)item1 < *(unsigned int *)item2)
- FUNCTION_TEST_RETURN(INT, -1);
+ const unsigned int uint1 = *(unsigned int *)uintPtr1;
+ const unsigned int uint2 = *(unsigned int *)uintPtr2;
- if (*(unsigned int *)item1 > *(unsigned int *)item2)
- FUNCTION_TEST_RETURN(INT, 1);
-
- FUNCTION_TEST_RETURN(INT, 0);
+ FUNCTION_TEST_RETURN(INT, LST_COMPARATOR_CMP(uint1, uint2));
}
/**********************************************************************************************************************************/
diff --git a/src/common/type/list.h b/src/common/type/list.h
index 164579149..0015bafff 100644
--- a/src/common/type/list.h
+++ b/src/common/type/list.h
@@ -52,6 +52,10 @@ FN_EXTERN int lstComparatorUInt(const void *item1, const void *item2);
// General purpose list comparator for zero-terminated strings or structs with a zero-terminated string as the first member
FN_EXTERN int lstComparatorZ(const void *item1, const void *item2);
+// Macro to compare two values in a branchless and transitive fashion
+#define LST_COMPARATOR_CMP(item1, item2) \
+ (((item1) > (item2)) - ((item1) < (item2)))
+
/***********************************************************************************************************************************
Constructors
***********************************************************************************************************************************/
diff --git a/test/src/module/common/typeListTest.c b/test/src/module/common/typeListTest.c
index eea6c64a6..9692912b9 100644
--- a/test/src/module/common/typeListTest.c
+++ b/test/src/module/common/typeListTest.c
@@ -9,16 +9,7 @@ Test sort comparator
static int
testComparator(const void *item1, const void *item2)
{
- int int1 = *(int *)item1;
- int int2 = *(int *)item2;
-
- if (int1 < int2)
- return -1;
-
- if (int1 > int2)
- return 1;
-
- return 0;
+ return LST_COMPARATOR_CMP(*(int *)item1, *(int *)item2);
}
/***********************************************************************************************************************************
diff --git a/test/src/module/performance/typeTest.c b/test/src/module/performance/typeTest.c
index b96147cf7..2a54d0929 100644
--- a/test/src/module/performance/typeTest.c
+++ b/test/src/module/performance/typeTest.c
@@ -31,16 +31,7 @@ Test sort comparator
static int
testComparator(const void *item1, const void *item2)
{
- int int1 = *(int *)item1;
- int int2 = *(int *)item2;
-
- if (int1 < int2)
- return -1;
-
- if (int1 > int2)
- return 1;
-
- return 0;
+ return LST_COMPARATOR_CMP(*(int *)item1, *(int *)item2);
}
/***********************************************************************************************************************************