summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-02-20 22:19:05 +0100
committerBram Moolenaar <Bram@vim.org>2019-02-20 22:19:05 +0100
commita25e3d06956f1bc11c68fe60149acce2d8547092 (patch)
treeea60ee4e461dec0d9ba55ac4c2018c1fef74a66d
parent38f08e76acf7d21bb34cf8f79f0f82eb63cdc987 (diff)
downloadvim-git-8.1.0959.tar.gz
patch 8.1.0959: sorting large numbers is not testedv8.1.0959
Problem: Sorting large numbers is not tested and does not work properly. Solution: Add test. Fix comparing lines with and without a number. (Dominique Pelle, closes #4017)
-rw-r--r--src/ex_cmds.c37
-rw-r--r--src/testdir/test_sort.vim71
-rw-r--r--src/version.c2
3 files changed, 98 insertions, 12 deletions
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
index da10c1291..7682931d8 100644
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -296,16 +296,20 @@ static int sort_abort; /* flag to indicate if sorting has been interrupted */
/* Struct to store info to be sorted. */
typedef struct
{
- linenr_T lnum; /* line number */
+ linenr_T lnum; // line number
union {
struct
{
- varnumber_T start_col_nr; /* starting column number */
- varnumber_T end_col_nr; /* ending column number */
+ varnumber_T start_col_nr; // starting column number
+ varnumber_T end_col_nr; // ending column number
} line;
- varnumber_T value; /* value if sorting by integer */
+ struct
+ {
+ varnumber_T value; // value if sorting by integer
+ int is_number; // TRUE when line contains a number
+ } num;
#ifdef FEAT_FLOAT
- float_T value_flt; /* value if sorting by float */
+ float_T value_flt; // value if sorting by float
#endif
} st_u;
} sorti_T;
@@ -335,11 +339,14 @@ sort_compare(const void *s1, const void *s2)
if (got_int)
sort_abort = TRUE;
- /* When sorting numbers "start_col_nr" is the number, not the column
- * number. */
if (sort_nr)
- result = l1.st_u.value == l2.st_u.value ? 0
- : l1.st_u.value > l2.st_u.value ? 1 : -1;
+ {
+ if (l1.st_u.num.is_number != l2.st_u.num.is_number)
+ result = l1.st_u.num.is_number - l2.st_u.num.is_number;
+ else
+ result = l1.st_u.num.value == l2.st_u.num.value ? 0
+ : l1.st_u.num.value > l2.st_u.num.value ? 1 : -1;
+ }
#ifdef FEAT_FLOAT
else if (sort_flt)
result = l1.st_u.value_flt == l2.st_u.value_flt ? 0
@@ -553,11 +560,17 @@ ex_sort(exarg_T *eap)
if (s > p && s[-1] == '-')
--s; /* include preceding negative sign */
if (*s == NUL)
- /* empty line should sort before any number */
- nrs[lnum - eap->line1].st_u.value = -MAXLNUM;
+ {
+ /* line without number should sort before any number */
+ nrs[lnum - eap->line1].st_u.num.is_number = FALSE;
+ nrs[lnum - eap->line1].st_u.num.value = 0;
+ }
else
+ {
+ nrs[lnum - eap->line1].st_u.num.is_number = TRUE;
vim_str2nr(s, NULL, NULL, sort_what,
- &nrs[lnum - eap->line1].st_u.value, NULL, 0);
+ &nrs[lnum - eap->line1].st_u.num.value, NULL, 0);
+ }
}
#ifdef FEAT_FLOAT
else
diff --git a/src/testdir/test_sort.vim b/src/testdir/test_sort.vim
index 14d008a17..7da82b018 100644
--- a/src/testdir/test_sort.vim
+++ b/src/testdir/test_sort.vim
@@ -1222,6 +1222,77 @@ func Test_sort_cmd()
enew!
endfunc
+func Test_sort_large_num()
+ new
+ a
+-2147483648
+-2147483647
+
+-1
+0
+1
+-2147483646
+2147483646
+2147483647
+2147483647
+-2147483648
+abc
+
+.
+ " Numerical sort. Non-numeric lines are ordered before numerical lines.
+ " Ordering of non-numerical is stable.
+ sort n
+ call assert_equal(['',
+ \ 'abc',
+ \ '',
+ \ '-2147483648',
+ \ '-2147483648',
+ \ '-2147483647',
+ \ '-2147483646',
+ \ '-1',
+ \ '0',
+ \ '1',
+ \ '2147483646',
+ \ '2147483647',
+ \ '2147483647'], getline(1, '$'))
+ bwipe!
+
+ if has('num64')
+ new
+ a
+-9223372036854775808
+-9223372036854775807
+
+-1
+0
+1
+-9223372036854775806
+9223372036854775806
+9223372036854775807
+9223372036854775807
+-9223372036854775808
+abc
+
+.
+ sort n
+ call assert_equal(['',
+ \ 'abc',
+ \ '',
+ \ '-9223372036854775808',
+ \ '-9223372036854775808',
+ \ '-9223372036854775807',
+ \ '-9223372036854775806',
+ \ '-1',
+ \ '0',
+ \ '1',
+ \ '9223372036854775806',
+ \ '9223372036854775807',
+ \ '9223372036854775807'], getline(1, '$'))
+ bwipe!
+ endif
+endfunc
+
+
func Test_sort_cmd_report()
enew!
call append(0, repeat([1], 3) + repeat([2], 3) + repeat([3], 3))
diff --git a/src/version.c b/src/version.c
index b2d76b752..0d9acf4fd 100644
--- a/src/version.c
+++ b/src/version.c
@@ -780,6 +780,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 959,
+/**/
958,
/**/
957,