-
-
Notifications
You must be signed in to change notification settings - Fork 175
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
feat: Map item iterators #1143
base: master
Are you sure you want to change the base?
feat: Map item iterators #1143
Conversation
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1143 +/- ##
==========================================
- Coverage 82.66% 82.13% -0.54%
==========================================
Files 53 53
Lines 7927 7971 +44
Branches 1239 1244 +5
==========================================
- Hits 6553 6547 -6
- Misses 1263 1312 +49
- Partials 111 112 +1 |
@@ -1,5 +1,9 @@ | |||
# Changelog | |||
|
|||
## Unreleased | |||
|
|||
- Add map item iterators. ([#1143](https://github.com/getsentry/sentry-native/pull/1143)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that the comments in the header use "map" quite often to talk about interfaces related to the "object" value type, but I would prefer to call this an "object item iterator", given that "object" is the nomenclature that the API uses, especially in the change log.
@@ -244,6 +244,50 @@ SENTRY_API int sentry_value_remove_by_key(sentry_value_t value, const char *k); | |||
SENTRY_API int sentry_value_remove_by_key_n( | |||
sentry_value_t value, const char *k, size_t k_len); | |||
|
|||
/** | |||
* Map item iterator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Map item iterator. | |
* Object item iterator. |
/** | ||
* Map item iterator. | ||
* | ||
* It's used to iterate over the key-value pairs of a map. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* It's used to iterate over the key-value pairs of a map. | |
* It's used to iterate over the key-value pairs of an object. |
typedef struct sentry_item_iter_s sentry_item_iter_t; | ||
|
||
/** | ||
* Creates a new map item iterator. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Creates a new map item iterator. | |
* Creates a new object item iterator. |
/** | ||
* Creates a new map item iterator. | ||
* | ||
* Returns NULL if the given value is not a map. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Returns NULL if the given value is not a map. | |
* Returns `NULL` if the given value is not an object. |
sentry_value_t | ||
sentry_value_item_iter_get_value(sentry_item_iter_t *item_iter) | ||
{ | ||
if (item_iter->index >= *item_iter->len) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
if (item_iter->index >= *item_iter->len) { | ||
return sentry_value_new_null(); | ||
} | ||
return item_iter->pairs[item_iter->index].v; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
int | ||
sentry_value_item_iter_valid(sentry_item_iter_t *item_iter) | ||
{ | ||
return item_iter->index < *item_iter->len && item_iter->pairs != NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we check pairs
here, we should check len
too.
if (item_iter->frozen || item_iter->index >= *item_iter->len) { | ||
return 1; | ||
} | ||
obj_pair_t *pair = &item_iter->pairs[item_iter->index]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, do we assume that pairs
and len
are valid pointers in this case?
If so, why? Because valid()
does the check? If so, we must decide whether users must check for validity every time either the iterator or the object changed and erase()
, get_key()
and get_value()
assume valid iterators or add the checks in all of those functions.
Whichever way we choose, we should be consistent regarding the guarantees of calling valid()
, the accessors, and mutators (since adding new keys will then also be used if iterators allow object mutation).
This demonstrates how easily checks (and thus guarantees) can become inconsistent quickly when an in-place erasure is introduced. If you introduce the guarantees for each getter and mutator (making valid()
solely a function for a loop-invariant), then you can't change that without breaking code. OTOH, adding those guarantees later won't break any code.
} | ||
sentry_free(it); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we keep the mutating iterator, please also add a loop that adds keys or documents that this is forbidden.
This PR introduces map item iterators. Iterator can be used to traverse the map (aka object) key-value pairs. Iterators can also be used to selectively erase items (aka filtering).
Rationale
There is currently no way to get the keys of a map object. We need such a function to build proper representations in upstream SDKs (like
sentry-godot
). See #1142 for more details.Supercedes #1142