Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ lib/*.so
lib/*.a
.vscode/
**/*.g.dart
doc/api
21 changes: 14 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
0.5.0 (2019-11-18)
------------------
* Dart 2.6 support - breaking change due to Dart 2.6 FFI changes.
Please keep using 0.4 if you're on Dart 2.5 or Flutter. Currently no Flutter version comes with Dart 2.6 final.
(thanks [Jasm Sison](https://github.com/Buggaboo) for [#54](https://github.com/objectbox/objectbox-dart/pull/57))
* Docs fixes & improvements

0.4.0 (2019-10-31)
------------------
* Flutter Android support
* Queries for all currently supported types
(thanks [Jasm Sison](https://github.com/Buggaboo) for [#27](https://github.com/objectbox/objectbox-dart/pull/27) and [#46](https://github.com/objectbox/objectbox-dart/pull/46)]
(thanks [Jasm Sison](https://github.com/Buggaboo) for [#27](https://github.com/objectbox/objectbox-dart/pull/27) and [#46](https://github.com/objectbox/objectbox-dart/pull/46))
* More Box functions (count, isEmpty, contains, remove and their bulk variants)
(thanks [liquidiert](https://github.com/liquidiert) for [#42](https://github.com/objectbox/objectbox-dart/pull/42) and [#45](https://github.com/objectbox/objectbox-dart/pull/45)]
(thanks [liquidiert](https://github.com/liquidiert) for [#42](https://github.com/objectbox/objectbox-dart/pull/42) and [#45](https://github.com/objectbox/objectbox-dart/pull/45))
* Explicit write transactions
(thanks [liquidiert](https://github.com/liquidiert) for [#50](https://github.com/objectbox/objectbox-dart/pull/50)]
(thanks [liquidiert](https://github.com/liquidiert) for [#50](https://github.com/objectbox/objectbox-dart/pull/50))
* Resolved linter issues
(thanks [Gregory Sech](https://github.com/GregorySech) for [#31](https://github.com/objectbox/objectbox-dart/pull/31)]
(thanks [Gregory Sech](https://github.com/GregorySech) for [#31](https://github.com/objectbox/objectbox-dart/pull/31))
* Updated to objectbox-c 0.7.2
* First release on pub.dev

Expand All @@ -17,12 +24,12 @@
* ID/UID generation and model persistence (objectbox-model.json)
* CI tests using GitHub Actions
* Code cleanup, refactoring and formatting
(thanks [Jasm Sison](https://github.com/Buggaboo) for [#20](https://github.com/objectbox/objectbox-dart/pull/20) & [#21](https://github.com/objectbox/objectbox-dart/pull/21)]
(thanks [Jasm Sison](https://github.com/Buggaboo) for [#20](https://github.com/objectbox/objectbox-dart/pull/20) & [#21](https://github.com/objectbox/objectbox-dart/pull/21))

0.2.0 (2019-09-11)
------------------Buggaboo
------------------
* UTF-8 support for Store and Box
(thanks to [Jasm Sison](https://github.com/Buggaboo) for [#14](https://github.com/objectbox/objectbox-dart/pull/14)!)
(thanks [Jasm Sison](https://github.com/Buggaboo) for [#14](https://github.com/objectbox/objectbox-dart/pull/14)!)
* Bulk put and get functions (getMany, getAll, putMany)
* Updated to objectbox-c 0.7
* Basic Store options
Expand Down
27 changes: 19 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,27 @@ ObjectBox for Dart/Flutter
==========================
ObjectBox for Dart is a standalone database storing Dart objects locally, with strong ACID semantics.

Flutter/Dart compatibility
--------------------------
This library depends on a new Dart feature, FFI, introduced in Dart 2.5 (Flutter 1.9) as a feature preview.
However, it has been change significantly significantly in Dart 2.6 (future Flutter 1.10.x), i.e. introduced breaking changes we had to reflect.
Versions starting with ObjectBox 0.5 support Dart 2.6 as well as Flutter 1.10 (when it's finally released).

The last supported version for Flutter 1.9/Dart 2.5 is ObjectBox 0.4.*, so if you can't upgrade yet, please use latest 0.4.x version instead.
For Flutter users, this is the only option, as long as a new version of Flutter (1.10), including Dart 2.6 is released.

If you're developing standalone/non-flutter dart programs, you can already use Dart 2.6 with the latest ObjectBox version.

Installation
------------
Add the following dependencies to your `pubspec.yaml`:
```yaml
dependencies:
objectbox: ^0.4.0
objectbox: ^0.5.0

dev_dependencies:
build_runner: ^1.0.0
objectbox_generator: ^0.4.0
objectbox_generator: ^0.5.0
```

Proceed based on whether you're developing a Flutter app or a standalone dart program:
Expand All @@ -34,7 +45,7 @@ Proceed based on whether you're developing a Flutter app or a standalone dart pr
* macOS: if dart later complains that it cannot find the `libobjectbox.dylib` you probably have to unsign the
`dart` binary (source: [dart issue](https://github.com/dart-lang/sdk/issues/38314#issuecomment-534102841)):
```shell script
sudo xcode --remove-signature $(which dart)
sudo codesign --remove-signature $(which dart)
```
* Windows: use "Git Bash" or similar to execute the following command
```shell script
Expand Down Expand Up @@ -111,17 +122,17 @@ queryNullText.close(); // We have to manually close queries and query builders.
```

More complex queries can be constructed using `and/or` operators.
Also there is basic operator overloading support for `equal`, `greater`, `less`, `and` and `or`,
respectively `==`, `>`, `<`, `&`, `|`.
Also there is basic operator overloading support for `greater`, `less`, `and` and `or`,
respectively `>`, `<`, `&`, `|`.

```dart
// final box ...

box.query(value.greaterThan(10).or(date.IsNull())).build();
box.query(value.greaterThan(10).or(date.isNull())).build();

// equivalent to

final overloaded = (value > 10) | date.IsNull();
final overloaded = (value > 10) | date.isNull();
box.query(overloaded as Condition).build(); // the cast is necessary due to the type analyzer
```

Expand All @@ -137,7 +148,7 @@ final q = box.query(Entity_.number > 0)
// ...

final qt = box.query(Entity_.text.notNull())
.order(Entity_.text, flags: OBXOrderFlag.DESCENDING | OBXOrderFlag.CASE_SENSITIVE)
.order(Entity_.text, flags: Order.descending | Order.caseSensitive)
.build();
```

Expand Down
4 changes: 2 additions & 2 deletions generator/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: objectbox_generator
version: 0.4.0
version: 0.5.0
repository: https://github.com/objectbox/objectbox-dart
homepage: https://objectbox.io
author: objectbox.io
Expand All @@ -9,7 +9,7 @@ environment:
sdk: ">=2.5.0 <3.0.0"

dependencies:
objectbox: 0.4.0
objectbox: 0.5.0
build: ^1.0.0
source_gen: ^0.9.0
analyzer: ">=0.35.0 <0.100.0"
Expand Down
3 changes: 0 additions & 3 deletions lib/objectbox.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
library objectbox;

export "dart:io"; // needed for generated files
export "dart:convert";

export "src/annotations.dart";
export "src/common.dart";
export "src/model.dart";
Expand Down
37 changes: 19 additions & 18 deletions lib/src/bindings/bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ class _ObjectBoxBindings {
// common functions
void Function(Pointer<Int32> major, Pointer<Int32> minor, Pointer<Int32> patch) obx_version;
Pointer<Uint8> Function() obx_version_string;
void Function(Pointer<Uint64> structPtr) obx_string_array_free,
obx_int64_array_free,
obx_int32_array_free,
obx_int16_array_free,
obx_int8_array_free,
obx_double_array_free,
obx_float_array_free;
obx_free_t<OBX_bytes_array> obx_bytes_array_free;
obx_free_t<OBX_id_array> obx_id_array_free;

obx_free_dart_t<OBX_bytes_array> obx_bytes_array_free;
obx_free_dart_t<OBX_id_array> obx_id_array_free;
// obx_free_dart_t<OBX__array> obx_string_array_free;
// obx_free_dart_t<OBX__array> obx_int64_array_free;
// obx_free_dart_t<OBX__array> obx_int32_array_free;
// obx_free_dart_t<OBX__array> obx_int16_array_free;
// obx_free_dart_t<OBX__array> obx_int8_array_free;
// obx_free_dart_t<OBX__array> obx_double_array_free;
// obx_free_dart_t<OBX__array> obx_float_array_free;

// error info
int Function() obx_last_error_code;
Expand Down Expand Up @@ -154,15 +155,15 @@ class _ObjectBoxBindings {
// common functions
obx_version = _fn<obx_version_native_t>("obx_version").asFunction();
obx_version_string = _fn<obx_version_string_native_t>("obx_version_string").asFunction();
obx_bytes_array_free = _fn<obx_free_t<OBX_bytes_array>>("obx_bytes_array_free").asFunction();
obx_id_array_free = _fn<obx_free_t<OBX_id_array>>("obx_id_array_free").asFunction();
obx_string_array_free = _fn<obx_free_struct_native_t>("obx_string_array_free").asFunction();
obx_int64_array_free = _fn<obx_free_struct_native_t>("obx_int64_array_free").asFunction();
obx_int32_array_free = _fn<obx_free_struct_native_t>("obx_int32_array_free").asFunction();
obx_int16_array_free = _fn<obx_free_struct_native_t>("obx_int16_array_free").asFunction();
obx_int8_array_free = _fn<obx_free_struct_native_t>("obx_int8_array_free").asFunction();
obx_double_array_free = _fn<obx_free_struct_native_t>("obx_double_array_free").asFunction();
obx_float_array_free = _fn<obx_free_struct_native_t>("obx_float_array_free").asFunction();
obx_bytes_array_free = _fn<obx_free_native_t<Pointer<OBX_bytes_array>>>("obx_bytes_array_free").asFunction();
obx_id_array_free = _fn<obx_free_native_t<Pointer<OBX_id_array>>>("obx_id_array_free").asFunction();
// obx_string_array_free = _fn<obx_free_native_t<Pointer<>>>("obx_string_array_free").asFunction();
// obx_int64_array_free = _fn<obx_free_native_t<Pointer<>>>("obx_int64_array_free").asFunction();
// obx_int32_array_free = _fn<obx_free_native_t<Pointer<>>>("obx_int32_array_free").asFunction();
// obx_int16_array_free = _fn<obx_free_native_t<Pointer<>>>("obx_int16_array_free").asFunction();
// obx_int8_array_free = _fn<obx_free_native_t<Pointer<>>>("obx_int8_array_free").asFunction();
// obx_double_array_free = _fn<obx_free_native_t<Pointer<>>>("obx_double_array_free").asFunction();
// obx_float_array_free = _fn<obx_free_native_t<Pointer<>>>("obx_float_array_free").asFunction();

// error info
obx_last_error_code = _fn<obx_last_error_code_native_t>("obx_last_error_code").asFunction();
Expand Down
2 changes: 1 addition & 1 deletion lib/src/bindings/flatbuffers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class OBXFlatbuffersManager<T> {

// expects pointer to OBX_bytes_array and manually resolves its contents (see objectbox.h)
List<T> unmarshalArray(final Pointer<OBX_bytes_array> bytesArray, {bool allowMissing = false}) {
final OBX_bytes_array array = bytesArray.load();
final OBX_bytes_array array = bytesArray.ref;
var fn = (OBX_bytes b) => unmarshal(b.data);
if (allowMissing) {
fn = (OBX_bytes b) => b.isEmpty ? null : unmarshal(b.data);
Expand Down
5 changes: 3 additions & 2 deletions lib/src/bindings/signatures.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import 'structs.dart';
// common functions
typedef obx_version_native_t = Void Function(Pointer<Int32> major, Pointer<Int32> minor, Pointer<Int32> patch);
typedef obx_version_string_native_t = Pointer<Uint8> Function();
typedef obx_free_t<T extends NativeType> = Void Function(Pointer<T> ptr);
typedef obx_free_struct_native_t = Void Function(Pointer<Uint64> structPtr);

typedef obx_free_dart_t<T extends NativeType> = void Function(Pointer<T> ptr);
typedef obx_free_native_t<T extends NativeType> = Void Function(T ptr); // no Pointer<T>, code analysis fails on usage

// error info
typedef obx_last_error_code_native_t = Int32 Function();
Expand Down
87 changes: 22 additions & 65 deletions lib/src/bindings/structs.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:ffi';
import "dart:typed_data" show Uint8List, Uint64List;
import "dart:typed_data" show Uint8List;
import "package:ffi/ffi.dart" show allocate, free;

import '../common.dart';

Expand All @@ -10,34 +11,34 @@ import '../common.dart';
/// obx_id* ids;
/// size_t count;
/// };
class OBX_id_array extends Struct<OBX_id_array> {
class OBX_id_array extends Struct {
Pointer<Uint64> _itemsPtr;

@IntPtr() // size_t
int length;

/// Get a copy of the list
List<int> items() => Uint64List.view(_itemsPtr.asExternalTypedData(count: length).buffer).toList();
List<int> items() => _itemsPtr.asTypedList(length);

/// Execute the given function, managing the resources consistently
static R executeWith<R>(List<int> items, R Function(Pointer<OBX_id_array>) fn) {
// allocate a temporary structure
final ptr = Pointer<OBX_id_array>.allocate();
final ptr = allocate<OBX_id_array>();

// fill it with data
OBX_id_array array = ptr.load();
OBX_id_array array = ptr.ref;
array.length = items.length;
array._itemsPtr = Pointer<Uint64>.allocate(count: array.length);
array._itemsPtr = allocate<Uint64>(count: array.length);
for (int i = 0; i < items.length; ++i) {
array._itemsPtr.elementAt(i).store(items[i]);
array._itemsPtr.elementAt(i).value = items[i];
}

// call the function with the structure and free afterwards
try {
return fn(ptr);
} finally {
array._itemsPtr.free();
ptr.free();
free(array._itemsPtr);
free(ptr);
}
}
}
Expand All @@ -47,16 +48,15 @@ class OBX_id_array extends Struct<OBX_id_array> {
/// const void* data;
/// size_t size;
/// };
class OBX_bytes extends Struct<OBX_bytes> {
class OBX_bytes extends Struct {
Pointer<Uint8> _dataPtr;

@IntPtr() // size_t
int length;

/// Get access to the data (no-copy)
Uint8List get data => isEmpty
? throw ObjectBoxException("can't access data of empty OBX_bytes")
: Uint8List.view(_dataPtr.asExternalTypedData(count: length).buffer);
Uint8List get data =>
isEmpty ? throw ObjectBoxException("can't access data of empty OBX_bytes") : _dataPtr.asTypedList(length);

bool get isEmpty => length == 0 || _dataPtr.address == 0;

Expand All @@ -65,8 +65,8 @@ class OBX_bytes extends Struct<OBX_bytes> {
/// Returns a pointer to OBX_bytes with copy of the passed data.
/// Warning: this creates an two unmanaged pointers which must be freed manually: OBX_bytes.freeManaged(result).
static Pointer<OBX_bytes> managedCopyOf(Uint8List data) {
final ptr = Pointer<OBX_bytes>.allocate();
final OBX_bytes bytes = ptr.load();
final ptr = allocate<OBX_bytes>();
final OBX_bytes bytes = ptr.ref;

const align = true; // ObjectBox requires data to be aligned to the length of 4
bytes.length = align ? ((data.length + 3.0) ~/ 4.0) * 4 : data.length;
Expand All @@ -79,19 +79,19 @@ class OBX_bytes extends Struct<OBX_bytes> {
// }

// create a copy of the data
bytes._dataPtr = Pointer<Uint8>.allocate(count: bytes.length);
bytes._dataPtr = allocate<Uint8>(count: bytes.length);
for (int i = 0; i < data.length; ++i) {
bytes._dataPtr.elementAt(i).store(data[i]);
bytes._dataPtr.elementAt(i).value = data[i];
}

return ptr;
}

/// Free a dart-created OBX_bytes pointer.
static void freeManaged(Pointer<OBX_bytes> ptr) {
final OBX_bytes bytes = ptr.load();
bytes._dataPtr.free();
ptr.free();
final OBX_bytes bytes = ptr.ref;
free(bytes._dataPtr);
free(ptr);
}
}

Expand All @@ -100,7 +100,7 @@ class OBX_bytes extends Struct<OBX_bytes> {
/// OBX_bytes* bytes;
/// size_t count;
/// };
class OBX_bytes_array extends Struct<OBX_bytes_array> {
class OBX_bytes_array extends Struct {
Pointer<OBX_bytes> _items;

@IntPtr() // size_t
Expand All @@ -110,51 +110,8 @@ class OBX_bytes_array extends Struct<OBX_bytes_array> {
List<OBX_bytes> items() {
final result = List<OBX_bytes>();
for (int i = 0; i < length; i++) {
result.add(_items.elementAt(i).load());
result.add(_items.elementAt(i).ref);
}
return result;
}

/// TODO: try this with new Dart 2.6 FFI... with the previous versions it was causing memory corruption issues.
/// It's supposed to be used by PutMany()
// /// Create a dart-managed OBX_bytes_array.
// static Pointer<OBX_bytes_array> createManaged(int count) {
// final ptr = Pointer<OBX_bytes_array>.allocate();
// final OBX_bytes_array array = ptr.load();
// array.length = count;
// array._items = Pointer<OBX_bytes>.allocate(count: count);
// return ptr;
// }
//
// /// Replace the data at the given index with the passed pointer.
// void setAndFree(int i, Pointer<OBX_bytes> src) {
// assert(i >= 0 && i < length);
//
// final OBX_bytes srcBytes = src.load();
// final OBX_bytes tarBytes = _items.elementAt(i).load();
//
// assert(!srcBytes.isEmpty);
// assert(tarBytes.isEmpty);
//
// tarBytes._dataPtr = srcBytes._dataPtr;
// tarBytes.length = srcBytes.length;
//
// srcBytes._dataPtr.store(nullptr.address);
// srcBytes.length = 0;
// src.free();
// }
//
// /// Free a dart-created OBX_bytes pointer.
// static void freeManaged(Pointer<OBX_bytes_array> ptr, bool freeIncludedBytes) {
// final OBX_bytes_array array = ptr.load();
// if (freeIncludedBytes) {
// for (int i = 0; i < array.length; i++) {
// // Calling OBX_bytes.freeManaged() would cause double free
// final OBX_bytes bytes = array._items.elementAt(i).load();
// bytes._dataPtr.free();
// }
// }
// array._items.free();
// ptr.free();
// }
}
Loading