Skip to content
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

Implement index-of expression #1113

Merged
merged 4 commits into from May 8, 2023
Merged

Conversation

SiarheiFedartsou
Copy link
Collaborator

Related to #264

@SiarheiFedartsou SiarheiFedartsou marked this pull request as ready for review May 7, 2023 13:51
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Copy link
Collaborator

@louwers louwers left a comment

Choose a reason for hiding this comment

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

Thanks for this great contribution!

Perhaps you could add a line to CHANGELOG.md and platform/android/CHANGELOG.md?

- Add support for [index-of expression](https://maplibre.org/maplibre-style-spec/expressions/#index-of) ([#1113](https://github.com/maplibre/maplibre-native/pull/1113))

Otherwise LGTM!

@wipfli
Copy link
Member

wipfli commented May 8, 2023

Thanks of contributing this @SiarheiFedartsou!

@SiarheiFedartsou
Copy link
Collaborator Author

Perhaps you could add a line to CHANGELOG.md and platform/android/CHANGELOG.md?

Done 👍

@github-actions
Copy link

github-actions bot commented May 8, 2023

@louwers louwers merged commit 379b1fc into maplibre:main May 8, 2023
20 of 21 checks passed
stefankarschti pushed a commit to stefankarschti/maplibre-native that referenced this pull request May 9, 2023
EvaluationResult IndexOf::evaluateForArrayInput(const std::vector<Value> &array,
const Value &keywordValue,
size_t fromIndexValue) const {
for (size_t index = fromIndexValue; index < array.size(); ++index) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't this allow out-of-bounds access (~crashing) with ["index-of", "foo", "foobar", -100000]?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah nevermind, it's size_t, which is unsigned.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is still different from the JS version probably:

// Should be ["index-of", "foo", "__foo__foo", -100]
"__foo__foo".indexOf("foo", -100) // returns 2

// Should be ["index-of", "foo", ["foo", "foo"], -100]
["foo", "foo"].indexOf("foo", -100) // returns 0

I believe the native version would return -1 in both of these cases.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for your comments @JannikGM !
I.e. JS version just makes fromIndex = std::max(fromIndex, 0) ? Okay, will apply a fix... Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes 👍

Background

I didn't try it in the maplibre-gl-js version. But I did skim over maplibre-gl-js code for index-of.

The code (in my previous comment) are browser devtools results. I believe the maplibre expressions mentioned in the comment would result in similar code running in maplibre-gl-js (haystack.indexOf(needle, fromIndex), where fromIndex can be negative).

So in maplibre-gl-js there isn't an explicit Math.max(fromIndex, 0), but <...>.indexOf seems to do it implicitly internally (negative fromIndex behaves as if the index was 0 in <string>.indexOf and <array>.indexOf).
So in the C++ version we should do the explicit std::max before casting to unsigned integers.

return EvaluationError{"Expected third argument to be of type number, but found " +
toString(typeOf(*evaluatedFromIndex)) + " instead."};
}
fromIndexValue = static_cast<size_t>(evaluatedFromIndex->get<double>());
Copy link
Contributor

Choose a reason for hiding this comment

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

This should have been something like fromIndexValue = static_cast<size_t>(std::max(evaluatedFromIndex->get<double>(), 0.0)); to avoid undefined behaviour of the static_cast for negative inputs.
See my other comment: #1113 (comment).

(There's still undefined behaviour for large numbers, but it's probably not a relevant case as it implies a huge haystack or very bad math error; negative indices on the other hand can easily happen and might be useful)

acalcutt pushed a commit to WifiDB/maplibre-native that referenced this pull request Jan 16, 2024
JannikGM pushed a commit to JannikGM/maplibre-native that referenced this pull request Feb 8, 2024
JannikGM pushed a commit to JannikGM/maplibre-native that referenced this pull request Feb 8, 2024
JannikGM pushed a commit to JannikGM/maplibre-native that referenced this pull request Feb 13, 2024
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.

None yet

4 participants