Changeset 7b87e1d in mainline for uspace/lib/sif/src/sif.c


Ignore:
Timestamp:
2018-08-02T11:39:22Z (6 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
233a3a06
Parents:
1c398db2
git-author:
Jiri Svoboda <jiri@…> (2018-08-01 17:38:51)
git-committer:
Jiri Svoboda <jiri@…> (2018-08-02 11:39:22)
Message:

Implement SIF attributes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/sif/src/sif.c

    r1c398db2 r7b87e1d  
    6060 */
    6161
     62#include <adt/list.h>
     63#include <adt/odict.h>
    6264#include <errno.h>
    6365#include <stdio.h>
     
    6971static errno_t sif_export_node(sif_node_t *, FILE *);
    7072static errno_t sif_import_node(sif_node_t *, FILE *, sif_node_t **);
     73static sif_attr_t *sif_node_first_attr(sif_node_t *);
     74static sif_attr_t *sif_node_next_attr(sif_attr_t *);
     75static void sif_attr_delete(sif_attr_t *);
     76static void *sif_attr_getkey(odlink_t *);
     77static int sif_attr_cmp(void *, void *);
    7178
    7279/** Create new SIF node.
    7380 *
    74  * @param parent Parent onde
     81 * @param parent Parent node
    7582 * @return Pointer to new node on success or @c NULL if out of memory
    7683 */
     
    8491
    8592        node->parent = parent;
     93        odict_initialize(&node->attrs, sif_attr_getkey, sif_attr_cmp);
    8694        list_initialize(&node->children);
    8795
     
    92100 *
    93101 * Delete a SIF node that has been already unlinked from the tree.
     102 * This will also delete any attributes or child nodes.
    94103 *
    95104 * @param node Node
     
    97106static void sif_node_delete(sif_node_t *node)
    98107{
     108        sif_attr_t *attr;
     109        sif_node_t *child;
     110
    99111        if (node == NULL)
    100112                return;
    101113
     114        assert(!link_used(&node->lparent));
     115
    102116        if (node->ntype != NULL)
    103117                free(node->ntype);
    104118
     119        attr = sif_node_first_attr(node);
     120        while (attr != NULL) {
     121                odict_remove(&attr->lattrs);
     122                sif_attr_delete(attr);
     123                attr = sif_node_first_attr(node);
     124        }
     125
     126        child = sif_node_first_child(node);
     127        while (child != NULL) {
     128                list_remove(&child->lparent);
     129                sif_node_delete(child);
     130                child = sif_node_first_child(node);
     131        }
     132
    105133        free(node);
     134}
     135
     136/** Create new SIF attribute.
     137 *
     138 * @param node Containing node
     139 * @return Pointer to new node on success or @c NULL if out of memory
     140 */
     141static sif_attr_t *sif_attr_new(sif_node_t *node)
     142{
     143        sif_attr_t *attr;
     144
     145        attr = calloc(1, sizeof(sif_attr_t));
     146        if (attr == NULL)
     147                return NULL;
     148
     149        attr->node = node;
     150        return attr;
     151}
     152
     153/** Delete SIF attribute.
     154 *
     155 * Delete a SIF attribute that has been already unlinked from is node.
     156 *
     157 * @param attr Attribute
     158 */
     159static void sif_attr_delete(sif_attr_t *attr)
     160{
     161        if (attr == NULL)
     162                return;
     163
     164        assert(!odlink_used(&attr->lattrs));
     165
     166        if (attr->aname != NULL)
     167                free(attr->aname);
     168        if (attr->avalue != NULL)
     169                free(attr->avalue);
     170
     171        free(attr);
    106172}
    107173
     
    114180 */
    115181errno_t sif_create(const char *fname, sif_sess_t **rsess)
     182{
     183        sif_sess_t *sess;
     184        sif_node_t *root = NULL;
     185        sif_trans_t *trans = NULL;
     186        errno_t rc;
     187        FILE *f;
     188
     189        sess = calloc(1, sizeof(sif_sess_t));
     190        if (sess == NULL)
     191                return ENOMEM;
     192
     193        root = sif_node_new(NULL);
     194        if (root == NULL) {
     195                rc = ENOMEM;
     196                goto error;
     197        }
     198
     199        root->ntype = str_dup("sif");
     200        if (root->ntype == NULL) {
     201                rc = ENOMEM;
     202                goto error;
     203        }
     204
     205        f = fopen(fname, "w");
     206        if (f == NULL) {
     207                rc = EIO;
     208                goto error;
     209        }
     210
     211        sess->f = f;
     212        sess->root = root;
     213
     214        /* Run a dummy trasaction to marshall initial repo state to file */
     215        rc = sif_trans_begin(sess, &trans);
     216        if (rc != EOK)
     217                goto error;
     218
     219        rc = sif_trans_end(trans);
     220        if (rc != EOK)
     221                goto error;
     222
     223        *rsess = sess;
     224        return EOK;
     225error:
     226        if (trans != NULL)
     227                sif_trans_abort(trans);
     228        sif_node_delete(root);
     229        free(sess);
     230        return rc;
     231}
     232
     233/** Open an existing SIF repository.
     234 *
     235 * @param fname File name
     236 * @param rsess Place to store pointer to new session.
     237 *
     238 * @return EOK on success or error code
     239 */
     240errno_t sif_open(const char *fname, sif_sess_t **rsess)
    116241{
    117242        sif_sess_t *sess;
     
    124249                return ENOMEM;
    125250
    126         root = sif_node_new(NULL);
    127         if (root == NULL) {
    128                 rc = ENOMEM;
    129                 goto error;
    130         }
    131 
    132         root->ntype = str_dup("sif");
    133         if (root->ntype == NULL) {
    134                 rc = ENOMEM;
    135                 goto error;
    136         }
    137 
    138         f = fopen(fname, "w");
     251        f = fopen(fname, "r+");
    139252        if (f == NULL) {
    140253                rc = EIO;
    141254                goto error;
    142255        }
     256
     257        rc = sif_import_node(NULL, f, &root);
     258        if (rc != EOK)
     259                goto error;
     260
     261        if (str_cmp(root->ntype, "sif") != 0) {
     262                rc = EIO;
     263                goto error;
     264        }
     265
     266        sess->root = root;
    143267
    144268        sess->f = f;
     
    152276}
    153277
    154 /** Open an existing SIF repository.
    155  *
    156  * @param fname File name
    157  * @param rsess Place to store pointer to new session.
    158  *
    159  * @return EOK on success or error code
    160  */
    161 errno_t sif_open(const char *fname, sif_sess_t **rsess)
    162 {
    163         sif_sess_t *sess;
    164         sif_node_t *root = NULL;
    165         errno_t rc;
    166         FILE *f;
    167 
    168         sess = calloc(1, sizeof(sif_sess_t));
    169         if (sess == NULL)
    170                 return ENOMEM;
    171 
    172         f = fopen(fname, "r+");
    173         if (f == NULL) {
    174                 rc = EIO;
    175                 goto error;
    176         }
    177 
    178         rc = sif_import_node(NULL, f, &root);
    179         if (rc != EOK)
    180                 goto error;
    181 
    182         if (str_cmp(root->ntype, "sif") != 0) {
    183                 rc = EIO;
    184                 goto error;
    185         }
    186 
    187         sess->root = root;
    188 
    189         sess->f = f;
    190         sess->root = root;
    191         *rsess = sess;
    192         return EOK;
    193 error:
    194         sif_node_delete(root);
    195         free(sess);
    196         return rc;
    197 }
    198 
    199278/** Close SIF session.
    200279 *
     
    274353const char *sif_node_get_attr(sif_node_t *node, const char *aname)
    275354{
    276         return NULL;
     355        odlink_t *link;
     356        sif_attr_t *attr;
     357
     358        link = odict_find_eq(&node->attrs, (void *)aname, NULL);
     359        if (link == NULL)
     360                return NULL;
     361
     362        attr = odict_get_instance(link, sif_attr_t, lattrs);
     363        return attr->avalue;
    277364}
    278365
     
    296383
    297384/** Commit SIF transaction.
     385 *
     386 * Commit and free the transaction. If an error is returned, that means
     387 * the transaction has not been freed (and sif_trans_abort() must be used).
    298388 *
    299389 * @param trans Transaction
     
    320410void sif_trans_abort(sif_trans_t *trans)
    321411{
     412        free(trans);
    322413}
    323414
     
    461552void sif_node_destroy(sif_trans_t *trans, sif_node_t *node)
    462553{
    463         sif_node_t *child;
    464 
    465         child = sif_node_first_child(node);
    466         while (child != NULL) {
    467                 sif_node_destroy(trans, child);
    468                 child = sif_node_first_child(node);
    469         }
    470 
    471554        list_remove(&node->lparent);
    472555        sif_node_delete(node);
     
    483566 */
    484567errno_t sif_node_set_attr(sif_trans_t *trans, sif_node_t *node,
    485     const char *aname, const char *value)
    486 {
     568    const char *aname, const char *avalue)
     569{
     570        odlink_t *link;
     571        sif_attr_t *attr;
     572        char *cvalue;
     573
     574        link = odict_find_eq(&node->attrs, (void *)aname, NULL);
     575
     576        if (link != NULL) {
     577                attr = odict_get_instance(link, sif_attr_t, lattrs);
     578                cvalue = str_dup(avalue);
     579                if (cvalue == NULL)
     580                        return ENOMEM;
     581
     582                free(attr->avalue);
     583                attr->avalue = cvalue;
     584        } else {
     585                attr = sif_attr_new(node);
     586                if (attr == NULL)
     587                        return ENOMEM;
     588
     589                attr->aname = str_dup(aname);
     590                if (attr->aname == NULL) {
     591                        sif_attr_delete(attr);
     592                        return ENOMEM;
     593                }
     594
     595                attr->avalue = str_dup(avalue);
     596                if (attr->avalue == NULL) {
     597                        sif_attr_delete(attr);
     598                        return ENOMEM;
     599                }
     600
     601                odict_insert(&attr->lattrs, &node->attrs, NULL);
     602        }
     603
    487604        return EOK;
    488605}
     
    500617    const char *aname)
    501618{
     619        odlink_t *link;
     620        sif_attr_t *attr;
     621
     622        link = odict_find_eq(&node->attrs, (void *)aname, NULL);
     623        if (link == NULL)
     624                return;
     625
     626        attr = odict_get_instance(link, sif_attr_t, lattrs);
     627        odict_remove(link);
     628        sif_attr_delete(attr);
    502629}
    503630
     
    601728}
    602729
     730/** Import SIF attribute from file.
     731 *
     732 * @param node Node under which attribute shou
     733 * @param f File
     734 * @param rattr Place to store pointer to imported SIF attribute
     735 * @return EOK on success, EIO on I/O error
     736 */
     737static errno_t sif_import_attr(sif_node_t *node, FILE *f, sif_attr_t **rattr)
     738{
     739        errno_t rc;
     740        char *aname = NULL;
     741        char *avalue = NULL;
     742        sif_attr_t *attr;
     743        int c;
     744
     745        rc = sif_import_string(f, &aname);
     746        if (rc != EOK)
     747                goto error;
     748
     749        c = fgetc(f);
     750        if (c != '=') {
     751                rc = EIO;
     752                goto error;
     753        }
     754
     755        rc = sif_import_string(f, &avalue);
     756        if (rc != EOK)
     757                goto error;
     758
     759        attr = sif_attr_new(node);
     760        if (attr == NULL) {
     761                rc = ENOMEM;
     762                goto error;
     763        }
     764
     765        attr->aname = aname;
     766        attr->avalue = avalue;
     767
     768        *rattr = attr;
     769        return EOK;
     770error:
     771        if (aname != NULL)
     772                free(aname);
     773        if (avalue != NULL)
     774                free(avalue);
     775        return rc;
     776}
     777
     778
     779/** Export SIF attribute to file.
     780 *
     781 * @param attr SIF attribute
     782 * @param f File
     783 * @return EOK on success, EIO on I/O error
     784 */
     785static errno_t sif_export_attr(sif_attr_t *attr, FILE *f)
     786{
     787        errno_t rc;
     788
     789        rc = sif_export_string(attr->aname, f);
     790        if (rc != EOK)
     791                return rc;
     792
     793        if (fputc('=', f) == EOF)
     794                return EIO;
     795
     796        rc = sif_export_string(attr->avalue, f);
     797        if (rc != EOK)
     798                return rc;
     799
     800        return EOK;
     801}
     802
    603803/** Export SIF node to file.
    604804 *
     
    610810{
    611811        errno_t rc;
     812        sif_attr_t *attr;
    612813        sif_node_t *child;
    613814
     
    615816        if (rc != EOK)
    616817                return rc;
     818
     819        /* Attributes */
     820
     821        if (fputc('(', f) == EOF)
     822                return EIO;
     823
     824        attr = sif_node_first_attr(node);
     825        while (attr != NULL) {
     826                rc = sif_export_attr(attr, f);
     827                if (rc != EOK)
     828                        return rc;
     829
     830                attr = sif_node_next_attr(attr);
     831        }
     832
     833        if (fputc(')', f) == EOF)
     834                return EIO;
     835
     836        /* Child nodes */
    617837
    618838        if (fputc('{', f) == EOF)
     
    646866        sif_node_t *node = NULL;
    647867        sif_node_t *child;
     868        sif_attr_t *attr;
    648869        char *ntype;
    649870        int c;
     
    659880        node->ntype = ntype;
    660881
     882        /* Attributes */
     883
    661884        c = fgetc(f);
    662         if (c != '{') {
     885        if (c != '(') {
    663886                rc = EIO;
    664887                goto error;
     
    671894        }
    672895
    673         while (c != '}') {
     896        while (c != ')') {
    674897                ungetc(c, f);
    675898
    676                 rc = sif_import_node(node, f, &child);
     899                rc = sif_import_attr(node, f, &attr);
    677900                if (rc != EOK)
    678901                        goto error;
    679902
    680                 list_append(&child->lparent, &node->children);
     903                odict_insert(&attr->lattrs, &node->attrs, NULL);
    681904
    682905                c = fgetc(f);
     
    687910        }
    688911
     912        /* Child nodes */
     913
     914        c = fgetc(f);
     915        if (c != '{') {
     916                rc = EIO;
     917                goto error;
     918        }
     919
     920        c = fgetc(f);
     921        if (c == EOF) {
     922                rc = EIO;
     923                goto error;
     924        }
     925
     926        while (c != '}') {
     927                ungetc(c, f);
     928
     929                rc = sif_import_node(node, f, &child);
     930                if (rc != EOK)
     931                        goto error;
     932
     933                list_append(&child->lparent, &node->children);
     934
     935                c = fgetc(f);
     936                if (c == EOF) {
     937                        rc = EIO;
     938                        goto error;
     939                }
     940        }
     941
    689942        *rnode = node;
    690943        return EOK;
     
    694947}
    695948
     949/** Get first attribute or a node.
     950 *
     951 * @param node SIF node
     952 * @return First attribute or @c NULL if there is none
     953 */
     954static sif_attr_t *sif_node_first_attr(sif_node_t *node)
     955{
     956        odlink_t *link;
     957
     958        link = odict_first(&node->attrs);
     959        if (link == NULL)
     960                return NULL;
     961
     962        return odict_get_instance(link, sif_attr_t, lattrs);
     963}
     964
     965/** Get next attribute or a node.
     966 *
     967 * @param cur Current attribute
     968 * @return Next attribute or @c NULL if there is none
     969 */
     970static sif_attr_t *sif_node_next_attr(sif_attr_t *cur)
     971{
     972        odlink_t *link;
     973
     974        link = odict_next(&cur->lattrs, &cur->node->attrs);
     975        if (link == NULL)
     976                return NULL;
     977
     978        return odict_get_instance(link, sif_attr_t, lattrs);
     979}
     980
     981/** Get key callback for ordered dictionary of node attributes.
     982 *
     983 * @param link Ordered dictionary link of attribute
     984 * @return Pointer to attribute name
     985 */
     986static void *sif_attr_getkey(odlink_t *link)
     987{
     988        return (void *)odict_get_instance(link, sif_attr_t, lattrs)->aname;
     989}
     990
     991/** Comparison callback for  ordered dictionary of node attributes.
     992 *
     993 * @param a Name of first attribute
     994 * @param b Name of second attribute
     995 * @return Less than zero, zero or greater than zero, if a < b, a == b, a > b,
     996 *         respectively.
     997 */
     998static int sif_attr_cmp(void *a, void *b)
     999{
     1000        char *ca, *cb;
     1001
     1002        ca = (char *)a;
     1003        cb = (char *)b;
     1004
     1005        return str_cmp(ca, cb);
     1006}
     1007
    6961008/** @}
    6971009 */
Note: See TracChangeset for help on using the changeset viewer.