Skip to content

Commit 2d948f7

Browse files
author
Ivan Dlugos
committed
box getAll/getMany - large array support on 32-bit systems
1 parent 7559acf commit 2d948f7

File tree

5 files changed

+76
-12
lines changed

5 files changed

+76
-12
lines changed

lib/src/bindings/bindings.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ class _ObjectBoxBindings {
6969
int Function(Pointer<Void> box, int id, Pointer<Pointer<Uint8>> data, Pointer<IntPtr> size) obx_box_get;
7070
Pointer<OBX_bytes_array> Function(Pointer<Void> box, Pointer<OBX_id_array> ids) obx_box_get_many;
7171
Pointer<OBX_bytes_array> Function(Pointer<Void> box) obx_box_get_all;
72+
int Function(Pointer<Void> box, Pointer<OBX_id_array> ids, Pointer<NativeFunction<obx_data_visitor_native_t>> visitor,
73+
Pointer<Void> user_data) obx_box_visit_many;
74+
int Function(Pointer<Void> box, Pointer<NativeFunction<obx_data_visitor_native_t>> visitor, Pointer<Void> user_data)
75+
obx_box_visit_all;
7276
int Function(Pointer<Void> box, int id_or_zero) obx_box_id_for_put;
7377
int Function(Pointer<Void> box, int count, Pointer<Uint64> out_first_id) obx_box_ids_for_put;
7478
int Function(Pointer<Void> box, int id, Pointer<Uint8> data, int size, int mode) obx_box_put;
@@ -217,6 +221,8 @@ class _ObjectBoxBindings {
217221
obx_box_get = _fn<obx_box_get_native_t>("obx_box_get").asFunction();
218222
obx_box_get_many = _fn<obx_box_get_many_native_t>("obx_box_get_many").asFunction();
219223
obx_box_get_all = _fn<obx_box_get_all_native_t>("obx_box_get_all").asFunction();
224+
obx_box_visit_many = _fn<obx_box_visit_many_native_t>("obx_box_visit_many").asFunction();
225+
obx_box_visit_all = _fn<obx_box_visit_all_native_t>("obx_box_visit_all").asFunction();
220226
obx_box_id_for_put = _fn<obx_box_id_for_put_native_t>("obx_box_id_for_put").asFunction();
221227
obx_box_ids_for_put = _fn<obx_box_ids_for_put_native_t>("obx_box_ids_for_put").asFunction();
222228
obx_box_put = _fn<obx_box_put_native_t>("obx_box_put").asFunction();

lib/src/bindings/signatures.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ typedef obx_box_get_native_t = Int32 Function(
6161
Pointer<Void> box, Uint64 id, Pointer<Pointer<Uint8>> data, Pointer<IntPtr> size);
6262
typedef obx_box_get_many_native_t = Pointer<OBX_bytes_array> Function(Pointer<Void> box, Pointer<OBX_id_array> ids);
6363
typedef obx_box_get_all_native_t = Pointer<OBX_bytes_array> Function(Pointer<Void> box);
64+
typedef obx_box_visit_many_native_t = Int32 Function(Pointer<Void> box, Pointer<OBX_id_array> ids,
65+
Pointer<NativeFunction<obx_data_visitor_native_t>> visitor, Pointer<Void> user_data);
66+
typedef obx_box_visit_all_native_t = Int32 Function(
67+
Pointer<Void> box, Pointer<NativeFunction<obx_data_visitor_native_t>> visitor, Pointer<Void> user_data);
6468
typedef obx_box_id_for_put_native_t = Uint64 Function(Pointer<Void> box, Uint64 id_or_zero);
6569
typedef obx_box_ids_for_put_native_t = Int32 Function(Pointer<Void> box, Uint64 count, Pointer<Uint64> out_first_id);
6670
typedef obx_box_put_native_t = Int32 Function(

lib/src/box.dart

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'common.dart';
55
import "store.dart";
66
import "bindings/bindings.dart";
77
import "bindings/constants.dart";
8+
import "bindings/data_visitor.dart";
89
import "bindings/flatbuffers.dart";
910
import "bindings/helpers.dart";
1011
import "bindings/structs.dart";
@@ -24,8 +25,9 @@ class Box<T> {
2425
ModelEntity _modelEntity;
2526
ObjectReader<T> _entityReader;
2627
OBXFlatbuffersManager<T> _fbManager;
28+
final bool _supportsBytesArrays;
2729

28-
Box(this._store) {
30+
Box(this._store) : _supportsBytesArrays = bindings.obx_supports_bytes_array() == 1 {
2931
EntityDefinition<T> entityDefs = _store.entityDef<T>();
3032
_modelEntity = entityDefs.model;
3133
_entityReader = entityDefs.reader;
@@ -160,34 +162,63 @@ class Box<T> {
160162
}
161163
}
162164

163-
List<T> _getMany(bool allowMissing, Pointer<OBX_bytes_array> Function() cCall) {
165+
List<T> _getMany(
166+
bool allowMissing, Pointer<OBX_bytes_array> Function() cGetArray, void Function(DataVisitor) cVisit) {
164167
return _store.runInTransaction(TxMode.Read, () {
165-
final bytesArray = cCall();
168+
if (_supportsBytesArrays) {
169+
final bytesArray = cGetArray();
170+
try {
171+
return _fbManager.unmarshalArray(bytesArray, allowMissing: false);
172+
} finally {
173+
bindings.obx_bytes_array_free(bytesArray);
174+
}
175+
}
176+
177+
final results = <T>[];
178+
final visitor = DataVisitor((Pointer<Uint8> dataPtr, int length) {
179+
if (dataPtr == null || dataPtr.address == 0 || length == 0) {
180+
if (allowMissing) {
181+
results.add(null);
182+
return true;
183+
} else {
184+
throw Exception('Object not found');
185+
}
186+
}
187+
final bytes = dataPtr.asTypedList(length);
188+
results.add(_fbManager.unmarshal(bytes));
189+
return true;
190+
});
191+
166192
try {
167-
return _fbManager.unmarshalArray(bytesArray, allowMissing: allowMissing);
193+
cVisit(visitor);
168194
} finally {
169-
bindings.obx_bytes_array_free(bytesArray);
195+
visitor.close();
170196
}
197+
return results;
171198
});
172199
}
173200

174201
/// Returns a list of [ids.length] Objects of type T, each corresponding to the location of its ID in [ids].
175-
/// Non-existant IDs become null.
202+
/// Non-existent IDs become null.
176203
List<T> getMany(List<int> ids) {
177204
if (ids.isEmpty) return [];
178205

179-
const bool allowMissing = true; // returns null if null is encountered in the data found
206+
const bool allowMissing = true; // result includes null if an object is missing
180207
return OBX_id_array.executeWith(
181208
ids,
182-
(ptr) => _getMany(allowMissing,
183-
() => checkObxPtr(bindings.obx_box_get_many(_cBox, ptr), "failed to get many objects from box")));
209+
(ptr) => _getMany(
210+
allowMissing,
211+
() => checkObxPtr(bindings.obx_box_get_many(_cBox, ptr), "failed to get many objects from box"),
212+
(DataVisitor visitor) => checkObx(bindings.obx_box_visit_many(_cBox, ptr, visitor.fn, visitor.userData))));
184213
}
185214

186215
/// Returns all stored objects in this Box.
187216
List<T> getAll() {
188217
const bool allowMissing = false; // throw if null is encountered in the data found
189218
return _getMany(
190-
allowMissing, () => checkObxPtr(bindings.obx_box_get_all(_cBox), "failed to get all objects from box"));
219+
allowMissing,
220+
() => checkObxPtr(bindings.obx_box_get_all(_cBox), "failed to get all objects from box"),
221+
(DataVisitor visitor) => checkObx(bindings.obx_box_visit_all(_cBox, visitor.fn, visitor.userData)));
191222
}
192223

193224
/// Returns a builder to create queries for Object matching supplied criteria.

test/box_test.dart

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,29 @@ void main() {
7878
}
7979
});
8080

81-
test(".getMany correctly handles non-existant items", () {
81+
test(".getAll/getMany works on large arrays", () {
82+
// This would fail on 32-bit system if objectbox-c obx_supports_bytes_array() wasn't respected
83+
final length = 10 * 1000;
84+
final largeString = 'A' * length;
85+
expect(largeString.length, length);
86+
87+
box.put(TestEntity(tString: largeString));
88+
box.put(TestEntity(tString: largeString));
89+
90+
List<TestEntity> items = box.getAll();
91+
expect(items.length, 2);
92+
expect(items[0].tString, largeString);
93+
expect(items[1].tString, largeString);
94+
95+
box.put(TestEntity(tString: largeString));
96+
97+
items = box.getMany([1, 2]);
98+
expect(items.length, 2);
99+
expect(items[0].tString, largeString);
100+
expect(items[1].tString, largeString);
101+
});
102+
103+
test(".getMany correctly handles non-existent items", () {
82104
final List<TestEntity> items = ["One", "Two"].map((s) => TestEntity(tString: s)).toList();
83105
final List<int> ids = box.putMany(items);
84106
int otherId = 1;

test/query_test.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,11 @@ void main() {
210210
final largeString = 'A' * length;
211211
expect(largeString.length, length);
212212

213+
box.put(TestEntity(tString: largeString));
213214
box.put(TestEntity(tString: largeString));
214215
box.put(TestEntity(tString: largeString));
215216

216-
List<TestEntity> items = box.query(TestEntity_.id.greaterThan(0)).build().find();
217+
List<TestEntity> items = box.query(TestEntity_.id.lessThan(3)).build().find();
217218
expect(items.length, 2);
218219
expect(items[0].tString, largeString);
219220
expect(items[1].tString, largeString);

0 commit comments

Comments
 (0)