Add mgp::map erase and update (#1103)

This commit is contained in:
imilinovic 2023-07-30 08:36:50 +02:00 committed by GitHub
parent be4eb95a98
commit 3fd9ce4a33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 98 additions and 2 deletions

View File

@ -335,6 +335,12 @@ inline void map_insert(mgp_map *map, const char *key, mgp_value *value) {
MgInvokeVoid(mgp_map_insert, map, key, value);
}
inline void map_update(mgp_map *map, const char *key, mgp_value *value) {
MgInvokeVoid(mgp_map_update, map, key, value);
}
inline void map_erase(mgp_map *map, const char *key) { MgInvokeVoid(mgp_map_erase, map, key); }
inline size_t map_size(mgp_map *map) { return MgInvoke<size_t>(mgp_map_size, map); }
inline mgp_value *map_at(mgp_map *map, const char *key) { return MgInvoke<mgp_value *>(mgp_map_at, map, key); }

View File

@ -462,6 +462,18 @@ void mgp_map_destroy(struct mgp_map *map);
/// Return mgp_error::MGP_ERROR_KEY_ALREADY_EXISTS if a previous mapping already exists.
enum mgp_error mgp_map_insert(struct mgp_map *map, const char *key, struct mgp_value *value);
/// Insert a mapping from a NULL terminated character string to a value.
/// If a mapping with the same key already exists, it is replaced.
/// In case of update, both the string and the value are copied into the map.
/// Therefore, the map does not take ownership of the original key nor value, so
/// you still need to free their memory explicitly.
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE is returned if unable to allocate for insertion.
enum mgp_error mgp_map_update(struct mgp_map *map, const char *key, struct mgp_value *value);
// Erase a mapping by key.
// If the key doesn't exist in the map nothing happens
enum mgp_error mgp_map_erase(struct mgp_map *map, const char *key);
/// Get the number of items stored in mgp_map.
/// Current implementation always returns without errors.
enum mgp_error mgp_map_size(struct mgp_map *map, size_t *result);

View File

@ -464,6 +464,7 @@ class Map {
public:
/// @brief Creates a Map from the copy of the given @ref mgp_map.
explicit Map(mgp_map *ptr);
/// @brief Creates a Map from the copy of the given @ref mgp_map.
explicit Map(const mgp_map *const_ptr);
@ -472,6 +473,7 @@ class Map {
/// @brief Creates a Map from the given vector.
explicit Map(const std::map<std::string_view, Value> &items);
/// @brief Creates a Map from the given vector.
explicit Map(std::map<std::string_view, Value> &&items);
@ -488,11 +490,13 @@ class Map {
/// @brief Returns the size of the map.
size_t Size() const;
/// @brief Returns whether the map is empty.
bool Empty() const;
/// @brief Returns the value at the given `key`.
Value const operator[](std::string_view key) const;
/// @brief Returns the value at the given `key`.
Value const At(std::string_view key) const;
@ -533,16 +537,30 @@ class Map {
/// @brief Inserts the given `key`-`value` pair into the map. The `value` is copied.
void Insert(std::string_view key, const Value &value);
/// @brief Inserts the given `key`-`value` pair into the map.
/// @note Takes the ownership of `value` by moving it. The behavior of accessing `value` after performing this
/// operation is undefined.
void Insert(std::string_view key, Value &&value);
// void Erase(std::string_view key); // not implemented (requires mgp_map_erase in the MGP API)
/// @brief Updates the `key`-`value` pair in the map. If the key doesn't exist, the value gets inserted. The `value`
/// is copied.
void Update(std::string_view key, const Value &value);
/// @brief Updates the `key`-`value` pair in the map. If the key doesn't exist, the value gets inserted. The `value`
/// is copied.
/// @note Takes the ownership of `value` by moving it. The behavior of accessing `value` after performing this
/// operation is undefined.
void Update(std::string_view key, Value &&value);
/// @brief Erases the element associated with the key from the map, if it doesn't exist does nothing.
void Erase(std::string_view key);
// void Clear(); // not implemented (requires mgp_map_clear in the MGP API)
/// @exception std::runtime_error Map contains value of unknown type.
bool operator==(const Map &other) const;
/// @exception std::runtime_error Map contains value of unknown type.
bool operator!=(const Map &other) const;
@ -2390,9 +2408,20 @@ inline void Map::Insert(std::string_view key, const Value &value) { mgp::map_ins
inline void Map::Insert(std::string_view key, Value &&value) {
mgp::map_insert(ptr_, key.data(), value.ptr_);
value.~Value();
value.ptr_ = nullptr;
}
inline void Map::Update(std::string_view key, const Value &value) { mgp::map_update(ptr_, key.data(), value.ptr_); }
inline void Map::Update(std::string_view key, Value &&value) {
mgp::map_update(ptr_, key.data(), value.ptr_);
value.~Value();
value.ptr_ = nullptr;
}
inline void Map::Erase(std::string_view key) { mgp::map_erase(ptr_, key.data()); }
inline bool Map::operator==(const Map &other) const { return util::MapsEqual(ptr_, other.ptr_); }
inline bool Map::operator!=(const Map &other) const { return !(*this == other); }
@ -3438,7 +3467,6 @@ inline std::ostream &operator<<(std::ostream &os, const mgp::Type &type) {
}
}
/* #endregion */
/* #region Record */

View File

@ -1043,6 +1043,25 @@ mgp_error mgp_map_insert(mgp_map *map, const char *key, mgp_value *value) {
});
}
mgp_error mgp_map_update(mgp_map *map, const char *key, mgp_value *value) {
return WrapExceptions([&] {
auto emplace_result = map->items.emplace(key, *value);
if (!emplace_result.second) {
map->items.erase(emplace_result.first);
map->items.emplace(key, *value);
}
});
}
mgp_error mgp_map_erase(mgp_map *map, const char *key) {
return WrapExceptions([&] {
auto iterator = map->items.find(key);
if (iterator != map->items.end()) {
map->items.erase(iterator);
}
});
}
mgp_error mgp_map_size(mgp_map *map, size_t *result) {
static_assert(noexcept(map->items.size()));
*result = map->items.size();

View File

@ -531,3 +531,34 @@ TYPED_TEST(CppApiTestFixture, TestTypeOperatorStream) {
ASSERT_EQ(int_test, "int");
ASSERT_EQ(list_test, "list");
}
TYPED_TEST(CppApiTestFixture, TestMapUpdate) {
mgp::Map map{};
mgp::Value double_1{1.0};
mgp::Value double_2{2.0};
map.Update("1", double_1);
ASSERT_EQ(map.At("1"), double_1);
map.Update("1", double_2);
ASSERT_EQ(map.At("1"), double_2);
}
TYPED_TEST(CppApiTestFixture, TestMapErase) {
mgp::Map map{};
mgp::Value double_1{1.0};
mgp::Value double_2{2.0};
map.Insert("1", double_1);
map.Insert("2", double_2);
ASSERT_EQ(map.Size(), 2);
map.Erase("1");
ASSERT_EQ(map.Size(), 1);
map.Erase("1");
ASSERT_EQ(map.Size(), 1);
map.Erase("2");
ASSERT_EQ(map.Size(), 0);
}