mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
ffi for tc_task_get/set_value
This commit is contained in:
parent
7cecac3328
commit
4fdb46fd47
3 changed files with 117 additions and 4 deletions
|
@ -111,6 +111,54 @@ static void test_task_get_set_description(void) {
|
|||
tc_replica_free(rep);
|
||||
}
|
||||
|
||||
// updating arbitrary attributes on a task works
|
||||
static void test_task_get_set_attribute(void) {
|
||||
TCReplica *rep = tc_replica_new_in_memory();
|
||||
TEST_ASSERT_NULL(tc_replica_error(rep).ptr);
|
||||
|
||||
TCTask *task = tc_replica_new_task(
|
||||
rep,
|
||||
TC_STATUS_PENDING,
|
||||
tc_string_borrow("my task"));
|
||||
TEST_ASSERT_NOT_NULL(task);
|
||||
|
||||
TCString foo;
|
||||
|
||||
foo = tc_task_get_value(task, tc_string_borrow("foo"));
|
||||
TEST_ASSERT_NULL(foo.ptr);
|
||||
|
||||
tc_task_to_mut(task, rep);
|
||||
TEST_ASSERT_EQUAL(TC_RESULT_OK, tc_task_set_value(task,
|
||||
tc_string_borrow("foo"),
|
||||
tc_string_borrow("updated")));
|
||||
|
||||
foo = tc_task_get_value(task, tc_string_borrow("foo"));
|
||||
TEST_ASSERT_NOT_NULL(foo.ptr);
|
||||
TEST_ASSERT_EQUAL_STRING("updated", tc_string_content(&foo));
|
||||
tc_string_free(&foo);
|
||||
|
||||
tc_task_to_immut(task);
|
||||
|
||||
foo = tc_task_get_value(task, tc_string_borrow("foo"));
|
||||
TEST_ASSERT_NOT_NULL(foo.ptr);
|
||||
TEST_ASSERT_EQUAL_STRING("updated", tc_string_content(&foo));
|
||||
tc_string_free(&foo);
|
||||
|
||||
TCString null = { .ptr = NULL };
|
||||
|
||||
tc_task_to_mut(task, rep);
|
||||
TEST_ASSERT_EQUAL(TC_RESULT_OK, tc_task_set_value(task,
|
||||
tc_string_borrow("foo"),
|
||||
null));
|
||||
|
||||
foo = tc_task_get_value(task, tc_string_borrow("foo"));
|
||||
TEST_ASSERT_NULL(foo.ptr);
|
||||
|
||||
tc_task_free(task);
|
||||
|
||||
tc_replica_free(rep);
|
||||
}
|
||||
|
||||
// updating entry on a task works
|
||||
static void test_task_get_set_entry(void) {
|
||||
TCReplica *rep = tc_replica_new_in_memory();
|
||||
|
@ -652,6 +700,7 @@ int task_tests(void) {
|
|||
RUN_TEST(test_task_free_mutable_task);
|
||||
RUN_TEST(test_task_get_set_status);
|
||||
RUN_TEST(test_task_get_set_description);
|
||||
RUN_TEST(test_task_get_set_attribute);
|
||||
RUN_TEST(test_task_get_set_entry);
|
||||
RUN_TEST(test_task_get_set_modified);
|
||||
RUN_TEST(test_task_get_set_wait_and_is_waiting);
|
||||
|
|
|
@ -294,8 +294,7 @@ pub unsafe extern "C" fn tc_task_get_taskmap(task: *mut TCTask) -> TCKVList {
|
|||
})
|
||||
}
|
||||
|
||||
/// Get a task's description, or NULL if the task cannot be represented as a C string (e.g., if it
|
||||
/// contains embedded NUL characters).
|
||||
/// Get a task's description.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tc_task_get_description(task: *mut TCTask) -> TCString {
|
||||
wrap(task, |task| {
|
||||
|
@ -306,6 +305,27 @@ pub unsafe extern "C" fn tc_task_get_description(task: *mut TCTask) -> TCString
|
|||
})
|
||||
}
|
||||
|
||||
/// Get a task property's value, or NULL if the task has no such property, (including if the
|
||||
/// property name is not valid utf-8).
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tc_task_get_value(task: *mut TCTask, property: TCString) -> TCString {
|
||||
// SAFETY:
|
||||
// - property is valid (promised by caller)
|
||||
// - caller will not use property after this call (convention)
|
||||
let mut property = unsafe { TCString::val_from_arg(property) };
|
||||
wrap(task, |task| {
|
||||
if let Ok(property) = property.as_str() {
|
||||
let value = task.get_value(property);
|
||||
if let Some(value) = value {
|
||||
// SAFETY:
|
||||
// - caller promises to free this string
|
||||
return unsafe { TCString::return_val(value.into()) };
|
||||
}
|
||||
}
|
||||
TCString::default() // null value
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the entry timestamp for a task (when it was created), or 0 if not set.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tc_task_get_entry(task: *mut TCTask) -> libc::time_t {
|
||||
|
@ -507,6 +527,40 @@ pub unsafe extern "C" fn tc_task_set_status(task: *mut TCTask, status: TCStatus)
|
|||
)
|
||||
}
|
||||
|
||||
/// Set a mutable task's property value by name. If value.ptr is NULL, the property is removed.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tc_task_set_value(
|
||||
task: *mut TCTask,
|
||||
property: TCString,
|
||||
value: TCString,
|
||||
) -> TCResult {
|
||||
// SAFETY:
|
||||
// - property is valid (promised by caller)
|
||||
// - caller will not use property after this call (convention)
|
||||
let mut property = unsafe { TCString::val_from_arg(property) };
|
||||
let value = if value.is_null() {
|
||||
None
|
||||
} else {
|
||||
// SAFETY:
|
||||
// - value is valid (promised by caller, after NULL check)
|
||||
// - caller will not use value after this call (convention)
|
||||
Some(unsafe { TCString::val_from_arg(value) })
|
||||
};
|
||||
wrap_mut(
|
||||
task,
|
||||
|task| {
|
||||
let value_str = if let Some(mut v) = value {
|
||||
Some(v.as_str()?.to_string())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
task.set_value(property.as_str()?.to_string(), value_str)?;
|
||||
Ok(TCResult::Ok)
|
||||
},
|
||||
TCResult::Error,
|
||||
)
|
||||
}
|
||||
|
||||
/// Set a mutable task's description.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tc_task_set_description(
|
||||
|
|
|
@ -751,11 +751,16 @@ enum TCStatus tc_task_get_status(struct TCTask *task);
|
|||
struct TCKVList tc_task_get_taskmap(struct TCTask *task);
|
||||
|
||||
/**
|
||||
* Get a task's description, or NULL if the task cannot be represented as a C string (e.g., if it
|
||||
* contains embedded NUL characters).
|
||||
* Get a task's description.
|
||||
*/
|
||||
struct TCString tc_task_get_description(struct TCTask *task);
|
||||
|
||||
/**
|
||||
* Get a task property's value, or NULL if the task has no such property, (including if the
|
||||
* property name is not valid utf-8).
|
||||
*/
|
||||
struct TCString tc_task_get_value(struct TCTask *task, struct TCString property);
|
||||
|
||||
/**
|
||||
* Get the entry timestamp for a task (when it was created), or 0 if not set.
|
||||
*/
|
||||
|
@ -837,6 +842,11 @@ struct TCUdaList tc_task_get_legacy_udas(struct TCTask *task);
|
|||
*/
|
||||
TCResult tc_task_set_status(struct TCTask *task, enum TCStatus status);
|
||||
|
||||
/**
|
||||
* Set a mutable task's property value by name. If value.ptr is NULL, the property is removed.
|
||||
*/
|
||||
TCResult tc_task_set_value(struct TCTask *task, struct TCString property, struct TCString value);
|
||||
|
||||
/**
|
||||
* Set a mutable task's description.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue