Browse Source

Merge branch 'NumSortHex' of https://github.com/qistoph/CyberChef into qistoph-NumSortHex

n1474335 6 years ago
parent
commit
5c598b69b0
2 changed files with 52 additions and 1 deletions
  1. 41 1
      src/core/operations/Sort.mjs
  2. 11 0
      test/tests/operations/SeqUtils.mjs

+ 41 - 1
src/core/operations/Sort.mjs

@@ -38,7 +38,7 @@ class Sort extends Operation {
             {
             {
                 "name": "Order",
                 "name": "Order",
                 "type": "option",
                 "type": "option",
-                "value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric"]
+                "value": ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric", "Numeric (hexadecimal)"]
             }
             }
         ];
         ];
     }
     }
@@ -62,6 +62,8 @@ class Sort extends Operation {
             sorted = sorted.sort(Sort._ipSort);
             sorted = sorted.sort(Sort._ipSort);
         } else if (order === "Numeric") {
         } else if (order === "Numeric") {
             sorted = sorted.sort(Sort._numericSort);
             sorted = sorted.sort(Sort._numericSort);
+        } else if (order === "Numeric (hexadecimal)") {
+            sorted = sorted.sort(Sort._hexadecimalSort);
         }
         }
 
 
         if (sortReverse) sorted.reverse();
         if (sortReverse) sorted.reverse();
@@ -131,6 +133,44 @@ class Sort extends Operation {
         return a.localeCompare(b);
         return a.localeCompare(b);
     }
     }
 
 
+    /**
+     * Comparison operation for sorting of hexadecimal values.
+     *
+     * @author Chris van Marle
+     * @private
+     * @param {string} a
+     * @param {string} b
+     * @returns {number}
+     */
+    static _hexadecimalSort(a, b) {
+        let a_ = a.split(/([^\da-f]+)/i),
+            b_ = b.split(/([^\da-f]+)/i);
+
+        a_ = a_.map(v => {
+            const t = parseInt(v, 16);
+            return isNaN(t) ? v : t;
+        });
+
+        b_ = b_.map(v => {
+            const t = parseInt(v, 16);
+            return isNaN(t) ? v : t;
+        });
+
+        for (let i = 0; i < a_.length && i < b.length; ++i) {
+            if (isNaN(a_[i]) && !isNaN(b_[i])) return 1; // Numbers after non-numbers
+            if (!isNaN(a_[i]) && isNaN(b_[i])) return -1;
+            if (isNaN(a_[i]) && isNaN(b_[i])) {
+                const ret = a_[i].localeCompare(b_[i]); // Compare strings
+                if (ret !== 0) return ret;
+            }
+            if (!isNaN(a_[i]) && !isNaN(a_[i])) { // Compare numbers
+                if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
+            }
+        }
+
+        return a.localeCompare(b);
+    }
+
 }
 }
 
 
 export default Sort;
 export default Sort;

+ 11 - 0
test/tests/operations/SeqUtils.mjs

@@ -30,4 +30,15 @@ TestRegister.addTests([
             }
             }
         ],
         ],
     },
     },
+    {
+        name: "SeqUtils - Hexadecimal sort",
+        input: "06,08,0a,0d,0f,1,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f,2,3,4,5,7,9,b,c,e",
+        expectedOutput: "1,2,3,4,5,06,7,08,9,0a,b,c,0d,e,0f,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f",
+        recipeConfig: [
+            {
+                "op": "Sort",
+                "args": ["Comma", false, "Numeric (hexadecimal)"]
+            }
+        ],
+    },
 ]);
 ]);