From 8f69f1911ab8668b75062e88b83d3996c05c6d40 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Wed, 25 Sep 2024 12:44:28 +0900 Subject: [PATCH] Fix A_SORT * Fix sorting of strings and floats * Avoid overflow in integer comparison --- src/page.c | 47 ++++++++++++++++++++++++++++++++++------ test/Source/arrays.jaf | 49 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 8 deletions(-) diff --git a/src/page.c b/src/page.c index 746cb47..82e8731 100644 --- a/src/page.c +++ b/src/page.c @@ -514,15 +514,33 @@ struct page *array_insert(struct page *page, int i, union vm_value v, enum ain_d return page; } +static int array_compare_int(const void *_a, const void *_b) +{ + union vm_value a = *((union vm_value*)_a); + union vm_value b = *((union vm_value*)_b); + return (a.i > b.i) - (a.i < b.i); +} + +static int array_compare_float(const void *_a, const void *_b) +{ + union vm_value a = *((union vm_value*)_a); + union vm_value b = *((union vm_value*)_b); + return (a.f > b.f) - (a.f < b.f); +} + +static int array_compare_string(const void *_a, const void *_b) +{ + union vm_value a = *((union vm_value*)_a); + union vm_value b = *((union vm_value*)_b); + return strcmp(heap_get_string(a.i)->text, heap_get_string(b.i)->text); +} + static int current_sort_function; -static int array_compare(const void *_a, const void *_b) +static int array_compare_custom(const void *_a, const void *_b) { union vm_value a = *((union vm_value*)_a); union vm_value b = *((union vm_value*)_b); - if (!current_sort_function) { - return a.i - b.i; - } stack_push(a); stack_push(b); vm_call(current_sort_function, -1); @@ -534,8 +552,25 @@ void array_sort(struct page *page, int compare_fno) if (!page) return; - current_sort_function = compare_fno; - qsort(page->values, page->nr_vars, sizeof(union vm_value), array_compare); + if (compare_fno) { + current_sort_function = compare_fno; + qsort(page->values, page->nr_vars, sizeof(union vm_value), array_compare_custom); + } else { + switch (page->a_type) { + case AIN_ARRAY_INT: + case AIN_ARRAY_LONG_INT: + qsort(page->values, page->nr_vars, sizeof(union vm_value), array_compare_int); + break; + case AIN_ARRAY_FLOAT: + qsort(page->values, page->nr_vars, sizeof(union vm_value), array_compare_float); + break; + case AIN_ARRAY_STRING: + qsort(page->values, page->nr_vars, sizeof(union vm_value), array_compare_string); + break; + default: + VM_ERROR("A_SORT(&NULL) called on ain_data_type %d", page->a_type); + } + } } static int current_sort_member; diff --git a/test/Source/arrays.jaf b/test/Source/arrays.jaf index cdbc446..c04e2a3 100755 --- a/test/Source/arrays.jaf +++ b/test/Source/arrays.jaf @@ -171,12 +171,54 @@ void test_array_insert(void) test_bool("array.Insert()", ar.Numof() == 3 && ar[0] == 0 && ar[1] == 1 && ar[2] == 2, true); } +void test_array_sort_int(void) +{ + int i; + bool failed = false; + array@int ar[2]; + ar[0] = 0x7fffffff; + ar[1] = -0x80000000; + ar.Sort(); + failed = (ar[0] != -0x80000000 || ar[1] != 0x7fffffff); + test_bool("array@int.Sort()", !failed, true); +} + +void test_array_sort_float(void) +{ + int i; + bool failed = false; + array@float ar[8]; + for (i = 0; i < 8; i++) { + ar[i] = (7 - i) * 0.1; + } + ar.Sort(); + for (i = 0; i < 8 && !failed; i++) { + failed = ar[i] != i * 0.1; + } + test_bool("array@float.Sort()", !failed, true); +} + +void test_array_sort_string(void) +{ + int i; + bool failed = false; + array@string ar[8]; + for (i = 0; i < 8; i++) { + ar[i] = string(7 - i); + } + ar.Sort(); + for (i = 0; i < 8 && !failed; i++) { + failed = ar[i] != string(i); + } + test_bool("array@string.Sort()", !failed, true); +} + int compare_int(int a, int b) { return a - b; } -void test_array_sort(void) +void test_array_sort_custom(void) { int i; bool failed = false; @@ -239,7 +281,10 @@ void test_arrays(void) test_array_empty(); test_array_erase(); test_array_insert(); - test_array_sort(); + test_array_sort_int(); + test_array_sort_float(); + test_array_sort_string(); + test_array_sort_custom(); test_array_constructors(); test_array_push_struct_with_ref(); }