HelenOS sources
This source file includes following definitions.
- contacts_open
- contacts_load
- contacts_create_contact
- contacts_delete_contact
- contacts_close
- contacts_first
- contacts_next
- contacts_entry_delete
- contacts_list_all
- contacts_main
- main
#include <adt/list.h>
#include <errno.h>
#include <nchoice.h>
#include <sif.h>
#include <stdio.h>
#include <stdlib.h>
#include <str.h>
typedef struct {
sif_sess_t *repo;
sif_node_t *nentries;
list_t entries;
} contacts_t;
typedef struct {
contacts_t *contacts;
link_t lentries;
sif_node_t *nentry;
char *name;
} contacts_entry_t;
typedef enum {
ac_create_contact,
ac_delete_contact,
ac_exit
} contact_action_t;
static errno_t contacts_load(sif_node_t *, contacts_t *);
static contacts_entry_t *contacts_first(contacts_t *);
static contacts_entry_t *contacts_next(contacts_entry_t *);
static void contacts_entry_delete(contacts_entry_t *);
static errno_t contacts_open(const char *fname, contacts_t **rcontacts)
{
contacts_t *contacts = NULL;
sif_sess_t *repo = NULL;
sif_trans_t *trans = NULL;
sif_node_t *node;
const char *ntype;
errno_t rc;
contacts = calloc(1, sizeof(contacts_t));
if (contacts == NULL)
return ENOMEM;
list_initialize(&contacts->entries);
rc = sif_open(fname, &repo);
if (rc != EOK) {
rc = sif_create(fname, &repo);
if (rc != EOK)
goto error;
rc = sif_trans_begin(repo, &trans);
if (rc != EOK)
goto error;
rc = sif_node_append_child(trans, sif_get_root(repo), "entries",
&contacts->nentries);
if (rc != EOK)
goto error;
rc = sif_trans_end(trans);
if (rc != EOK)
goto error;
trans = NULL;
} else {
node = sif_node_first_child(sif_get_root(repo));
if (node == NULL) {
rc = EIO;
goto error;
}
ntype = sif_node_get_type(node);
if (str_cmp(ntype, "entries") != 0) {
rc = EIO;
goto error;
}
rc = contacts_load(node, contacts);
if (rc != EOK)
goto error;
}
contacts->repo = repo;
*rcontacts = contacts;
return EOK;
error:
if (trans != NULL)
sif_trans_abort(trans);
if (repo != NULL)
(void) sif_close(repo);
if (contacts != NULL)
free(contacts);
return rc;
}
static errno_t contacts_load(sif_node_t *nentries, contacts_t *contacts)
{
sif_node_t *nentry;
contacts_entry_t *entry;
const char *name;
contacts->nentries = nentries;
nentry = sif_node_first_child(nentries);
while (nentry != NULL) {
if (str_cmp(sif_node_get_type(nentry), "entry") != 0)
return EIO;
entry = calloc(1, sizeof(contacts_entry_t));
if (entry == NULL)
return ENOMEM;
name = sif_node_get_attr(nentry, "name");
if (name == NULL) {
free(entry);
return EIO;
}
entry->name = str_dup(name);
if (entry->name == NULL) {
free(entry);
return ENOMEM;
}
entry->contacts = contacts;
entry->nentry = nentry;
list_append(&entry->lentries, &contacts->entries);
nentry = sif_node_next_child(nentry);
}
return EOK;
}
static errno_t contacts_create_contact(contacts_t *contacts)
{
tinput_t *tinput;
sif_trans_t *trans = NULL;
sif_node_t *nentry;
contacts_entry_t *entry = NULL;
errno_t rc;
char *cname = NULL;
tinput = tinput_new();
if (tinput == NULL)
return ENOMEM;
printf("Contact name:\n");
rc = tinput_set_prompt(tinput, "?> ");
if (rc != EOK)
goto error;
rc = tinput_read(tinput, &cname);
if (rc != EOK)
goto error;
entry = calloc(1, sizeof(contacts_entry_t));
if (entry == NULL) {
rc = ENOMEM;
goto error;
}
rc = sif_trans_begin(contacts->repo, &trans);
if (rc != EOK)
goto error;
rc = sif_node_append_child(trans, contacts->nentries, "entry", &nentry);
if (rc != EOK)
goto error;
rc = sif_node_set_attr(trans, nentry, "name", cname);
if (rc != EOK)
goto error;
rc = sif_trans_end(trans);
if (rc != EOK)
goto error;
trans = NULL;
entry->contacts = contacts;
entry->nentry = nentry;
entry->name = cname;
list_append(&entry->lentries, &contacts->entries);
tinput_destroy(tinput);
return EOK;
error:
if (trans != NULL)
sif_trans_abort(trans);
if (cname != NULL)
free(cname);
if (entry != NULL)
free(entry);
return rc;
}
static errno_t contacts_delete_contact(contacts_t *contacts)
{
nchoice_t *choice = NULL;
contacts_entry_t *entry;
sif_trans_t *trans = NULL;
errno_t rc;
void *sel;
rc = nchoice_create(&choice);
if (rc != EOK) {
assert(rc == ENOMEM);
printf("Out of memory.\n");
goto error;
}
rc = nchoice_set_prompt(choice, "Select contact to delete");
if (rc != EOK) {
assert(rc == ENOMEM);
printf("Out of memory.\n");
goto error;
}
entry = contacts_first(contacts);
while (entry != NULL) {
rc = nchoice_add(choice, entry->name, (void *)entry, 0);
if (rc != EOK) {
assert(rc == ENOMEM);
printf("Out of memory.\n");
goto error;
}
entry = contacts_next(entry);
}
rc = nchoice_add(choice, "Cancel", NULL, 0);
if (rc != EOK) {
assert(rc == ENOMEM);
printf("Out of memory.\n");
goto error;
}
rc = nchoice_get(choice, &sel);
if (rc != EOK) {
printf("Error getting user selection.\n");
return rc;
}
if (sel != NULL) {
entry = (contacts_entry_t *)sel;
rc = sif_trans_begin(contacts->repo, &trans);
if (rc != EOK)
goto error;
sif_node_destroy(trans, entry->nentry);
rc = sif_trans_end(trans);
if (rc != EOK)
goto error;
trans = NULL;
list_remove(&entry->lentries);
contacts_entry_delete(entry);
}
nchoice_destroy(choice);
return EOK;
error:
if (trans != NULL)
sif_trans_abort(trans);
if (choice != NULL)
nchoice_destroy(choice);
return rc;
}
static void contacts_close(contacts_t *contacts)
{
contacts_entry_t *entry;
sif_close(contacts->repo);
entry = contacts_first(contacts);
while (entry != NULL) {
list_remove(&entry->lentries);
contacts_entry_delete(entry);
entry = contacts_first(contacts);
}
free(contacts);
}
static contacts_entry_t *contacts_first(contacts_t *contacts)
{
link_t *link;
link = list_first(&contacts->entries);
if (link == NULL)
return NULL;
return list_get_instance(link, contacts_entry_t, lentries);
}
static contacts_entry_t *contacts_next(contacts_entry_t *cur)
{
link_t *link;
link = list_next(&cur->lentries, &cur->contacts->entries);
if (link == NULL)
return NULL;
return list_get_instance(link, contacts_entry_t, lentries);
}
static void contacts_entry_delete(contacts_entry_t *entry)
{
if (entry == NULL)
return;
if (entry->name != NULL)
free(entry->name);
free(entry);
}
static void contacts_list_all(contacts_t *contacts)
{
contacts_entry_t *entry;
entry = contacts_first(contacts);
while (entry != NULL) {
printf(" * %s\n", entry->name);
entry = contacts_next(entry);
}
}
static errno_t contacts_main(contacts_t *contacts)
{
nchoice_t *choice = NULL;
errno_t rc;
bool quit = false;
void *sel;
rc = nchoice_create(&choice);
if (rc != EOK) {
assert(rc == ENOMEM);
printf("Out of memory.\n");
goto error;
}
rc = nchoice_set_prompt(choice, "Select action");
if (rc != EOK) {
assert(rc == ENOMEM);
printf("Out of memory.\n");
goto error;
}
rc = nchoice_add(choice, "Create contact",
(void *)ac_create_contact, 0);
if (rc != EOK) {
assert(rc == ENOMEM);
printf("Out of memory.\n");
goto error;
}
rc = nchoice_add(choice, "Delete contact",
(void *)ac_delete_contact, 0);
if (rc != EOK) {
assert(rc == ENOMEM);
printf("Out of memory.\n");
goto error;
}
rc = nchoice_add(choice, "Exit",
(void *)ac_exit, 0);
if (rc != EOK) {
assert(rc == ENOMEM);
printf("Out of memory.\n");
goto error;
}
while (!quit) {
contacts_list_all(contacts);
rc = nchoice_get(choice, &sel);
if (rc != EOK) {
printf("Error getting user selection.\n");
return rc;
}
switch ((contact_action_t)sel) {
case ac_create_contact:
(void) contacts_create_contact(contacts);
break;
case ac_delete_contact:
(void) contacts_delete_contact(contacts);
break;
case ac_exit:
quit = true;
break;
}
}
nchoice_destroy(choice);
return EOK;
error:
if (choice != NULL)
nchoice_destroy(choice);
return rc;
}
int main(void)
{
errno_t rc;
contacts_t *contacts = NULL;
rc = contacts_open("contacts.sif", &contacts);
if (rc != EOK)
return 1;
rc = contacts_main(contacts);
contacts_close(contacts);
if (rc != EOK)
return 1;
return 0;
}
HelenOS homepage, sources at GitHub