-
Notifications
You must be signed in to change notification settings - Fork 168
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
Rework KeyPathArray filters for notifications in the C-API. #7087
Changes from 4 commits
ca8e1c5
a0a4d37
c0b6c00
d36ee75
4ab3166
6cca07f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
#include <realm/object-store/c_api/types.hpp> | ||
#include <realm/object-store/c_api/util.hpp> | ||
#include <realm/object-store/keypath_helpers.hpp> | ||
|
||
namespace realm::c_api { | ||
namespace { | ||
|
@@ -65,24 +66,78 @@ struct DictionaryNotificationsCallback { | |
|
||
std::optional<KeyPathArray> build_key_path_array(realm_key_path_array_t* key_path_array) | ||
{ | ||
if (key_path_array) { | ||
KeyPathArray ret; | ||
for (size_t i = 0; i < key_path_array->nb_elements; i++) { | ||
realm_key_path_t* key_path = key_path_array->paths + i; | ||
ret.emplace_back(); | ||
KeyPath& kp = ret.back(); | ||
for (size_t j = 0; j < key_path->nb_elements; j++) { | ||
realm_key_path_elem_t* path_elem = key_path->path_elements + j; | ||
kp.emplace_back(TableKey(path_elem->object), ColKey(path_elem->property)); | ||
std::optional<KeyPathArray> ret; | ||
if (key_path_array && key_path_array->size()) { | ||
ret.emplace(std::move(*key_path_array)); | ||
} | ||
return ret; | ||
} | ||
|
||
static KeyPathArray create_key_path_array(Group& g, const ObjectSchema& object_schema, const Schema& schema, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't there be value in having this method available to SDKs that do not use the C-API? I guess it is already available since it is just a static helper method, but maybe the location is a bit wierd. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A static function is actually private within the compilation unit. We might consider making it public somewhere. At least to the binding generator. |
||
const char** all_key_paths_begin, const char** all_key_paths_end) | ||
{ | ||
KeyPathArray resolved_key_path_array; | ||
for (auto it = all_key_paths_begin; it != all_key_paths_end; it++) { | ||
KeyPath resolved_key_path; | ||
const ObjectSchema* schema_at_index = &object_schema; | ||
const Property* prop = nullptr; | ||
// Split string based on '.' | ||
const char* path = *it; | ||
do { | ||
auto p = find_chr(path, '.'); | ||
StringData property(path, p - path); | ||
path = p; | ||
if (!schema_at_index) { | ||
throw InvalidArgument( | ||
util::format("Property '%1' in KeyPath '%2' is not a collection of objects or an object " | ||
"reference, so it cannot be used as an intermediate keypath element.", | ||
prop->public_name, *it)); | ||
} | ||
} | ||
return ret; | ||
prop = schema_at_index->property_for_public_name(property); | ||
if (prop) { | ||
ColKey col_key = prop->column_key; | ||
if (prop->type == PropertyType::Object || prop->type == PropertyType::LinkingObjects) { | ||
auto found_schema = schema.find(prop->object_type); | ||
if (found_schema != schema.end()) { | ||
schema_at_index = &*found_schema; | ||
if (prop->type == PropertyType::LinkingObjects) { | ||
// Find backlink column key | ||
auto origin_prop = schema_at_index->property_for_name(prop->link_origin_property_name); | ||
auto origin_table = ObjectStore::table_for_object_type(g, schema_at_index->name); | ||
col_key = origin_table->get_opposite_column(origin_prop->column_key); | ||
} | ||
} | ||
} | ||
resolved_key_path.emplace_back(schema_at_index->table_key, col_key); | ||
} | ||
else { | ||
throw InvalidArgument(util::format("Property '%1' in KeyPath '%2' is not a valid property in %3.", | ||
property, *it, schema_at_index->name)); | ||
} | ||
} while (*path++ == '.'); | ||
resolved_key_path_array.push_back(std::move(resolved_key_path)); | ||
} | ||
return std::nullopt; | ||
return resolved_key_path_array; | ||
} | ||
|
||
} // namespace | ||
|
||
RLM_API realm_key_path_array_t* realm_create_key_path_array(const realm_t* realm, | ||
const realm_class_key_t object_class_key, | ||
int user_key_paths_count, const char** user_key_paths) | ||
{ | ||
return wrap_err([&]() { | ||
KeyPathArray ret; | ||
if (user_key_paths) { | ||
const Schema& schema = (*realm)->schema(); | ||
const ObjectSchema& object_schema = schema_for_table(*realm, TableKey(object_class_key)); | ||
ret = create_key_path_array((*realm)->read_group(), object_schema, schema, user_key_paths, | ||
user_key_paths + user_key_paths_count); | ||
} | ||
return new realm_key_path_array_t(std::move(ret)); | ||
}); | ||
} | ||
|
||
RLM_API realm_notification_token_t* realm_object_add_notification_callback(realm_object_t* obj, | ||
realm_userdata_t userdata, | ||
realm_free_userdata_func_t free, | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -361,6 +361,14 @@ constexpr inline size_t round_down(size_t p, size_t align) | |
return r & (~(align - 1)); | ||
} | ||
|
||
// return pointer to found character or to terminating NUL | ||
static inline const char* find_chr(const char* p, char c) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need this utility? It seems to me that it is just a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. strchr will return nullptr if not found. We need it to return a pointer to terminating NUL character. GCC has a function called strchrnul, but that is not generally available. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I think it does not make a huge difference if we call |
||
{ | ||
while (*p && *p != c) { | ||
++p; | ||
} | ||
return p; | ||
} | ||
|
||
#ifdef _WIN32 | ||
typedef HANDLE FileDesc; | ||
|
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 guess
user_key_paths_count
cannot be negative.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.
Sure not.