Skip to content

Commit

Permalink
Expose list_find in the c api (#5848)
Browse files Browse the repository at this point in the history
* expose list_find in the c api

* changelog entry

* fix compilation warning

* Support finding a typed link in LnkLst

* allow type_TypedLink for sets

* Fix

* added some more testing for element not found

* more testing

Co-authored-by: Jørgen Edelbo <[email protected]>
  • Loading branch information
nicola-cab and jedelbo authored Sep 14, 2022
1 parent e7e2b8a commit 4d21f9a
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* <New feature description> (PR [#????](https://github.com/realm/realm-core/pull/????))
* Convert object_store::Collection types into Results (PR [#5845](https://github.com/realm/realm-core/pull/5845))
* Expose `realm_object_get_parent` in the C API (PR [#5851](https://github.com/realm/realm-core/pull/5851))
* Expose `realm_list_find` in the C API (PR [#5848](https://github.com/realm/realm-core/pull/5848))

### Fixed
* <How do the end-user experience this issue? what was the impact?> ([#????](https://github.com/realm/realm-core/issues/????), since v?.?.?)
Expand Down
9 changes: 9 additions & 0 deletions src/realm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1703,6 +1703,15 @@ RLM_API bool realm_list_get_property(const realm_list_t*, realm_property_info_t*
*/
RLM_API bool realm_list_get(const realm_list_t*, size_t index, realm_value_t* out_value);

/**
* Find the value in the list passed as parameter.
* @param value to search in the list
* @param out_index the index in the list where the value has been found or realm::not_found.
* @param out_found boolean that indicates whether the value is found or not
* @return true if no exception occurred.
*/
RLM_API bool realm_list_find(const realm_list_t*, const realm_value_t* value, size_t* out_index, bool* out_found);

/**
* Set the value at @a index.
*
Expand Down
6 changes: 6 additions & 0 deletions src/realm/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,12 @@ inline size_t LnkLst::find_any(Mixed value) const
else if (value.get_type() == type_Link) {
return find_first(value.get<ObjKey>());
}
else if (value.get_type() == type_TypedLink) {
auto link = value.get_link();
if (link.get_table_key() == get_target_table()->get_key()) {
return find_first(link.get_obj_key());
}
}
return realm::not_found;
}

Expand Down
21 changes: 21 additions & 0 deletions src/realm/object-store/c_api/list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,27 @@ RLM_API bool realm_list_get(const realm_list_t* list, size_t index, realm_value_
});
}

RLM_API bool realm_list_find(const realm_list_t* list, const realm_value_t* value, size_t* out_index, bool* out_found)
{
if (out_index)
*out_index = realm::not_found;
if (out_found)
*out_found = false;

return wrap_err([&] {
list->verify_attached();
auto val = from_capi(*value);
check_value_assignable(*list, val);
auto index = list->find_any(val);
if (out_index)
*out_index = index;
if (out_found)
*out_found = index < list->size();
return true;
});
}


RLM_API bool realm_list_insert(realm_list_t* list, size_t index, realm_value_t value)
{
return wrap_err([&]() {
Expand Down
17 changes: 11 additions & 6 deletions src/realm/set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1240,13 +1240,18 @@ inline size_t LnkSet::find_any(Mixed value) const
{
if (value.is_null())
return not_found;
if (value.get_type() != type_Link)
return not_found;
size_t found = find(value.get<ObjKey>());
if (found != not_found) {
found = real2virtual(found);

const auto type = value.get_type();
if (type == type_Link) {
return find(value.get<ObjKey>());
}
if (type == type_TypedLink) {
auto link = value.get_link();
if (link.get_table_key() == get_target_table()->get_key()) {
return find(link.get_obj_key());
}
}
return found;
return not_found;
}

inline bool LnkSet::is_obj_valid(size_t) const noexcept
Expand Down
61 changes: 60 additions & 1 deletion test/object-store/c_api/c_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2460,6 +2460,23 @@ TEST_CASE("C API", "[c_api]") {
CHECK(rlm_stdstr(a2) == "a");
CHECK(rlm_stdstr(b2) == "b");
CHECK(c2.type == RLM_TYPE_NULL);

size_t out_index = -1;
bool found;
CHECK(checked(realm_list_find(strings.get(), &a2, &out_index, &found)));
CHECK(out_index == 0);
CHECK(found);
CHECK(checked(realm_list_find(strings.get(), &b2, &out_index, &found)));
CHECK(out_index == 1);
CHECK(found);
CHECK(checked(realm_list_find(strings.get(), &c2, &out_index, &found)));
CHECK(out_index == 2);
CHECK(found);

realm_value_t dummy = rlm_str_val("c");
CHECK(checked(realm_list_find(strings.get(), &dummy, &out_index, &found)));
CHECK(!found);
CHECK(out_index == realm::not_found);
});
}

Expand Down Expand Up @@ -2558,49 +2575,77 @@ TEST_CASE("C API", "[c_api]") {
CHECK(realm_list_insert(nullable_uuid_list.get(), 1, null));
});

realm_value_t value;
auto find = ([&](auto* list, auto* value) {
std::size_t index = -1;
bool found = false;
CHECK(checked(realm_list_find(list, value, &index, &found)));
CHECK(index == 0);
CHECK(found);
return (index < list->size()) && found == true;
});

realm_value_t value;
CHECK(realm_list_get(int_list.get(), 0, &value));
CHECK(rlm_val_eq(value, integer));
CHECK(!realm_list_get_linked_object(int_list.get(), 0));
CHECK(find(int_list.get(), &value));
CHECK(realm_list_get(bool_list.get(), 0, &value));
CHECK(rlm_val_eq(value, boolean));
CHECK(find(bool_list.get(), &value));
CHECK(realm_list_get(string_list.get(), 0, &value));
CHECK(rlm_val_eq(value, string));
CHECK(find(string_list.get(), &value));
CHECK(realm_list_get(binary_list.get(), 0, &value));
CHECK(rlm_val_eq(value, binary));
CHECK(find(binary_list.get(), &value));
CHECK(realm_list_get(timestamp_list.get(), 0, &value));
CHECK(rlm_val_eq(value, timestamp));
CHECK(find(timestamp_list.get(), &value));
CHECK(realm_list_get(float_list.get(), 0, &value));
CHECK(rlm_val_eq(value, fnum));
CHECK(find(float_list.get(), &value));
CHECK(realm_list_get(double_list.get(), 0, &value));
CHECK(rlm_val_eq(value, dnum));
CHECK(find(double_list.get(), &value));
CHECK(realm_list_get(decimal_list.get(), 0, &value));
CHECK(rlm_val_eq(value, decimal));
CHECK(find(decimal_list.get(), &value));
CHECK(realm_list_get(object_id_list.get(), 0, &value));
CHECK(rlm_val_eq(value, object_id));
CHECK(find(object_id_list.get(), &value));
CHECK(realm_list_get(uuid_list.get(), 0, &value));
CHECK(rlm_val_eq(value, uuid));
CHECK(find(uuid_list.get(), &value));
CHECK(realm_list_get(nullable_int_list.get(), 0, &value));
CHECK(rlm_val_eq(value, integer));
CHECK(find(nullable_int_list.get(), &value));
CHECK(realm_list_get(nullable_bool_list.get(), 0, &value));
CHECK(rlm_val_eq(value, boolean));
CHECK(find(nullable_bool_list.get(), &value));
CHECK(realm_list_get(nullable_string_list.get(), 0, &value));
CHECK(rlm_val_eq(value, string));
CHECK(find(nullable_string_list.get(), &value));
CHECK(realm_list_get(nullable_binary_list.get(), 0, &value));
CHECK(rlm_val_eq(value, binary));
CHECK(find(nullable_binary_list.get(), &value));
CHECK(realm_list_get(nullable_timestamp_list.get(), 0, &value));
CHECK(rlm_val_eq(value, timestamp));
CHECK(find(nullable_timestamp_list.get(), &value));
CHECK(realm_list_get(nullable_float_list.get(), 0, &value));
CHECK(rlm_val_eq(value, fnum));
CHECK(find(nullable_float_list.get(), &value));
CHECK(realm_list_get(nullable_double_list.get(), 0, &value));
CHECK(rlm_val_eq(value, dnum));
CHECK(find(nullable_double_list.get(), &value));
CHECK(realm_list_get(nullable_decimal_list.get(), 0, &value));
CHECK(rlm_val_eq(value, decimal));
CHECK(find(nullable_decimal_list.get(), &value));
CHECK(realm_list_get(nullable_object_id_list.get(), 0, &value));
CHECK(rlm_val_eq(value, object_id));
CHECK(find(nullable_object_id_list.get(), &value));
CHECK(realm_list_get(nullable_uuid_list.get(), 0, &value));
CHECK(rlm_val_eq(value, uuid));
CHECK(find(nullable_uuid_list.get(), &value));

write([&]() {
CHECK(realm_list_insert(nullable_int_list.get(), 0, null));
Expand Down Expand Up @@ -2651,6 +2696,20 @@ TEST_CASE("C API", "[c_api]") {
size_t size;
CHECK(checked(realm_list_size(bars.get(), &size)));
CHECK(size == 2);

bool found = true;
size_t index = -1;
CHECK(checked(realm_list_find(bars.get(), &bar_link_val, &index, &found)));
CHECK(index == 0);
CHECK(found);

realm_list_clear(bars.get());
CHECK(checked(realm_list_find(bars.get(), &bar_link_val, &index, &found)));
CHECK(index == realm::not_found);
CHECK(!found);

CHECK(checked(realm_list_insert(bars.get(), 0, bar_link_val)));
CHECK(checked(realm_list_insert(bars.get(), 1, bar_link_val)));
});

SECTION("get") {
Expand Down
9 changes: 6 additions & 3 deletions test/test_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,9 @@ TEST(Set_Links)
CHECK_EQUAL(set_mixeds.find(bar3.get_link()), realm::npos);

bar1.remove();
set_links.insert(bar4.get_key());

CHECK_EQUAL(set_links.size(), 2);
CHECK_EQUAL(set_links.size(), 3);
CHECK_EQUAL(set_typed_links.size(), 3);
CHECK_EQUAL(set_mixeds.size(), 3);

Expand All @@ -281,14 +282,16 @@ TEST(Set_Links)
auto bar2_link = bar2.get_link();
bar2.invalidate();

CHECK_EQUAL(set_links.size(), 2);
CHECK_EQUAL(lnkset_links->size(), 1); // Unresolved link was hidden from LnkSet
CHECK_EQUAL(set_links.size(), 3);
CHECK_EQUAL(lnkset_links->size(), 2); // Unresolved link was hidden from LnkSet
CHECK_EQUAL(set_typed_links.size(), 3);
CHECK_EQUAL(set_mixeds.size(), 3);

CHECK_EQUAL(set_links.find(bar2_key), realm::npos); // The original bar2 key is no longer in the set
CHECK_NOT_EQUAL(set_links.find(bar2.get_key()), realm::npos); // The unresolved bar2 key is in the set
CHECK_EQUAL(lnkset_links->find_any(bar2.get_key()), realm::npos); // The unresolved bar2 key is hidden by LnkSet
CHECK_EQUAL(lnkset_links->find_any(bar3.get_key()), 0);
CHECK_EQUAL(lnkset_links->find_any(bar4.get_key()), 1);
CHECK_EQUAL(set_typed_links.find(bar2_link), realm::npos);
CHECK_EQUAL(set_mixeds.find(bar2_link), realm::npos);

Expand Down

0 comments on commit 4d21f9a

Please sign in to comment.