|
7 | 7 | #endif
|
8 | 8 | #include <sys/time.h>
|
9 | 9 | #include <stdlib.h>
|
| 10 | +#include <stdio.h> |
10 | 11 | #include <stddef.h>
|
11 | 12 | #ifdef HAVE_ALLOCA_H
|
12 | 13 | # include <alloca.h>
|
@@ -46,7 +47,6 @@ void *alloca (size_t);
|
46 | 47 | #include "jv_private.h"
|
47 | 48 | #include "util.h"
|
48 | 49 |
|
49 |
| - |
50 | 50 | #define BINOP(name) \
|
51 | 51 | static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
|
52 | 52 | jv_free(input); \
|
@@ -807,6 +807,62 @@ static jv f_sort_by_impl(jq_state *jq, jv input, jv keys) {
|
807 | 807 | }
|
808 | 808 | }
|
809 | 809 |
|
| 810 | +/* Assuming the input array is sorted, bsearch/1 returns */ |
| 811 | +/* the index of the target if the target is in the input array; and otherwise */ |
| 812 | +/* (-1 - ix), where ix is the insertion point that would leave the array sorted. */ |
| 813 | +/* If the input is not sorted, bsearch will terminate but with irrelevant results. */ |
| 814 | +static jv f_bsearch(jq_state *jq, jv input, jv target) { |
| 815 | + assert(jv_get_kind(input) == JV_KIND_ARRAY); |
| 816 | + assert(jv_get_kind(target) == JV_KIND_NUMBER); |
| 817 | + int len = jv_array_length(jv_copy(input)); |
| 818 | + if (len == 0) { |
| 819 | + jv_free(input); |
| 820 | + jv_free(target); |
| 821 | + return jv_number(-1); |
| 822 | + } else if (len == 1) { |
| 823 | + int result = jv_cmp(target, jv_array_get(input, 0)); |
| 824 | + if (result == 0 ) { |
| 825 | + return jv_number(0); |
| 826 | + } else if (result > 0) { |
| 827 | + return jv_number(-2); |
| 828 | + } else { |
| 829 | + return jv_number(-1); |
| 830 | + } |
| 831 | + } |
| 832 | + |
| 833 | + int start = 0; |
| 834 | + int end = len - 1; |
| 835 | + jv answer = jv_null(); |
| 836 | + while (start <end) { |
| 837 | + int mid = (start + end) / 2; |
| 838 | + int result = jv_cmp(jv_copy(target), jv_array_get(jv_copy(input), mid)); |
| 839 | + if (result == 0) { |
| 840 | + answer = jv_number(mid); |
| 841 | + break; |
| 842 | + } else if (start == end ) { |
| 843 | + answer = jv_number(-1); |
| 844 | + break; |
| 845 | + } else if (result < 0 ) { |
| 846 | + end = mid -1; |
| 847 | + } else { |
| 848 | + start = mid +1; |
| 849 | + } |
| 850 | + } |
| 851 | + if (jv_get_kind(answer) == JV_KIND_NULL) { |
| 852 | + int result = jv_cmp(target, jv_array_get(jv_copy(input), start)); |
| 853 | + if (result < 0) { |
| 854 | + answer = jv_number(-1 - start); |
| 855 | + }else { |
| 856 | + answer = jv_number(-2 - start); |
| 857 | + } |
| 858 | + } else { |
| 859 | + jv_free(target); |
| 860 | + } |
| 861 | + |
| 862 | + jv_free(input); |
| 863 | + return answer; |
| 864 | +} |
| 865 | + |
810 | 866 | static jv f_group_by_impl(jq_state *jq, jv input, jv keys) {
|
811 | 867 | if (jv_get_kind(input) == JV_KIND_ARRAY &&
|
812 | 868 | jv_get_kind(keys) == JV_KIND_ARRAY &&
|
@@ -1754,6 +1810,7 @@ BINOPS
|
1754 | 1810 | {f_sort, "sort", 1},
|
1755 | 1811 | {f_sort_by_impl, "_sort_by_impl", 2},
|
1756 | 1812 | {f_group_by_impl, "_group_by_impl", 2},
|
| 1813 | + {f_bsearch, "bsearch", 2}, |
1757 | 1814 | {f_min, "min", 1},
|
1758 | 1815 | {f_max, "max", 1},
|
1759 | 1816 | {f_min_by_impl, "_min_by_impl", 2},
|
|
0 commit comments