Skip to content

refactor: move bsearch function to C-code #2945

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 25, 2025
Merged

Conversation

eloycoto
Copy link
Contributor

@eloycoto eloycoto commented Nov 15, 2023

This commit fixes issue #527 and move the bsearch function to a native C-code.

The performance is a bit better:

Testing script:

clear
if [[ `uname` == Darwin ]]; then
    MAX_MEMORY_UNITS=KB
else
    MAX_MEMORY_UNITS=MB
fi

export TIMEFMT='%J   %U  user %S system %P cpu %*E total'$'\n'\
'avg shared (code):         %X KB'$'\n'\
'avg unshared (data/stack): %D KB'$'\n'\
'total (sum):               %K KB'$'\n'\
'max memory:                %M '$MAX_MEMORY_UNITS''$'\n'\
'page faults from disk:     %F'$'\n'\
'other page faults:         %R'

echo "JQ code bsearch"
time /usr/bin/jq -n '[range(30000000)] | bsearch(3000)'

echo "C code bsearch"
time ./jq -n '[range(30000000)] | bsearch(3000)'

Results:

JQ code bsearch
3000
/usr/bin/jq -n '[range(30000000)] | bsearch(3000)'   8.63s  user 0.77s system 98% cpu 9.542 total
avg shared (code):         0 KB
avg unshared (data/stack): 0 KB
total (sum):               0 KB
max memory:                823 MB
page faults from disk:     1
other page faults:         432828
C code bsearch
3000
./jq -n '[range(30000000)] | bsearch(3000)'   8.44s  user 0.74s system 99% cpu 9.249 total
avg shared (code):         0 KB
avg unshared (data/stack): 0 KB
total (sum):               0 KB
max memory:                824 MB
page faults from disk:     0
other page faults:         432766

The results may be better if we can use jvp_array_read, and there is no need to copy/free the input array in each iteration. I guess that is like that for API pourposes when the libjq is in use with multiple threads in place.


Closes #527

@eloycoto eloycoto force-pushed the BSearchCCode branch 2 times, most recently from d975a4c to 9e3c7bc Compare November 15, 2023 16:23
@eloycoto eloycoto changed the title refactor: move bsearch function to C-code WIP refactor: move bsearch function to C-code Nov 15, 2023
@eloycoto eloycoto force-pushed the BSearchCCode branch 2 times, most recently from 29c1f4e to 618c10f Compare November 16, 2023 10:43
@eloycoto eloycoto changed the title WIP refactor: move bsearch function to C-code refactor: move bsearch function to C-code Nov 16, 2023
@eloycoto
Copy link
Contributor Author

@emanuele6 I think this is ready

@itchyny
Copy link
Contributor

itchyny commented Dec 4, 2023

The bsearch filter should support searching from an array of any kind.

 $ jq -n '[{x:range(3),y:range(3)}] | debug(. == sort) | bsearch({x:1,y:1})'
["DEBUG:",true]
4

@eloycoto eloycoto force-pushed the BSearchCCode branch 2 times, most recently from 4866769 to 949b647 Compare February 5, 2024 08:17
@eloycoto
Copy link
Contributor Author

eloycoto commented Feb 5, 2024

@emanuele6 @itchyny I've just refactored this, and merging should be okay.

@itchyny
Copy link
Contributor

itchyny commented Feb 7, 2024

I found a regression. On updating tests see my review comment above.

 $ jq -n '[1,2] | bsearch(2)'          
1
 $ ./jq -n '[1,2] | bsearch(2)'
-3

@eloycoto eloycoto force-pushed the BSearchCCode branch 2 times, most recently from a77f02a to 42135ed Compare February 10, 2024 12:38
@itchyny
Copy link
Contributor

itchyny commented Feb 12, 2024

I think we can reduce special cases, simplify the logic.

