Skip to content

Commit

Permalink
0.14.0
Browse files Browse the repository at this point in the history
  • Loading branch information
vaind committed May 13, 2021
1 parent 5ced603 commit 4d8db6c
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 56 deletions.
16 changes: 14 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
ObjectBox C and C++ API Changelog
=================================

0.14.0 (2021-05-13)
-------------------

* change `obx_query_prop_count()` to respect case-sensitivity setting when counting distinct strings
* change `OBXSyncCredentialsType` values to start at 1
* add `obx_query_find_first()` to get a first object matching the query
* add `obx_query_find_unique()` to get the only object matching the query
* add `obx_async_put_object4()` accepting a put_mode
* updated ARMv7hf toolchain, now requires GLIBC v2.28 (e.g. Raspbian 10, Ubuntu 20.04)
* semi-internal Dart APIs: add query streaming and finalizers

0.13.0 (2021-03-16)
-------------------

* add Sync binary library variants for all supported platforms
* add MacOS universal binary library, supporting Intel x64 and Apple Silicon arm64
* split Sync symbols out of objectbox.h/pp into objectbox-sync.h/pp
* add Sync server-time getter, listener and local-to-server diff info - to access server time info on clients
* split Sync symbols out of objectbox.h/pp into objectbox-sync.h/pp
* add Sync server-time getter, listener and local-to-server diff info - to access server time info on clients
* add Sync heartbeat interval configuration and an option to send one immediately
* semi-internal: update Dart/Flutter SDK to v2.0

Expand Down
56 changes: 33 additions & 23 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,29 @@ if (${CMAKE_VERSION} VERSION_LESS "3.11.0")
endif ()
link_directories("${CMAKE_CURRENT_SOURCE_DIR}/lib")
else ()
project(objectbox-download)
function(defineObjectBoxLibForURL VARIANT DL_URL)
include(FetchContent)
project(objectbox${VARIANT}-download)
FetchContent_Declare(${PROJECT_NAME} URL ${DL_URL})

if (DEFINED ENV{OBJECTBOX_ARTIFACT_URL})
set(DL_URL $ENV{OBJECTBOX_ARTIFACT_URL})
message(STATUS "Using pre-compiled ObjectBox library from the OBJECTBOX_ARTIFACT_URL environment variable: ${DL_URL}")
else ()
FetchContent_Populate(${PROJECT_NAME})
set(DL_DIR "${${PROJECT_NAME}_SOURCE_DIR}")
message(STATUS "Pre-compiled ObjectBox library is saved in ${DL_DIR}")

project(objectbox${VARIANT})
add_library(${PROJECT_NAME} SHARED IMPORTED GLOBAL)
set(objectbox_include_dirs ${DL_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/external/)
set_target_properties(
${PROJECT_NAME} PROPERTIES
IMPORTED_LOCATION ${DL_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}objectbox${CMAKE_SHARED_LIBRARY_SUFFIX}
IMPORTED_IMPLIB ${DL_DIR}/lib/${CMAKE_IMPORT_LIBRARY_PREFIX}objectbox${CMAKE_IMPORT_LIBRARY_SUFFIX}
INTERFACE_INCLUDE_DIRECTORIES "${objectbox_include_dirs}"
)
endfunction()

function(defineObjectBoxLib VARIANT)
# Configuration updated for each release
set(DL_VERSION 0.13.0)
set(DL_VERSION 0.14.0)

# Platform detection and other setup
set(DL_URL https://github.com/objectbox/objectbox-c/releases/download)
Expand Down Expand Up @@ -45,25 +60,20 @@ else ()
endif ()

string(TOLOWER ${DL_PLATFORM} DL_PLATFORM)
set(DL_URL ${DL_URL}/v${DL_VERSION}/objectbox-${DL_PLATFORM}.${DL_EXTENSION})
message(STATUS "Using pre-compiled ObjectBox library v${DL_VERSION} for ${DL_PLATFORM}: ${DL_URL}")
endif ()
set(DL_URL ${DL_URL}/v${DL_VERSION}/objectbox${VARIANT}-${DL_PLATFORM}.${DL_EXTENSION})
message(STATUS "Using pre-compiled ObjectBox${VARIANT} library v${DL_VERSION} for ${DL_PLATFORM}: ${DL_URL}")

include(FetchContent)
FetchContent_Declare(${PROJECT_NAME} URL ${DL_URL})
defineObjectBoxLibForURL("${VARIANT}" "${DL_URL}")
endfunction()

FetchContent_Populate(${PROJECT_NAME})
message(STATUS "Pre-compiled ObjectBox library is saved in ${objectbox-download_SOURCE_DIR}")

project(objectbox)
add_library(${PROJECT_NAME} SHARED IMPORTED GLOBAL)
set(objectbox_include_dirs ${objectbox-download_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/external/)
set_target_properties(
${PROJECT_NAME} PROPERTIES
IMPORTED_LOCATION ${objectbox-download_SOURCE_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}objectbox${CMAKE_SHARED_LIBRARY_SUFFIX}
IMPORTED_IMPLIB ${objectbox-download_SOURCE_DIR}/lib/${CMAKE_IMPORT_LIBRARY_PREFIX}objectbox${CMAKE_IMPORT_LIBRARY_SUFFIX}
INTERFACE_INCLUDE_DIRECTORIES "${objectbox_include_dirs}"
)
if (DEFINED ENV{OBJECTBOX_ARTIFACT_URL})
set(DL_URL $ENV{OBJECTBOX_ARTIFACT_URL})
message(STATUS "Using pre-compiled ObjectBox library from the OBJECTBOX_ARTIFACT_URL environment variable: ${DL_URL}")
defineObjectBoxLibForURL("" "${DL_URL}")
else ()
defineObjectBoxLib("")
defineObjectBoxLib("-sync")
endif ()
endif ()

add_subdirectory(src-test)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ box.put({.text = "Buy milk"});
See [ObjectBox C and C++ docs](https://cpp.objectbox.io/) for API details.
**Latest version: 0.13.0** (2021-03-16).
**Latest version: 0.14.0** (2021-05-13).
See [changelog](CHANGELOG.md) for more details.
Feature Highlights
Expand Down
2 changes: 1 addition & 1 deletion download.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ tty -s || quiet=true

# Note: optional arguments like "--quiet" shifts argument positions in the case block above

version=${1:-0.13.0}
version=${1:-0.14.0}
os=${2:-$(uname)}
arch=${3:-$(uname -m)}
echo "Base config: OS ${os} and architecture ${arch}"
Expand Down
18 changes: 16 additions & 2 deletions doxygen/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,24 @@
ObjectBox C and C++ API Changelog
=================================

0.14.0 (2021-05-13)
-------------------

* change `obx_query_prop_count()` to respect case-sensitivity setting when counting distinct strings
* change `OBXSyncCredentialsType` values to start at 1
* add `obx_query_find_first()` to get a first object matching the query
* add `obx_query_find_unique()` to get the only object matching the query
* add `obx_async_put_object4()` accepting a put_mode
* updated ARMv7hf toolchain, now requires GLIBC v2.28 (e.g. Raspbian 10, Ubuntu 20.04)
* semi-internal Dart APIs: add query streaming and finalizers

0.13.0 (2021-03-16)
-------------------
* split Sync symbols out of objectbox.h/pp into objectbox-sync.h/pp
* add Sync server-time getter, listener and local-to-server diff info - to access server time info on clients

* add Sync binary library variants for all supported platforms
* add MacOS universal binary library, supporting Intel x64 and Apple Silicon arm64
* split Sync symbols out of objectbox.h/pp into objectbox-sync.h/pp
* add Sync server-time getter, listener and local-to-server diff info - to access server time info on clients
* add Sync heartbeat interval configuration and an option to send one immediately
* semi-internal: update Dart/Flutter SDK to v2.0

Expand Down
2 changes: 1 addition & 1 deletion doxygen/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ PROJECT_NAME = "ObjectBox C and C++ API"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = "0.13.0"
PROJECT_NUMBER = "0.14.0"

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
34 changes: 34 additions & 0 deletions include/objectbox-dart.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <stdint.h>

#include "dart_api.h"
#include "objectbox-sync.h"

#ifdef __cplusplus
Expand Down Expand Up @@ -71,6 +72,39 @@ OBX_dart_sync_listener* obx_dart_sync_listener_change(OBX_sync* sync, int64_t na
/// @see obx_sync_listener_server_time()
OBX_dart_sync_listener* obx_dart_sync_listener_server_time(OBX_sync* sync, int64_t native_port);

/// @see obx_async_put_object()
obx_id obx_dart_async_put_object(OBX_async* async, int64_t native_port, void* data, size_t size, OBXPutMode mode);

struct OBX_dart_stream;
typedef struct OBX_dart_stream OBX_dart_stream;

obx_err obx_dart_stream_close(OBX_dart_stream* stream);

/// @see obx_dart_stream_query_find
OBX_dart_stream* obx_dart_query_find(OBX_query* query, int64_t native_port);

OBX_dart_stream* obx_dart_query_find_ptr(OBX_query* query, int64_t native_port);

struct OBX_dart_finalizer;
typedef struct OBX_dart_finalizer OBX_dart_finalizer;

/// A function to clean up native resources. Must be a c-function (non-throwing). The returned error is ignored.
/// e.g. obx_query_close(), obx_store_close(), ...
typedef obx_err obx_dart_closer(void* native_object);

/// Attaches a finalizer (destructor) to be called when the given object is garbage-collected.
/// @param dart_object marks the object owning the native pointer
/// @param native_object is the native pointer to be freed
/// @param closer is the function that frees native_object
/// @param native_object_size is an allocated size estimate - can be used by a the Dart garbage collector to prioritize
/// @return a finalizer freed automatically when the GC finalizer runs (or manually by obx_dart_detach_finalizer())
/// @return NULL if the finalizer couldn't be attached, in which case the caller is responsible for running the closer
OBX_dart_finalizer* obx_dart_attach_finalizer(Dart_Handle dart_object, obx_dart_closer* closer, void* native_object,
size_t native_object_size);

/// Detach the finalizer preliminarily, without executing its "closer"
obx_err obx_dart_detach_finalizer(OBX_dart_finalizer* finalizer, Dart_Handle dart_object);

#ifdef __cplusplus
}
#endif
Expand Down
11 changes: 8 additions & 3 deletions include/objectbox-sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@

#include "objectbox.h"

#if defined(static_assert) || defined(__cplusplus)
static_assert(OBX_VERSION_MAJOR == 0 && OBX_VERSION_MINOR == 14 && OBX_VERSION_PATCH == 0,
"Versions of objectbox.h and objectbox-sync.h files do not match, please update");
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -51,9 +56,9 @@ struct OBX_sync;
typedef struct OBX_sync OBX_sync;

typedef enum {
OBXSyncCredentialsType_NONE = 0,
OBXSyncCredentialsType_SHARED_SECRET = 1,
OBXSyncCredentialsType_GOOGLE_AUTH = 2,
OBXSyncCredentialsType_NONE = 1,
OBXSyncCredentialsType_SHARED_SECRET = 2,
OBXSyncCredentialsType_GOOGLE_AUTH = 3,
} OBXSyncCredentialsType;

// TODO sync prefix
Expand Down
4 changes: 2 additions & 2 deletions include/objectbox-sync.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
#include "objectbox-sync.h"
#include "objectbox.hpp"

static_assert(OBX_VERSION_MAJOR == 0 && OBX_VERSION_MINOR == 13 && OBX_VERSION_PATCH == 0,
"Versions of objectbox.h and objectbox-sync.hpp files must be exactly the same");
static_assert(OBX_VERSION_MAJOR == 0 && OBX_VERSION_MINOR == 14 && OBX_VERSION_PATCH == 0,
"Versions of objectbox.h and objectbox-sync.hpp files do not match, please update");

static_assert(sizeof(obx_id) == sizeof(OBX_id_array::ids[0]),
"Can't directly link OBX_id_array.ids to std::vector<obx_id>::data()");
Expand Down
29 changes: 26 additions & 3 deletions include/objectbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ extern "C" {
/// When using ObjectBox as a dynamic library, you should verify that a compatible version was linked using
/// obx_version() or obx_version_is_at_least().
#define OBX_VERSION_MAJOR 0
#define OBX_VERSION_MINOR 13
#define OBX_VERSION_MINOR 14
#define OBX_VERSION_PATCH 0 // values >= 100 are reserved for dev releases leading to the next minor/major increase

//----------------------------------------------
Expand Down Expand Up @@ -996,12 +996,12 @@ obx_err obx_box_put5(OBX_box* box, obx_id id, const void* data, size_t size, OBX

/// FB ID slot must be present in the given data; new entities must have an ID value of zero or OBX_ID_NEW.
/// @param data writable data buffer, which may be updated for the ID
/// @returns 0 on error
/// @returns id if the object could be put, or 0 in case of an error
obx_id obx_box_put_object(OBX_box* box, void* data, size_t size);

/// FB ID slot must be present in the given data; new entities must have an ID value of zero or OBX_ID_NEW
/// @param data writable data buffer, which may be updated for the ID
/// @returns 0 on error, e.g. the entity was not put according to OBXPutMode
/// @returns id if the object, or 0 in case of an error, e.g. the entity was not put according to OBXPutMode
obx_id obx_box_put_object4(OBX_box* box, void* data, size_t size, OBXPutMode mode);

/// Put all given objects in the database in a single transaction. If any of the individual objects failed to put,
Expand Down Expand Up @@ -1124,11 +1124,18 @@ obx_err obx_async_update(OBX_async* async, obx_id id, const void* data, size_t s
/// Reserve an ID, which is returned immediately for future reference, and put asynchronously.
/// Note: of course, it can NOT be guaranteed that the entity will actually be put successfully in the DB.
/// @param data the given bytes are mutated to update the contained ID data.
/// @returns id of the new object, 0 on error
obx_id obx_async_put_object(OBX_async* async, void* data, size_t size);

/// FB ID slot must be present in the given data; new entities must have an ID value of zero or OBX_ID_NEW
/// @param data writable data buffer, which may be updated for the ID
/// @returns id of the new object, 0 on error, e.g. the entity can't be put according to OBXPutMode
obx_id obx_async_put_object4(OBX_async* async, void* data, size_t size, OBXPutMode mode);

/// Reserve an ID, which is returned immediately for future reference, and insert asynchronously.
/// Note: of course, it can NOT be guaranteed that the entity will actually be inserted successfully in the DB.
/// @param data the given bytes are mutated to update the contained ID data.
/// @returns id of the new object, 0 on error
obx_id obx_async_insert_object(OBX_async* async, void* data, size_t size);

/// Remove asynchronously.
Expand Down Expand Up @@ -1384,6 +1391,22 @@ obx_err obx_query_limit(OBX_query* query, uint64_t limit);
/// Find entities matching the query. NOTE: the returned data is only valid as long the transaction is active!
OBX_bytes_array* obx_query_find(OBX_query* query);

/// Find the first object matching the query.
/// @returns OBX_NOT_FOUND if no object matches.
/// The exposed data comes directly from the OS to allow zero-copy access, which limits the data lifetime:
/// @warning Currently ignores offset, taking the the first matching element.
/// @attention The exposed data is only valid as long as the (top) transaction is still active and no write
/// operation (e.g. put/remove) was executed. Accessing data after this is undefined behavior.
obx_err obx_query_find_first(OBX_query* query, const void** data, size_t* size);

/// Find the only object matching the query.
/// @returns OBX_NOT_FOUND if no object matches, an error if there are multiple objects matching the query.
/// The exposed data comes directly from the OS to allow zero-copy access, which limits the data lifetime:
/// @warning Currently ignores offset and limit, considering all matching elements.
/// @attention The exposed data is only valid as long as the (top) transaction is still active and no write
/// operation (e.g. put/remove) was executed. Accessing data after this is undefined behavior.
obx_err obx_query_find_unique(OBX_query* query, const void** data, size_t* size);

/// Walk over matching objects using the given data visitor
obx_err obx_query_visit(OBX_query* query, obx_data_visitor* visitor, void* user_data);

Expand Down
58 changes: 40 additions & 18 deletions include/objectbox.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
#include <optional>
#endif

static_assert(OBX_VERSION_MAJOR == 0 && OBX_VERSION_MINOR == 13 && OBX_VERSION_PATCH == 0,
"Versions of objectbox.h and objectbox.hpp files must be exactly the same");
static_assert(OBX_VERSION_MAJOR == 0 && OBX_VERSION_MINOR == 14 && OBX_VERSION_PATCH == 0,
"Versions of objectbox.h and objectbox.hpp files do not match, please update");

static_assert(sizeof(obx_id) == sizeof(OBX_id_array::ids[0]),
"Can't directly link OBX_id_array.ids to std::vector<obx_id>::data()");
Expand Down Expand Up @@ -1396,6 +1396,30 @@ class Query {
return std::move(visitor.items);
}

/// Find the first object matching the query or nullptr if none matches.
std::unique_ptr<EntityT> findFirst() {
return findSingle<std::unique_ptr<EntityT>>(obx_query_find_first, EntityT::_OBX_MetaInfo::newFromFlatBuffer);
}

/// Find the only object matching the query.
/// @throws if there are multiple objects matching the query
std::unique_ptr<EntityT> findUnique() {
return findSingle<std::unique_ptr<EntityT>>(obx_query_find_unique, EntityT::_OBX_MetaInfo::newFromFlatBuffer);
}

#ifdef __cpp_lib_optional
/// Find the first object matching the query or nullptr if none matches.
std::optional<EntityT> findFirstOptional() {
return findSingle<std::optional<EntityT>>(obx_query_find_first, EntityT::_OBX_MetaInfo::fromFlatBuffer);
}

/// Find the only object matching the query.
/// @throws if there are multiple objects matching the query
std::optional<EntityT> findUniqueOptional() {
return findSingle<std::optional<EntityT>>(obx_query_find_unique, EntityT::_OBX_MetaInfo::fromFlatBuffer);
}
#endif

/// Returns IDs of all matching objects.
std::vector<obx_id> findIds() { return idVectorOrThrow(obx_query_find_ids(cQuery_)); }

Expand Down Expand Up @@ -1524,6 +1548,19 @@ class Query {
const std::vector<uint8_t>& value) {
return setParameter(property, value.data(), value.size());
}

private:
template <typename RET, typename T>
RET findSingle(obx_err nativeFn(OBX_query*, const void**, size_t*), T fromFlatBuffer(const void*, size_t)) {
OBJECTBOX_VERIFY_STATE(cQuery_ != nullptr);
Transaction tx = store_.txRead();
const void* data;
size_t size;
obx_err err = nativeFn(cQuery_, &data, &size);
if (err == OBX_NOT_FOUND) return RET();
checkErrOrThrow(err);
return fromFlatBuffer(data, size);
}
};

template <typename EntityT>
Expand Down Expand Up @@ -2023,22 +2060,7 @@ class AsyncBox {
/// @return the reserved ID which will be used for the object if the asynchronous insert succeeds.
obx_id put(const EntityT& object, OBXPutMode mode = OBXPutMode_PUT) {
EntityBinding::toFlatBuffer(fbb, object);
obx_id id;
switch (mode) {
case OBXPutMode_PUT:
id = obx_async_put_object(cPtr(), fbb.GetBufferPointer(), fbb.GetSize());
break;
case OBXPutMode_INSERT:
id = obx_async_insert_object(cPtr(), fbb.GetBufferPointer(), fbb.GetSize());
break;
case OBXPutMode_UPDATE:
// TODO this looks like we should adjust the the C API...
throw std::invalid_argument(
"UPDATE mode is currently not supported in C++ API AsyncBox, because C-API requires providing an "
"ID. Use C-API directly.");
default:
throw std::invalid_argument("unknown mode");
}
obx_id id = obx_async_put_object4(cPtr(), fbb.GetBufferPointer(), fbb.GetSize(), mode);
fbbCleanAfterUse();
if (id == 0) throwLastError();
return id;
Expand Down

0 comments on commit 4d8db6c

Please sign in to comment.