Skip to content
You are viewing the corvid 0.4.1 release snapshot — frozen at the 0.4.1 engine release.Current documentation

Functions: lifecycle & values

Conventions used throughout the function pages: corvid_status return unless stated; (const char* s, size_t len) = borrowed, binary-safe, UTF-8 where the engine takes &str; NULL pointer with len > 0 is CORVID_E_ARGUMENT, NULL with len == 0 is empty only where marked nullable; const corvid_value* inputs are CLONED — the caller keeps ownership.

uint32_t corvid_ffi_version(void);

Returns 1. No engine counterpart — pure ABI versioning. Bindings verify this before anything else.

corvid_db* corvid_open(const char *path, size_t path_len);

Open (creating if absent) a file-backed database. Wraps Db::open. Returns the handle, or NULL + CORVID_E_DATABASE / CORVID_E_INCOMPATIBLE_FORMAT / CORVID_E_IO (non-UTF-8 paths answer CORVID_E_ARGUMENT — the universal UTF-8 rule).

corvid_db* corvid_open_memory(void);

In-memory database. Wraps Db::open_in_memory.

corvid_status corvid_close(corvid_db *db);

Releases the handle’s reference. Persistence is durable per-transaction — no explicit close/flush exists in the engine either. Freeing the db while rows/iterators from it are live is fine (they own their data).

corvid_err corvid_last_error_code(void);
const char* corvid_last_error_message(size_t *len_out);

Thread-local last error — NULL message when none recorded. See errors.

void corvid_free(void *ptr);

The ONLY buffer deallocator — for ABI-returned buffers (corvid_insert_auto keys, corvid_page’s next_after cursor). Does NOT free handles or values. corvid_free(NULL) is a no-op.

corvid_strs* corvid_collections(corvid_db *db);

User collection names (engine __ namespaces excluded), name order, as a string cursor. Listing creates nothing (collections are lazy on first write).

corvid_coll* corvid_collection(corvid_db *db, const char *name, size_t name_len);
void corvid_collection_free(corvid_coll *coll);
const char* corvid_collection_name(corvid_coll *coll, size_t *len_out);

corvid_collection returns NULL only on NULL arguments; reserved/invalid names fail at write time (lazy validation, as in Rust). The name is BORROWED from the handle until corvid_collection_free.

All constructors return an OWNED corvid_value* or NULL + CORVID_E_ARGUMENT. Byte/text/vector inputs are CLONED into the value.

corvid_value* corvid_value_null(void);
corvid_value* corvid_value_bool(int v); /* v != 0 */
corvid_value* corvid_value_int(int64_t v);
corvid_value* corvid_value_float(double v); /* NaN/±inf/-0.0 bit-exact */
corvid_value* corvid_value_text(const char *s, size_t len); /* must be UTF-8 */
corvid_value* corvid_value_bytes(const uint8_t *b, size_t len);
corvid_value* corvid_value_vector(const float *v, size_t dim); /* dim 0 legal */
corvid_value* corvid_value_array_new(void);
corvid_status corvid_value_array_push(corvid_value *arr, corvid_value *item);
corvid_value* corvid_value_map_new(void);
corvid_status corvid_value_map_put(corvid_value *map, const char *key, size_t key_len,
corvid_value *val);
  • array_push/map_put consume item/val (ownership moves in; do not free them afterwards). Single-threaded mutation of the container.
  • A duplicate map key REPLACES the previous entry (last write wins; the replaced child is dropped). Map order in the engine is sorted by key — construction order never matters.
  • Pushing/putting invalidates previously borrowed children of the container (see ownership).
corvid_value_type_t corvid_value_type(const corvid_value *v); /* discriminant */
int corvid_value_as_bool(const corvid_value *v, int *ok);
int64_t corvid_value_as_int(const corvid_value *v, int *ok);
double corvid_value_as_float(const corvid_value *v, int *ok);

Wrong type sets *ok = 0 and returns 0 — not an error (mirrors the Rust Option accessors).

const char* corvid_value_text_ref(const corvid_value *v, size_t *len_out);
const uint8_t* corvid_value_bytes_ref(const corvid_value *v, size_t *len_out);
const float* corvid_value_vector_ref(const corvid_value *v, size_t *dim_out);

Zero-copy BORROWED views. NULL when the value is a different type (not an error). Valid until the parent value is freed or mutated — writing through these pointers is UB.

const corvid_value* corvid_value_array_get(const corvid_value *arr, size_t index);
const corvid_value* corvid_value_map_get(const corvid_value *map, const char *key, size_t key_len);

BORROWED children; NULL when out of range / absent / wrong container (not an error). Child lifetime rides the parent — freeing a borrowed child is UB.

corvid_strs* corvid_value_map_keys(const corvid_value *v);

The map’s keys as an OWNED string cursor (added in 0.3.0), in ascending key-BYTE order — the engine’s BTreeMap iteration order. Drive it with corvid_strs_next / corvid_strs_free (see graph & geo); each key is UTF-8 handed out as a binary-safe (pointer, length) pair borrowed until the cursor’s next next or its free. A non-map v yields an EMPTY cursor — inert, not an error (the as_* wrong-type convention). NULL v answers NULL + CORVID_E_ARGUMENT.

size_t corvid_value_len(const corvid_value *v); /* items/entries/dims/bytes */
corvid_value* corvid_value_clone(const corvid_value *v); /* deep copy, OWNED */
void corvid_value_free(corvid_value *v); /* OWNED values only */

corvid_value_clone is the sanctioned way to keep data observed through a borrowed pointer (e.g. a rows document) beyond the parent’s lifetime. corvid_value_free on a borrowed child (from _ref, array_get, map_get, rows_next, geohits_next, callbacks, or already-consumed push/put inputs) is undefined behavior.

Next: predicates & queries.