static jv f_bsearch(jq_state *jq, jv input, jv target) {
  if (jv_get_kind(input) != JV_KIND_ARRAY) {
    return type_error(input, "cannot be searched from");
  }
  int start = 0;
  int end = jv_array_length(jv_copy(input));
  jv answer = jv_invalid();
  while (start < end) {
    int mid = (start + end) / 2;
    int result = jv_cmp(jv_copy(target), jv_array_get(jv_copy(input), mid));
    if (result == 0) {
      answer = jv_number(mid);
      break;
    } else if (result < 0) {
      end = mid;
    } else {
      start = mid + 1;
    }
  }
  if (!jv_is_valid(answer)) {
    answer = jv_number(-1 - start);
  }
  jv_free(input);
  jv_free(target);
  return answer;
}

@eloycoto eloycoto requested a review from itchyny February 14, 2024 12:51
/* If the input is not sorted, bsearch will terminate but with irrelevant results. */
static jv f_bsearch(jq_state *jq, jv input, jv target) {
if (jv_get_kind(input) != JV_KIND_ARRAY) {
return type_error(input, "cannot be searched from");
Copy link
Member

@emanuele6 emanuele6 Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you are leaking target; you need to free it before returning.
Otherwise looks good to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also add a test with a non-array input, and a target that uses allocated memory (e.g. a string), so this can be caught by the CI?

@emanuele6
Copy link
Member

emanuele6 commented Feb 20, 2024

I just remembered that (start + end) / 2 for binary search is not recommended because it can overflow.
This can be avoided using start + (end - start) / 2 instead.
See https://en.wikipedia.org/wiki/Binary_search_algorithm#Implementation_issues

@eloycoto eloycoto force-pushed the BSearchCCode branch 4 times, most recently from 359f0e2 to 2667c55 Compare February 29, 2024 09:58
eloycoto and others added 3 commits February 29, 2024 12:24
This commit fixes issue jqlang#527 and move the bsearch function to a native
C-code.

The performance is a bit better:

Testing script:
```bash
clear
if [[ `uname` == Darwin ]]; then
    MAX_MEMORY_UNITS=KB
else
    MAX_MEMORY_UNITS=MB
fi

export TIMEFMT='%J   %U  user %S system %P cpu %*E total'$'\n'\
'avg shared (code):         %X KB'$'\n'\
'avg unshared (data/stack): %D KB'$'\n'\
'total (sum):               %K KB'$'\n'\
'max memory:                %M '$MAX_MEMORY_UNITS''$'\n'\
'page faults from disk:     %F'$'\n'\
'other page faults:         %R'

echo "JQ code bsearch"
time /usr/bin/jq -n '[range(30000000)] | bsearch(3000)'

echo "C code bsearch"
time ./jq -n '[range(30000000)] | bsearch(3000)'
````

Results:

```
JQ code bsearch
3000
/usr/bin/jq -n '[range(30000000)] | bsearch(3000)'   8.63s  user 0.77s system 98% cpu 9.542 total
avg shared (code):         0 KB
avg unshared (data/stack): 0 KB
total (sum):               0 KB
max memory:                823 MB
page faults from disk:     1
other page faults:         432828
C code bsearch
3000
./jq -n '[range(30000000)] | bsearch(3000)'   8.44s  user 0.74s system 99% cpu 9.249 total
avg shared (code):         0 KB
avg unshared (data/stack): 0 KB
total (sum):               0 KB
max memory:                824 MB
page faults from disk:     0
other page faults:         432766
```

The results may be better if we can use jvp_array_read, and there is no
need to copy/free the input array in each iteration. I guess that is
like that for API pourposes when the libjq is in use with multiple
threads in place.

Signed-off-by: Eloy Coto <[email protected]>
Co-authored-by: itchyny <[email protected]>
Signed-off-by: Eloy Coto <[email protected]>
@itchyny itchyny added this to the 1.8 release milestone Mar 6, 2024
@wader
Copy link
Member

wader commented Jan 23, 2025

Looks good to me, I'm a bit surprised of the small performance difference, calling overhead etc in both cases are larger than the binary search or something?

@itchyny
Copy link
Contributor

itchyny commented Jan 25, 2025

I'm a bit surprised of the small performance difference, calling overhead etc in both cases are larger than the binary search or something?

Because [range(30000000)] took most of the time in the entire query.
Reading the target array from file is better in comparing the performance,
but it still costs, so it cannot compare only of bsearch.

 $ jq -nc '[range(3000000)]' > /tmp/x.json
 $ hyperfine --warmup 10 'jq "bsearch(100)" /tmp/x.json' './jq "bsearch(100)" /tmp/x.json'
Benchmark 1: jq "bsearch(100)" /tmp/x.json
  Time (mean ± σ):     575.6 ms ±   5.4 ms    [User: 513.4 ms, System: 56.1 ms]
  Range (min … max):   570.1 ms … 588.7 ms    10 runs

Benchmark 2: ./jq "bsearch(100)" /tmp/x.json
  Time (mean ± σ):     478.9 ms ±   3.9 ms    [User: 419.8 ms, System: 52.6 ms]
  Range (min … max):   473.4 ms … 483.5 ms    10 runs

Summary
  ./jq "bsearch(100)" /tmp/x.json ran
    1.20 ± 0.01 times faster than jq "bsearch(100)" /tmp/x.json

 $ jq -nc '[range(10000000)]' > /tmp/x.json
 $ hyperfine --warmup 10 'jq "bsearch(100)" /tmp/x.json' './jq "bsearch(100)" /tmp/x.json'
Benchmark 1: jq "bsearch(100)" /tmp/x.json
  Time (mean ± σ):      2.002 s ±  0.056 s    [User: 1.759 s, System: 0.208 s]
  Range (min … max):    1.956 s …  2.121 s    10 runs

Benchmark 2: ./jq "bsearch(100)" /tmp/x.json
  Time (mean ± σ):      1.683 s ±  0.077 s    [User: 1.435 s, System: 0.203 s]
  Range (min … max):    1.612 s …  1.821 s    10 runs

Summary
  ./jq "bsearch(100)" /tmp/x.json ran
    1.19 ± 0.06 times faster than jq "bsearch(100)" /tmp/x.json

@itchyny
Copy link
Contributor

itchyny commented Jan 25, 2025

Merging, but with dropping the misleading profiling result comments.

@itchyny itchyny merged commit 562ffec into jqlang:master Jan 25, 2025
28 checks passed
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jun 12, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [jqlang/jq](https://github.com/jqlang/jq) | minor | `1.7.1` -> `1.8.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jqlang/jq (jqlang/jq)</summary>

### [`v1.8.0`](https://github.com/jqlang/jq/releases/tag/jq-1.8.0): jq 1.8.0

[Compare Source](jqlang/jq@jq-1.7.1...jq-1.8.0)

We are pleased to announce the release of version 1.8.0.
This release includes a number of improvements since the last version.
Note that some changes may introduce breaking changes to existing scripts,
so be sure to read the following information carefully.
Full commit log can be found at <jqlang/jq@jq-1.7.1...jq-1.8.0>.

#### Releasing

-   Change the version number pattern to `1.X.Y` (`1.8.0` instead of `1.8`). [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;2999](jqlang/jq#2999)
-   Generate provenance attestations for release artifacts and docker image. [@&#8203;lectrical](https://github.com/lectrical) [#&#8203;3225](jqlang/jq#3225)

    ```sh
    gh attestation verify --repo jqlang/jq jq-linux-amd64
    gh attestation verify --repo jqlang/jq oci://ghcr.io/jqlang/jq:1.8.0
    ```

#### Security fixes

-   CVE-2024-23337: Fix signed integer overflow in `jvp_array_write` and `jvp_object_rehash`. [@&#8203;itchyny](https://github.com/itchyny) [`de21386`](jqlang/jq@de21386)
    -   The fix for this issue now limits the maximum size of arrays and objects to [`5368709`](jqlang/jq@536870912) (`2^29`) elements.
-   CVE-2024-53427: Reject NaN with payload while parsing JSON. [@&#8203;itchyny](https://github.com/itchyny) [`a09a4df`](jqlang/jq@a09a4df)
    -   The fix for this issue now drops support for NaN with payload in JSON (like `NaN123`).
        Other JSON extensions like `NaN` and `Infinity` are still supported.
-   CVE-2025-48060: Fix heap buffer overflow in `jv_string_vfmt`. [@&#8203;itchyny](https://github.com/itchyny) [`c6e0416`](jqlang/jq@c6e0416)
-   Fix use of uninitialized value in `check_literal`. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3324](jqlang/jq#3324)
-   Fix segmentation fault on `strftime/1`, `strflocaltime/1`. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3271](jqlang/jq#3271)
-   Fix unhandled overflow in `@base64d`. [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;3080](jqlang/jq#3080)

#### CLI changes

-   Fix `--indent 0` implicitly enabling `--compact-output`. [@&#8203;amarshall](https://github.com/amarshall) [@&#8203;gbrlmarn](https://github.com/gbrlmarn) [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3232](jqlang/jq#3232)

    ```sh
    $ jq --indent 0 . <<< '{ "foo": ["hello", "world"] }'
    {
    "foo": [
    "hello",
    "world"
    ]
    }
    ```

### Previously, this implied --compact-output, but now outputs with new lines.

````

- Improve error messages to show problematic position in the filter. @&#8203;itchyny #&#8203;3292

```sh
$ jq -n '1 + $foo + 2'
jq: error: $foo is not defined at <top-level>, line 1, column 5:
    1 + $foo + 2
        ^^^^
jq: 1 compile error
````

-   Include column number in parser and compiler error messages. [@&#8203;liviubobocu](https://github.com/liviubobocu) [#&#8203;3257](jqlang/jq#3257)
-   Fix error message for string literal beginning with single quote. [@&#8203;mattmeyers](https://github.com/mattmeyers) [#&#8203;2964](jqlang/jq#2964)

    ```sh
    $ jq .foo <<< "{'foo':'bar'}"
    jq: parse error: Invalid string literal; expected ", but got ' at line 1, column 7
    ```

### Previously, the error message was Invalid numeric literal at line 1, column 7.

````

- Improve `JQ_COLORS` environment variable to support larger escapes like truecolor. @&#8203;SArpnt #&#8203;3282

```sh
JQ_COLORS="38;2;255;173;173:38;2;255;214;165:38;2;253;255;182:38;2;202;255;191:38;2;155;246;255:38;2;160;196;255:38;2;189;178;255:38;2;255;198;255" jq -nc '[null,false,true,42,{"a":"bc"}]'
````

-   Add `--library-path` long option for `-L`. [@&#8203;thaliaarchi](https://github.com/thaliaarchi) [#&#8203;3194](jqlang/jq#3194)
-   Fix `--slurp --stream` when input has no trailing newline character. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3279](jqlang/jq#3279)
-   Fix `--indent` option to error for malformed values. [@&#8203;thaliaarchi](https://github.com/thaliaarchi) [#&#8203;3195](jqlang/jq#3195)
-   Fix option parsing of `--binary` on non-Windows platforms. [@&#8203;calestyo](https://github.com/calestyo) [#&#8203;3131](jqlang/jq#3131)
-   Fix issue with `~/.jq` on Windows where `$HOME` is not set. [@&#8203;kirkoman](https://github.com/kirkoman) [#&#8203;3114](jqlang/jq#3114)
-   Fix broken non-Latin output in the command help on Windows. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3299](jqlang/jq#3299)
-   Increase the maximum parsing depth for JSON to 10000. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3328](jqlang/jq#3328)
-   Parse short options in order given. [@&#8203;thaliaarchi](https://github.com/thaliaarchi) [#&#8203;3194](jqlang/jq#3194)
-   Consistently reset color formatting. [@&#8203;thaliaarchi](https://github.com/thaliaarchi) [#&#8203;3034](jqlang/jq#3034)

#### New functions

-   Add `trim/0`, `ltrim/0` and `rtrim/0` to trim leading and trailing white spaces. [@&#8203;wader](https://github.com/wader) [#&#8203;3056](jqlang/jq#3056)

    ```sh
    $ jq -n '" hello " | trim, ltrim, rtrim'
    "hello"
    "hello "
    " hello"
    ```

-   Add `trimstr/1` to trim string from both ends. [@&#8203;gbrlmarn](https://github.com/gbrlmarn) [#&#8203;3319](jqlang/jq#3319)

    ```sh
    $ jq -n '"foobarfoo" | trimstr("foo")'
    "bar"
    ```

-   Add `add/1`. Generator variant of `add/0`. [@&#8203;myaaaaaaaaa](https://github.com/myaaaaaaaaa) [#&#8203;3144](jqlang/jq#3144)

    ```sh
    $ jq -c '.sum = add(.xs[])' <<< '{"xs":[1,2,3]}'
    {"xs":[1,2,3],"sum":6}
    ```

-   Add `skip/2` as the counterpart to `limit/2`. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3181](jqlang/jq#3181)

    ```sh
    $ jq -nc '[1,2,3,4,5] | [skip(2; .[])]'
    [3,4,5]
    ```

-   Add `toboolean/0` to convert strings to booleans. [@&#8203;brahmlower](https://github.com/brahmlower) [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;2098](jqlang/jq#2098)

    ```sh
    $ jq -n '"true", "false" | toboolean'
    true
    false
    ```

-   Add `@urid` format. Reverse of `@uri`. [@&#8203;fmgornick](https://github.com/fmgornick) [#&#8203;3161](jqlang/jq#3161)

    ```sh
    $ jq -Rr '@&#8203;urid' <<< '%6a%71'
    jq
    ```

#### Changes to existing functions

-   Use code point index for `indices/1`, `index/1` and `rindex/1`. [@&#8203;wader](https://github.com/wader) [#&#8203;3065](jqlang/jq#3065)
    -   This is a breaking change. Use `utf8bytelength/0` to get byte index.
-   Improve `tonumber/0` performance and rejects numbers with leading or trailing white spaces. [@&#8203;itchyny](https://github.com/itchyny) [@&#8203;thaliaarchi](https://github.com/thaliaarchi) [#&#8203;3055](jqlang/jq#3055) [#&#8203;3195](jqlang/jq#3195)
    -   This is a breaking change. Use `trim/0` to remove leading and trailing white spaces.
-   Populate timezone data when formatting time. This fixes timezone name in
    `strftime/1`, `strflocaltime/1` for DST. [@&#8203;marcin-serwin](https://github.com/marcin-serwin) [@&#8203;sihde](https://github.com/sihde) [#&#8203;3203](jqlang/jq#3203) [#&#8203;3264](jqlang/jq#3264) [#&#8203;3323](jqlang/jq#3323)
-   Preserve numerical precision on unary negation, `abs/0`, `length/0`. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3242](jqlang/jq#3242) [#&#8203;3275](jqlang/jq#3275)
-   Make `last(empty)` yield no output values like `first(empty)`. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3179](jqlang/jq#3179)
-   Make `ltrimstr/1` and `rtrimstr/1` error for non-string inputs. [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;2969](jqlang/jq#2969)
-   Make `limit/2` error for negative count. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3181](jqlang/jq#3181)
-   Fix `mktime/0` overflow and allow fewer elements in date-time representation array. [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;3070](jqlang/jq#3070) [#&#8203;3162](jqlang/jq#3162)
-   Fix non-matched optional capture group. [@&#8203;wader](https://github.com/wader) [#&#8203;3238](jqlang/jq#3238)
-   Provide `strptime/1` on all systems. [@&#8203;george-hopkins](https://github.com/george-hopkins) [@&#8203;fdellwing](https://github.com/fdellwing)  [#&#8203;3008](jqlang/jq#3008) [#&#8203;3094](jqlang/jq#3094)
-   Fix `_WIN32` port of `strptime`. [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;3071](jqlang/jq#3071)
-   Improve `bsearch/1` performance by implementing in C. [@&#8203;eloycoto](https://github.com/eloycoto) [#&#8203;2945](jqlang/jq#2945)
-   Improve `unique/0` and `unique_by/1` performance. [@&#8203;itchyny](https://github.com/itchyny) [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;3254](jqlang/jq#3254) [#&#8203;3304](jqlang/jq#3304)
-   Fix error messages including long string literal not to break Unicode characters. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3249](jqlang/jq#3249)
-   Remove `pow10/0` as it has been deprecated in glibc 2.27. Use `exp10/0` instead. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3059](jqlang/jq#3059)
-   Remove private (and undocumented) `_nwise` filter. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3260](jqlang/jq#3260)

#### Language changes

-   Fix precedence of binding syntax against unary and binary operators.
    Also, allow some expressions as object values. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3053](jqlang/jq#3053) [#&#8203;3326](jqlang/jq#3326)

    -   This is a breaking change that may change the output of filters with binding syntax as follows.

    ```sh
    $ jq -nc '[-1 as $x | 1,$x]'
    [1,-1]    # previously, [-1,-1]
    $ jq -nc '1 | . + 2 as $x | -$x'
    -3        # previously, -1
    $ jq -nc '{x: 1 + 2, y: false or true, z: null // 3}'
    {"x":3,"y":true,"z":3}    # previously, syntax error
    ```

-   Support Tcl-style multiline comments. [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;2989](jqlang/jq#2989)

    ```sh
    #!/bin/sh --
    ```

### Can be use to do shebang scripts.

### Next line will be seen as a comment be of the trailing backslash. \\

exec jq ...

### this jq expression will result in \[1]

\[
1,

### \\

    2

]

````

- Fix `foreach` not to break init backtracking with `DUPN`. @&#8203;kanwren #&#8203;3266

```sh
$ jq -n '[1, 2] | foreach .[] as $x (0, 1; . + $x)'
1
3
2
4
````

-   Fix `reduce`/`foreach` state variable should not be reset each iteration. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3205](jqlang/jq#3205)

    ```sh
    $ jq -n 'reduce range(5) as $x (0; .+$x | select($x!=2))'
    8
    $ jq -nc '[foreach range(5) as $x (0; .+$x | select($x!=2); [$x,.])]'
    [[0,0],[1,1],[3,4],[4,8]]
    ```

-   Support CRLF line breaks in filters. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3274](jqlang/jq#3274)

-   Improve performance of repeating strings. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3272](jqlang/jq#3272)

#### Documentation changes

-   Switch the homepage to custom domain [jqlang.org](https://jqlang.org). [@&#8203;itchyny](https://github.com/itchyny) [@&#8203;owenthereal](https://github.com/owenthereal) [#&#8203;3243](jqlang/jq#3243)
-   Make latest release instead of development version the default manual. [@&#8203;wader](https://github.com/wader) [#&#8203;3130](jqlang/jq#3130)
-   Add opengraph meta tags. [@&#8203;wader](https://github.com/wader) [#&#8203;3247](jqlang/jq#3247)
-   Replace jqplay.org with play.jqlang.org [@&#8203;owenthereal](https://github.com/owenthereal) [#&#8203;3265](jqlang/jq#3265)
-   Add missing line from decNumber's licence to `COPYING`. [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;3106](jqlang/jq#3106)
-   Various document improvements. [@&#8203;tsibley](https://github.com/tsibley) [#&#8203;3322](jqlang/jq#3322), [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3240](jqlang/jq#3240), [@&#8203;jhcarl0814](https://github.com/jhcarl0814) [#&#8203;3239](jqlang/jq#3239),
    [@&#8203;01mf02](https://github.com/01mf02) [#&#8203;3184](jqlang/jq#3184), [@&#8203;thaliaarchi](https://github.com/thaliaarchi) [#&#8203;3199](jqlang/jq#3199), [@&#8203;NathanBaulch](https://github.com/NathanBaulch) [#&#8203;3173](jqlang/jq#3173), [@&#8203;cjlarose](https://github.com/cjlarose) [#&#8203;3164](jqlang/jq#3164),
    [@&#8203;sheepster1](https://github.com/sheepster1) [#&#8203;3105](jqlang/jq#3105), [#&#8203;3103](jqlang/jq#3103), [@&#8203;kishoreinvits](https://github.com/kishoreinvits) [#&#8203;3042](jqlang/jq#3042), [@&#8203;jbrains](https://github.com/jbrains) [#&#8203;3035](jqlang/jq#3035), [@&#8203;thalman](https://github.com/thalman) [#&#8203;3033](jqlang/jq#3033),
    [@&#8203;SOF3](https://github.com/SOF3) [#&#8203;3017](jqlang/jq#3017), [@&#8203;wader](https://github.com/wader) [#&#8203;3015](jqlang/jq#3015), [@&#8203;wllm-rbnt](https://github.com/wllm-rbnt) [#&#8203;3002](jqlang/jq#3002)

#### Build improvements

-   Fix build with GCC 15 (C23). [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;3209](jqlang/jq#3209)
-   Fix build with `-Woverlength-strings` [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;3019](jqlang/jq#3019)
-   Fix compiler warning `type-limits` in `found_string`. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3263](jqlang/jq#3263)
-   Fix compiler error in `jv_dtoa.c` and `builtin.c`. [@&#8203;UlrichEckhardt](https://github.com/UlrichEckhardt) [#&#8203;3036](jqlang/jq#3036)
-   Fix warning: a function definition without a prototype is deprecated. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3259](jqlang/jq#3259)
-   Define `_BSD_SOURCE` in `builtin.c` for OpenBSD support. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3278](jqlang/jq#3278)
-   Define empty `JV_{,V}PRINTF_LIKE` macros if `__GNUC__` is not defined. [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;3160](jqlang/jq#3160)
-   Avoid `ctype.h` abuse: cast `char` to `unsigned char` first. [@&#8203;riastradh](https://github.com/riastradh) [#&#8203;3152](jqlang/jq#3152)
-   Remove multiple calls to free when successively calling `jq_reset`. [@&#8203;Sameesunkaria](https://github.com/Sameesunkaria) [#&#8203;3134](jqlang/jq#3134)
-   Enable IBM z/OS support. [@&#8203;sachintu47](https://github.com/sachintu47) [#&#8203;3277](jqlang/jq#3277)
-   Fix insecure `RUNPATH`. [@&#8203;orbea](https://github.com/orbea) [#&#8203;3212](jqlang/jq#3212)
-   Avoid zero-length `calloc`. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3280](jqlang/jq#3280)
-   Move oniguruma and decNumber to vendor directory. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3234](jqlang/jq#3234)

#### Test improvements

-   Run tests in C locale. [@&#8203;emanuele6](https://github.com/emanuele6) [#&#8203;3039](jqlang/jq#3039)
-   Improve reliability of `NO_COLOR` tests. [@&#8203;dag-erling](https://github.com/dag-erling) [#&#8203;3188](jqlang/jq#3188)
-   Improve `shtest` not to fail if `JQ_COLORS` and `NO_COLOR` are already set. [@&#8203;SArpnt](https://github.com/SArpnt) [#&#8203;3283](jqlang/jq#3283)
-   Refactor constant folding tests. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3233](jqlang/jq#3233)
-   Make tests pass when `--disable-decnum`. [@&#8203;nicowilliams](https://github.com/nicowilliams) [`6d02d53`](jqlang/jq@6d02d53)
-   Disable Valgrind by default during testing. [@&#8203;itchyny](https://github.com/itchyny) [#&#8203;3269](jqlang/jq#3269)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC41MC4wIiwidXBkYXRlZEluVmVyIjoiNDAuNTAuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90Il19-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bsearch as C-coded builtin
6 participants