• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

realm / realm-core / 2213

10 Apr 2024 11:21PM UTC coverage: 91.792% (-0.8%) from 92.623%
2213

push

Evergreen

web-flow
Add missing availability checks for SecCopyErrorMessageString (#7577)

This requires iOS 11.3 and we currently target iOS 11.

94842 of 175770 branches covered (53.96%)

7 of 22 new or added lines in 2 files covered. (31.82%)

1861 existing lines in 82 files now uncovered.

242866 of 264583 relevant lines covered (91.79%)

5593111.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.15
/src/realm/object-store/c_api/realm.cpp
1
#include <realm/object-store/c_api/types.hpp>
2
#include "realm.hpp"
3

4

5
realm_callback_token_realm::~realm_callback_token_realm()
6
{
2✔
7
    realm::c_api::CBindingContext::get(*m_realm).realm_changed_callbacks().remove(m_token);
2✔
8
}
2✔
9

10
realm_callback_token_schema::~realm_callback_token_schema()
11
{
2✔
12
    realm::c_api::CBindingContext::get(*m_realm).schema_changed_callbacks().remove(m_token);
2✔
13
}
2✔
14

15
realm_refresh_callback_token::~realm_refresh_callback_token()
16
{
6✔
17
    realm::c_api::CBindingContext::get(*m_realm).realm_pending_refresh_callbacks().remove(m_token);
6✔
18
}
6✔
19

20
namespace realm::c_api {
21

22

23
RLM_API bool realm_get_version_id(const realm_t* realm, bool* out_found, realm_version_id_t* out_version)
24
{
×
25
    return wrap_err([&]() {
×
26
        util::Optional<VersionID> version = (*realm)->current_transaction_version();
×
27
        if (version) {
×
28
            if (out_version) {
×
29
                *out_version = to_capi(*version);
×
30
            }
×
31
            if (out_found) {
×
32
                *out_found = true;
×
33
            }
×
34
        }
×
35
        else {
×
36
            if (out_version) {
×
37
                *out_version = to_capi(VersionID(0, 0));
×
38
            }
×
39
            if (out_found) {
×
40
                *out_found = false;
×
41
            }
×
42
        }
×
43
        return true;
×
44
    });
×
45
}
×
46

47
RLM_API bool realm_get_num_versions(const realm_t* realm, uint64_t* out_versions_count)
48
{
×
49
    return wrap_err([&]() {
×
50
        if (out_versions_count) {
×
51
            *out_versions_count = (*realm)->get_number_of_versions();
×
52
        }
×
53
        return true;
×
54
    });
×
55
}
×
56

57
RLM_API const char* realm_get_library_version()
58
{
2✔
59
    return REALM_VERSION_STRING;
2✔
60
}
2✔
61

62
RLM_API void realm_get_library_version_numbers(int* out_major, int* out_minor, int* out_patch, const char** out_extra)
63
{
2✔
64
    *out_major = REALM_VERSION_MAJOR;
2✔
65
    *out_minor = REALM_VERSION_MINOR;
2✔
66
    *out_patch = REALM_VERSION_PATCH;
2✔
67
    *out_extra = REALM_VERSION_EXTRA;
2✔
68
}
2✔
69

70
RLM_API realm_t* realm_open(const realm_config_t* config)
71
{
684✔
72
    return wrap_err([&]() {
684✔
73
        return new shared_realm{Realm::get_shared_realm(*config)};
684✔
74
    });
684✔
75
}
684✔
76

77
RLM_API bool realm_convert_with_config(const realm_t* realm, const realm_config_t* config, bool merge_with_existing)
78
{
8✔
79
    return wrap_err([&]() {
8✔
80
        (*realm)->convert(*config, merge_with_existing);
8✔
81
        return true;
8✔
82
    });
8✔
83
}
8✔
84

85
RLM_API bool realm_convert_with_path(const realm_t* realm, const char* path, realm_binary_t encryption_key,
86
                                     bool merge_with_existing)
87
{
8✔
88
    return wrap_err([&]() {
8✔
89
        Realm::Config config;
8✔
90
        config.path = path;
8✔
91
        if (encryption_key.data) {
8✔
92
            config.encryption_key.assign(encryption_key.data, encryption_key.data + encryption_key.size);
×
93
        }
×
94
        (*realm)->convert(config, merge_with_existing);
8✔
95
        return true;
8✔
96
    });
8✔
97
}
8✔
98

99
RLM_API bool realm_delete_files(const char* realm_file_path, bool* did_delete_realm)
100
{
×
101
    return wrap_err([&]() {
×
102
        Realm::delete_files(realm_file_path, did_delete_realm);
×
103
        return true;
×
104
    });
×
105
}
×
106

107
RLM_API realm_t* _realm_from_native_ptr(const void* pshared_ptr, size_t n)
108
{
2✔
109
    REALM_ASSERT_RELEASE(n == sizeof(SharedRealm));
2✔
110
    auto ptr = static_cast<const SharedRealm*>(pshared_ptr);
2✔
111
    return new shared_realm{*ptr};
2✔
112
}
2✔
113

114
RLM_API void _realm_get_native_ptr(const realm_t* realm, void* pshared_ptr, size_t n)
115
{
2✔
116
    REALM_ASSERT_RELEASE(n == sizeof(SharedRealm));
2✔
117
    auto& shared_ptr = *static_cast<SharedRealm*>(pshared_ptr);
2✔
118
    shared_ptr = *realm;
2✔
119
}
2✔
120

121
RLM_API bool realm_is_closed(realm_t* realm)
122
{
318✔
123
    return (*realm)->is_closed();
318✔
124
}
318✔
125

126
RLM_API bool realm_is_writable(const realm_t* realm)
127
{
4✔
128
    return (*realm)->is_in_transaction() || (*realm)->is_in_async_transaction();
4✔
129
}
4✔
130

131
RLM_API bool realm_close(realm_t* realm)
132
{
316✔
133
    return wrap_err([&]() {
316✔
134
        (*realm)->close();
316✔
135
        return true;
316✔
136
    });
316✔
137
}
316✔
138

139
RLM_API bool realm_begin_read(realm_t* realm)
140
{
8✔
141
    return wrap_err([&]() {
8✔
142
        (*realm)->read_group();
8✔
143
        return true;
8✔
144
    });
8✔
145
}
8✔
146

147
RLM_API bool realm_begin_write(realm_t* realm)
148
{
484✔
149
    return wrap_err([&]() {
484✔
150
        (*realm)->begin_transaction();
484✔
151
        return true;
484✔
152
    });
484✔
153
}
484✔
154

155
RLM_API bool realm_commit(realm_t* realm)
156
{
474✔
157
    return wrap_err([&]() {
474✔
158
        (*realm)->commit_transaction();
474✔
159
        return true;
474✔
160
    });
474✔
161
}
474✔
162

163
RLM_API bool realm_rollback(realm_t* realm)
164
{
2✔
165
    return wrap_err([&]() {
2✔
166
        (*realm)->cancel_transaction();
2✔
167
        return true;
2✔
168
    });
2✔
169
}
2✔
170

171
RLM_API bool realm_async_begin_write(realm_t* realm, realm_async_begin_write_func_t callback,
172
                                     realm_userdata_t userdata, realm_free_userdata_func_t userdata_free,
173
                                     bool notify_only, unsigned int* transaction_id)
174
{
×
175
    auto cb = [callback, userdata = UserdataPtr{userdata, userdata_free}]() {
×
176
        callback(userdata.get());
×
177
    };
×
178
    return wrap_err([&]() {
×
179
        auto id = (*realm)->async_begin_transaction(std::move(cb), notify_only);
×
180
        if (transaction_id)
×
181
            *transaction_id = id;
×
182
        return true;
×
183
    });
×
184
}
×
185

186
RLM_API bool realm_async_commit(realm_t* realm, realm_async_commit_func_t callback, realm_userdata_t userdata,
187
                                realm_free_userdata_func_t userdata_free, bool allow_grouping,
188
                                unsigned int* transaction_id)
189
{
×
190
    auto cb = [callback, userdata = UserdataPtr{userdata, userdata_free}](std::exception_ptr err) {
×
191
        if (err) {
×
192
            try {
×
193
                std::rethrow_exception(err);
×
194
            }
×
195
            catch (const std::exception& e) {
×
196
                callback(userdata.get(), true, e.what());
×
197
            }
×
198
        }
×
199
        else {
×
200
            callback(userdata.get(), false, nullptr);
×
201
        }
×
202
    };
×
203
    return wrap_err([&]() {
×
204
        auto id = (*realm)->async_commit_transaction(std::move(cb), allow_grouping);
×
205
        if (transaction_id)
×
206
            *transaction_id = id;
×
207
        return true;
×
208
    });
×
209
}
×
210

211
RLM_API bool realm_async_cancel(realm_t* realm, unsigned int token, bool* cancelled)
212
{
×
213
    return wrap_err([&]() {
×
214
        auto res = (*realm)->async_cancel_transaction(token);
×
215
        if (cancelled)
×
216
            *cancelled = res;
×
217
        return true;
×
218
    });
×
219
}
×
220

221
RLM_API realm_callback_token_t* realm_add_realm_changed_callback(realm_t* realm,
222
                                                                 realm_on_realm_change_func_t callback,
223
                                                                 realm_userdata_t userdata,
224
                                                                 realm_free_userdata_func_t free_userdata)
225
{
2✔
226
    util::UniqueFunction<void()> func = [callback, userdata = UserdataPtr{userdata, free_userdata}]() {
2✔
227
        callback(userdata.get());
2✔
228
    };
2✔
229
    return new realm_callback_token_realm(
2✔
230
        realm, CBindingContext::get(*realm).realm_changed_callbacks().add(std::move(func)));
2✔
231
}
2✔
232

233
RLM_API realm_refresh_callback_token_t* realm_add_realm_refresh_callback(realm_t* realm,
234
                                                                         realm_on_realm_refresh_func_t callback,
235
                                                                         realm_userdata_t userdata,
236
                                                                         realm_free_userdata_func_t userdata_free)
237
{
14✔
238
    util::UniqueFunction<void()> func = [callback, userdata = UserdataPtr{userdata, userdata_free}]() {
10✔
239
        callback(userdata.get());
6✔
240
    };
6✔
241

7✔
242
    if ((*realm)->is_frozen())
14✔
243
        return nullptr;
2✔
244

6✔
245
    const util::Optional<DB::version_type>& latest_snapshot_version = (*realm)->latest_snapshot_version();
12✔
246

6✔
247
    if (!latest_snapshot_version)
12✔
248
        return nullptr;
2✔
249

5✔
250
    const auto current_version = (*realm)->current_transaction_version();
10✔
251
    if (!current_version || *latest_snapshot_version <= (*current_version).version)
10✔
252
        return nullptr;
4✔
253

3✔
254
    auto& refresh_callbacks = CBindingContext::get(*realm).realm_pending_refresh_callbacks();
6✔
255
    return new realm_refresh_callback_token(realm, refresh_callbacks.add(*latest_snapshot_version, std::move(func)));
6✔
256
}
6✔
257

258
RLM_API bool realm_refresh(realm_t* realm, bool* did_refresh)
259
{
494✔
260
    return wrap_err([&]() {
494✔
261
        bool result = (*realm)->refresh();
494✔
262
        if (did_refresh) {
494✔
263
            *did_refresh = result;
2✔
264
        }
2✔
265

247✔
266
        // the call succeeded
247✔
267
        return true;
494✔
268
    });
494✔
269
}
494✔
270

271
RLM_API realm_t* realm_freeze(const realm_t* live_realm)
272
{
22✔
273
    return wrap_err([&]() {
22✔
274
        auto& p = **live_realm;
22✔
275
        return new realm_t{p.freeze()};
22✔
276
    });
22✔
277
}
22✔
278

279
RLM_API bool realm_compact(realm_t* realm, bool* did_compact)
280
{
2✔
281
    return wrap_err([&]() {
2✔
282
        auto& p = **realm;
2✔
283
        bool result = p.compact();
2✔
284
        if (did_compact) {
2✔
285
            *did_compact = result;
2✔
286
        }
2✔
287

1✔
288
        // the call succeeded
1✔
289
        return true;
2✔
290
    });
2✔
291
}
2✔
292

293
RLM_API bool realm_remove_table(realm_t* realm, const char* table_name, bool* table_deleted)
294
{
4✔
295
    if (table_deleted)
4✔
296
        *table_deleted = false;
4✔
297

2✔
298
    return wrap_err([&] {
4✔
299
        auto table = ObjectStore::table_for_object_type((*realm)->read_group(), table_name);
4✔
300
        if (table) {
4✔
301
            const auto& schema = (*realm)->schema();
4✔
302
            const auto& object_schema = schema.find(table_name);
4✔
303
            if (object_schema != schema.end()) {
4✔
304
                throw LogicError(ErrorCodes::InvalidSchemaChange,
2✔
305
                                 "Attempt to remove a table that is currently part of the schema");
2✔
306
            }
2✔
307
            (*realm)->read_group().remove_table(table->get_key());
2✔
308
            *table_deleted = true;
2✔
309
        }
2✔
310
        return true;
3✔
311
    });
4✔
312
}
4✔
313

314
RLM_API realm_t* realm_from_thread_safe_reference(realm_thread_safe_reference_t* tsr, realm_scheduler_t* scheduler)
315
{
4✔
316
    return wrap_err([&]() {
4✔
317
        auto rtsr = dynamic_cast<shared_realm::thread_safe_reference*>(tsr);
4✔
318
        if (!rtsr) {
4✔
319
            throw LogicError{ErrorCodes::IllegalOperation, "Thread safe reference type mismatch"};
2✔
320
        }
2✔
321

1✔
322
        std::shared_ptr<util::Scheduler> sch;
2✔
323
        if (scheduler) {
2✔
UNCOV
324
            sch = *scheduler;
×
UNCOV
325
        }
×
326
        auto realm = Realm::get_shared_realm(static_cast<ThreadSafeReference&&>(*rtsr), sch);
2✔
327
        return new shared_realm{std::move(realm)};
2✔
328
    });
2✔
329
}
4✔
330

331
CBindingContext& CBindingContext::get(SharedRealm realm)
332
{
20✔
333
    if (!realm->m_binding_context) {
20✔
334
        realm->m_binding_context.reset(new CBindingContext(realm));
8✔
335
    }
8✔
336

10✔
337
    CBindingContext* ctx = dynamic_cast<CBindingContext*>(realm->m_binding_context.get());
20✔
338
    REALM_ASSERT(ctx != nullptr);
20✔
339
    return *ctx;
20✔
340
}
20✔
341

342
void CBindingContext::did_change(std::vector<ObserverState> const&, std::vector<void*> const&, bool)
343
{
8✔
344
    if (auto ptr = realm.lock()) {
8✔
345
        auto version_id = ptr->read_transaction_version();
8✔
346
        m_realm_pending_refresh_callbacks.invoke(version_id.version);
8✔
347
    }
8✔
348
    m_realm_changed_callbacks.invoke();
8✔
349
}
8✔
350

351
} // namespace realm::c_api
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc